diff --git a/DagorEngine.rev.txt b/DagorEngine.rev.txt index 038f855b0..d742b6797 100644 --- a/DagorEngine.rev.txt +++ b/DagorEngine.rev.txt @@ -1 +1 @@ -0c5bf9c1d82d7491c925febbb3bfd48d015637df +15cc17d1f9d3b49624a81f7fbaf7aa63f0dc125d diff --git a/LICENSE b/LICENSE index df8ee3add..c62a74f38 100644 --- a/LICENSE +++ b/LICENSE @@ -129,6 +129,7 @@ third-party component as follows: prog/3rdPartyLibs/lottie/COPYING prog/3rdPartyLibs/math/carve/LICENSE prog/3rdPartyLibs/math/clipper-4.x/license.txt + prog/3rdPartyLibs/math/DelaunayTriangulator/LICENSE prog/3rdPartyLibs/math/misc/LICENSE prog/3rdPartyLibs/math/poly2tri/LICENSE prog/3rdPartyLibs/math/vhacd/LICENSE diff --git a/README.md b/README.md new file mode 100644 index 000000000..d49a9d920 --- /dev/null +++ b/README.md @@ -0,0 +1,74 @@ +## How to Build: Environment +Requirements for building and using the Dagor Engine toolkit: Windows 10 (x64), 16 GB of RAM, 200 GB of HDD/SSD space. + +* Install Git: https://git-scm.com/download/win +* Install 7-Zip: https://www.7-zip.org/ +* Install Python 3 +* If you plan to use the FMOD sound library, also install FMOD Studio SDK 2.02.15 + +Create a project folder at the root of any drive (the folder name should not contain spaces or non-Latin characters). +``` +md X:\develop && cd X:\develop +``` + +Clone the Dagor Engine source code and samples: +``` +git clone https://github.com/GaijinEntertainment/DagorEngine.git +cd DagorEngine +``` + +Run the `make_devtools.py` script. This script will download, install, and configure the build toolkit. You should provide the path to the build toolkit folder as an argument, and the script will create this folder if it doesn't exist. + +``` +python3 make_devtools.py X:\develop\devtools +``` + +If the script is not run as an administrator, installers of certain programs may request permission for installation, which you should grant. If you plan to use plugins for 3ds Max, press 'Y' when the script asks if you want to install the 3ds Max SDK. The script will also ask to add the path X:\develop\devtools to the PATH environment variable and set the GDEVTOOL variable to point to this folder. + +After the script completes its work, the X:\develop\devtools folder will be configured with the following SDKs and tools: + +* FidelityFX_SC - a library for image quality enhancement +* fmod-studio-2.xx.xx [optional] - FMOD sound library +* LLVM-15.0.7 - C/C++ compiler and libraries (Clang) +* nasm - assembler +* max2024.sdk - 3ds Max 2004 SDK +* openxr-1.0.16 - library for AR/VR +* vc2019_16.10.3 - C/C++ compiler and libraries (MSVC) +* win.sdk.100 - Windows 10 SDK +* win.sdk.81 - Windows 8.1 SDK +* ducible.exe - a tool to make builds of Portable Executables (PEs) and PDBs reproducible +* pdbdump.exe - a tool for dumping the content of PDB files +* jam.exe - a small build tool that can be used as a replacement for Make + +Restart the command line console to make the new environment variables available. + +## How to Build: Prebuilt Binaries + +You will need to download and extract additional binary files from the repository [https://github.com/GaijinEntertainment/DagorEngine/releases](https://github.com/GaijinEntertainment/DagorEngine/releases) into the X:\develop\DagorEngine folder: + +* samples-base.7z - contains initial assets that will be compiled into binary files that will be loaded the game +* samples-prebuilt-game.7z - contains precompiled assets +* tools-prebuilt.7z - contains the prebuilt engine toolkit + +The directory structure should look like this: +``` +X:\develop\DagorEngine\tools\... + +X:\develop\DagorEngine\samples\skiesSample\game + \skiesSample\develop + \skiesSample\prog + +X:\develop\DagorEngine\samples\testGI\game + \testGI\develop + \testGI\prog +``` + +* prog - game source code +* develop - initial assets +* game - directory where assets are placed after building and game executable files are located + +## How to Build: Build from Source Code + +To build the "testGI" sample, navigate to the X:\develop\DagorEngine\samples\testGI\prog folder and run the "jam" command. After building, the executable file will be placed in the testGI\game folder. + +Run DagorEngine/build_all.cmd to build the entire project toolkit from the source code. This process may take a considerable amount of time. diff --git a/make_devtools.py b/make_devtools.py index d74a72cd7..7b5643f93 100644 --- a/make_devtools.py +++ b/make_devtools.py @@ -1,33 +1,88 @@ import sys + +if sys.version_info.major < 3: + print("\nERROR: Python 3 or a higher version is required to run this script.") + exit(1) + import subprocess import pathlib import os import urllib +import ssl import ctypes import zipfile import shutil from urllib import request -if len(sys.argv) < 2: - print('echo usage: make_devtools.py DEVTOOLS_DEST_DIR') + +if len(sys.argv) != 2: + print('\nUsage: make_devtools.py DEVTOOLS_DEST_DIR\nexample: python3 make_devtools.py d:\\devtools\n') exit(1) -dest_dir = sys.argv[1] -dest_dir = dest_dir.replace('\\', '/') -if dest_dir.find(' ') != -1: - print('bad dest_dir="{0}", spaces are not allowed!'.format(dest_dir)) +def error(s): + print(f"\nERROR: {s}\n") exit(1) -def make_symlink(src, dest): - subprocess.run(['cmd', '/C', 'mklink', '/j', os.path.normpath(dest), os.path.normpath(src)]) +def ask(s): + while True: + answer = input(f"\n{s} [Y/n]: ").strip().lower() + if answer == "y" or answer == "y" or answer == "": + return True + if answer == "n" or answer == "no": + return False + +def contains_spaces(s): + return ' ' in s + +def contains_non_ascii(s): + try: + s.encode('ascii') + except UnicodeEncodeError: + return True + return False + +dest_dir = sys.argv[1].replace('\\', '/').rstrip('/') + +if contains_spaces(dest_dir): + error("The destination directory contains spaces, which are not allowed in a file path.") + +if contains_non_ascii(dest_dir): + error("The destination directory contains non-ASCII characters.") + +if not os.path.isabs(dest_dir): + error("The destination directory must be an absolute path.") + + +def make_directory_symlink(src, dest): + try: + subprocess.run(['cmd', '/C', 'mklink', '/J', os.path.normpath(dest), os.path.normpath(src)], shell = True, check = True) + except subprocess.CalledProcessError as e: + error(f"Symlink command failed with a non-zero exit code. Error: {e}, Source = '{src}', Destination = '{dest}'") + except OSError as e: + print(f"An OSError occurred. Symlink command may have failed. Error: {e}, Source = '{src}', Destination = '{dest}'") + +def make_file_link(src, dest): + os.link(src, dest) + +def run(cmd): + try: + print(f"Running: {cmd}") + subprocess.run(cmd, shell = True, check = True) + except subprocess.CalledProcessError as e: + error(f"subprocess.run failed with a non-zero exit code. Error: {e}") + except OSError as e: + print(f"An OSError occurred, subprocess.run command may have failed. Error: {e}") + + +ssl._create_default_https_context = ssl._create_unverified_context def download_url2(url, file): - file = '{0}/.packages/{1}'.format(dest_dir, file) + file = "{0}/.packages/{1}".format(dest_dir, file) if not pathlib.Path(file).exists(): - print('downloading {0} to {1} ...'.format(url, file)); + print("Downloading '{0}' to '{1}' ...".format(url, file)); response = request.urlretrieve(url, file) else: - print('package {0} present'.format(file)); + print(f"Package '{file}' already exists"); def download_url(url): path, file = os.path.split(os.path.normpath(url)) @@ -39,7 +94,7 @@ def download_url(url): # python3 python_dest_folder = dest_dir+'/python3' if pathlib.Path(python_dest_folder).exists(): - print('=== Python-3 symlink found at {0}, skipping setup'.format(python_dest_folder)) + print('=== Python 3 symlink found at {0}, skipping setup'.format(python_dest_folder)) else: python_src_folder = os.path.dirname(sys.executable) if not pathlib.Path(python_src_folder+'/python.exe').exists(): @@ -51,85 +106,170 @@ def download_url(url): if pathlib.Path(os.path.normpath(item)+'/python.exe').exists(): python_src_folder = os.path.normpath(item) break - print('+++ Python-3 found at {0}'.format(python_src_folder)) - make_symlink(python_src_folder, python_dest_folder) + print('+++ Python 3 found at {0}'.format(python_src_folder)) + make_directory_symlink(python_src_folder, python_dest_folder) subprocess.run([python_dest_folder+'/python.exe', '-m', 'pip', 'install', '--upgrade', 'pip']) subprocess.run([python_dest_folder+'/python.exe', '-m', 'pip', '--version']) - subprocess.run([python_dest_folder+'/python.exe', '-m', 'pip', 'install', 'clang']) + subprocess.run([python_dest_folder+'/python.exe', '-m', 'pip', 'install', 'clang==14.0.6']) subprocess.run([python_dest_folder+'/python.exe', '-m', 'pip', 'install', 'cymbal']) - shutil.copyfile(python_dest_folder+'/python.exe', python_dest_folder+'/python3.exe') - + if not pathlib.Path(python_dest_folder+'/python3.exe').exists(): + make_file_link(python_dest_folder+'/python.exe', python_dest_folder+'/python3.exe') else: - print('--- Python-3 not found') + error("Python 3 not found") -# Visual C/C++ 2015 -vc2015_dest_folder = dest_dir+'/vc2015.3' -if pathlib.Path(vc2015_dest_folder).exists(): - print('=== VC2015 symlink found at {0}, skipping setup'.format(vc2015_dest_folder)) -else: - vc2015_src_folder = os.environ.get('VS140COMNTOOLS', '') - if vc2015_src_folder != '': - vc2015_src_folder = os.path.normpath(vc2015_src_folder+'/../..') - else: - vc2015_src_folder = '{0}/Microsoft Visual Studio 14.0'.format(os.environ['ProgramFiles(x86)']) - if vc2015_src_folder and pathlib.Path(vc2015_src_folder).exists(): - print('+++ VC2015 found at {0}'.format(vc2015_src_folder)) - make_symlink(vc2015_src_folder+'/VC', vc2015_dest_folder) + +microsoft_retry = [] + +# vs140 +def setup_vs140(check_again_after_download): + vc2015_dest_folder = dest_dir+'/vc2015.3' + if pathlib.Path(vc2015_dest_folder).exists(): + print('=== VC2015 symlink found at {0}, skipping setup'.format(vc2015_dest_folder)) else: - print('--- VC2015 not found (VS140COMNTOOLS env var is empty), install VisualStudio 2015 upd.3 and re-run setup') - download_url('https://aka.ms/vs/17/release/vs_buildtools.exe') + vc2015_src_folder = os.environ.get('VS140COMNTOOLS', '') + if vc2015_src_folder != '': + vc2015_src_folder = os.path.normpath(vc2015_src_folder+'/../..') + else: + vc2015_src_folder = '{0}/Microsoft Visual Studio 14.0'.format(os.environ['ProgramFiles(x86)']) -# Visual C/C++ 2019 -vc2019_dest_folder = dest_dir+'/vc2019_16.10.3' -if pathlib.Path(vc2019_dest_folder).exists(): - print('=== VC2019 symlink found at {0}, skipping setup'.format(vc2019_dest_folder)) -else: - vc2019_src_folder = '{0}/Microsoft Visual Studio/2019'.format(os.environ['ProgramFiles(x86)']) - if not pathlib.Path(vc2019_src_folder).exists(): - vc2019_src_folder = '{0}/Microsoft Visual Studio/2022/BuildTools'.format(os.environ['ProgramFiles(x86)']) - if vc2019_src_folder and pathlib.Path(vc2019_src_folder).exists(): - for nm in ['/Community', '/Enterprise', '/Professional', '']: - if pathlib.Path(vc2019_src_folder+nm+'/VC/Tools/MSVC').exists(): - vc2019_src_folder = vc2019_src_folder+nm+'/VC/Tools/MSVC' - for item in pathlib.Path(vc2019_src_folder).glob("*"): - if item.is_dir(): - if pathlib.Path(os.path.normpath(item)+'/bin').exists(): - vc2019_src_folder = os.path.normpath(item) - break - break - - print('+++ VC2019 found at {0}'.format(vc2019_src_folder)) - make_symlink(vc2019_src_folder, vc2019_dest_folder) + if vc2015_src_folder and pathlib.Path(vc2015_src_folder).exists(): + print('+++ VC2015 found at {0}'.format(vc2015_src_folder)) + make_directory_symlink(vc2015_src_folder+'/VC', vc2015_dest_folder) + else: + print('--- VC2015 not found (VS140COMNTOOLS env var is empty), install VisualStudio 2015 upd.3 and re-run setup') + if not check_again_after_download: + error(f"Visual Studio 2015 is required but not found at '{vc2015_src_folder}'") + microsoft_retry.append(setup_vs140) + +#Visual Studio 2015 is turned off +#setup_vs140(True) + + +# vs142 +def setup_vs142(check_again_after_download): + vs142_ver = "14.29" + vc2019_dest_folder = dest_dir + '/vc2019_16.10.3' + + if pathlib.Path(vc2019_dest_folder).exists(): + real_path = "" + try: + real_path = os.path.realpath(vc2019_dest_folder) + except OSError as e: + pass + + if (not pathlib.Path(vc2019_dest_folder + '/bin/HostX64/x64/1033').exists() or + (real_path.find("Microsoft") != -1 and real_path.find(vs142_ver) == -1)): + print(f"{vc2019_dest_folder} contains invalid version of build tools.") + print(f"...removing {vc2019_dest_folder}") + try: + os.remove(vc2019_dest_folder) + except OSError as e: + error(f"Cannot remove link {vc2019_dest_folder}: {e}") + + + if pathlib.Path(vc2019_dest_folder).exists(): + print('=== VC2019 symlink found at {0}, skipping setup'.format(vc2019_dest_folder)) else: - print('--- VC2019 not found, install VisualStudio 2019 16.10.3+ and re-run setup') - download_url('https://aka.ms/vs/17/release/vs_buildtools.exe') + ok = False + vc2019_src_folder = '{0}/Microsoft Visual Studio'.format(os.environ['ProgramFiles(x86)']) + if vc2019_src_folder and pathlib.Path(vc2019_src_folder).exists(): + for nm in ['/2022/BuildTools', '/2022/Community', '/2022/Enterprise', '/2022/Professional', + '/2019/BuildTools', '/2019/Community', '/2019/Enterprise', '/2019/Professional']: + if pathlib.Path(vc2019_src_folder + nm + '/VC/Tools/MSVC').exists(): + versions_folder = vc2019_src_folder + nm + '/VC/Tools/MSVC' + for item in pathlib.Path(versions_folder).glob(vs142_ver + ".*"): + if item.is_dir(): + if pathlib.Path(os.path.normpath(item)+'/bin/HostX64/x64/1033').exists(): + if pathlib.Path(os.path.normpath(item)+'/bin/HostX86/x86/1033').exists(): + vc2019_src_folder = os.path.normpath(item) + ok = True + break + + if ok: + print('+++ VC2019 found at {0}'.format(vc2019_src_folder)) + make_directory_symlink(vc2019_src_folder, vc2019_dest_folder) + else: + print('--- VC2019 not found, install VisualStudio 2019 16.10.3+ and re-run setup') + if not check_again_after_download: + error(f"Visual Studio 2019 is required but not found at '{vc2019_src_folder}'") + microsoft_retry.append(setup_vs142) -# Microsoft SDK 10.0 -winsdk_dest_folder = dest_dir+'/win.sdk.100' -if pathlib.Path(winsdk_dest_folder).exists(): - print('=== Windows SDK 10.0 symlink found at {0}, skipping setup'.format(winsdk_dest_folder)) -else: - winsdk_src_folder = '{0}/Windows Kits/10'.format(os.environ['ProgramFiles(x86)']) - if pathlib.Path(winsdk_src_folder+'/bin').exists(): - print('+++ Windows SDK 10.0 found at {0}'.format(winsdk_src_folder)) - make_symlink(winsdk_src_folder, winsdk_dest_folder) + +setup_vs142(True) + + +# Microsoft Windows 10 SDK +def setup_winsdk_100(check_again_after_download): + winsdk_dest_folder = dest_dir+'/win.sdk.100' + if pathlib.Path(winsdk_dest_folder).exists(): + print('=== Windows 10 SDK symlink found at {0}, skipping setup'.format(winsdk_dest_folder)) else: - print('--- Windows SDK 10.0 not found, install Windows SDK and re-run setup') - download_url('https://aka.ms/vs/17/release/vs_buildtools.exe') + winsdk_src_folder = '{0}/Windows Kits/10'.format(os.environ['ProgramFiles(x86)']) + if pathlib.Path(winsdk_src_folder+'/include/10.0.19041.0').exists(): + print('+++ Windows 10 SDK found at {0}'.format(winsdk_src_folder)) + make_directory_symlink(winsdk_src_folder, winsdk_dest_folder) + else: + print('--- Windows 10 SDK not found, install Windows SDK and re-run setup') + if not check_again_after_download: + error(f"Windows 10 SDK is required but not found at '{winsdk_src_folder}'") + microsoft_retry.append(setup_winsdk_100) -# Microsoft SDK 8.1 -winsdk_dest_folder = dest_dir+'/win.sdk.81' -if pathlib.Path(winsdk_dest_folder).exists(): - print('=== Windows SDK 8.1 symlink found at {0}, skipping setup'.format(winsdk_dest_folder)) -else: - winsdk_src_folder = '{0}/Windows Kits/8.1'.format(os.environ['ProgramFiles(x86)']) - if pathlib.Path(winsdk_src_folder+'/bin').exists(): - print('+++ Windows SDK 8.1 found at {0}'.format(winsdk_src_folder)) - make_symlink(winsdk_src_folder, winsdk_dest_folder) +setup_winsdk_100(True) + + +# Microsoft Windows 8.1 SDK +def setup_winsdk_81(check_again_after_download): + winsdk_dest_folder = dest_dir+'/win.sdk.81' + if pathlib.Path(winsdk_dest_folder).exists(): + print('=== Windows 8.1 SDK symlink found at {0}, skipping setup'.format(winsdk_dest_folder)) else: - print('--- Windows SDK 8.1 not found, install Windows SDK and re-run setup') - download_url('https://aka.ms/vs/17/release/vs_buildtools.exe') + winsdk_src_folder = '{0}/Windows Kits/8.1'.format(os.environ['ProgramFiles(x86)']) + if pathlib.Path(winsdk_src_folder+'/include').exists(): + print('+++ Windows 8.1 SDK found at {0}'.format(winsdk_src_folder)) + make_directory_symlink(winsdk_src_folder, winsdk_dest_folder) + else: + print('--- Windows 8.1 SDK not found, install Windows SDK and re-run setup') + if not check_again_after_download: + error(f"Windows 8.1 SDK is required but not found at '{winsdk_src_folder}'") + + pathlib.Path(f"{dest_dir}/.packages/vs140").mkdir(parents=True, exist_ok=True) + download_url2("https://aka.ms/vs/15/release/vs_buildtools.exe", f"vs140/vs_buildtools.exe") + run(f"{dest_dir}/.packages/vs140/vs_buildtools.exe --wait --passive --add " + + "Microsoft.VisualStudio.Component.Windows81SDK ") + setup_winsdk_81(False) + +setup_winsdk_81(True) + + +if len(microsoft_retry) > 0: + download_url('https://aka.ms/vs/17/release/vs_buildtools.exe') + run(f"{dest_dir}/.packages/vs_buildtools.exe --wait --passive --addProductLang en-US --add " + + " Microsoft.VisualStudio.Component.Roslyn.Compiler" + + " Microsoft.Component.MSBuild" + + " Microsoft.VisualStudio.Component.CoreBuildTools" + + " Microsoft.VisualStudio.Workload.MSBuildTools" + + " Microsoft.VisualStudio.Component.Windows10SDK" + + " Microsoft.VisualStudio.Component.VC.CoreBuildTools" + + " Microsoft.VisualStudio.Component.VC.Redist.14.Latest" + + " Microsoft.VisualStudio.Component.TestTools.BuildTools" + + " Microsoft.Net.Component.4.7.2.TargetingPack" + + " Microsoft.VisualStudio.Component.VC.ASAN" + + " Microsoft.VisualStudio.Component.TextTemplating" + + " Microsoft.VisualStudio.Component.VC.CoreIde" + + " Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core" + + " Microsoft.VisualStudio.Component.Windows10SDK.19041" + + " Microsoft.VisualStudio.ComponentGroup.VC.Tools.142.x86.x64" + + " Microsoft.Component.VC.Runtime.UCRTSDK" + + " Microsoft.VisualStudio.Component.VC.140" + + " Microsoft.VisualStudio.Workload.VCTools" + + " Microsoft.VisualStudio.Component.VC.14.29.16.11.x86.x64" + + " Microsoft.VisualStudio.Component.VC.14.29.16.11.ATL" ) + + for fn in microsoft_retry: + fn(False) + + # LLVM 15.0.7 llvm_dest_folder = dest_dir+'/LLVM-15.0.7' @@ -140,13 +280,14 @@ def download_url(url): if not pathlib.Path(llvm_src_folder+'/bin').exists(): print('--- LLVM 15.0.7 not found, trying to install') download_url('https://github.com/llvm/llvm-project/releases/download/llvmorg-15.0.7/LLVM-15.0.7-win64.exe') - ctypes.windll.shell32.ShellExecuteW(None, "runas", os.path.normpath(dest_dir+'/.packages/LLVM-15.0.7-win64.exe'), '/s', None, 1) + run(dest_dir+'/.packages/LLVM-15.0.7-win64.exe /S') if pathlib.Path(llvm_src_folder+'/bin').exists(): print('+++ LLVM 15.0.7 found at {0}'.format(llvm_src_folder)) - make_symlink(llvm_src_folder, llvm_dest_folder) + make_directory_symlink(llvm_src_folder, llvm_dest_folder) else: - print('--- LLVM 15.0.7 not found, skipped setup') + error("LLVM 15.0.7 not found") + # nasm nasm_dest_folder = dest_dir+'/nasm' @@ -156,11 +297,12 @@ def download_url(url): download_url('https://www.nasm.us/pub/nasm/releasebuilds/2.16/win64/nasm-2.16-win64.zip') with zipfile.ZipFile(os.path.normpath(dest_dir+'/.packages/nasm-2.16-win64.zip'), 'r') as zip_file: zip_file.extractall(dest_dir) - make_symlink(dest_dir+'/nasm-2.16', nasm_dest_folder) + make_directory_symlink(dest_dir+'/nasm-2.16', nasm_dest_folder) shutil.copyfile(nasm_dest_folder+'/nasm.exe', nasm_dest_folder+'/nasmw.exe') shutil.copyfile(nasm_dest_folder+'/ndisasm.exe', nasm_dest_folder+'/ndisasmw.exe') print('+++ NASM 2.16 installed at {0}'.format(nasm_dest_folder)) + # ducible ducible_dest_file = dest_dir+'/ducible.exe' if pathlib.Path(ducible_dest_file).exists(): @@ -171,6 +313,7 @@ def download_url(url): zip_file.extractall(dest_dir) print('+++ Ducible tool installed at {0}'.format(dest_dir)) + # boost-1.62 def install_boost_1_62(): boost_dest_folder = dest_dir+'/boost-1.62' @@ -187,7 +330,7 @@ def install_boost_1_62(): if boost_src_folder != '': print('+++ boost-1.62 found at {0}'.format(boost_src_folder)) - make_symlink(boost_src_folder, boost_dest_folder) + make_directory_symlink(boost_src_folder, boost_dest_folder) else: download_url('https://sourceforge.net/projects/boost/files/boost/1.62.0/boost_1_62_0.zip') with zipfile.ZipFile(os.path.normpath(dest_dir+'/.packages/boost_1_62_0.zip'), 'r') as zip_file: @@ -204,24 +347,26 @@ def install_boost_1_62(): #install_boost_1_62() + # 3ds Max SDK def install_3ds_Max_SDK(ver, url): maxsdk_dest_folder = dest_dir+'/max'+ver+'.sdk' if pathlib.Path(maxsdk_dest_folder).exists(): print('=== 3ds Max SDK {1} symlink found at {0}, skipping setup'.format(maxsdk_dest_folder, ver)) else: - maxsdk_src_folder = '{0}/Autodesk/3ds Max {1} SDK'.format(os.environ['ProgramFiles'], ver) - if not pathlib.Path(maxsdk_src_folder+'/maxsdk').exists(): - print('--- 3ds Max SDK '+ver+' not found, trying to install') - download_url(url) - path, file = os.path.split(os.path.normpath(url)) - ctypes.windll.shell32.ShellExecuteW(None, "open", os.path.normpath(dest_dir+'/.packages/'+file), '', None, 1) - - if pathlib.Path(maxsdk_src_folder+'/maxsdk').exists(): - print('+++ 3ds Max SDK {1} found at {0}'.format(maxsdk_src_folder, ver)) - make_symlink(maxsdk_src_folder+'/maxsdk', maxsdk_dest_folder) - else: - print('--- 3ds Max SDK {1} not found at {0}, skipped setup'.format(maxsdk_src_folder, ver)) + if ask(f"Do you want to install 3ds Max {ver} SDK?"): + maxsdk_src_folder = '{0}/Autodesk/3ds Max {1} SDK'.format(os.environ['ProgramFiles'], ver) + if not pathlib.Path(maxsdk_src_folder+'/maxsdk').exists(): + print('--- 3ds Max SDK '+ver+' not found, trying to install') + download_url(url) + path, file = os.path.split(os.path.normpath(url)) + run('msiexec /i ' + os.path.normpath(dest_dir + '/.packages/' + file) + ' /qb') + + if pathlib.Path(maxsdk_src_folder+'/maxsdk').exists(): + print('+++ 3ds Max SDK {1} found at {0}'.format(maxsdk_src_folder, ver)) + make_directory_symlink(maxsdk_src_folder+'/maxsdk', maxsdk_dest_folder) + else: + print('--- 3ds Max SDK {1} not found at {0}, skipped setup'.format(maxsdk_src_folder, ver)) install_3ds_Max_SDK('2024', 'https://autodesk-adn-transfer.s3.us-west-2.amazonaws.com/ADN+Extranet/M%26E/Max/Autodesk+3ds+Max+2024/SDK_3dsMax2024.msi') @@ -230,6 +375,7 @@ def install_3ds_Max_SDK(ver, url): #install_3ds_Max_SDK('2019', # 'https://autodesk-adn-transfer.s3.us-west-2.amazonaws.com/ADN%20Extranet/M%26E/Max/Autodesk%203ds%20Max%202019/SDK_3dsMax2019.msi') + # FMOD fmod_dest_folder = dest_dir+'/fmod-studio-2.xx.xx' if pathlib.Path(fmod_dest_folder).exists(): @@ -240,20 +386,20 @@ def install_3ds_Max_SDK(ver, url): print('+++ FMOD found at {0}'.format(fmod_src_folder)) pathlib.Path(fmod_dest_folder+'/core/win32').mkdir(parents=True, exist_ok=True) - make_symlink(fmod_src_folder+'/api/core/inc', fmod_dest_folder+'/core/win32/inc') - make_symlink(fmod_src_folder+'/api/core/lib/x86', fmod_dest_folder+'/core/win32/lib') + make_directory_symlink(fmod_src_folder+'/api/core/inc', fmod_dest_folder+'/core/win32/inc') + make_directory_symlink(fmod_src_folder+'/api/core/lib/x86', fmod_dest_folder+'/core/win32/lib') pathlib.Path(fmod_dest_folder+'/core/win64').mkdir(parents=True, exist_ok=True) - make_symlink(fmod_src_folder+'/api/core/inc', fmod_dest_folder+'/core/win64/inc') - make_symlink(fmod_src_folder+'/api/core/lib/x64', fmod_dest_folder+'/core/win64/lib') + make_directory_symlink(fmod_src_folder+'/api/core/inc', fmod_dest_folder+'/core/win64/inc') + make_directory_symlink(fmod_src_folder+'/api/core/lib/x64', fmod_dest_folder+'/core/win64/lib') pathlib.Path(fmod_dest_folder+'/studio/win32').mkdir(parents=True, exist_ok=True) - make_symlink(fmod_src_folder+'/api/studio/inc', fmod_dest_folder+'/studio/win32/inc') - make_symlink(fmod_src_folder+'/api/studio/lib/x86', fmod_dest_folder+'/studio/win32/lib') + make_directory_symlink(fmod_src_folder+'/api/studio/inc', fmod_dest_folder+'/studio/win32/inc') + make_directory_symlink(fmod_src_folder+'/api/studio/lib/x86', fmod_dest_folder+'/studio/win32/lib') pathlib.Path(fmod_dest_folder+'/studio/win64').mkdir(parents=True, exist_ok=True) - make_symlink(fmod_src_folder+'/api/studio/inc', fmod_dest_folder+'/studio/win64/inc') - make_symlink(fmod_src_folder+'/api/studio/lib/x64', fmod_dest_folder+'/studio/win64/lib') + make_directory_symlink(fmod_src_folder+'/api/studio/inc', fmod_dest_folder+'/studio/win64/inc') + make_directory_symlink(fmod_src_folder+'/api/studio/lib/x64', fmod_dest_folder+'/studio/win64/lib') else: print('--- FMOD not found at {0}, creating stub folders'.format(fmod_src_folder)) print('consider downloading and installing https://www.fmod.com/download#fmodengine - Windows Download') @@ -262,6 +408,7 @@ def install_3ds_Max_SDK(ver, url): pathlib.Path(fmod_dest_folder+'/studio/win32/inc').mkdir(parents=True, exist_ok=True) pathlib.Path(fmod_dest_folder+'/studio/win64/inc').mkdir(parents=True, exist_ok=True) + # OpenXR 1.0.16 openxr_dest_folder = dest_dir+'/openxr-1.0.16' if pathlib.Path(openxr_dest_folder).exists(): @@ -270,11 +417,12 @@ def install_3ds_Max_SDK(ver, url): download_url('https://github.com/KhronosGroup/OpenXR-SDK-Source/releases/download/release-1.0.16/openxr_loader_windows-1.0.16.zip') with zipfile.ZipFile(os.path.normpath(dest_dir+'/.packages/openxr_loader_windows-1.0.16.zip'), 'r') as zip_file: zip_file.extractall(openxr_dest_folder) - make_symlink(openxr_dest_folder+'/openxr_loader_windows/include', openxr_dest_folder+'/include') - make_symlink(openxr_dest_folder+'/openxr_loader_windows/Win32', openxr_dest_folder+'/win32') - make_symlink(openxr_dest_folder+'/openxr_loader_windows/x64', openxr_dest_folder+'/win64') + make_directory_symlink(openxr_dest_folder+'/openxr_loader_windows/include', openxr_dest_folder+'/include') + make_directory_symlink(openxr_dest_folder+'/openxr_loader_windows/Win32', openxr_dest_folder+'/win32') + make_directory_symlink(openxr_dest_folder+'/openxr_loader_windows/x64', openxr_dest_folder+'/win64') print('+++ OpenXR 1.0.16 installed at {0}'.format(openxr_dest_folder)) + # FidelityFX-FSR2 compiler ffxsc_dest_folder = dest_dir+'/FidelityFX_SC' if pathlib.Path(ffxsc_dest_folder).exists(): @@ -283,10 +431,30 @@ def install_3ds_Max_SDK(ver, url): download_url2('https://github.com/GPUOpen-Effects/FidelityFX-FSR2/archive/refs/tags/v2.2.1.zip', 'FidelityFX-FSR2.zip') with zipfile.ZipFile(os.path.normpath(dest_dir+'/.packages/FidelityFX-FSR2.zip'), 'r') as zip_file: zip_file.extractall(dest_dir+'/.packages/') - make_symlink(dest_dir+'/.packages/FidelityFX-FSR2-2.2.1/tools/sc', ffxsc_dest_folder) + make_directory_symlink(dest_dir+'/.packages/FidelityFX-FSR2-2.2.1/tools/sc', ffxsc_dest_folder) print('+++ FidelityFX_SC 2.2.1 installed at {0}'.format(ffxsc_dest_folder)) +# DXC-1.7.2207 +dxc_dest_folder = dest_dir+'/DXC-1.7.2207' +if pathlib.Path(dxc_dest_folder).exists(): + print('=== DXC Jul 2022 found at {0}, skipping setup'.format(dxc_dest_folder)) +else: + download_url('https://github.com/microsoft/DirectXShaderCompiler/releases/download/v1.7.2207/dxc_2022_07_18.zip') + download_url('https://github.com/microsoft/DirectXShaderCompiler/archive/refs/tags/v1.7.2207.zip') + with zipfile.ZipFile(os.path.normpath(dest_dir+'/.packages/v1.7.2207.zip'), 'r') as zip_file: + zip_file.extractall(dest_dir+'/.packages/') + with zipfile.ZipFile(os.path.normpath(dest_dir+'/.packages/dxc_2022_07_18.zip'), 'r') as zip_file: + zip_file.extractall(dest_dir+'/.packages/DirectXShaderCompiler-1.7.2207/_win') + + pathlib.Path(dxc_dest_folder+'/include').mkdir(parents=True, exist_ok=True) + pathlib.Path(dxc_dest_folder+'/lib/win64').mkdir(parents=True, exist_ok=True) + make_directory_symlink(dest_dir+'/.packages/DirectXShaderCompiler-1.7.2207/include/dxc', dxc_dest_folder+'/include/dxc') + shutil.copyfile(dest_dir+'/.packages/DirectXShaderCompiler-1.7.2207/_win/bin/x64/dxcompiler.dll', dxc_dest_folder+'/lib/win64/dxcompiler.dll') + shutil.copyfile(dest_dir+'/.packages/DirectXShaderCompiler-1.7.2207/LICENSE.TXT', dxc_dest_folder+'/LICENSE.TXT') + print('+++ DXC Jul 2022 installed at {0}'.format(dxc_dest_folder)) + + # re-write platform.jam if pathlib.Path('prog/platform.jam').exists(): with open('prog/platform.jam', 'w') as fd: @@ -296,3 +464,37 @@ def install_3ds_Max_SDK(ver, url): fd.write('BulletSdkVer = 3 ;\n') fd.write('OpenSSLVer = 3.x ;\n') fd.close() + + +nomalized_dest = os.path.normpath(dest_dir) +env_updated = False + +if os.environ.get('GDEVTOOL', '') == '': + if ask("Environment variable 'GDEVTOOL' not found. Do you want to set it?"): + subprocess.run(["setx", "GDEVTOOL", nomalized_dest], shell=True, text=True) + os.environ["GDEVTOOL"] = nomalized_dest + env_updated = True +elif os.environ.get('GDEVTOOL', '') != nomalized_dest: + if ask("Environment variable 'GDEVTOOL' points to another directory. Do you want to update it?"): + subprocess.run(["setx", "GDEVTOOL", nomalized_dest], shell=True, text=True) + os.environ["GDEVTOOL"] = nomalized_dest + env_updated = True + +if nomalized_dest not in os.environ.get('PATH', '').split(os.pathsep): + if ask(f"'{nomalized_dest}' is not found in 'PATH' variable. Do you want to add it?"): + subprocess.run(["setx", "PATH", f"{nomalized_dest};{os.environ.get('PATH', '')}"], shell=True, text=True) + os.environ["PATH"] = os.environ.get('PATH', '') + ";" + nomalized_dest + env_updated = True + +try: + subprocess.run(["jam", "-v"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) +except FileNotFoundError: + print("jam.exe not found, installing jam...") + download_url2("https://github.com/GaijinEntertainment/jam-G8/releases/download/2.5-G8-1.2-2023%2F05%2F04/jam-win64.zip", "jam.zip") + with zipfile.ZipFile(os.path.normpath(dest_dir+'/.packages/jam.zip'), 'r') as zip_file: + zip_file.extractall(dest_dir) + +if env_updated: + print("\nDone. Please restart your comandline environment to apply the environment variables.") +else: + print("\nDone.") diff --git a/prog/1stPartyLibs/daScript/include/daScript/ast/ast.h b/prog/1stPartyLibs/daScript/include/daScript/ast/ast.h index f4f6116d9..75ba2bfc5 100644 --- a/prog/1stPartyLibs/daScript/include/daScript/ast/ast.h +++ b/prog/1stPartyLibs/daScript/include/daScript/ast/ast.h @@ -1343,7 +1343,8 @@ namespace das bool no_aliasing = false; // if true, aliasing will be reported as error, otherwise will turn off optimization bool strict_smart_pointers = false; // collection of tests for smart pointers, like van inscope for any local, etc bool no_init = false; // if true, then no [init] is allowed in any shape or form - bool strict_unsafe_delete = false; // if true, delete of type which contains 'unsafe' delete is unsafe // TODO: enable when need be + bool strict_unsafe_delete = false; // if true, delete of type which contains 'unsafe' delete is unsafe // TODO: enable when need be + bool no_members_functions_in_struct = false; // structures can't have member functions // environment bool no_optimizations = false; // disable optimizations, regardless of settings bool fail_on_no_aot = true; // AOT link failure is error @@ -1433,7 +1434,7 @@ namespace das void markModuleSymbolUse(TextWriter * logs = nullptr); void markMacroSymbolUse(TextWriter * logs = nullptr); void markExecutableSymbolUse(TextWriter * logs = nullptr); - void markFoldingSymbolUse(TextWriter * logs = nullptr); + void markFoldingSymbolUse(const vector & needRun, TextWriter * logs = nullptr); void removeUnusedSymbols(); void clearSymbolUse(); void dumpSymbolUse(TextWriter & logs); diff --git a/prog/1stPartyLibs/daScript/src/ast/ast_const_folding.cpp b/prog/1stPartyLibs/daScript/src/ast/ast_const_folding.cpp index a47f54f0b..109ec3191 100644 --- a/prog/1stPartyLibs/daScript/src/ast/ast_const_folding.cpp +++ b/prog/1stPartyLibs/daScript/src/ast/ast_const_folding.cpp @@ -413,9 +413,8 @@ namespace das { class ConstFolding : public FoldingVisitor { public: ConstFolding( const ProgramPtr & prog ) : FoldingVisitor(prog) {} - bool needRun() const { return runMe; } - protected: - bool runMe = false; + public: + vector needRun; protected: // function which is fully a nop bool isNop ( const FunctionPtr & func ) { @@ -706,7 +705,7 @@ namespace das { if ( expr->func->builtIn ) { return evalAndFold(expr); } else { - runMe = true; + needRun.push_back(expr->func); } } } @@ -809,9 +808,13 @@ namespace das { class RunFolding : public FoldingVisitor { public: - bool simulated = false; + RunFolding( const ProgramPtr & prog, const vector & _needRun ) : FoldingVisitor(prog), + runProgram(prog.get()), needRun(_needRun) { + } + protected: Program * runProgram = nullptr; - RunFolding( const ProgramPtr & prog ) : FoldingVisitor(prog), runProgram(prog.get()) {} + const vector & needRun; + bool anySimulated = false; protected: // ExprCall virtual ExpressionPtr visit ( ExprCall * expr ) override { @@ -823,11 +826,11 @@ namespace das { } } if ( allConst ) { - if ( !simulated ) { - simulated = true; + if ( !anySimulated ) { // the reason for lazy simulation is that function can be optimized out during the same pass as it was marked for folding + anySimulated = true; TextWriter dummy; runProgram->folding = true; - runProgram->markFoldingSymbolUse(); + runProgram->markFoldingSymbolUse(needRun); DAS_ASSERTF ( !runProgram->failed(), "internal error while folding (remove unused)?" ); runProgram->allocateStack(dummy); DAS_ASSERTF ( !runProgram->failed(), "internal error while folding (allocate stack)?" ); @@ -861,9 +864,9 @@ namespace das { ConstFolding cfe(this); visit(cfe); bool any = cfe.didAnything(); - if ( cfe.needRun() ) { + if ( !cfe.needRun.empty() ) { if ( !options.getBoolOption("disable_run",false) ) { - RunFolding rfe(this); + RunFolding rfe(this,cfe.needRun); visit(rfe); any |= rfe.didAnything(); } diff --git a/prog/1stPartyLibs/daScript/src/ast/ast_export.cpp b/prog/1stPartyLibs/daScript/src/ast/ast_export.cpp index adcd1cdeb..e81531f51 100644 --- a/prog/1stPartyLibs/daScript/src/ast/ast_export.cpp +++ b/prog/1stPartyLibs/daScript/src/ast/ast_export.cpp @@ -291,18 +291,14 @@ namespace das { vis.markVarsUsed(library, false); } - void Program::markFoldingSymbolUse(TextWriter * logs) { + void Program::markFoldingSymbolUse(const vector & needRun, TextWriter * logs) { clearSymbolUse(); MarkSymbolUse vis(false); vis.tw = logs; visit(vis); - - thisModule->functions.foreach([&](auto fn) { - vis.propagateFunctionUse(fn); - }); - thisModule->globals.foreach([&](auto var) { - vis.propageteVarUse(var); - }); + for ( auto fun : needRun ) { + vis.propagateFunctionUse(fun); + } } void Program::markSymbolUse(bool builtInSym, bool forceAll, bool initThis, Module * macroModule, TextWriter * logs) { diff --git a/prog/1stPartyLibs/daScript/src/builtin/builtin.das b/prog/1stPartyLibs/daScript/src/builtin/builtin.das index e1f193b29..1bf4c59f8 100644 --- a/prog/1stPartyLibs/daScript/src/builtin/builtin.das +++ b/prog/1stPartyLibs/daScript/src/builtin/builtin.das @@ -256,6 +256,14 @@ def erase(var Arr:array;at:int;count:int) _builtin_verify_locks(Arr) __builtin_array_erase_range(Arr,at,count,typeinfo(sizeof Arr[0])) +def remove_value(var arr : array|#; key : TT) : bool + //! Removes the first occurrence of a specific object from the collection. + let idx = find_index(arr, key) + if idx != -1 + arr |> erase(idx) + return true + return false + [unused_argument(a)] def length(a:auto[]):int return typeinfo(dim a) diff --git a/prog/1stPartyLibs/daScript/src/parser/parser_impl.cpp b/prog/1stPartyLibs/daScript/src/parser/parser_impl.cpp index 9759e05fa..0e2de2986 100644 --- a/prog/1stPartyLibs/daScript/src/parser/parser_impl.cpp +++ b/prog/1stPartyLibs/daScript/src/parser/parser_impl.cpp @@ -480,7 +480,7 @@ namespace das { vector * ast_structVarDefAbstract ( yyscan_t scanner, vector * list, AnnotationList * annL, bool isPrivate, bool cnst, Function * func ) { - if ( !yyextra->g_thisStructure->isClass ) { + if ( yyextra->g_Program->policies.no_members_functions_in_struct && !yyextra->g_thisStructure->isClass ) { das_yyerror(scanner,"structure can't have a member function", func->at, CompilationError::invalid_member_function); } else if ( func->isGeneric() ) { @@ -538,7 +538,7 @@ namespace das { if ( !yyextra->g_thisStructure ) { das_yyerror(scanner,"internal error or invalid macro. member function is declared outside of a class", func->at, CompilationError::invalid_member_function); - } else if ( !yyextra->g_thisStructure->isClass ) { + } else if ( yyextra->g_Program->policies.no_members_functions_in_struct && !yyextra->g_thisStructure->isClass ) { das_yyerror(scanner,"structure can't have a member function", func->at, CompilationError::invalid_member_function); } else if ( func->isGeneric() ) { diff --git a/prog/1stPartyLibs/dag/dag_relocatable.h b/prog/1stPartyLibs/dag/dag_relocatable.h index 43d6cbf8c..d178645aa 100644 --- a/prog/1stPartyLibs/dag/dag_relocatable.h +++ b/prog/1stPartyLibs/dag/dag_relocatable.h @@ -2,7 +2,7 @@ * Dagor Engine * Copyright (C) 2023 Gaijin Games KFT. All rights reserved * - * (for conditions of distribution and use, see EULA in "prog/eula.txt") + * (for conditions of use see prog/license.txt) */ #ifndef _DAGOR_DAG_RELOCATABLE_H_ diff --git a/prog/1stPartyLibs/dag/dag_vector.h b/prog/1stPartyLibs/dag/dag_vector.h index ba200a62d..9c14e402c 100644 --- a/prog/1stPartyLibs/dag/dag_vector.h +++ b/prog/1stPartyLibs/dag/dag_vector.h @@ -2,7 +2,7 @@ * Dagor Engine * Copyright (C) 2023 Gaijin Games KFT. All rights reserved * - * (for conditions of distribution and use, see EULA in "prog/eula.txt") + * (for conditions of use see prog/license.txt) */ #ifndef _DAGOR_DAG_VECTOR_H_ diff --git a/prog/1stPartyLibs/dag/dag_vectorMap.h b/prog/1stPartyLibs/dag/dag_vectorMap.h index 6a4ab615c..2c63b90f9 100644 --- a/prog/1stPartyLibs/dag/dag_vectorMap.h +++ b/prog/1stPartyLibs/dag/dag_vectorMap.h @@ -2,7 +2,7 @@ * Dagor Engine * Copyright (C) 2023 Gaijin Games KFT. All rights reserved * - * (for conditions of distribution and use, see EULA in "prog/eula.txt") + * (for conditions of use see prog/license.txt) */ #ifndef _DAGOR_DAG_VECTOR_MAP_H_ diff --git a/prog/1stPartyLibs/dag/dag_vectorSet.h b/prog/1stPartyLibs/dag/dag_vectorSet.h index 565eb8e87..29c0e71ed 100644 --- a/prog/1stPartyLibs/dag/dag_vectorSet.h +++ b/prog/1stPartyLibs/dag/dag_vectorSet.h @@ -2,7 +2,7 @@ * Dagor Engine * Copyright (C) 2023 Gaijin Games KFT. All rights reserved * - * (for conditions of distribution and use, see EULA in "prog/eula.txt") + * (for conditions of use see prog/license.txt) */ #ifndef _DAGOR_DAG_VECTOR_SET_H_ diff --git a/prog/1stPartyLibs/quirrel/quirrel/include/sqstddebug.h b/prog/1stPartyLibs/quirrel/quirrel/include/sqstddebug.h new file mode 100644 index 000000000..142b76ba8 --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/include/sqstddebug.h @@ -0,0 +1,16 @@ +/* see copyright notice in squirrel.h */ +#ifndef _SQSTD_DEBUG_H_ +#define _SQSTD_DEBUG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +SQUIRREL_API SQRESULT sqstd_register_debuglib(HSQUIRRELVM v); + + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif // _SQSTD_DEBUG_H_ diff --git a/prog/1stPartyLibs/quirrel/quirrel/include/squirrel.h b/prog/1stPartyLibs/quirrel/quirrel/include/squirrel.h index 153ef0d4e..4fb534a88 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/include/squirrel.h +++ b/prog/1stPartyLibs/quirrel/quirrel/include/squirrel.h @@ -275,6 +275,7 @@ SQUIRREL_API SQInteger sq_gettop(HSQUIRRELVM v); SQUIRREL_API void sq_settop(HSQUIRRELVM v,SQInteger newtop); SQUIRREL_API SQRESULT sq_reservestack(HSQUIRRELVM v,SQInteger nsize); SQUIRREL_API SQInteger sq_cmp(HSQUIRRELVM v); +SQUIRREL_API bool sq_cmpraw(HSQUIRRELVM v, HSQOBJECT &lhs, HSQOBJECT &rhs, SQInteger &res); SQUIRREL_API void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx); /*object creation handling*/ @@ -368,6 +369,7 @@ SQUIRREL_API SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval,SQBool invoke_err_ha SQUIRREL_API const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx); SQUIRREL_API SQRESULT sq_getcallee(HSQUIRRELVM v); SQUIRREL_API const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval); +SQUIRREL_API void sq_throwparamtypeerror(HSQUIRRELVM v, SQInteger nparam, SQInteger typemask, SQInteger type); SQUIRREL_API SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err); SQUIRREL_API SQRESULT sq_throwobject(HSQUIRRELVM v); SQUIRREL_API void sq_reseterror(HSQUIRRELVM v); @@ -430,6 +432,7 @@ SQUIRREL_API void sq_printwarningslist(FILE *ostream); SQUIRREL_API void sq_disablesyntaxwarnings(); SQUIRREL_API void sq_enablesyntaxwarnings(); SQUIRREL_API void sq_checkglobalnames(HSQUIRRELVM v); +SQUIRREL_API void sq_mergeglobalnames(const HSQOBJECT *bindings); /*UTILITY MACRO*/ diff --git a/prog/1stPartyLibs/quirrel/quirrel/jamfile b/prog/1stPartyLibs/quirrel/quirrel/jamfile index bdbb1be11..c56d4442a 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/jamfile +++ b/prog/1stPartyLibs/quirrel/quirrel/jamfile @@ -46,6 +46,7 @@ Sources = sqstdlib/sqstdmath.cpp sqstdlib/sqstdstring.cpp sqstdlib/sqstdblob.cpp + sqstdlib/sqstddebug.cpp sqstdlib/sqstdio.cpp sqstdlib/sqstdstream.cpp sqstdlib/sqstdsystem.cpp diff --git a/prog/1stPartyLibs/quirrel/quirrel/sq/sq.cpp b/prog/1stPartyLibs/quirrel/quirrel/sq/sq.cpp index 92c51ff20..8aed52c04 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/sq/sq.cpp +++ b/prog/1stPartyLibs/quirrel/quirrel/sq/sq.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -559,6 +560,7 @@ int DagorWinMain(bool /*debugmode*/) sqstd_register_datetimelib(v); sqstd_register_mathlib(v); sqstd_register_stringlib(v); + sqstd_register_debuglib(v); //aux library //sets error handlers @@ -571,6 +573,7 @@ int DagorWinMain(bool /*debugmode*/) module_mgr->registerIoStreamLib(); module_mgr->registerIoLib(); module_mgr->registerDateTimeLib(); + module_mgr->registerDebugLib(); sqstd_register_command_line_args(v, ::dgs_argc, ::dgs_argv); diff --git a/prog/1stPartyLibs/quirrel/quirrel/sqmodules/sqmodules.cpp b/prog/1stPartyLibs/quirrel/quirrel/sqmodules/sqmodules.cpp index c8e05283d..e25083b87 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/sqmodules/sqmodules.cpp +++ b/prog/1stPartyLibs/quirrel/quirrel/sqmodules/sqmodules.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -568,6 +569,11 @@ void SqModules::registerDateTimeLib() registerStdLibNativeModule("datetime", sqstd_register_datetimelib); } +void SqModules::registerDebugLib() +{ + registerStdLibNativeModule("debug", sqstd_register_debuglib); +} + void SqModules::registerIoStreamLib() { HSQOBJECT hModule; diff --git a/prog/1stPartyLibs/quirrel/quirrel/sqmodules/sqmodules.h b/prog/1stPartyLibs/quirrel/quirrel/sqmodules/sqmodules.h index cb92bc9ed..0f9dd4f0f 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/sqmodules/sqmodules.h +++ b/prog/1stPartyLibs/quirrel/quirrel/sqmodules/sqmodules.h @@ -61,6 +61,7 @@ class SqModules void registerIoStreamLib(); void registerIoLib(); void registerDateTimeLib(); + void registerDebugLib(); Sqrat::Object *findNativeModule(const string &module_name); diff --git a/prog/1stPartyLibs/quirrel/quirrel/sqstdlib/CMakeLists.txt b/prog/1stPartyLibs/quirrel/quirrel/sqstdlib/CMakeLists.txt index 242889ce8..bdbfa25a3 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/sqstdlib/CMakeLists.txt +++ b/prog/1stPartyLibs/quirrel/quirrel/sqstdlib/CMakeLists.txt @@ -1,5 +1,6 @@ set(SQSTDLIB_SRC sqstdaux.cpp sqstdblob.cpp + sqstddebug.cpp sqstdio.cpp sqstdmath.cpp sqstdrex.cpp diff --git a/prog/1stPartyLibs/quirrel/quirrel/sqstdlib/sqstddebug.cpp b/prog/1stPartyLibs/quirrel/quirrel/sqstdlib/sqstddebug.cpp new file mode 100644 index 000000000..49e5dec95 --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/sqstdlib/sqstddebug.cpp @@ -0,0 +1,91 @@ +#include +#include + + +static SQInteger debug_seterrorhandler(HSQUIRRELVM v) +{ + sq_seterrorhandler(v); + return 0; +} + +static SQInteger debug_setdebughook(HSQUIRRELVM v) +{ + sq_setdebughook(v); + return 0; +} + +SQInteger __getcallstackinfos(HSQUIRRELVM v, SQInteger level); + +static SQInteger debug_getstackinfos(HSQUIRRELVM v) +{ + SQInteger level; + sq_getinteger(v, -1, &level); + return __getcallstackinfos(v, level); +} + +#ifndef NO_GARBAGE_COLLECTOR +static SQInteger debug_collectgarbage(HSQUIRRELVM v) +{ + sq_pushinteger(v, sq_collectgarbage(v)); + return 1; +} +static SQInteger debug_resurrectunreachable(HSQUIRRELVM v) +{ + sq_resurrectunreachable(v); + return 1; +} +#endif + +static SQInteger debug_getbuildinfo(HSQUIRRELVM v) +{ + sq_newtable(v); + sq_pushstring(v, _SC("version"), -1); + sq_pushstring(v, SQUIRREL_VERSION, -1); + sq_newslot(v, -3, SQFalse); + sq_pushstring(v, _SC("charsize"), -1); + sq_pushinteger(v, sizeof(SQChar)); + sq_newslot(v, -3, SQFalse); + sq_pushstring(v, _SC("intsize"), -1); + sq_pushinteger(v, sizeof(SQInteger)); + sq_newslot(v, -3, SQFalse); + sq_pushstring(v, _SC("floatsize"), -1); + sq_pushinteger(v, sizeof(SQFloat)); + sq_newslot(v, -3, SQFalse); + sq_pushstring(v, _SC("gc"), -1); +#ifndef NO_GARBAGE_COLLECTOR + sq_pushstring(v, _SC("enabled"), -1); +#else + sq_pushstring(v, _SC("disabled"), -1); +#endif // NO_GARBAGE_COLLECTOR + sq_newslot(v, -3, SQFalse); + return 1; +} + + +static const SQRegFunction debuglib_funcs[] = { + {_SC("seterrorhandler"),debug_seterrorhandler,2, NULL}, + {_SC("setdebughook"),debug_setdebughook,2, NULL}, + {_SC("getstackinfos"),debug_getstackinfos,2, _SC(".n")}, +#ifndef NO_GARBAGE_COLLECTOR + {_SC("collectgarbage"),debug_collectgarbage,0, NULL}, + {_SC("resurrectunreachable"),debug_resurrectunreachable,0, NULL}, +#endif + {_SC("getbuildinfo"), debug_getbuildinfo,1,NULL}, + {NULL,(SQFUNCTION)0,0,NULL} +}; + + +SQRESULT sqstd_register_debuglib(HSQUIRRELVM v) +{ + SQInteger i = 0; + while (debuglib_funcs[i].name != 0) + { + sq_pushstring(v, debuglib_funcs[i].name, -1); + sq_newclosure(v, debuglib_funcs[i].f, 0); + sq_setparamscheck(v, debuglib_funcs[i].nparamscheck, debuglib_funcs[i].typemask); + sq_setnativeclosurename(v, -1, debuglib_funcs[i].name); + sq_newslot(v, -3, SQFalse); + i++; + } + return SQ_OK; +} diff --git a/prog/1stPartyLibs/quirrel/quirrel/sqstdlib/sqstdmath.cpp b/prog/1stPartyLibs/quirrel/quirrel/sqstdlib/sqstdmath.cpp index 2837c9365..6a150b96e 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/sqstdlib/sqstdmath.cpp +++ b/prog/1stPartyLibs/quirrel/quirrel/sqstdlib/sqstdmath.cpp @@ -60,6 +60,81 @@ SINGLE_ARG_FUNC(ceil) SINGLE_ARG_FUNC(round) SINGLE_ARG_FUNC(exp) +template +static SQInteger math_min_max(HSQUIRRELVM v) +{ + SQInteger nArgs = sq_gettop(v); + SQObject objRes; + sq_getstackobj(v, 2, &objRes); + + for (SQInteger i = 3; i <= nArgs; ++i) { + SQObject cur; + sq_getstackobj(v, i, &cur); + if (!(sq_type(cur) & SQOBJECT_NUMERIC)) { + sq_throwparamtypeerror(v, i, _RT_FLOAT | _RT_INTEGER, sq_type(cur)); + return SQ_ERROR; + } + + SQInteger cres = 0; + if (!sq_cmpraw(v, cur, objRes, cres)) + return sq_throwerror(v, _SC("Internal error, comparison failed")); + + if (cres == CmpRes) + objRes = cur; + } + + sq_pushobject(v, objRes); + return 1; +} + +static SQInteger math_min(HSQUIRRELVM v) +{ + return math_min_max<-1>(v); +} + +static SQInteger math_max(HSQUIRRELVM v) +{ + return math_min_max<+1>(v); +} + +static SQInteger math_clamp(HSQUIRRELVM v) +{ + SQObject x, lo, hi; + SQInteger cres = 0; + + sq_getstackobj(v, 2, &x); + sq_getstackobj(v, 3, &lo); + sq_getstackobj(v, 4, &hi); + + const SQChar *cmpFailedErrText = _SC("Internal error, comparison failed"); + + if (!sq_cmpraw(v, lo, hi, cres)) + return sq_throwerror(v, cmpFailedErrText); + + if (cres > 0) + return sq_throwerror(v, _SC("Invalid clamp range: min>max")); + + if (!sq_cmpraw(v, x, lo, cres)) + return sq_throwerror(v, cmpFailedErrText); + + if (cres < 0) { + sq_pushobject(v, lo); + return 1; + } + + if (!sq_cmpraw(v, x, hi, cres)) + return sq_throwerror(v, cmpFailedErrText); + + if (cres > 0) { + sq_pushobject(v, hi); + return 1; + } + + sq_pushobject(v, x); + return 1; +} + + #define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),math_##name,nparams,tycheck} static const SQRegFunction mathlib_funcs[] = { _DECL_FUNC(sqrt,2,_SC(".n")), @@ -81,6 +156,9 @@ static const SQRegFunction mathlib_funcs[] = { _DECL_FUNC(rand,1,NULL), _DECL_FUNC(fabs,2,_SC(".n")), _DECL_FUNC(abs,2,_SC(".n")), + _DECL_FUNC(min,-3,_SC(".nnnnnnnn")), + _DECL_FUNC(max,-3,_SC(".nnnnnnnn")), + _DECL_FUNC(clamp,4,_SC(".nnn")), {NULL,(SQFUNCTION)0,0,NULL} }; #undef _DECL_FUNC diff --git a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqapi.cpp b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqapi.cpp index 8aff13d10..015f64fe4 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqapi.cpp +++ b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqapi.cpp @@ -941,6 +941,12 @@ SQInteger sq_cmp(HSQUIRRELVM v) return res; } +bool sq_cmpraw(HSQUIRRELVM v, HSQOBJECT &lhs, HSQOBJECT &rhs, SQInteger &res) +{ + return v->ObjCmp(lhs, rhs, res); +} + + SQRESULT sq_newslot(HSQUIRRELVM v, SQInteger idx, SQBool bstatic) { v->ValidateThreadAccess(); @@ -1246,6 +1252,11 @@ void sq_resetobject(HSQOBJECT *po) po->_unVal.raw=0;po->_type=OT_NULL;po->_flags=0; } +void sq_throwparamtypeerror(HSQUIRRELVM v, SQInteger nparam, SQInteger typemask, SQInteger type) +{ + v->Raise_ParamTypeError(nparam, typemask, type); +} + SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err) { v->_lasterror=SQString::Create(_ss(v),err); @@ -1892,3 +1903,7 @@ void sq_enablesyntaxwarnings() { void sq_checkglobalnames(HSQUIRRELVM v) { StaticAnalyser::reportGlobalNameDiagnostics(v); } + +void sq_mergeglobalnames(const HSQOBJECT *bindings) { + StaticAnalyser::mergeKnownBindings(bindings); +} diff --git a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqast.h b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqast.h index e16d1cb12..0ff432cb8 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqast.h +++ b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqast.h @@ -324,11 +324,16 @@ class FieldAccessExpr : public AccessExpr { }; class GetFieldExpr : public FieldAccessExpr { + bool _isBuiltInGet; public: - GetFieldExpr(Expr *receiver, const SQChar *field, bool nullable): FieldAccessExpr(TO_GETFIELD, receiver, field, nullable) {} + GetFieldExpr(Expr *receiver, const SQChar *field, bool nullable, bool builtin) + : FieldAccessExpr(TO_GETFIELD, receiver, field, nullable) + , _isBuiltInGet(builtin) {} void visitChildren(Visitor *visitor); void transformChildren(Transformer *transformer); + + bool isBuiltInGet() const { return _isBuiltInGet; } }; @@ -695,6 +700,7 @@ class FunctionDecl : public Decl { void visitChildren(Visitor *visitor); void transformChildren(Transformer *transformer); + void setName(const SQChar *newName) { _name = newName; } const SQChar *name() const { return _name; } bool isVararg() const { return _vararg; } Block *body() const { return _body; } @@ -776,7 +782,11 @@ class DeclGroup : public Decl { public: DeclGroup(Arena *arena) : Decl(TO_DECL_GROUP), _decls(arena) {} - void addDeclaration(VarDecl *d) { _decls.push_back(d); } + void addDeclaration(VarDecl *d) { + _decls.push_back(d); + setLineEndPos(d->lineEnd()); + setColumnEndPos(d->columnEnd()); + } void visitChildren(Visitor *visitor); void transformChildren(Transformer *transformer); @@ -800,7 +810,11 @@ class DestructuringDecl : public DeclGroup { void visitChildren(Visitor *visitor); void transformChildren(Transformer *transformer); - void setExpression(Expr *expr) { _expr = expr; } + void setExpression(Expr *expr) { + _expr = expr; + setLineEndPos(expr->lineEnd()); + setColumnEndPos(expr->columnEnd()); + } Expr *initiExpression() const { return _expr; } void setType(enum DestructuringType t) { _dt_type = t; } diff --git a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqastcodegen.cpp b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqastcodegen.cpp index fdd728502..593768d51 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqastcodegen.cpp +++ b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqastcodegen.cpp @@ -939,11 +939,15 @@ void CodegenVisitor::visitCallExpr(CallExpr *call) { Expr *callee = deparen(call->callee()); bool isNullCall = call->isNullable(); + bool isBuiltInCall = false; + if (callee->op() == TO_GETFIELD) { + isBuiltInCall = callee->asGetField()->isBuiltInGet(); + } visitNoGet(callee); if (isObject(callee)) { - if (!isNullCall) { + if (!isNullCall && !isBuiltInCall && ((_fs->lang_features & LF_FORBID_IMPLICIT_DEF_DELEGATE) == 0)) { SQInteger key = _fs->PopTarget(); /* location of the key */ SQInteger table = _fs->PopTarget(); /* location of the object */ SQInteger closure = _fs->PushTarget(); /* location for the closure */ @@ -955,7 +959,16 @@ void CodegenVisitor::visitCallExpr(CallExpr *call) { SQInteger storedSelf = _fs->PushTarget(); _fs->AddInstruction(_OP_MOVE, storedSelf, self); _fs->PopTarget(); - Emit2ArgsOP(_OP_GET, OP_GET_FLAG_NO_ERROR | OP_GET_FLAG_ALLOW_DEF_DELEGATE); + SQInteger flags = 0; + if (isBuiltInCall) { + flags |= OP_GET_FLAG_BUILTIN_ONLY; + } else if ((_fs->lang_features & LF_FORBID_IMPLICIT_DEF_DELEGATE) == 0) { + flags |= OP_GET_FLAG_ALLOW_DEF_DELEGATE; + } + if (isNullCall) + flags |= OP_GET_FLAG_NO_ERROR; + + Emit2ArgsOP(_OP_GET, flags); SQInteger ttarget = _fs->PushTarget(); _fs->AddInstruction(_OP_MOVE, ttarget, storedSelf); } @@ -1256,6 +1269,9 @@ bool CodegenVisitor::canBeLiteral(AccessExpr *expr) { bool CodegenVisitor::CanBeDefaultDelegate(const SQChar *key) { + if (_fs->lang_features & LF_FORBID_IMPLICIT_DEF_DELEGATE) + return false; + // this can be optimized by keeping joined list/table of used keys SQTable *delegTbls[] = { _table(_fs->_sharedstate->_table_default_delegate), @@ -1369,6 +1385,10 @@ void CodegenVisitor::visitGetFieldExpr(GetFieldExpr *expr) { flags |= OP_GET_FLAG_ALLOW_DEF_DELEGATE; } + if (expr->isBuiltInGet()) { + flags |= OP_GET_FLAG_BUILTIN_ONLY; + } + if (expr->receiver()->op() == TO_BASE) { Emit2ArgsOP(_OP_GET, flags); } else if (!_donot_get) { diff --git a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqastparser.cpp b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqastparser.cpp index ce18ac67c..90ad1c70e 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqastparser.cpp +++ b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqastparser.cpp @@ -43,6 +43,7 @@ SQParser::SQParser(SQVM *v, const char *sourceText, size_t sourceTextSize, const _expression_context = SQE_REGULAR; _lang_features = _ss(v)->defaultLangFeatures; _depth = 0; + _rangeIteratorId = 0; _token = 0; } @@ -100,7 +101,9 @@ static const SQPragmaDescriptor pragmaDescriptors[] = { { "forbid-delete-operator", LF_FORBID_DELETE_OP, 0 }, { "allow-delete-operator", 0, LF_FORBID_DELETE_OP }, { "forbid-clone-operator", LF_FORBID_CLONE_OP, 0 }, - { "allow-clone-operator", 0, LF_FORBID_CLONE_OP } + { "allow-clone-operator", 0, LF_FORBID_CLONE_OP }, + { "forbid-implicit-default-delegates", LF_FORBID_IMPLICIT_DEF_DELEGATE, 0 }, + { "allow-implicit-default-delegates", 0, LF_FORBID_IMPLICIT_DEF_DELEGATE } }; Statement* SQParser::parseDirectiveStatement() @@ -721,18 +724,23 @@ Expr* SQParser::PrefixedExpr() nc.inc(); switch(_token) { case _SC('.'): - case TK_NULLGETSTR: { - if (_token == TK_NULLGETSTR || nextIsNullable) + case TK_NULLGETSTR: + case TK_BUILT_IN_GETSTR: + case TK_NULLABLE_BUILT_IN_GETSTR: { + if (_token == TK_NULLGETSTR || _token == TK_NULLABLE_BUILT_IN_GETSTR || nextIsNullable) { nextIsNullable = true; } + + bool isBuintInGet = _token == TK_BUILT_IN_GETSTR || _token == TK_NULLABLE_BUILT_IN_GETSTR; + Lex(); SQInteger l = _lex._currentline, c = _lex._currentcolumn; Expr *receiver = e; Id *id = (Id *)Expect(TK_IDENTIFIER); assert(id); - e = newNode(receiver, id->id(), nextIsNullable); //-V522 + e = newNode(receiver, id->id(), nextIsNullable, isBuintInGet); //-V522 e->setLineStartPos(receiver->lineStart()); e->setColumnStartPos(receiver->columnStart()); e->setLineEndPos(l); e->setColumnEndPos(c); break; @@ -864,7 +872,7 @@ Expr *SQParser::parseStringTemplate() { result = fmt; } else { - Expr *callee = setCoordinates(newNode(fmt, "subst", false), l, c); + Expr *callee = setCoordinates(newNode(fmt, "subst", false, /* force built-in member */ true), l, c); CallExpr *call = setCoordinates(newNode(arena(), callee, false), l, c); for (Expr *arg : args) @@ -894,7 +902,7 @@ Expr* SQParser::Factor(SQInteger &pos) r->setLineStartPos(l); r->setColumnStartPos(c); Lex(); break; - case _SC('$'): + case TK_TEMPLATE_OP: r = parseStringTemplate(); break; case TK_BASE: @@ -1166,6 +1174,7 @@ Decl* SQParser::parseLocalDeclStatement() NestingChecker nc(this); assert(_token == TK_LET || _token == TK_LOCAL); + SQInteger gl = line(), gc = column(); bool assignable = _token == TK_LOCAL; Lex(); @@ -1175,6 +1184,7 @@ Decl* SQParser::parseLocalDeclStatement() return parseLocalClassDeclStmt(assignable); } + DeclGroup *decls = NULL; DestructuringDecl *dd = NULL; Decl *decl = NULL; @@ -1197,6 +1207,12 @@ Decl* SQParser::parseLocalDeclStatement() if(_token == _SC('=')) { Lex(); Expr *expr = Expression(SQE_REGULAR); + if (!assignable && expr->op() == TO_DECL_EXPR && expr->asDeclExpr()->declaration()->op() == TO_FUNCTION) { + FunctionDecl *f = static_cast(expr->asDeclExpr()->declaration()); + if (!f->name() || f->name()[0] == _SC('(')) { + f->setName(varname->id()); + } + } cur = newNode(varname->id(), expr, assignable, destructurer != 0); //-V522 } else { @@ -1210,7 +1226,7 @@ Decl* SQParser::parseLocalDeclStatement() if (decls) { decls->addDeclaration(cur); } else if (decl) { - decls = newNode(arena()); + decls = setCoordinates(newNode(arena()), gl, gc); decls->addDeclaration(static_cast(decl)); decls->addDeclaration(cur); decl = decls; @@ -1377,28 +1393,127 @@ ForStatement* SQParser::parseForStatement() SQInteger l = line(), c = column(); + /* range-loop cases + 1. for (count) == for (local $i = 0; $i < count; ++$i) + 2. for (variable : count) == for (local variable = 0; variable < count; ++variable) + 3. for (variable : from, to) == for (local variable = from; variable < to; ++variable) + 4. for (variable : from, to, step) == for (local variable = from; variable < to; variable += step) + 5. for (from, to) == for (local $i = from; $i < to; ++$i) + 6. for (a, b, s, ...) -- syntax error + 7. for (a, b, s, x; ...; ....) -- regular for-loop + */ + Consume(TK_FOR); Expect(_SC('(')); + SQInteger l2 = line(), c2 = column(); + Node *init = NULL; - if (_token == TK_LOCAL) - init = parseLocalDeclStatement(); + Expr *cond = nullptr, *mod = nullptr; + if (_token == TK_LOCAL) { + init = parseLocalDeclStatement(); + } else if (_token != _SC(';')) { - init = parseCommaExpr(SQE_REGULAR); + init = parseCommaExpr(SQE_REGULAR); } - Expect(_SC(';')); - Expr *cond = NULL; - if(_token != _SC(';')) { + if (_token == _SC(';')) { + // Regular loop + Lex(); + if (_token != _SC(';')) { cond = Expression(SQE_LOOP_CONDITION); - } - Expect(_SC(';')); + } + Expect(_SC(';')); - Expr *mod = NULL; - if(_token != _SC(')')) { + if (_token != _SC(')')) { mod = parseCommaExpr(SQE_REGULAR); + } } + else { + // Range loop + if (init == nullptr) { + reportDiagnostic(DiagnosticsId::DI_SUSPICIOUS_SYNTAX_RANGE_LOOP); + } + + Expr *initValue = nullptr, *limit = nullptr, *step = nullptr; + Id *id = nullptr; + + size_t commaSizeLimit = 3; + const char *loopForm = nullptr; + + if (_token == _SC(':')) { + Lex(); + if (init->op() != TO_ID) { // -V1004 + _ctx.reportDiagnostic(DiagnosticsId::DI_ID_RANGE_LOOP, init->lineStart(), init->columnStart(), init->textWidth()); + } + else { + id = init->asId(); + } + + loopForm = "for (variable: [from,] to [, step])"; + + init = parseCommaExpr(SQE_REGULAR); + } + else { + char buf[128] = { 0 }; + snprintf(buf, sizeof buf, "$it%u", _rangeIteratorId++); + id = newId(buf); + id->setLineStartPos(l); id->setColumnStartPos(c); + id->setLineEndPos(l2); id->setColumnEndPos(c2); + commaSizeLimit = 2; + loopForm = "for ([from, ] to)"; + } + + if (init->op() == TO_COMMA) { + CommaExpr *cma = static_cast(init); + auto &expressions = cma->expressions(); // -V522 + size_t size = expressions.size(); + if (size > commaSizeLimit) { + const Expr *e = expressions[commaSizeLimit]; + _ctx.reportDiagnostic(DiagnosticsId::DI_COMMA_RANGE_LOOP, e->lineStart(), e->columnStart(), e->textWidth(), loopForm); + } + + limit = expressions[0]; + if (size > 1) { + initValue = limit; + limit = expressions[1]; + } + if (size > 2) { + step = expressions[2]; + } + } + else { + if (!init->isExpression()) { // -V1004 + _ctx.reportDiagnostic(DiagnosticsId::DI_EXPECTED_TOKEN, init->lineStart(), init->columnStart(), init->textWidth(), "expression"); + } + limit = init->asExpression(); + } + + assert(limit != nullptr); + + if (!initValue) { + initValue = newNode(SQInteger(0)); + initValue->setLineStartPos(l); initValue->setColumnStartPos(c); + initValue->setLineEndPos(l2); initValue->setColumnEndPos(c2); + } + + init = newNode(id->id(), initValue, true); // -V522 + init->setLineStartPos(id->lineStart()); init->setColumnStartPos(id->columnStart()); + init->setLineEndPos(initValue->lineStart()); init->setColumnEndPos(initValue->columnStart()); + + Id *checkId = copyCoordinates(id, newId(id->id())); + cond = copyCoordinates(limit, newNode(TO_LT, checkId, limit)); + + Id *modId = copyCoordinates(id, newId(id->id())); + if (step) { + mod = copyCoordinates(step, newNode(TO_PLUSEQ, modId, step)); + } + else { + mod = copyCoordinates(id, newNode(id, 1, IF_PREFIX)); + } + } + Expect(_SC(')')); bool wrapped = false; diff --git a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqastparser.h b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqastparser.h index 8b4d7cc4d..8ecd8d03a 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqastparser.h +++ b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqastparser.h @@ -77,6 +77,7 @@ class SQParser void reportDiagnostic(int32_t id, ...); uint32_t _depth; + uint32_t _rangeIteratorId; SQParser(SQVM *v, const char *sourceText, size_t sourceTextSize, const SQChar* sourcename, Arena *astArena, SQCompilationContext &ctx, Comments *comments); diff --git a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqastrender.h b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqastrender.h index 3e6415402..ee3fd8c66 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqastrender.h +++ b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqastrender.h @@ -123,6 +123,7 @@ class RenderVisitor : public Visitor { expr->receiver()->visit(this); if (expr->isNullable()) _out->writeInt8('?'); _out->writeChar('.'); + if (expr->isBuiltInGet()) _out->writeInt8('$'); _out->writeString(expr->fieldName()); } virtual void visitSetFieldExpr(SetFieldExpr *expr) { diff --git a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqbaselib.cpp b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqbaselib.cpp index 0774e7c1e..d886d9edb 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqbaselib.cpp +++ b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqbaselib.cpp @@ -77,20 +77,6 @@ static SQInteger get_allowed_args_count(SQObject &closure, SQInteger num_support return -1; } - -#ifndef NO_GARBAGE_COLLECTOR -static SQInteger base_collectgarbage(HSQUIRRELVM v) -{ - sq_pushinteger(v, sq_collectgarbage(v)); - return 1; -} -static SQInteger base_resurrectunreachable(HSQUIRRELVM v) -{ - sq_resurrectunreachable(v); - return 1; -} -#endif - static SQInteger base_getroottable(HSQUIRRELVM v) { v->Push(v->_roottable); @@ -103,20 +89,7 @@ static SQInteger base_getconsttable(HSQUIRRELVM v) return 1; } - -static SQInteger base_seterrorhandler(HSQUIRRELVM v) -{ - sq_seterrorhandler(v); - return 0; -} - -static SQInteger base_setdebughook(HSQUIRRELVM v) -{ - sq_setdebughook(v); - return 0; -} - -static SQInteger __getcallstackinfos(HSQUIRRELVM v,SQInteger level) +SQInteger __getcallstackinfos(HSQUIRRELVM v,SQInteger level) { SQStackInfos si; SQInteger seq = 0; @@ -154,12 +127,6 @@ static SQInteger __getcallstackinfos(HSQUIRRELVM v,SQInteger level) return 0; } -static SQInteger base_getstackinfos(HSQUIRRELVM v) -{ - SQInteger level; - sq_getinteger(v, -1, &level); - return __getcallstackinfos(v,level); -} static SQInteger base_assert(HSQUIRRELVM v) { @@ -315,101 +282,160 @@ static SQInteger base_callee(HSQUIRRELVM v) return sq_throwerror(v,_SC("no closure in the calls stack")); } +static SQInteger base_freeze(HSQUIRRELVM v) +{ + return SQ_SUCCEEDED(sq_freeze(v, 2)) ? 1 : SQ_ERROR; +} + +static SQInteger base_getobjflags(HSQUIRRELVM v) +{ + sq_pushinteger(v, sq_objflags(stack_get(v, 2))); + return 1; +} -template -static SQInteger base_min_max(HSQUIRRELVM v) +static SQInteger base_call_method_impl(HSQUIRRELVM v, bool safe) { - SQInteger nArgs = sq_gettop(v); - SQObject objRes = stack_get(v, 2); + SQChar message[1024] = {0}; + int32_t nArgs = sq_gettop(v); - for (SQInteger i = 3; i <= nArgs; ++i) { - SQObjectPtr &cur = stack_get(v, i); - if (!(sq_type(cur) & SQOBJECT_NUMERIC)) { - v->Raise_ParamTypeError(i, _RT_FLOAT|_RT_INTEGER, sq_type(cur)); - return SQ_ERROR; + if (nArgs < 3) + { + if (safe) + { + v->Pop(nArgs); + v->PushNull(); + return 1; } + snprintf(message, sizeof message, _SC("'__call_method(...)' recieves at least 2 arguments (%d), object to method on and method's name"), nArgs); + return sq_throwerror(v, message); + } - SQInteger cres = 0; - if (!v->ObjCmp(cur, objRes, cres)) - return sq_throwerror(v, _SC("Internal error, comparison failed")); + SQObject obj = stack_get(v, 2); + SQObject name = stack_get(v, 3); - if (cres == CmpRes) - objRes = cur; + if (!sq_isstring(name)) + { + if (safe) + { + v->Pop(nArgs); + v->PushNull(); + return 1; + } + snprintf(message, sizeof message, _SC("'__call_method(...)' expects 2nd argument to be string, actual '%s'"), IdType2Name(sq_type(name))); + return sq_throwerror(v, message); } - v->Push(objRes); - return 1; -} - + SQObject delegates; + SQObjectType type = sq_type(obj); + switch (type) + { + case OT_INTEGER: + case OT_FLOAT: + case OT_BOOL: + delegates = _ss(v)->_number_default_delegate; + break; + case OT_STRING: + delegates = _ss(v)->_string_default_delegate; + break; + case OT_TABLE: + delegates = _ss(v)->_table_default_delegate; + break; + case OT_ARRAY: + delegates = _ss(v)->_array_default_delegate; + break; + case OT_USERDATA: + delegates = _ss(v)->_userdata_default_delegate; + break; + case OT_CLOSURE: + case OT_NATIVECLOSURE: + delegates = _ss(v)->_closure_default_delegate; + break; + case OT_GENERATOR: + delegates = _ss(v)->_generator_default_delegate; + break; + case OT_THREAD: + delegates = _ss(v)->_thread_default_delegate; + break; + case OT_CLASS: + delegates = _ss(v)->_class_default_delegate; + break; + case OT_INSTANCE: + delegates = _ss(v)->_instance_default_delegate; + break; + case OT_WEAKREF: + delegates = _ss(v)->_weakref_default_delegate; + break; + default: + if (safe) + { + v->Pop(nArgs); + v->PushNull(); + return 1; + } + snprintf(message, sizeof message, _SC("unsupported object type '%s' as receiver in '__call_method(...)' function"), IdType2Name(type)); + return sq_throwerror(v, message); + } -static SQInteger base_clamp(HSQUIRRELVM v) -{ - SQObject x = stack_get(v, 2), lo = stack_get(v, 3), hi = stack_get(v, 4); - SQInteger cres = 0; + assert(sq_istable(delegates)); - const SQChar *cmpFailedErrText = _SC("Internal error, comparison failed"); + SQObjectPtr callee; + if (!_table(delegates)->Get(name, callee)) + { + if (safe) + { + v->Pop(nArgs); + v->PushNull(); + return 1; + } + else + { + snprintf(message, sizeof message, _SC("function '%s' not found in '%s' delegates"), _stringval(name), IdType2Name(type)); + return sq_throwerror(v, message); + } + } - if (!v->ObjCmp(lo, hi, cres)) - return sq_throwerror(v, cmpFailedErrText); + assert(sq_isnativeclosure(callee)); - if (cres > 0) - return sq_throwerror(v, _SC("Invalid clamp range: min>max")); + sqvector args(_ss(v)->_alloc_ctx); - if (!v->ObjCmp(x, lo, cres)) - return sq_throwerror(v, cmpFailedErrText); + args.reserve(nArgs - 2); + args.push_back(obj); - if (cres < 0) { - v->Push(lo); - return 1; + for (int32_t i = 4; i <= nArgs; ++i) // skip reciever + name + { + SQObject arg = stack_get(v, i); + args.push_back(arg); } - if (!v->ObjCmp(x, hi, cres)) - return sq_throwerror(v, cmpFailedErrText); + for (int32_t i = 0; i < args.size(); ++i) + { + v->Push(args[i]); + } - if (cres > 0) { - v->Push(hi); - return 1; + bool s, t; + SQObjectPtr ret; + if (!v->CallNative(_nativeclosure(callee), nArgs - 2, v->_stackbase + nArgs, ret, -1, s, t)) + { + return SQ_ERROR; } - v->Push(x); + v->Pop(nArgs); + v->Push(ret); return 1; } -static SQInteger base_freeze(HSQUIRRELVM v) +static SQInteger base_call_method(HSQUIRRELVM v) { - return SQ_SUCCEEDED(sq_freeze(v, 2)) ? 1 : SQ_ERROR; + return base_call_method_impl(v, false); } -static SQInteger base_getobjflags(HSQUIRRELVM v) +static SQInteger base_call_method_safe(HSQUIRRELVM v) { - sq_pushinteger(v, sq_objflags(stack_get(v, 2))); - return 1; -} - -static SQInteger base_getbuildinfo(HSQUIRRELVM v) -{ - sq_newtable(v); - sq_pushstring(v,_SC("version"),-1); - sq_pushstring(v,SQUIRREL_VERSION,-1); - sq_newslot(v,-3, SQFalse); - sq_pushstring(v,_SC("charsize"),-1); - sq_pushinteger(v,sizeof(SQChar)); - sq_newslot(v,-3, SQFalse); - sq_pushstring(v,_SC("intsize"),-1); - sq_pushinteger(v,sizeof(SQInteger)); - sq_newslot(v,-3, SQFalse); - sq_pushstring(v,_SC("floatsize"),-1); - sq_pushinteger(v,sizeof(SQFloat)); - sq_newslot(v,-3, SQFalse); - return 1; + return base_call_method_impl(v, true); } - static const SQRegFunction base_funcs[]={ //generic - {_SC("seterrorhandler"),base_seterrorhandler,2, NULL}, - {_SC("setdebughook"),base_setdebughook,2, NULL}, - {_SC("getstackinfos"),base_getstackinfos,2, _SC(".n")}, {_SC("getroottable"),base_getroottable,1, NULL}, {_SC("getconsttable"),base_getconsttable,1, NULL}, {_SC("assert"),base_assert, -2, NULL}, @@ -423,16 +449,10 @@ static const SQRegFunction base_funcs[]={ {_SC("array"),base_array,-2, _SC(".n")}, {_SC("type"),base_type,2, NULL}, {_SC("callee"),base_callee,0,NULL}, -#ifndef NO_GARBAGE_COLLECTOR - {_SC("collectgarbage"),base_collectgarbage,0, NULL}, - {_SC("resurrectunreachable"),base_resurrectunreachable,0, NULL}, -#endif - {_SC("min"),base_min_max<-1>,-3,_SC(".nnnnnnnn")}, - {_SC("max"),base_min_max<1>,-3,_SC(".nnnnnnnn")}, - {_SC("clamp"),base_clamp,4,_SC(".nnn")}, {_SC("freeze"),base_freeze,2,NULL}, {_SC("getobjflags"), base_getobjflags,2,NULL}, - {_SC("getbuildinfo"), base_getbuildinfo,1,NULL}, + {_SC("call_type_method"),base_call_method,-1,NULL}, + {_SC("call_type_method_safe"),base_call_method_safe,-1,NULL}, {NULL,(SQFUNCTION)0,0,NULL} }; @@ -948,6 +968,15 @@ static SQInteger obj_clone(HSQUIRRELVM vm) { return 1; } +static SQInteger obj_is_frozen(HSQUIRRELVM vm) { + SQObjectPtr self = vm->PopGet(); + SQObjectPtr target; + + sq_pushbool(vm, (self._flags & SQOBJ_FLAG_IMMUTABLE) != 0); + + return 1; +} + const SQRegFunction SQSharedState::_table_default_delegate_funcz[]={ {_SC("len"),default_delegate_len,1, _SC("t")}, {_SC("rawget"),container_rawget,2, _SC("t")}, @@ -970,6 +999,7 @@ const SQRegFunction SQSharedState::_table_default_delegate_funcz[]={ {_SC("__merge"),container_merge, -2, _SC("t|yt|y|x") }, {_SC("topairs"),table_to_pairs, 1, _SC("t") }, {_SC("clone"),obj_clone, 1, _SC(".") }, + {_SC("is_frozen"),obj_is_frozen, 1, _SC(".") }, {NULL,(SQFUNCTION)0,0,NULL} }; @@ -1437,6 +1467,7 @@ const SQRegFunction SQSharedState::_array_default_delegate_funcz[]={ {_SC("totable"),pairs_to_table,1, _SC("a") }, {_SC("replace"),array_replace,2, _SC("aa")}, {_SC("clone"),obj_clone, 1, _SC(".") }, + {_SC("is_frozen"),obj_is_frozen, 1, _SC(".") }, {NULL,(SQFUNCTION)0,0,NULL} }; @@ -2274,6 +2305,7 @@ const SQRegFunction SQSharedState::_class_default_delegate_funcz[] = { {_SC("__merge"),container_merge, -2, _SC("t|yt|y|x") }, {_SC("getmetamethod"),get_class_metamethod, 2, _SC("ys")}, {_SC("clone"),obj_clone, 1, _SC(".") }, + {_SC("is_frozen"),obj_is_frozen, 1, _SC(".") }, {NULL,(SQFUNCTION)0,0,NULL} }; @@ -2295,6 +2327,7 @@ const SQRegFunction SQSharedState::_instance_default_delegate_funcz[] = { {_SC("getfuncinfos"),delegable_getfuncinfos,1, _SC("x")}, {_SC("getmetamethod"),get_class_metamethod, 2, _SC("xs")}, {_SC("clone"),obj_clone, 1, _SC(".") }, + {_SC("is_frozen"),obj_is_frozen, 1, _SC(".") }, {NULL,(SQFUNCTION)0,0,NULL} }; @@ -2316,5 +2349,6 @@ const SQRegFunction SQSharedState::_weakref_default_delegate_funcz[] = { const SQRegFunction SQSharedState::_userdata_default_delegate_funcz[] = { {_SC("getfuncinfos"),delegable_getfuncinfos,1, _SC("u")}, {_SC("clone"),obj_clone, 1, _SC(".") }, + {_SC("is_frozen"),obj_is_frozen, 1, _SC(".") }, {NULL,(SQFUNCTION)0,0,NULL} }; diff --git a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqbinaryast.cpp b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqbinaryast.cpp index 24fdd2ad7..b9c796de1 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqbinaryast.cpp +++ b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqbinaryast.cpp @@ -202,6 +202,7 @@ void SQASTWritingVisitor::visitGetFieldExpr(GetFieldExpr *gf) { writeNodeHeader(gf); gf->receiver()->visit(this); stream->writeInt8(gf->isNullable()); + stream->writeInt8(gf->isBuiltInGet()); writeString(gf->fieldName()); } @@ -988,9 +989,10 @@ GetFieldExpr *SQASTReader::readGetFieldExpr() { Expr *receiver = readExpression(); bool nullable = (bool)stream->readInt8(); + bool builtIn = (bool)stream->readInt8(); const SQChar *s = readString(); - return newNode(receiver, s, nullable); + return newNode(receiver, s, nullable, builtIn); } GetTableExpr *SQASTReader::readGetTableExpr() { diff --git a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqcompilationcontext.cpp b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqcompilationcontext.cpp index 44a409dc0..308cf5bcb 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqcompilationcontext.cpp +++ b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqcompilationcontext.cpp @@ -486,69 +486,72 @@ void SQCompilationContext::vrenderDiagnosticHeader(enum DiagnosticsId diag, std: void SQCompilationContext::vreportDiagnostic(enum DiagnosticsId diagId, int32_t line, int32_t pos, int32_t width, va_list vargs) { assert(diagId < DI_NUM_OF_DIAGNOSTICS); - if (isDisabled(diagId, line, pos)) { - return; - } + bool doJump = false; - auto &desc = diagnosticDescriptors[diagId]; - bool isError = desc.severity >= DS_ERROR; - std::string message; + if (!isDisabled(diagId, line, pos)) { - vrenderDiagnosticHeader(diagId, message, vargs); + auto &desc = diagnosticDescriptors[diagId]; + bool isError = desc.severity >= DS_ERROR; + std::string message; - std::string extraInfo; + vrenderDiagnosticHeader(diagId, message, vargs); - const char *l1 = findLine(line - 1); - const char *l2 = findLine(line); - const char *l3 = findLine(line + 1); + std::string extraInfo; - if (!isBlankLine(l1)) { - extraInfo.push_back('\n'); - int32_t j = 0; - while (l1[j] && l1[j] != '\n' && l1[j] != '\r') { //-V522 - extraInfo.push_back(l1[j++]); //-V595 - } - } + const char *l1 = findLine(line - 1); + const char *l2 = findLine(line); + const char *l3 = findLine(line + 1); - if (l2 != nullptr) { - extraInfo.push_back('\n'); - int32_t j = 0; - while (l2[j] && l2[j] != '\n' && l2[j] != '\r') { //-V522 - extraInfo.push_back(l2[j++]); //-V595 + if (!isBlankLine(l1)) { + extraInfo.push_back('\n'); + int32_t j = 0; + while (l1[j] && l1[j] != '\n' && l1[j] != '\r') { //-V522 + extraInfo.push_back(l1[j++]); //-V595 + } } - extraInfo.push_back('\n'); - j = 0; + if (l2 != nullptr) { + extraInfo.push_back('\n'); + int32_t j = 0; + while (l2[j] && l2[j] != '\n' && l2[j] != '\r') { //-V522 + extraInfo.push_back(l2[j++]); //-V595 + } - drawUnderliner(pos, width, extraInfo); - } + extraInfo.push_back('\n'); + j = 0; - if (!isBlankLine(l3)) { - extraInfo.push_back('\n'); - int32_t j = 0; - while (l3[j] && l3[j] != '\n' && l3[j] != '\r') { //-V522 - extraInfo.push_back(l3[j++]); //-V595 + drawUnderliner(pos, width, extraInfo); } - } - const char *extra = nullptr; - if (l1 || l2 || l3) { - extraInfo.push_back('\n'); - extraInfo.push_back('\n'); // separate with extra line - extra = extraInfo.c_str(); - } + if (!isBlankLine(l3)) { + extraInfo.push_back('\n'); + int32_t j = 0; + while (l3[j] && l3[j] != '\n' && l3[j] != '\r') { //-V522 + extraInfo.push_back(l3[j++]); //-V595 + } + } + + const char *extra = nullptr; + if (l1 || l2 || l3) { + extraInfo.push_back('\n'); + extraInfo.push_back('\n'); // separate with extra line + extra = extraInfo.c_str(); + } - auto errorFunc = _ss(_vm)->_compilererrorhandler; + auto errorFunc = _ss(_vm)->_compilererrorhandler; - const char *msg = message.c_str(); + const char *msg = message.c_str(); - if (_raiseError && errorFunc) { - errorFunc(_vm, msg, _sourceName, line, pos, extra); + if (_raiseError && errorFunc) { + errorFunc(_vm, msg, _sourceName, line, pos, extra); + } + if (isError) { + _vm->_lasterror = SQString::Create(_ss(_vm), msg, message.length()); + doJump = true; + } } - if (isError) { - _vm->_lasterror = SQString::Create(_ss(_vm), msg, message.length()); + if (doJump) longjmp(_errorjmp, 1); - } } void SQCompilationContext::reportDiagnostic(enum DiagnosticsId diagId, int32_t line, int32_t pos, int32_t width, ...) { diff --git a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqcompilationcontext.h b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqcompilationcontext.h index 9b0745a8e..8ca4db594 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqcompilationcontext.h +++ b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqcompilationcontext.h @@ -72,6 +72,9 @@ class KeyValueFile; DEF_DIAGNOSTIC(LOCAL_CLASS_SYNTAX, ERROR, SEMA, -1, "", "cannot create a local class with the syntax (class )"), \ DEF_DIAGNOSTIC(INVALID_CLASS_NAME, ERROR, SEMA, -1, "", "invalid class name or context"), \ DEF_DIAGNOSTIC(INC_DEC_NOT_ASSIGNABLE, ERROR, SEMA, -1, "", "argument of inc/dec operation is not assignable"), \ + DEF_DIAGNOSTIC(SUSPICIOUS_SYNTAX_RANGE_LOOP, ERROR, SEMA, -1, "", "Very suspicious range-loop syntax construction"), \ + DEF_DIAGNOSTIC(ID_RANGE_LOOP, ERROR, SEMA, -1, "", "iterator name (identifier) is expected in 'for ([variable:] [from,] to[, step])', got 'expression'"), \ + DEF_DIAGNOSTIC(COMMA_RANGE_LOOP, ERROR, SEMA, -1, "", "too many expressions separated by comma in '%s' - loop"), \ DEF_DIAGNOSTIC(TOO_MANY_SYMBOLS, ERROR, SEMA, -1, "", "internal compiler error: too many %s"), \ DEF_DIAGNOSTIC(PAREN_IS_FUNC_CALL, WARNING, SYNTAX, 190, "paren-is-function-call", "'(' on a new line parsed as function call."), \ DEF_DIAGNOSTIC(STMT_SAME_LINE, WARNING, SYNTAX, 192, "statement-on-same-line", "Next statement on the same line after '%s' statement."), \ diff --git a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqcompiler.h b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqcompiler.h index 54160932f..c43eaba0c 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqcompiler.h +++ b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqcompiler.h @@ -99,6 +99,9 @@ struct SqASTData { #define TK_TEMPLATE_PREFIX 337 #define TK_TEMPLATE_INFIX 338 #define TK_TEMPLATE_SUFFIX 339 +#define TK_TEMPLATE_OP 340 +#define TK_BUILT_IN_GETSTR 341 +#define TK_NULLABLE_BUILT_IN_GETSTR 342 #ifndef SQ_LINE_INFO_IN_STRUCTURES # define SQ_LINE_INFO_IN_STRUCTURES 1 diff --git a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqfuncproto.h b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqfuncproto.h index 9efe16fd3..b270f820c 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqfuncproto.h +++ b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqfuncproto.h @@ -22,10 +22,11 @@ enum SQLangFeature { LF_TOOLS_COMPILE_CHECK = BIT(4), LF_DISABLE_OPTIMIZER = BIT(5), LF_FORBID_GLOBAL_CONST_REWRITE = BIT(6), + LF_FORBID_IMPLICIT_DEF_DELEGATE = BIT(7), // runtime stage - LF_STRICT_BOOL = BIT(7), - LF_NO_PLUS_CONCAT = BIT(8), + LF_STRICT_BOOL = BIT(8), + LF_NO_PLUS_CONCAT = BIT(9), LF_STRICT = LF_STRICT_BOOL | LF_NO_PLUS_CONCAT | diff --git a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqlexer.cpp b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqlexer.cpp index 7132f9c19..58fa651ce 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqlexer.cpp +++ b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqlexer.cpp @@ -275,7 +275,12 @@ SQInteger SQLexer::LexSingleToken() } case _SC('$'): { NEXT(); - RETURN_TOKEN('$'); + if (CUR_CHAR == _SC('"')) { + RETURN_TOKEN(TK_TEMPLATE_OP); + } + else { + RETURN_TOKEN('$'); + } } case _SC('@'): { SQInteger stype; @@ -304,13 +309,26 @@ SQInteger SQLexer::LexSingleToken() NEXT(); RETURN_TOKEN(ret); } case _SC('?'): {NEXT(); - if (CUR_CHAR == _SC('.')) { NEXT(); RETURN_TOKEN(TK_NULLGETSTR); } + if (CUR_CHAR == _SC('.')) { + NEXT(); + if (CUR_CHAR == _SC('$')) { + NEXT(); + RETURN_TOKEN(TK_NULLABLE_BUILT_IN_GETSTR); + } + else { + RETURN_TOKEN(TK_NULLGETSTR); + } + } if (CUR_CHAR == _SC('[')) { NEXT(); RETURN_TOKEN(TK_NULLGETOBJ); } if (CUR_CHAR == _SC('(')) { NEXT(); RETURN_TOKEN(TK_NULLCALL); } if (CUR_CHAR == _SC('?')) { NEXT(); RETURN_TOKEN(TK_NULLCOALESCE); } RETURN_TOKEN('?'); } case _SC('.'): NEXT(); + if (CUR_CHAR == _SC('$')) { + NEXT(); + RETURN_TOKEN(TK_BUILT_IN_GETSTR); + } if (CUR_CHAR != _SC('.')){ RETURN_TOKEN('.') } NEXT(); if (CUR_CHAR != _SC('.')){ diff --git a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqopcodes.h b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqopcodes.h index b1c04b0c1..322d3ff3c 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqopcodes.h +++ b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqopcodes.h @@ -145,5 +145,6 @@ typedef sqvector SQInstructionVec; #define OP_GET_FLAG_ALLOW_DEF_DELEGATE 0x01 #define OP_GET_FLAG_NO_ERROR 0x02 #define OP_GET_FLAG_KEEP_VAL 0x04 //< only used with OP_GET_FLAG_NO_ERROR +#define OP_GET_FLAG_BUILTIN_ONLY 0x08 #endif // _SQOPCODES_H_ diff --git a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqvm.cpp b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqvm.cpp index 4c4ea46a9..eb7928580 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqvm.cpp +++ b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqvm.cpp @@ -977,6 +977,8 @@ bool SQVM::Execute(SQObjectPtr &closure, SQInteger nargs, SQInteger stackbase,SQ continue; case _OP_GETK:{ SQUnsignedInteger getFlagsByOp = (arg3 & OP_GET_FLAG_ALLOW_DEF_DELEGATE) ? 0 : GET_FLAG_NO_DEF_DELEGATE; + if (arg3 & OP_GET_FLAG_BUILTIN_ONLY) + getFlagsByOp |= GET_FLAG_DEF_DELEGATE_ONLY; if (arg3 & OP_GET_FLAG_NO_ERROR) { SQInteger fb = GetImpl(STK(arg2), ci->_literals[arg1], temp_reg, GET_FLAG_DO_NOT_RAISE_ERROR | getFlagsByOp, DONT_FALL_BACK); if (fb == SLOT_RESOLVE_STATUS_OK) { @@ -1158,6 +1160,8 @@ bool SQVM::Execute(SQObjectPtr &closure, SQInteger nargs, SQInteger stackbase,SQ } case _OP_GET:{ SQUnsignedInteger getFlagsByOp = (arg3 & OP_GET_FLAG_ALLOW_DEF_DELEGATE) ? 0 : GET_FLAG_NO_DEF_DELEGATE; + if (arg3 & OP_GET_FLAG_BUILTIN_ONLY) + getFlagsByOp |= GET_FLAG_DEF_DELEGATE_ONLY; if (arg3 & OP_GET_FLAG_NO_ERROR) { SQInteger fb = GetImpl(STK(arg1), STK(arg2), temp_reg, GET_FLAG_DO_NOT_RAISE_ERROR | getFlagsByOp, DONT_FALL_BACK); if (fb == SLOT_RESOLVE_STATUS_OK) { @@ -1727,6 +1731,14 @@ bool SQVM::Get(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &des SQInteger SQVM::GetImpl(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &dest, SQUnsignedInteger getflags, SQInteger selfidx) { + if (getflags & GET_FLAG_DEF_DELEGATE_ONLY) { + if (InvokeDefaultDelegate(self, key, dest)) { + propagate_immutable(self, dest); + return SLOT_RESOLVE_STATUS_OK; + } + if ((getflags & GET_FLAG_DO_NOT_RAISE_ERROR) == 0) Raise_IdxError(key); + return SLOT_RESOLVE_STATUS_NO_MATCH; + } switch(sq_type(self)){ case OT_TABLE: if(_table(self)->Get(key,dest)) { diff --git a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqvm.h b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqvm.h index 657383662..ff9ea7cfe 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqvm.h +++ b/prog/1stPartyLibs/quirrel/quirrel/squirrel/sqvm.h @@ -15,6 +15,7 @@ #define GET_FLAG_RAW 0x00000001 #define GET_FLAG_DO_NOT_RAISE_ERROR 0x00000002 #define GET_FLAG_NO_DEF_DELEGATE 0x00000004 +#define GET_FLAG_DEF_DELEGATE_ONLY 0x00000008 //base lib void sq_base_register(HSQUIRRELVM v); diff --git a/prog/1stPartyLibs/quirrel/quirrel/squirrel/static_analyser/analyser.cpp b/prog/1stPartyLibs/quirrel/quirrel/squirrel/static_analyser/analyser.cpp index 56c84a6b6..b99d3de8b 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/squirrel/static_analyser/analyser.cpp +++ b/prog/1stPartyLibs/quirrel/quirrel/squirrel/static_analyser/analyser.cpp @@ -2323,7 +2323,8 @@ enum SymbolKind { SK_ENUM, SK_ENUM_CONST, SK_PARAM, - SK_FOREACH + SK_FOREACH, + SK_EXTERNAL_BINDING }; static const char *symbolContextName(enum SymbolKind k) { @@ -2340,6 +2341,7 @@ static const char *symbolContextName(enum SymbolKind k) { case SK_ENUM_CONST: return "enum const"; case SK_PARAM: return "parameter"; case SK_FOREACH: return "foreach var"; + case SK_EXTERNAL_BINDING: return "external binding"; default: return ""; } } @@ -7769,13 +7771,25 @@ class NameShadowingChecker : public Visitor { return new(mem) SymbolInfo(k); } + struct Scope rootScope; + struct Scope *scope; + void loadBindings(const HSQOBJECT *bindings); + void declareVar(enum SymbolKind k, const VarDecl *v); void declareSymbol(const SQChar *name, SymbolInfo *info); + Id rootPointerNode; public: - NameShadowingChecker(SQCompilationContext &ctx) : _ctx(ctx), scope(nullptr) {} + NameShadowingChecker(SQCompilationContext &ctx, const HSQOBJECT *bindings) + : _ctx(ctx) + , rootScope(this, nullptr) + , scope(&rootScope) + , rootPointerNode("") { + rootScope.parent = nullptr; + loadBindings(bindings); + } void visitNode(Node *n); @@ -7797,6 +7811,25 @@ class NameShadowingChecker : public Visitor { } }; +void NameShadowingChecker::loadBindings(const HSQOBJECT *bindings) { + if (bindings && sq_istable(*bindings)) { + SQTable *table = _table(*bindings); + + SQInteger idx = 0; + SQObjectPtr pos(idx), key, val; + + while ((idx = table->Next(false, pos, key, val)) >= 0) { + if (sq_isstring(key)) { + SQInteger len = _string(key)->_len; + const SQChar *s = _string(key)->_val; + SymbolInfo *info = newSymbolInfo(SK_EXTERNAL_BINDING); + declareSymbol(s, info); + } + pos._unVal.nInteger = idx; + } + } +} + const Node *NameShadowingChecker::extractPointedNode(const SymbolInfo *info) { switch (info->kind) { @@ -7820,6 +7853,8 @@ const Node *NameShadowingChecker::extractPointedNode(const SymbolInfo *info) { return info->declaration.ec->val; case SK_PARAM: return info->declaration.p; + case SK_EXTERNAL_BINDING: + return &rootPointerNode; default: assert(0); return nullptr; @@ -8003,7 +8038,7 @@ void NameShadowingChecker::visitClassDecl(ClassDecl *k) { } void NameShadowingChecker::visitBlock(Block *block) { - Scope blockScope(this, scope ? scope->owner : nullptr); + Scope blockScope(this, scope->owner); Visitor::visitBlock(block); } @@ -8138,7 +8173,7 @@ void StaticAnalyser::checkTrailingWhitespaces(HSQUIRRELVM vm, const SQChar *sour } } -static void mergeKnownBindings(const HSQOBJECT *bindings) { +void StaticAnalyser::mergeKnownBindings(const HSQOBJECT *bindings) { if (bindings && sq_istable(*bindings)) { SQTable *table = _table(*bindings); @@ -8161,7 +8196,7 @@ void StaticAnalyser::runAnalysis(RootBlock *root, const HSQOBJECT *bindings) { mergeKnownBindings(bindings); CheckerVisitor(_ctx).analyse(root); - NameShadowingChecker(_ctx).analyse(root); + NameShadowingChecker(_ctx, bindings).analyse(root); } } diff --git a/prog/1stPartyLibs/quirrel/quirrel/squirrel/static_analyser/analyser.h b/prog/1stPartyLibs/quirrel/quirrel/squirrel/static_analyser/analyser.h index 84e360ed5..f3acb0ff3 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/squirrel/static_analyser/analyser.h +++ b/prog/1stPartyLibs/quirrel/quirrel/squirrel/static_analyser/analyser.h @@ -16,6 +16,7 @@ class StaticAnalyser { void runAnalysis(RootBlock *r, const HSQOBJECT *bindings); + static void mergeKnownBindings(const HSQOBJECT *bindings); static void reportGlobalNameDiagnostics(HSQUIRRELVM vm); static void checkTrailingWhitespaces(HSQUIRRELVM vm, const SQChar *sn, const SQChar *code, size_t codeSize); diff --git a/prog/1stPartyLibs/quirrel/quirrel/static_analyzer/quirrel_static_analyzer.cpp b/prog/1stPartyLibs/quirrel/quirrel/static_analyzer/quirrel_static_analyzer.cpp index 8d328dc2a..d2d8c5f7e 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/static_analyzer/quirrel_static_analyzer.cpp +++ b/prog/1stPartyLibs/quirrel/quirrel/static_analyzer/quirrel_static_analyzer.cpp @@ -225,26 +225,17 @@ namespace settings std_function = { - "seterrorhandler", - "setdebughook", - "getstackinfos", "getroottable", "getconsttable", "getclass", "assert", "print", - "error", "compilestring", "newthread", "suspend", "array", "type", "callee", - "collectgarbage", - "resurrectunreachable", - "min", - "max", - "clamp", }; function_result_must_be_utilized = diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/ast/optimizations/closureHoisting/implicitChainedFuncs2.opt.txt b/prog/1stPartyLibs/quirrel/quirrel/testData/ast/optimizations/closureHoisting/implicitChainedFuncs2.opt.txt index e42b416cb..1f56c3d06 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/testData/ast/optimizations/closureHoisting/implicitChainedFuncs2.opt.txt +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/ast/optimizations/closureHoisting/implicitChainedFuncs2.opt.txt @@ -1,6 +1,6 @@ { local z = 0 - let $ch0 = FUNCTION (implicitChainedFuncs2.nut:5)(this) { + let $ch0 = FUNCTION fff(this) { RETURN z } let foo = FUNCTION foo(this, x, y) { diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/ast/optimizations/closureHoisting/simple2.opt.txt b/prog/1stPartyLibs/quirrel/quirrel/testData/ast/optimizations/closureHoisting/simple2.opt.txt index d64c53d7b..2e962b649 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/testData/ast/optimizations/closureHoisting/simple2.opt.txt +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/ast/optimizations/closureHoisting/simple2.opt.txt @@ -1,11 +1,11 @@ { local z = 0 let foo = FUNCTION foo(this, x, y) { - let f1 = FUNCTION (simple2.nut:3)(this, a) { - let $ch0 = FUNCTION (simple2.nut:5)(this, c) { + let f1 = FUNCTION f1(this, a) { + let $ch0 = FUNCTION f3(this, c) { RETURN a + c } - let f2 = FUNCTION (simple2.nut:4)(this, x) { + let f2 = FUNCTION f2(this, x) { let f3 = $ch0 RETURN x + y } diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/interp_str_not_string.diag.txt b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/interp_str_not_string.diag.txt index 37e342e66..455200e7d 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/interp_str_not_string.diag.txt +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/interp_str_not_string.diag.txt @@ -1,7 +1,7 @@ -ERROR: expected string -testData/diagnostics/interp_str_not_string.nut:3:9 +ERROR: expected 'expression' +testData/diagnostics/interp_str_not_string.nut:3:8 println($'{{{{{{{{') - ^ + ^ diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/interp_str_not_string_2.diag.txt b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/interp_str_not_string_2.diag.txt index 58885a6d9..ee7fc0782 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/interp_str_not_string_2.diag.txt +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/interp_str_not_string_2.diag.txt @@ -1,7 +1,7 @@ -ERROR: expected 'STRING_LITERAL' -testData/diagnostics/interp_str_not_string_2.nut:5:9 +ERROR: expected 'expression' +testData/diagnostics/interp_str_not_string_2.nut:5:8 println($foo()) - ^-- + ^ diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop1.diag.txt b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop1.diag.txt new file mode 100644 index 000000000..8e0b1fad6 --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop1.diag.txt @@ -0,0 +1,8 @@ +ERROR: too many expressions separated by comma in 'for ([from, ] to)' - loop +testData/diagnostics/rangeloop1.nut.txt:4:11 + +for (a, b, s, g) { + ^ + println("ERROR loop 1") + + diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop1.nut.txt b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop1.nut.txt new file mode 100644 index 000000000..1704cea60 --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop1.nut.txt @@ -0,0 +1,6 @@ + +let a = 1, b = 2, s = 3, g = 4 + +for (a, b, s, g) { + println("ERROR loop 1") +} \ No newline at end of file diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop2.diag.txt b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop2.diag.txt new file mode 100644 index 000000000..1018a0e9b --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop2.diag.txt @@ -0,0 +1,8 @@ +ERROR: too many expressions separated by comma in 'for (variable: [from,] to [, step])' - loop +testData/diagnostics/rangeloop2.nut.txt:3:18 + +for (i : a, b, s, g) { + ^ + println("ERROR loop 2") + + diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop2.nut.txt b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop2.nut.txt new file mode 100644 index 000000000..3bfc3688f --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop2.nut.txt @@ -0,0 +1,5 @@ +let a = 1, b = 2, s = 3, g = 4 + +for (i : a, b, s, g) { + println("ERROR loop 2") +} \ No newline at end of file diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop3.diag.txt b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop3.diag.txt new file mode 100644 index 000000000..fc44f1672 --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop3.diag.txt @@ -0,0 +1,8 @@ +ERROR: expected 'expression' +testData/diagnostics/rangeloop3.nut.txt:3:5 + +for (:a, b) { + ^ + println("ERROR loop 3") + + diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop3.nut.txt b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop3.nut.txt new file mode 100644 index 000000000..3e1f20e2a --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop3.nut.txt @@ -0,0 +1,5 @@ +let a = 1, b = 2, s = 3, g = 4 + +for (:a, b) { + println("ERROR loop 3") +} \ No newline at end of file diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop4.diag.txt b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop4.diag.txt new file mode 100644 index 000000000..09523fcfb --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop4.diag.txt @@ -0,0 +1,8 @@ +ERROR: iterator name (identifier) is expected in 'for ([variable:] [from,] to[, step])', got 'expression' +testData/diagnostics/rangeloop4.nut.txt:3:5 + +for (a.b : a, b) { + ^-- + println("ERROR loop 4") + + diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop4.nut.txt b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop4.nut.txt new file mode 100644 index 000000000..90ea29bf7 --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop4.nut.txt @@ -0,0 +1,5 @@ +let a = 1, b = 2, s = 3, g = 4 + +for (a.b : a, b) { + println("ERROR loop 4") +} \ No newline at end of file diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop5.diag.txt b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop5.diag.txt new file mode 100644 index 000000000..76def4413 --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop5.diag.txt @@ -0,0 +1,8 @@ +ERROR: iterator name (identifier) is expected in 'for ([variable:] [from,] to[, step])', got 'expression' +testData/diagnostics/rangeloop5.nut.txt:3:11 + +for (local i = 0: a, b) { + ^----- + println("ERROR loop 5") + + diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop5.nut.txt b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop5.nut.txt new file mode 100644 index 000000000..1e48854b1 --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop5.nut.txt @@ -0,0 +1,5 @@ +let a = 1, b = 2, s = 3, g = 4 + +for (local i = 0: a, b) { + println("ERROR loop 5") +} \ No newline at end of file diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop6.diag.txt b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop6.diag.txt new file mode 100644 index 000000000..1c2a65548 --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop6.diag.txt @@ -0,0 +1,8 @@ +ERROR: expected 'expression' +testData/diagnostics/rangeloop6.nut.txt:3:5 + +for (local i = 0, a, b) { + ^----------------- + println("ERROR loop 6") + + diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop6.nut.txt b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop6.nut.txt new file mode 100644 index 000000000..a620140f6 --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop6.nut.txt @@ -0,0 +1,5 @@ + + +for (local i = 0, a, b) { + println("ERROR loop 6") +} diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop7.diag.txt b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop7.diag.txt new file mode 100644 index 000000000..5d44a6af4 --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop7.diag.txt @@ -0,0 +1,8 @@ +ERROR: expected 'expression' +testData/diagnostics/rangeloop7.nut.txt:1:9 + +for (10, local i = 0) { + ^---- + println("ERROR loop 7") + + diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop7.nut.txt b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop7.nut.txt new file mode 100644 index 000000000..60bdf31c9 --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/diagnostics/rangeloop7.nut.txt @@ -0,0 +1,3 @@ +for (10, local i = 0) { + println("ERROR loop 7") +} \ No newline at end of file diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/exec/call_method.nut b/prog/1stPartyLibs/quirrel/quirrel/testData/exec/call_method.nut new file mode 100644 index 000000000..cc4c5aaf1 --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/exec/call_method.nut @@ -0,0 +1,64 @@ + + + + +let t = { + rawget = function(k) { + return $"overriden rawget({k})" + } + + xxx = "RealValue" + + keys = function() { + return [1, 2, 3] + } + + rawset = function(k, v) { + println($"overriden rawset({k} -> {v})") + } + + xyz = "Original" +} + + +println($"t.rawget(\"xxx\") --> {t.rawget("xxx")}") +println($"call_type_method(t, \"rawget\", \"xxx\") --> {call_type_method(t, "rawget", "xxx")}") + + +let k = t.keys() + +println($"t.keys()") +foreach (idx, v in k) { + println($"{idx} --> {v}") +} + +let b = call_type_method(t, "keys"); + +println($"call_type_method(t, keys)") +foreach (idx, v in b) { + println($"{idx} --> {v}") +} + +println("rawset(...) regular") +t.rawset("xyz", "ABC") +println($"t.xyz --> {t.xyz}") + + +println("rawset(...) call_type_method") +call_type_method(t, "rawset", "xyz", "Updated"); +println($"t.xyz --> {t.xyz}") + +try { + call_type_method(t, "dummy", "xyz", "Updated"); + println("FAILED to call dummy method") +} catch (ex) { + println($"OK: invokation of 'dummy()' raised exception \"{ex}\"") +} + + +try { + call_type_method_safe(t, "dummy", "xyz", "Updated"); + println($"OK: safe call succeseded") +} catch (ex) { + println("FAIL: Safe call raised exception") +} diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/exec/call_method.out b/prog/1stPartyLibs/quirrel/quirrel/testData/exec/call_method.out new file mode 100644 index 000000000..500b334bb --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/exec/call_method.out @@ -0,0 +1,19 @@ +t.rawget("xxx") --> overriden rawget(xxx) +call_type_method(t, "rawget", "xxx") --> RealValue +t.keys() +0 --> 1 +1 --> 2 +2 --> 3 +call_type_method(t, keys) +0 --> rawget +1 --> xyz +2 --> keys +3 --> rawset +4 --> xxx +rawset(...) regular +overriden rawset(xyz -> ABC) +t.xyz --> Original +rawset(...) call_type_method +t.xyz --> Updated +OK: invokation of 'dummy()' raised exception "function 'dummy' not found in 'table' delegates" +OK: safe call succeseded diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/exec/is_frozen.nut b/prog/1stPartyLibs/quirrel/quirrel/testData/exec/is_frozen.nut new file mode 100644 index 000000000..3485fec05 --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/exec/is_frozen.nut @@ -0,0 +1,29 @@ + + +let a1 = [10, 20, 30] +let a2 = freeze([10, 20, 30]) + + +println($"Array R: {a1.is_frozen()}") +println($"Arrat F: {a2.is_frozen()}") + + +let t1 = { a = 10, b = 20, c = 30 } +let t2 = freeze({ a = 10, b = 20, c = 30 }) + +println($"Table R: {t1.is_frozen()}") +println($"Table F: {t2.is_frozen()}") + + +let C = class {} +let F = freeze(class {}) + +println($"Class R: {C.is_frozen()}") +println($"Class F: {F.is_frozen()}") + + +let ri = C() +let fi = freeze(C()) + +println($"Instance R: {ri.is_frozen()}") +println($"Instance F: {fi.is_frozen()}") diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/exec/is_frozen.out b/prog/1stPartyLibs/quirrel/quirrel/testData/exec/is_frozen.out new file mode 100644 index 000000000..ec4d4a63b --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/exec/is_frozen.out @@ -0,0 +1,8 @@ +Array R: false +Arrat F: true +Table R: false +Table F: true +Class R: false +Class F: true +Instance R: false +Instance F: true diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/exec/spec/delegate_get.nut.txt b/prog/1stPartyLibs/quirrel/quirrel/testData/exec/spec/delegate_get.nut.txt new file mode 100644 index 000000000..7a7fb97f5 --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/exec/spec/delegate_get.nut.txt @@ -0,0 +1,81 @@ + +let t = { + rawget = function (k) { return $"HAHA -- {k}" }, + a = "10", + b = "Foo Foo" +} + +let x = t.$rawget("b") +let y = t.rawget("b") + +println($"rawget(\"b\") = {y}, $rawget(\"b\") = {x}") + +let z = t?.$foo +let nz = t?.foo + +println($"t?.$foo = {z}, t?.foo = {nz}") + +try { + let vf = t.$bar + println("FAIL: '$bar' is not a built-in member of table but successfully accessed") +} catch (e) { + println($"OK: '$bar' is not a built-in member of table and access raised exectpion: \"{e}\"") +} + +#forbid-implicit-default-delegates + +println("Forbid implicit default delegates") + +try { + let rg1 = t.rawget + println("OK: 'rawget' is field in table") +} catch (e) { + println($"FAIL: 'rawget' is field in table. Exception: \"{e}\"") +} + +try { + let ks = t.keys + println("FAIL: 'keys' is built-in method of table which are forbiden.") +} catch (e) { + println($"OK: 'keys' is built-in method of table. Exception: \"{e}\"") +} + +try { + let rg2 = t.$rawget + println("OK: 'rawget' is built-in method of table accessed via '$'") +} catch (e) { + println($"FAIL: 'rawget' is built-in method of table accessed via '$'. Exception: \"{e}\"") +} + +try { + let nks = t?.keys + let nks2 = t?.$keys + println($"OK: Safe access of built-in method 'keys' in both '$' and regular cases succeseded") +} catch (e) { + println($"FAIL: Safe access of built-in method 'keys' failed. Exception: \"{e}\"") +} + +#allow-implicit-default-delegates + +println("Allow implicit default delegates") + +try { + let rg1 = t.rawget + println("OK: 'rawget' is field in table") +} catch (e) { + println($"FAIL: 'rawget' is field in table. Exception: \"{e}\"") +} + +try { + let ks = t.keys + println($"OK: 'keys' is built-in method of table.") +} catch (e) { + println("FAIL: 'keys' is built-in method of table which are forbiden.") +} + +try { + let rg2 = t.$rawget + println("OK: 'rawget' is built-in method of table accessed via '$'") +} catch (e) { + println($"FAIL: 'rawget' is built-in method of table accessed via '$'. Exception: \"{e}\"") +} diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/exec/spec/delegate_get.out b/prog/1stPartyLibs/quirrel/quirrel/testData/exec/spec/delegate_get.out new file mode 100644 index 000000000..9a707d67d --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/exec/spec/delegate_get.out @@ -0,0 +1,12 @@ +rawget("b") = HAHA -- b, $rawget("b") = Foo Foo +t?.$foo = null, t?.foo = null +OK: '$bar' is not a built-in member of table and access raised exectpion: "the index 'bar' does not exist" +Forbid implicit default delegates +OK: 'rawget' is field in table +OK: 'keys' is built-in method of table. Exception: "the index 'keys' does not exist" +OK: 'rawget' is built-in method of table accessed via '$' +OK: Safe access of built-in method 'keys' in both '$' and regular cases succeseded +Allow implicit default delegates +OK: 'rawget' is field in table +OK: 'keys' is built-in method of table. +OK: 'rawget' is built-in method of table accessed via '$' diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/exec/spec/rangeloop.nut.txt b/prog/1stPartyLibs/quirrel/quirrel/testData/exec/spec/rangeloop.nut.txt new file mode 100644 index 000000000..4f2f9ec97 --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/exec/spec/rangeloop.nut.txt @@ -0,0 +1,41 @@ + + +let a = 3, b = 7, s = 2 + +let t = { + a = 3 + b = 7 + s = 2 +} + +function foo(k) { + return t[k] +} + +function step(k) { + println("STEP") + return t[k] +} + +local g = 0 + +for (a) { + println($"simplest range loop: {g++}") +} + +for (t.a + 1, b) { + println($"anonymous range loop with start and limit: {g++}") +} + +for (i : t["a"]) { + println($"range loop with limit: i = {i}") +} + + +for (i : foo("a"), b) { + println($"range loop with start and limit: i = {i}") +} + +for (i : a, t.b, step("s")) { + println($"range loop with start, limit and step: i = {i}") +} diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/exec/spec/rangeloop.out b/prog/1stPartyLibs/quirrel/quirrel/testData/exec/spec/rangeloop.out new file mode 100644 index 000000000..79c92a8b4 --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/exec/spec/rangeloop.out @@ -0,0 +1,17 @@ +simplest range loop: 0 +simplest range loop: 1 +simplest range loop: 2 +anonymous range loop with start and limit: 3 +anonymous range loop with start and limit: 4 +anonymous range loop with start and limit: 5 +range loop with limit: i = 0 +range loop with limit: i = 1 +range loop with limit: i = 2 +range loop with start and limit: i = 3 +range loop with start and limit: i = 4 +range loop with start and limit: i = 5 +range loop with start and limit: i = 6 +range loop with start, limit and step: i = 3 +STEP +range loop with start, limit and step: i = 5 +STEP diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/exec/stdlib/debug.nut b/prog/1stPartyLibs/quirrel/quirrel/testData/exec/stdlib/debug.nut new file mode 100644 index 000000000..20294ff68 --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/exec/stdlib/debug.nut @@ -0,0 +1,37 @@ +let dbg = require("debug") + +let info = dbg.getbuildinfo() + +println($"Version: {info.version}") +println($"seterrorhandler: {type(dbg.seterrorhandler)}") +println($"setdebughook: {type(dbg.setdebughook)}") +println($"getstackinfos: {type(dbg.getstackinfos)}") +println($"error: {type(error)}") +println($"errorln: {type(errorln)}") + +if (info.gc == "enabled") { + if (type(dbg.collectgarbage) == "function") { + println($"collectgarbage: OK") + } else { + println($"collectgarbage: FAIL") + } + if (type(dbg.resurrectunreachable) == "function") { + println($"resurrectunreachable: OK") + } else { + println($"resurrectunreachable: FAIL") + } +} else { + if (dbg?.collectgarbage == null) { + println($"collectgarbage: OK") + } else { + println($"collectgarbage: FAIL") + } + if (dbg?.resurrectunreachable == null) { + println($"resurrectunreachable: OK") + } else { + println($"resurrectunreachable: FAIL") + } +} + +println($"getobjflags: {type(getobjflags)}") +println($"getbuildinfo: {type(dbg.getbuildinfo)}") diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/exec/stdlib/debug.out b/prog/1stPartyLibs/quirrel/quirrel/testData/exec/stdlib/debug.out new file mode 100644 index 000000000..e020410f4 --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/exec/stdlib/debug.out @@ -0,0 +1,10 @@ +Version: 4.6.0 +seterrorhandler: function +setdebughook: function +getstackinfos: function +error: function +errorln: function +collectgarbage: OK +resurrectunreachable: OK +getobjflags: function +getbuildinfo: function diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/exec/stdlib/math_min_max_clamp.nut b/prog/1stPartyLibs/quirrel/quirrel/testData/exec/stdlib/math_min_max_clamp.nut new file mode 100644 index 000000000..c2bf702c4 --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/exec/stdlib/math_min_max_clamp.nut @@ -0,0 +1,8 @@ + + +let math = require("math") + + +println($"min(-1, 1, 2, 3, 4, 5, -1000, 6, 7): {math.min(-1, 1, 2, 3, 4, 5, -1000, 6, 7)}") +println($"max(-1, 1, 2, 3, 4, 5, -1000, 8, 9): {math.max(-1, 1, 2, 3, 4, 5, -1000, 8, 9)}") +println($"clamp(10, -100, 300): {math.clamp(10, -100, 300)}") diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/exec/stdlib/math_min_max_clamp.out b/prog/1stPartyLibs/quirrel/quirrel/testData/exec/stdlib/math_min_max_clamp.out new file mode 100644 index 000000000..dbdb52b48 --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/exec/stdlib/math_min_max_clamp.out @@ -0,0 +1,3 @@ +min(-1, 1, 2, 3, 4, 5, -1000, 6, 7): -1000 +max(-1, 1, 2, 3, 4, 5, -1000, 8, 9): 9 +clamp(10, -100, 300): 10 diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/exec/string_interpolation_new.nut b/prog/1stPartyLibs/quirrel/quirrel/testData/exec/string_interpolation_new.nut.txt similarity index 88% rename from prog/1stPartyLibs/quirrel/quirrel/testData/exec/string_interpolation_new.nut rename to prog/1stPartyLibs/quirrel/quirrel/testData/exec/string_interpolation_new.nut.txt index 80db008a5..789a03d79 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/testData/exec/string_interpolation_new.nut +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/exec/string_interpolation_new.nut.txt @@ -20,7 +20,3 @@ println($" foo bar ") print("#5: ") println($"{foo()}}}}}}") - -print("#6: ") -println($//"x") -"{foo()}") \ No newline at end of file diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/exec/string_interpolation_new.out b/prog/1stPartyLibs/quirrel/quirrel/testData/exec/string_interpolation_new.out index 6ac232f8d..9032e7f1e 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/testData/exec/string_interpolation_new.out +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/exec/string_interpolation_new.out @@ -1,6 +1,5 @@ #1: x1 = foo, x2 = [bar qux = foo] #2: 2 #3: { gg = 123 } -#4: foo bar +#4: foo bar #5: foo}}}}} -#6: foo diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/static_analyser/w227_external.diag.txt b/prog/1stPartyLibs/quirrel/quirrel/testData/static_analyser/w227_external.diag.txt new file mode 100644 index 000000000..f8cd73e0d --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/static_analyser/w227_external.diag.txt @@ -0,0 +1,8 @@ +WARNING: w227 (ident-hides-ident) parameter 'println' hides external binding with the same name. +testData/static_analyser/w227_external.nut:1:14 + +function _foo(println) { + ^------ + return println + 1 + + diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/static_analyser/w227_external.nut b/prog/1stPartyLibs/quirrel/quirrel/testData/static_analyser/w227_external.nut new file mode 100644 index 000000000..f1a6e40ed --- /dev/null +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/static_analyser/w227_external.nut @@ -0,0 +1,3 @@ +function _foo(println) { + return println + 1 +} diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/static_analyser/w259.diag.txt b/prog/1stPartyLibs/quirrel/quirrel/testData/static_analyser/w259.diag.txt index a1c52ac55..44065762d 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/testData/static_analyser/w259.diag.txt +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/static_analyser/w259.diag.txt @@ -13,8 +13,8 @@ CALLSTACK *FUNCTION [__main__()] testData/static_analyser/w259.nut line [19] LOCALS -[_M] CLOSURE=FN:(w259.nut:17) -[_P] CLOSURE=FN:(w259.nut:16) +[_M] CLOSURE=FN:_M +[_P] CLOSURE=FN:_P [S] CLOSURE=FN:S [_ttp] NULL [$ch1] CLOSURE=FN:(w259.nut:12) diff --git a/prog/1stPartyLibs/quirrel/quirrel/testData/static_analyser/w288_dp_va.diag.txt b/prog/1stPartyLibs/quirrel/quirrel/testData/static_analyser/w288_dp_va.diag.txt index 784960fdc..df3b6b604 100644 --- a/prog/1stPartyLibs/quirrel/quirrel/testData/static_analyser/w288_dp_va.diag.txt +++ b/prog/1stPartyLibs/quirrel/quirrel/testData/static_analyser/w288_dp_va.diag.txt @@ -46,7 +46,7 @@ CALLSTACK *FUNCTION [__main__()] testData/static_analyser/w288_dp_va.nut line [11] LOCALS -[hflow] CLOSURE=FN:(w288_dp_va.nut:9) +[hflow] CLOSURE=FN:hflow [FlowH] 30 [bar] CLOSURE=FN:bar [foo] CLOSURE=FN:foo diff --git a/prog/3rdPartyLibs/breakpad/tools/windows/dump_syms/jamfile b/prog/3rdPartyLibs/breakpad/tools/windows/dump_syms/jamfile index d95c6a86d..e91c26a23 100644 --- a/prog/3rdPartyLibs/breakpad/tools/windows/dump_syms/jamfile +++ b/prog/3rdPartyLibs/breakpad/tools/windows/dump_syms/jamfile @@ -2,6 +2,7 @@ Root ?= ../../../../../.. ; BreakpadRoot = prog/3rdPartyLibs/breakpad ; Location = $(BreakpadRoot)/tools/windows/dump_syms ; Platform = win32 ; +PlatformSpec = vc16 ; FullOOPEnabled = yes ; @@ -10,13 +11,13 @@ TargetType = exe ; OutDir = $(Root)/tools/util ; include $(Root)/prog/_jBuild/defaults.jam ; +include $(Root)/prog/_jBuild/$(Platform)/$(PlatformSpec)-sets.jam ; Target = 3rdPartyLibs/breakpad/tools/windows/dump_syms ; AddIncludes += $(Root)/$(BreakpadRoot) - $(Root)/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl - $(Root)/prog/3rdPartyLibs/wtl-8.1/include + $(_VC_DIR)/atlmfc/include $(Root)/prog/3rdPartyLibs/diasdk/include ; local CommonWinLibPath = 3rdPartyLibs/breakpad/common/windows ; @@ -32,10 +33,10 @@ AddLibs = version.lib imagehlp.lib $(Root)/prog/3rdPartyLibs/diasdk/lib/diaguids.lib - $(Root)/prog/3rdPartyLibs/wtl-8.1/lib/vc8_atl/atls.lib + $(_VC_DIR)/atlmfc/lib/x86/atls.lib ; -CPPopt += -DUNICODE -D_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS ; +CPPopt += -DUNICODE -D_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS -D_ATL_ALLOW_CHAR_UNSIGNED ; LINKopt += -ignore:4254 ; # silence old ATL library merging GlobalCPPopt += -D__B_NO_MEM_BASE_INCLUDE ; diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/CODE_OF_CONDUCT.md b/prog/3rdPartyLibs/math/DelaunayTriangulator/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..7006cfcb6 --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at kbentley@cognitics.net. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/CONTRIBUTING.md b/prog/3rdPartyLibs/math/DelaunayTriangulator/CONTRIBUTING.md new file mode 100644 index 000000000..a89f2ccb6 --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/CONTRIBUTING.md @@ -0,0 +1 @@ +Please submit a pull request, or contact me via email (kbentley@cognitics.net). Any bug fixes and/or cleanup is appreciated! diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/LICENSE b/prog/3rdPartyLibs/math/DelaunayTriangulator/LICENSE new file mode 100644 index 000000000..3db113ba8 --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Cognitics, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/README.md b/prog/3rdPartyLibs/math/DelaunayTriangulator/README.md new file mode 100644 index 000000000..c01d9c64d --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/README.md @@ -0,0 +1,131 @@ +# DelaunayTriangulator +Provides a Dynamically Constrained Delaunay Triangulation system. Based on an incremental Delaunay Triangulation algorithm with the added feature of constraint insertion and removal. Capable of creating a point only Delaunay Triangulation in O(n4/3) time ( provided the points are inserted randomly - worst case time is n2 and is encounted when inserting points of a grid in order, to counter this worst case behaviour an even faster algorithm for generating DelaunayTringulations from a grid is provided). + +## License +The Delaunay Triangulator is provided under the [MIT License](#license-text) + +## DelaunayTriangulation Construction: +When creating a DelaunayTriangulation a few options must be specified. + +|Option|Description| +|------|-----------------------------------------------------------------| +|BoundingRegion|A DelaunayTriangulation must be initially constrainted to some bounding region (in this implementation a quad).
  • This must be specified by the user upon construction.
  • The user can specify 4 points of a bounding QUAD upon construction.
  • The user can specify a CGrid (which contains a bounding QUAD) upon construction.
  • Defaults to (NO DEFAULT - MUST BE SPECIFIED).
  • Must be counter-clockwise in orientation.
| +|DataBlockSize|The DelaunayTriangulation needs to know how large to make new Vertex and Edge data blocks if more Edges or Verts are needed.
This value will set the size (as in number of Edges or Verts to a block, not the number of bytes) per block. A larger size per block will result in fewer blocks overall and thus less time spent on memory management, while a smaller block size will result in less unused allocated memory at any given time, but result in longer processing times since more blocks must be managed.
**Default to (100)** +|Epsilon|A custom epsilon can be defined for comparisons in this DelaunayTriangulation. If the epsilon is set too small, some rounding errors can lead to crashes or infinite loops. The default has been tested to work for a large number of cases. If undesired results are present, try increasing the epsilon slightly.
**Default to (3e-13)**| +|MaxEdgeFlips|The maximum number of Edge flips that will be performed for any call to FlipEdges by the DelaunayTriangulation. This is important because a Constrained Delaunay Triangulation is not garunteed to be Delaunay since many Edges are restricted from Edge flips and no extra Vertices (other than intersection points) are created. With this in mind it is possible for the EdgeFlips to ripple outward from a new constraint for many itterations (which get increasingly worse with a DelaunayTriangulation with many Edges). To avoid this, MaxEdgeFlips is specified which will constrain the number of flips the DelaunayTriangulation will use in an attempt to correct the triangulation after inserting a new constraint.
**Defaults to (10000)**| +|Options|Additional Options may be specified or enabled for this DelaunayTriangulation (several options may be | together). The Options allowed are:
CLIPPING When Enabled, if a portion of a constraint lies outside of the bounding region, the DelaunayTriangulation will first try clipping the constraint to see if any portion is inside the DelaunayTriangulation. When Disabled, if ANY portion of the constraint is outside of the bouning region, the entire constraint will be ignored.
FLATTENINGWhen Enabled, all Z values of points added to this Triangulation will become 0.
INTERPOLATE_EDGESWhen Enabled, any intersecting constrained Edges will create a new point with a Z value intepolated by the currently inserted Edge.
INTERPOLATE_FACESWhen Enabled, any Point inserted into a face, will have its Z value adjusted to match the face.
| + +## Constraints: +A constraint is defined as a single Point or a single list of Points that form a line string. When a constraint is inserted into the DT it will force all the segments of the constraint to appear in the DT regardless if they are Delaunay or not. If two constraints are found to intersect or overlap one another, a new Vertex point will be generated at the intersection and placed into the DT to ensure that both constraints are satisfied. Note that this new Vertex will have a z value determined based on the ZInterpolationOption settings. Upon removing one of the overlapping constraints, if it is found that the newly created Vertex is no longer necessary, the Vertex will be removed and the DelaunayTriangulation will be simplified. + +### Insertion + +|Constraint Type|Description| +|---------------|-------------------------------------------| +|WorkingPoint|When a working point is inserted, it is a temporary point that will only be gaurunteed to last until the next insertion or removal.| +|ConstrainedPoint|When a constrained Point is inserted, the only way that point will ever be removed is by calling RemoveConstraint with its unique ID. Note that ID values are unique even between Point constraints and LineString constraints, so no ID assigned to a Point will ever be given to a LineString or vice versa.| +|ConstrainedLineString|A constrained LineString inserts a series of constrained Edges into the DelaunayTriangualtion. The Z values of the constraints are handled by the settings.| +|ConstrainedPolygon|A constrained Polygon inserts a series of constrained Edges that form a single closed/simple area. After inserting a Polygon, all points and edges inside the Polygon are simplified and removed if possible or else interpolated to the Z value of the Polygon by force. In this regard, the Z interpolation settings are disregarded in this method and the Z values of the Polygon are used always. This method is great for inserting roads if they already have the z values you want.| + +### ConstraintID values +When inserting a Constraint, an ID value will always be returned. If this ID is 0, the insertion failed for some reason (the constraint may be outside of this DelaunayTriangulation). The ID 0 is reserved internally for the boundary of the DelaunayTriangulation and will never be assigned to any constraint that a user has any control over. ID values are unique within this DelaunayTriangulation. No ID assigned to a Point will be shared by any other Point OR LineString OR Polygon. Because of this there is only one method to remove a constraint. It will determine what type the constraint is based on the ID. + + ## Exporting the Data from a DelaunayTriangulation +A DelaunayTriangulation is capable of exporting the triangulation at any given moment as either a Subdivision or TIN. +When retrieving the Subdivision of a DelaunayTriangulation, the actual raw data-structure used by the DelaunayTriangulation system itself will be returned. +This data is fragile and should not be changed outside the scope of the DelaunayTriangulation class itself. If using the Subdivision of a DelaunayTriangulation, be careful not to change and data within a Vertex or Edge or the DelaunayTriangulation might (and most probably will) break. + +A TIN can also be retrieved. Note that all needed data is copied to the TIN and therefore no access to the original Subdivision is given to the TIN. A TIN can be used if no topology information is needed. All normals are computed before hand for the TIN while the data is still within the Subdivision. See ctl::TIN for more information on Creating a TIN out of a DelaunayTriangulation. + +## Linking multiple DelaunayTriangulations together +An interface for linking multiple neighbooring DelaunayTriangulations is provided. Note that no linker passes ownership and no memory is shared by either DelaunayTriangulation (meaning no neighboors are deleted upong this DelaunayTriangulations destruction). Each DelaunayTriangulation has a left, right, up and down neighboor. These neighboors are used when computing vertex normals. + +## Notes +This implementation uses the quad-edge data structure presented by Guibas and Stolfi (1985) (See ctl::Subdivision and ctl::Edge for more information), and used Graphics Gems IV (Paul S. Heckbert) as a reference for some of the basic Delaunay Triangulation code, while referencing a paper by Marcelo Kallmann for strategies and algorithms for handling constrained edges within a DelaunayTriangulation. + +A DelaunayTriangualtion cannot be copied or assigned due to the delicate data structures that hold the Edges and Vertices. No shared or reference pointer is typedefed for a DelaunayTriangulation, but it is best to create some form of managed pointer if you plan on using a DelaunayTriangulation outside of a single scope. +## Usage Examples: + +```cpp +// Create the boundary of your triangulation + PointList boundary; + boundary.push_back(Point(0,0)); + boundary.push_back(Point(10,0)); + boundary.push_back(Point(10,10)); + boundary.push_back(Point(0,10)); +// Create the triangulation + DelaunayTriangulation* DT = new DelaunayTriangulation(boundary); +// Altering settings +// Disable and Enable clipping + DT->Disable( DelaunayTriangualtion::CLIPPING ); + DT->Enable( DelaunayTriangualtion::CLIPPING ); +// Insert a working Point + DT->InsertWorkingPoint(Point(5,7,8)); +// Insert a constrained Point + ID p0_id = DT->InsertConstrainedPoint(Point(5,7,8)); + if (p0_id == 0) + { + //... Handle failed point insertion + } +// Inserting a constrained LineString or Polygon -> For Polygon the LineString MUST be defined CCW. + PointList points; + points.push_back(1,1,5); + points.push_back(2,1,5); + points.push_back(2,2,5); + points.push_back(2,1,5); + ID l0_id = DT->InsertConstrainedLineString(points); + if (l0_id == 0) + { + //... Handle failed linestring insertion + } +// a DT will close your polygon for you if you fail to close it yourself + ID poly0_id = DT->InsertConstrainedPolygon(points); + if (poly0_id == 0) + { + //... Handle failed polygon insertion + } +// Removing the constraints + DT->RemoveConstraint(p0_id); + DT->RemoveConstraint(l0_id); + DT->RemoveConstraint(poly0_id); +// Linking a neighbor DelaunayTriangulation + DelaunayTriangulation *DT_2 = new DelaunayTriangulation( ...some boundary lines up with the right side of DT... ); + bool linked = DT->LinkNeighbor( DelaunayTriangulation::EAST, DT_2 ); + if (!linked) + { + //... Handle failed DelaunayTriangulation linking + } +// Unlink + DT->UnlinkNeighbor( DelaunayTriangulation::EAST ); +// Or you can simply wait till one of the DelaunayTriangulations is deleted and the link will be automatically broken. +// Data Exporting + TIN* tin_all = new TIN(DT); // For entire DelaunayTriangulation ...or... + TIN* tin_some = new TIN( DT, DT->GetBoundedTriangled( ...some area... ) ); // For only the triangles within a given area (tested by point in polygon of their centroids + delete tin_all; + delete tin_some; +// Finished using DelaunayTriangulation + delete DT; // If the link still exists, it will be removed now + delete DT_2; +``` + +## License Text + +**Copyright 2017, Cognitics Inc.** + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/jamfile b/prog/3rdPartyLibs/math/DelaunayTriangulator/jamfile new file mode 100644 index 000000000..2f4983235 --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/jamfile @@ -0,0 +1,11 @@ +Root ?= ../../../.. ; +Location = prog/3rdPartyLibs/math/DelaunayTriangulator ; + +TargetType = lib ; +Target = 3rdPartyLibs/math/DelaunayTriangulator.lib ; + + +include $(Root)/prog/_jBuild/defaults.jam ; +AutoscanBuildLists source : *.cpp : Sources ; + +include $(Root)/prog/_jBuild/build.jam ; diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/source/BlockList.h b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/BlockList.h new file mode 100644 index 000000000..514dca5a7 --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/BlockList.h @@ -0,0 +1,113 @@ +/**************************************************************************** +Copyright 2017, Cognitics Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ +#pragma once + +#include "Edge.h" +#include + +namespace ctl { + +////////////////////////////////////////////////////////////////////// +//! Wrapper to a simple array of data of type T. +////////////////////////////////////////////////////////////////////// + template + class Block + { + private: + + + public: + Block(size_t num) + { + size = num; + data = new T[size]; + } + ~Block(void) { delete [] data; } + + size_t size; + T* data; + }; + +////////////////////////////////////////////////////////////////////// +//! Container that stores a list of consecutive Blocks. Also allows +//! access to compute the total size of all Blocks as well as access +//! individual memebers. +////////////////////////////////////////////////////////////////////// + template + class BlockList + { + private: + std::vector*> blocks; + size_t totalSize = 0; + + + + public: + BlockList(void) { } + ~BlockList(void) + { + while (!blocks.empty()) + PopBlock(); + } + + void PushBlock(Block* block) + { + if (block) + { + blocks.push_back(block); + totalSize += block->size; + } + } + + void PopBlock(void) + { + if (blocks.size()) + { + Block* t = blocks.back(); + totalSize = totalSize - t->size; + blocks.pop_back(); + delete t; + } + } + + // Get data at location i + T* operator[](const unsigned int& i) + { + size_t current = 0; + typedef typename std::vector*>::iterator block_iterator; + for (block_iterator next = blocks.begin(); next != blocks.end(); ++next) + { + if ( i < (*next)->size + current ) + return &(*next)->data[ i - current ]; + else + current += (*next)->size; + } + return NULL; + } + + size_t size(void) const + { + return totalSize; + } + }; + +} diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/source/CGrid.cpp b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/CGrid.cpp new file mode 100644 index 000000000..295ad1215 --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/CGrid.cpp @@ -0,0 +1,109 @@ +/**************************************************************************** +Copyright 2017, Cognitics Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ +#include "CGrid.h" + +namespace ctl { + + CGrid::CGrid(Point o, Vector u, Vector v, int xsize, int ysize) + { + origin = o; + U = u; + V = v; + XSize = xsize; + YSize = ysize; + + data.resize(xsize); + for (int i = 0; i < xsize; i++) + data[i].resize(ysize); + + for (int i = 0; i < xsize; i++) + for (int j = 0; j < ysize; j++) + data[i][j] = 0; + } + + Point CGrid::getPoint(int x, int y) + { + return origin + U*x + V*y; + } + + PointList CGrid::getEnvelope(void) + { + PointList points; + points.resize(4); + points[0] = getPoint(0,0) + Point(0,0,1)*getValue(0,0); + points[1] = getPoint(XSize-1,0) + Point(0,0,1)*getValue(XSize-1,0); + points[2] = getPoint(XSize-1,YSize-1) + Point(0,0,1)*getValue(XSize-1,YSize-1); + points[3] = getPoint(0,YSize-1) + Point(0,0,1)*getValue(0,YSize-1); + return points; + } + + double CGrid::getValue(int x, int y) + { + return data[x][y]; + } + + void CGrid::setValue(int x, int y, double value) + { + data[x][y] = value; + } + + Point CGrid::getOrigin(void) + { + return origin; + } + + void CGrid::setOrigin(Point org) + { + origin = org; + } + + int CGrid::getXSize(void) + { + return XSize; + } + + int CGrid::getYSize(void) + { + return YSize; + } + + Vector CGrid::getU(void) + { + return U; + } + + Vector CGrid::getV(void) + { + return V; + } + + void CGrid::setU(Vector u) + { + U = u; + } + + void CGrid::setV(Vector v) + { + V = v; + } + +} \ No newline at end of file diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/source/CGrid.h b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/CGrid.h new file mode 100644 index 000000000..4346d37f7 --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/CGrid.h @@ -0,0 +1,73 @@ +/**************************************************************************** +Copyright 2017, Cognitics Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ +#pragma once + +#include "Vector.h" +#include + +namespace ctl { + +/*! \brief Cartesean Grid + + Provides an interface for a cartesean grid, may be used to represent a 3D surface, or the isovalues of a volume + along a plane. Origin must be at the bottom left. + + U and V are vectors representing the two directions of the grid (traditionally x and y). Their lengths are the + dimensions of a single grid cell. By customizing which U and V to use, a non square grid can be generated with + minimal effort. +*/ + class CGrid + { + protected: + Point origin; + Vector U; + Vector V; + int XSize, YSize; + + std::vector > data; + + public: + CGrid(Point o, Point u, Point v, int xsize, int ysize); + ~CGrid(void) { } + + Point getPoint(int x, int y); + + PointList getEnvelope(void); + + double getValue(int x, int y); + void setValue(int x, int y, double value); + + Point getOrigin(void); + void setOrigin(Point org); + + int getXSize(void); + int getYSize(void); + + Vector getU(void); + Vector getV(void); + + void setU(Vector u); + void setV(Vector v); + + }; + +} \ No newline at end of file diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/source/ConstraintMap.cpp b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/ConstraintMap.cpp new file mode 100644 index 000000000..b5c6d081e --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/ConstraintMap.cpp @@ -0,0 +1,159 @@ +/**************************************************************************** +Copyright 2017, Cognitics Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ +#include "ConstraintMap.h" +#include + +//#pragma optimize("", off) + +namespace ctl { + + ID ConstraintMap::GetNextConstraintID(void) + { + ID id = id_generator.getID(); + Constraint_To_Vertex.resize(std::max((ID)Constraint_To_Vertex.size(),id+1),-1); + return id; + } + + void ConstraintMap::FreeConstraintID(ID constraintID) + { + Constraint_To_Vertex[constraintID] = NULL; + id_generator.freeID(constraintID); + } + + void ConstraintMap::BindVertex(ID constraintID, Vertex* vert) + { + if (vert) + Constraint_To_Vertex[constraintID] = vert->getID(); + } + + ID ConstraintMap::GetBoundVertex(ID constraintID) + { + return Constraint_To_Vertex[constraintID]; + } + + void ConstraintMap::FreeVertex(ID constraintID) + { + Constraint_To_Vertex[constraintID] = -1; + } + + bool ConstraintMap::IsVertexBound(Vertex* vert) + { + if (!vert) return false; + for (unsigned int i = 0; i < Constraint_To_Vertex.size(); i++) + { + if (Constraint_To_Vertex[i] == vert->getID()) return true; + } + Edge* start = vert->getEdges(); + Edge* next = start; + do { + if (IsEdgeBound(next)) + return true; + next = next->Onext(); + } while (next != start); + return false; + } + + void ConstraintMap::BindEdge(Edge* edge, ID constraintID) + { + if (!edge) return; + + if(edge->getID()>=Edge_To_Constraint.size()) + Edge_To_Constraint.resize(edge->getID()+1); + IDList::iterator it = upper_bound(Edge_To_Constraint[edge->getID()].begin(),Edge_To_Constraint[edge->getID()].end(),constraintID); + Edge_To_Constraint[edge->getID()].insert(it,constraintID); + } + + void ConstraintMap::BindEdge(Edge* edge, IDList constraints) + { + if (edge) + { + if(edge->getID()>=Edge_To_Constraint.size()) + Edge_To_Constraint.resize(edge->getID()+1); + Edge_To_Constraint[edge->getID()] = constraints; + } + } + + void ConstraintMap::FreeEdge(Edge* edge, ID constraintID) + { + if (!edge) return; + if(edge->getID()>=Edge_To_Constraint.size()) + Edge_To_Constraint.resize(edge->getID()+1); + IDList::iterator it = lower_bound(Edge_To_Constraint[edge->getID()].begin(),Edge_To_Constraint[edge->getID()].end(),constraintID); + if ( (*it) == constraintID) Edge_To_Constraint[edge->getID()].erase(it); + } + + void ConstraintMap::FreeEdge(Edge* edge) + { + if (edge) + { + if(edge->getID()>=Edge_To_Constraint.size()) + Edge_To_Constraint.resize(edge->getID()+1); + Edge_To_Constraint[edge->getID()].clear(); + } + } + + bool ConstraintMap::IsEdgeBound(Edge* edge) + { + if (edge) + { + if(edge->getID()>=Edge_To_Constraint.size()) + Edge_To_Constraint.resize(edge->getID()+1); + return (Edge_To_Constraint[edge->getID()].size() > 0); + } + else return false; + } + + bool ConstraintMap::IsEdgeBound(Edge* edge, ID constraintID) + { + if (edge) + { + if(edge->getID()>=Edge_To_Constraint.size()) + Edge_To_Constraint.resize(edge->getID()+1); + return binary_search(Edge_To_Constraint[edge->getID()].begin(),Edge_To_Constraint[edge->getID()].end(),constraintID); + } + else return false; + } + + IDList ConstraintMap::GetConstraints(Edge* edge) + { + if(edge->getID()>=Edge_To_Constraint.size()) + Edge_To_Constraint.resize(edge->getID()+1); + return Edge_To_Constraint[edge->getID()]; + } + + int ConstraintMap::GetNumBoundEdges(Vertex* vert) + { + if (IsVertexBound(vert)) return 1; + if (!vert) return 0; + int count = 0; + Edge* start = vert->getEdges(); + if (!start) return 0; + Edge* next = start; + do + { + if (IsEdgeBound(next)) count++; + next = next->Onext(); + } while (next != start); + return count; + } + +} \ No newline at end of file diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/source/ConstraintMap.h b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/ConstraintMap.h new file mode 100644 index 000000000..0963808cf --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/ConstraintMap.h @@ -0,0 +1,123 @@ +/**************************************************************************** +Copyright 2017, Cognitics Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ +#pragma once + +#include "ID.h" +#include "Vertex.h" +#include "Edge.h" + +namespace ctl { + +/*! \class ctl::ConstraintMap ctl/ConstraintMap.h ctl/ConstraintMap.h + \brief CosntraintMap + + Provides an interface for binding Edges to Constraints. A Constraint is not an actual class or object, only an ID value + that represents some constraining factor in a DelaunayTriangulation. + + Vertex Binding - + + A Vertex can be bound\ + + There are two forms of binding possible to a Vertex. Active and Passive. + + Active binding is when a Vertex is bonded directly to a Constraint. Each Constraint can only have ONE actively bonded Vertex. + Active binding is used to bind a series of Constrained Edges together by identifying at least one of the Vertices of those connected + Edges (usually the first Vertex of the Constraint). It can also be used by active bind a single Vertex to a single Constraint in the + case of inserting Constrained Points. + + Passive binding is when a Vertex is bonded indirectly to a Constraint through an Edge. This is equivalent to an Edge being + bound to a Constraint and having a Vertex as its origin or destination. Passive binding is a result of tracking Edge binding. + + + Edge Binding - + + Only Active Edge binding is supported. There is no way for an Edge to be "Passively" bound. Each Edge can be bound to any number of + Constraints and all Constraints binding each Edge are tracked (unlike Vertex binding tracking). +*/ + class ConstraintMap + { + private: + IDGenerator id_generator; /* ID Generator in charge of assigning ID values to new Constraints. */ + + IDList Constraint_To_Vertex; + std::vector Edge_To_Constraint; + public: + ConstraintMap(void) { } + ~ConstraintMap(void) { } + +/****************************************************************************************************** + CONSTRAINT ID ASSIGNMENT +*******************************************************************************************************/ + +//! \return Returns a newly reserved ID (unique amost this ConstraintMap). + ID GetNextConstraintID(void); + +//! \brief Free an ID to be used by another constraint. + void FreeConstraintID(ID constraintID); + +/****************************************************************************************************** + VERTEX BINDING +*******************************************************************************************************/ + +//! \brief Actively Bind a Vertex to a constraint. + void BindVertex(ID constraintID, Vertex* vert); + +//! \return Returns the ID of the Vertex bound to the given constraint. + ID GetBoundVertex(ID constraintID); + +//! \brief Frees the Vertex bound by the constraint. + void FreeVertex(ID constraintID); + +//! \return Returns TRUE if the Vertex is bound to at least one constraint. + bool IsVertexBound(Vertex* vert); + +/****************************************************************************************************** + EDGE BINDING +*******************************************************************************************************/ + +//! \brief Bind an Edge to a constraint. + void BindEdge(Edge* edge, ID constraintID); + +//! \brief Set the constraint list of an Edge. + void BindEdge(Edge* edge, IDList constraintIDs); + +//! \brief Frees the Edge bound by the cosntraint. + void FreeEdge(Edge* edge, ID constraintID); + +//! \brief Frees the Edge from all constraint binding. + void FreeEdge(Edge* edge); + +//! \return Returns TRUE if Edge is bound by at least one constraint. + bool IsEdgeBound(Edge* edge); + +//! \return Returns TRUE if Edge is bound by the constraint. + bool IsEdgeBound(Edge* edge, ID constraintID); + +//! \return Returns the constraints binding the given Edge. + IDList GetConstraints(Edge* edge); + +//! \return Returns the number of bound Edges about the Vertex. + int GetNumBoundEdges(Vertex* vert); + + }; + +} \ No newline at end of file diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/source/DelaunayTriangulation.cpp b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/DelaunayTriangulation.cpp new file mode 100644 index 000000000..1a66cf7e3 --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/DelaunayTriangulation.cpp @@ -0,0 +1,2097 @@ +/**************************************************************************** +Copyright 2017, Cognitics Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ + +//#pragma optimize( "", off ) +#include +#include +#include "DelaunayTriangulation.h" +#include "Vertex.h" +#include "Edge.h" +#include "Util.h" + +#include +#include +#include +#include +#include +#include + +#undef min +#undef max + +int GlobalCTLDebugEnabled = 1; + +//#define CTL_DEBUG +#ifdef CTL_DEBUG +#include +#endif + +#define INIT_CORRUPT_TEST\ + int _CORRUPT_TEST_counter = 0;\ + int _CORRUPT_TEST_max_counter = subdivision_->getNumEdges()*32; + +#define RUN_CORRUPT_TEST\ + _CORRUPT_TEST_counter++;\ + if (_CORRUPT_TEST_counter > _CORRUPT_TEST_max_counter) {\ + error_ |= CORRUPTION_DETECTED;\ + break;\ + } + +namespace ctl { + + +/****************************************************************************************************** + INITIALIZATION +*******************************************************************************************************/ + + DelaunayTriangulation::DelaunayTriangulation + ( + PointList boundary, + int resizeIncriment, + double epsilon, + double areaEpsilon, + int maxEdgeFlips, + int settings + ) + { + epsilon_ = epsilon; + areaEpsilon_ = areaEpsilon; + maxEdgeFlips_ = maxEdgeFlips; + settings_ = settings; + subdivision_ = new Subdivision(resizeIncriment < 10 ? 10 : resizeIncriment); + error_ = 0; + + // transform to local coordinates + origin_ = boundary.size()>0 ? boundary[0] : ctl::Point(0,0,0); + for (size_t i = 0; i < boundary.size(); i++) + boundary[i] = TransformPointToLocal(boundary[i]); + + bsp = new DelaunayBSP(boundary); + + + // remove duplicate points + boundary.reserve(boundary.size()); + for (size_t i = 0; i < boundary.size(); i++) + { + if (boundary_.empty()) + boundary_.push_back(boundary[i]); + else if ((boundary_.front() - boundary[i]).length2D() <= epsilon) + continue; + else if ((boundary_.back() - boundary[i]).length2D() <= epsilon) + continue; + else + boundary_.push_back(boundary[i]); + } + + // check for valid boundary + if (boundary_.size() < 3) + { + //ccl::ObjLog log; + //log << ccl::LERR << "(DelaunayTriangulation) Boundary has too few unique points." << log.endl; + error_ = INVALID_BOUNDARY; + return; + } + double area = PArea2D(boundary_); + if (area > 0) + std::reverse(boundary_.begin(), boundary_.end()); + else + area = -area; + if (area < areaEpsilon_) + { + //ccl::ObjLog log; + //log << ccl::LERR << "(DelaunayTriangulation) Boundary has 0 area." << log.endl; + error_ = INVALID_BOUNDARY; + return; + } + for (int curr = 0, num = int(boundary_.size()); curr < num; curr++) + { + int prev = (curr - 1 + num) % num; + int next = (curr + 1) % num; + + if (IsLeft(boundary_[curr], boundary_[prev], boundary_[next])) + { + //ccl::ObjLog log; + //log << ccl::LERR << "(DelaunayTriangulation) Boundary must be convex." << log.endl; + error_ = INVALID_BOUNDARY; + return; + } + } + +#ifdef CTL_DEBUG + if (GlobalCTLDebugEnabled) + { + double minx = 0, maxx = 0, miny = 0, maxy = 0; + for (size_t i = 0; i < boundary.size(); i++) + { + const ctl::Point& p = boundary[i]; + if (p.x < minx) minx = p.x; + if (p.x > maxx) maxx = p.x; + if (p.y < miny) miny = p.y; + if (p.y > maxy) maxy = p.y; + } + glViewer::Initialize(); + glViewer::glVector target((minx + maxx) / 2, (miny + maxy) / 2); + glViewer::glVector position = glViewer::glVector(0, 0, maxx / 2); + glViewer::setWindow(minx, maxx, miny, maxy); + } +#endif + + neighbors_.resize(boundary_.size(), NULL); + + // Reserve constraint ID of 0 for boundary + cmap_.GetNextConstraintID(); + + size_t n = boundary_.size(); + + std::vector verts; + for (size_t i = 0; i < n; i++) + { + Vertex* vert = subdivision_->CreateVertex(boundary_[i]); + verts.push_back(vert); + } + + // save the boundary verts so we can remove them later + boundary_verts = verts; + + std::vector edges; + for (size_t i = 0; i < n; i++) + edges.push_back(subdivision_->CreateEdge(verts[i], verts[(i+1)%n])); + + for (size_t i = 0; i < n; i++) + { + cmap_.BindEdge(edges[i],0); + subdivision_->Splice(edges[i]->Sym(), edges[(i+1)%n]); + } + + // Connect edges + for (size_t i = 1; i < (n-2); i++) + subdivision_->Connect(edges[i],edges[0]); + + // Flip edges + for (size_t i = 1; i < (n-1); i++) + FlipEdges(boundary[0], edges[i]); + } + + DelaunayTriangulation::~DelaunayTriangulation(void) + { + delete bsp; + delete subdivision_; + for (size_t i = 0, n = neighbors_.size(); i < n; i++) + UnlinkNeighbor(i); + } + + int DelaunayTriangulation::error(void) const { + return error_; + } + + void DelaunayTriangulation::removeBoundaryVerts(void) + { + for(size_t i = 0, c = boundary_verts.size(); i < c; ++i) + RemoveVertex(boundary_verts[i]); + } + +/****************************************************************************************************** + BOUNDARY QUERIES +*******************************************************************************************************/ + static void GetBoundingRect(const PointList& polygon, Point& minPoint, Point& maxPoint) + { + double minX = DBL_MAX; + double maxX = -DBL_MAX; + double minY = DBL_MAX; + double maxY = -DBL_MAX; + for(auto &point: polygon) + { + minX = std::min(minX, point.x); + maxX = std::max(maxX, point.x); + minY = std::min(minY, point.y); + maxY = std::max(maxY, point.y); + } + minPoint = Point(minX, minY); + maxPoint = Point(maxX, maxY); + } + + Point DelaunayTriangulation::GetLowerBound(void) + { + double x = DBL_MAX; + double y = DBL_MAX; + double z = DBL_MAX; + for (size_t i = 1; i < boundary_.size(); i++) + { + x = std::min(boundary_[i].x, x); + y = std::min(boundary_[i].y, y); + z = std::min(boundary_[i].z, z); + } + return TransformPointToGlobal(Point(x, y, z)); + } + + Point DelaunayTriangulation::GetUpperBound(void) + { + double x = -DBL_MAX; + double y = -DBL_MAX; + double z = -DBL_MAX; + for (size_t i = 1; i < boundary_.size(); i++) + { + x = std::max(boundary_[i].x, x); + y = std::max(boundary_[i].y, y); + z = std::max(boundary_[i].z, z); + } + return TransformPointToGlobal(Point(x, y, z)); + } + + PointList DelaunayTriangulation::GetBoundary(void) + { + PointList temp; + for (size_t i = 0; i < boundary_.size(); i++) + temp.push_back(TransformPointToGlobal(boundary_[i])); + return temp; + } + +/****************************************************************************************************** + SETTINGS CONTROL +*******************************************************************************************************/ + + double DelaunayTriangulation::GetEpsilon(void) const { + return epsilon_; + } + + void DelaunayTriangulation::SetEpsilon(double newEpsilon) { + epsilon_ = newEpsilon; + } + + double DelaunayTriangulation::GetAreaEpsilon(void) const { + return areaEpsilon_; + } + + void DelaunayTriangulation::SetAreaEpsilon(double newAreaEpsilon) { + areaEpsilon_ = newAreaEpsilon; + } + + int DelaunayTriangulation::GetMaxEdgeFlips(void) const { + return maxEdgeFlips_; + } + + void DelaunayTriangulation::SetMaxEdgeFlips(int maxEdgeFlips) { + maxEdgeFlips_ = maxEdgeFlips; + } + + bool DelaunayTriangulation::Enabled(Option option) const { + return (settings_ & option) == option; + } + + void DelaunayTriangulation::Enable(Option option) { + +#ifdef CTL_DEBUG + if (option == VISUAL_DEBUG && GlobalCTLDebugEnabled) + { + glViewer::Clear(); + glViewer::AddCDT(this); + glViewer::Display(); + } +#endif + settings_ |= option; + } + + void DelaunayTriangulation::Disable(Option option) { + settings_ &= ~option; + } + +/****************************************************************************************************** + SIZE QUERIES +*******************************************************************************************************/ + + int DelaunayTriangulation::GetNumEdges(void) { + return subdivision_->getNumEdges(); + } + + int DelaunayTriangulation::GetNumConstrainedEdges(void) + { + int count = 0; + + for (int i = 0; i < subdivision_->getMaxEdges(); i++) + if (cmap_.IsEdgeBound(subdivision_->getEdge(i))) count++; + + return count; + } + + int DelaunayTriangulation::GetNumVertices(void) + { + return subdivision_->getNumVerts(); + } + + int DelaunayTriangulation::GetNumConstrainedVertices(void) + { + int count = 0; + + for (int i = 0; i < subdivision_->getMaxVerts(); i++) + if (cmap_.IsVertexBound(subdivision_->getVertex(i))) count++; + + return count; + } + + int DelaunayTriangulation::GetNumTriangles(bool rough) + { + int base = 2*GetNumEdges(); + if (!rough) // extract excess boundary triangles + { + for (int i = 0; i < subdivision_->getMaxEdges(); i++) + { + Edge* e = subdivision_->getEdge(i); + if (e && cmap_.IsEdgeBound(e, 0)) + base--; + } + } + return base/3; + } + +/****************************************************************************************************** + POINT QUERIES +*******************************************************************************************************/ + + Point DelaunayTriangulation::GetNearestPoint(Point point) + { + // Out of bounds + if (!IsInside(point)) + return point; + + Point nearest = point; + + LocationResult loc = LocatePoint(point); + if (loc.getType() == LR_VERTEX) + nearest = loc.getEdge()->Org()->point; + else if (loc.getType() == LR_EDGE) + { + // Find which end of the edge the point is closest to. + Point a = loc.getEdge()->Org()->point; + Point b = loc.getEdge()->Dest()->point; + double dist = (point-a).dot(b-a)/(b-a).length2D(); + nearest = (dist < 0.5 ? a : b); + } + else if (loc.getType() == LR_FACE) + { + double d = (point - loc.getEdge()->Org()->point).length2D(); + double d1 = (point - loc.getEdge()->Dest()->point).length2D(); + double d2 = (point - loc.getEdge()->Onext()->Dest()->point).length2D(); + + nearest = loc.getEdge()->Org()->point; + if (d < d1) nearest = loc.getEdge()->Dest()->point; + if (d < d2) nearest = loc.getEdge()->Onext()->Dest()->point; + } + + return nearest; + } + + double DelaunayTriangulation::GetZValue(Point point, double outsideZ) + { + point = TransformPointToLocal(point); + + // Out of bounds + if (!IsInside(point)) + return outsideZ; + + double z = 0; + + Vertex* vert = SnapPointToVertex(point); + if (vert) + return vert->point.z + origin_.z; + + LocationResult loc = LocatePoint(point); + if (loc.getType() == LR_VERTEX) + z = loc.getEdge()->Org()->point.z; + else if (loc.getType() == LR_EDGE) + { + // Interpolate + Point a = loc.getEdge()->Org()->point; + Point b = loc.getEdge()->Dest()->point; + double dist = (point-a).dot(b-a)/(b-a).length2D(); + z = a.z*(1 - dist) + b.z; + } + else if (loc.getType() == LR_FACE) + { + Vector O = loc.getEdge()->Org()->point; + Vector U = loc.getEdge()->Dest()->point - O; + Vector V = loc.getEdge()->Onext()->Dest()->point - O; + + Point P = point - O; + double denom = V.x*U.y - V.y*U.x; + double v = ( P.x*U.y - P.y*U.x )/denom; + double u = ( P.y*V.x - P.x*V.y )/denom; + z = O.z + u*U.z + v*V.z; + + } + + return z + origin_.z; + } + +/****************************************************************************************************** + INSERTION AND REMOVAL +*******************************************************************************************************/ + + void DelaunayTriangulation::InsertWorkingPoint(Point point) + { + if (error_) + return; + + point = TransformPointToLocal(point); + if (IsInside(point)) + InsertPoint(point); + } + + void DelaunayTriangulation::RemoveWorkingPoints(const PointList &polygon) + { + if (error_) + return; + + std::vector verts = GatherWorkingVerts(polygon); + for (size_t i = 0; i < verts.size(); i++) + RemoveVertex(verts[i]); + } + + ID DelaunayTriangulation::InsertConstrainedPoint(Point point) + { + if (error_) + return 0; + + // Transform + point = TransformPointToLocal(point); + + if (!IsInside(point)) + return 0; + + Vertex* vert = InsertPoint(point); + if (error_) return 0; + + ID constraintID = cmap_.GetNextConstraintID(); + cmap_.BindVertex(constraintID,vert); + return constraintID; + } + + ID DelaunayTriangulation::InsertConstrainedLineString(PointList constraint) + { + if (error_) + return 0; + + // Transform + for (size_t i = 0; i < constraint.size(); i++) + constraint[i] = TransformPointToLocal(constraint[i]); + + // Clip + if (!IsInside(constraint)) + { + if (Enabled(CLIPPING)) + constraint = ClipToPolygon(constraint,boundary_,0); + else + return 0; + } + + if (constraint.size() < 2) + return 0; + + return InsertConstrainedLineStringPrivate(constraint); + } + + ID DelaunayTriangulation::InsertConstrainedLineStringPrivate(const PointList& constraint) + { +#ifdef CTL_DEBUG + if (GlobalCTLDebugEnabled && this->Enabled(VISUAL_DEBUG)){ + glViewer::Clear(); + glViewer::AddText("InsertConstraint-constraint",0,0,0); + glViewer::AddPointList(constraint); + glViewer::AddCDT(this); + glViewer::Display(); + } +#endif + // Insert constraint points + std::vector verts; + verts.reserve(constraint.size()); + for (unsigned int i = 0; i < constraint.size(); i++) + { + Vertex* vert = SnapPointToVertex(constraint[i]); + if (!vert) + vert = SnapPointToEdge(constraint[i]); + if (!vert) + vert = InsertPoint(constraint[i]); +#ifdef CTL_DEBUG + if (GlobalCTLDebugEnabled && this->Enabled(VISUAL_DEBUG)){ + glViewer::Clear(); + glViewer::AddText("InsertConstraint-points",0,0,0); + glViewer::AddPoint(vert->point); + glViewer::AddCDT(this); + glViewer::Display(); + } + + if (GlobalCTLDebugEnabled && (error_ || !vert)) + { + glViewer::Clear(); + glViewer::AddText("Error inserting-points",0,0,0); + glViewer::AddPoint(vert->point); + glViewer::AddCDT(this); + glViewer::Display(); + + } +#endif + if (error_) return 0; + if (vert) + verts.push_back(vert); + } + + ID constraintID = cmap_.GetNextConstraintID(); + cmap_.BindVertex(constraintID,verts[0]); + + // Insert Constrained Edges + for (int i = 1; i < int(verts.size()); i++) + { + InsertSegment(verts[i-1],verts[i],constraintID); + if (error_) return 0; + } + + return error_ ? 0 : constraintID; + } + + ID DelaunayTriangulation::InsertConstrainedPolygon(PointList constraint) + { + if (error_) + return 0; + + // Transform + for (size_t i = 0; i < constraint.size(); i++) + constraint[i] = TransformPointToLocal(constraint[i]); + + // Clip + if (!IsInside(constraint)) + { + if (Enabled(CLIPPING)) + { + constraint = ClipToPolygon(constraint,boundary_,0); + } + else + return 0; + } + + // Collapsed constraint + if (constraint.size() < 2) + return 0; + + // Check for collapsed polygon + double area = PArea2D(constraint); + if (abs(area) < areaEpsilon_) + return 0; + if (area < 0) + std::reverse(constraint.begin(), constraint.end()); + + return InsertConstrainedPolygonPrivate(constraint); + } + + ID DelaunayTriangulation::InsertConstrainedPolygonPrivate(const PointList& constraint) + { + // Insert constraint like normal + ID constraintID = InsertConstrainedLineStringPrivate(constraint); + + if (error_) + return 0; + + // Gather Verts inside this constraint. The working vertices are simplified + // There are two ways to define the Z of the constrained vertices + // -set the polygon vertices to the Z of the grid. This is done if + // INTERPOLATE_EDGES and INTERPOLATE_FACES are enabled + // -set all the vertices to the Z of the polygon. If + // INTERPOLATE_EDGES and INTERPOLATE_FACES are disabled + bool usePolygonZ = !Enabled(INTERPOLATE_EDGES); + std::vector verts = GatherVertsLocal(constraint, usePolygonZ, true); + + if (error_) + return 0; + + if (usePolygonZ) + { + // Find basis of the polygon list + Point O = constraint[0]; + Vector U = constraint[1] - constraint[0]; + Vector V; + + for (unsigned int i = 2; i < constraint.size(); i++) + { + V = constraint[i] - constraint[0]; + if (std::abs(U.cross(V).z) > areaEpsilon_) + break; + } + + for (unsigned int i = 0; i < verts.size(); i++) + InterpolateZ(O, U, V, verts[i]); + } + // Remove unconstrained vertices inside the polygon + // AFTER Z has been set in case the simplification needs Z + for (unsigned int i = 0; i < verts.size(); i++) + { + SimplifyEdges(verts[i]); + if (error_) return 0; + } + + return constraintID; + } + + void DelaunayTriangulation::RemoveConstraint(ID constraintID) + { + if (error_) + return; + + // Do NOT allow removal of boundary + if (constraintID == 0) + return; + + // Get starting Edge of constraint + Vertex* vert = subdivision_->getVertex(cmap_.GetBoundVertex(constraintID)); + if (!vert) return; + Edge* edge = vert->getEdges(); + if (!edge) return; + + // Unbind this Vertex from the Constraint (this must be done now so the first point can be removed + cmap_.FreeVertex(constraintID); + + Edge* start = edge->Oprev(); + int LOOP_LIMIT_i = 0; + int LOOP_LIMIT_n = subdivision_->getNumEdges()*32; + while (!cmap_.IsEdgeBound(edge,constraintID) && edge != start) + { + if (LOOP_LIMIT_i++ > LOOP_LIMIT_n) + { +#ifdef CTL_DEBUG + if (GlobalCTLDebugEnabled) + { + glViewer::Clear(); + glViewer::AddCDT(this); + glViewer::Display(); + } +#endif + //ccl::ObjLog log; + //log << ccl::LERR << "(DelaunayTriangulation) Vertex Edge list has become corrupt." << log.endl; + error_ = CORRUPTION_DETECTED; + return; + } + edge = edge->Onext(); + } + + std::set verts; + + if (!cmap_.IsEdgeBound(edge,constraintID)) + verts.insert(edge->Org()); + else + { + // Gather Edges of Constraint + bool *marked = new bool[subdivision_->getMaxEdges()](); + std::vector edges; + GatherConstraintEdges(edge,edges,marked,constraintID); + delete [] marked; + + // Check for corruption + if (error_) return; + + // Remove constraintID from all edges + for (std::vector::iterator it = edges.begin(); it != edges.end(); ++ it) + cmap_.FreeEdge(*it,constraintID); + + // gather all verts of this constraint + + for (std::vector::iterator it = edges.begin(); it != edges.end(); ++it) + { + verts.insert((*it)->Org()); + verts.insert((*it)->Dest()); + } + } + + for (std::set::iterator it = verts.begin(); it != verts.end(); ++it) + { + /* Constraints may have caused non-delaunay sections. + In order to eliminate retriangulation errors, FlipEdges now + that they are no longer constrained, then simplify the remaining + Edges. + */ + FlipEdges((*it)->point,(*it)->getEdges()->Sym()); + SimplifyEdges(*it); + } + } + +/****************************************************************************************************** + DATA STRUCTURE EXPORTING +*******************************************************************************************************/ + + const ConstraintMap* DelaunayTriangulation::GetConstraintMap(void) const + { + return &cmap_; + } + + const Subdivision* DelaunayTriangulation::GetSubdivision(void) const + { + return subdivision_; + } + +/****************************************************************************************************** + NEIGHBOOR OPERATIONS +*******************************************************************************************************/ + + bool DelaunayTriangulation::LinkNeighbor(size_t location, DelaunayTriangulation* dt, size_t dt_location) + { + // Check if boundaries line up appropriately + Vertex* b0[2]; + Vertex* b1[2]; + + if ( ! (boundary_[location].equals(dt->boundary_[(dt_location+1)%dt->boundary_.size()],epsilon_) && + boundary_[(location+1)%boundary_.size()].equals(dt->boundary_[dt_location],epsilon_)) ) + return false; + + b0[0] = InsertPoint(boundary_[(location+1)%boundary_.size()]); + b0[1] = InsertPoint(boundary_[location]); + b1[0] = dt->InsertPoint(dt->boundary_[dt_location]); + b1[1] = dt->InsertPoint(dt->boundary_[(dt_location+1)%dt->boundary_.size()]); + + // Now check if the boundaries line up by checking the vertices along the boundary using Edge Traversal + Edge *b0_e, *b1_e; + + b0_e = b0[0]->getEdges(); + b1_e = b1[0]->getEdges(); + + while (IsOn(b0_e->Dest()->point,b0[0]->point,b0[1]->point) == -1) + b0_e = b0_e->Onext(); + + while (IsOn(b1_e->Dest()->point,b1[0]->point,b1[1]->point) == -1) + b1_e = b1_e->Onext(); + + while (b0_e->Dest() != b0[1] && b1_e->Dest() != b1[1]) + { + if (b0_e->Dest()->point.equals(b1_e->Dest()->point,epsilon_)) + { + Edge* b0_next = b0_e->Sym()->Onext(); + Edge* b1_next = b1_e->Sym()->Onext(); + + while (IsOn(b0_next->Dest()->point,b0_e) == -1 && b0_next != b0_e->Sym()) + b0_next = b0_next->Onext(); + + while (IsOn(b1_next->Dest()->point,b1_e) == -1 && b1_next != b1_e->Sym()) + b1_next = b1_next->Onext(); + + if (b0_next == b0_e->Sym() || b1_next == b1_e->Sym()) + return false; + else + { + b0_e = b0_next; + b1_e = b1_next; + } + } + else + return false; + } + + neighbors_[location] = dt; + dt->neighbors_[dt_location] = this; + + return true; + } + + void DelaunayTriangulation::UnlinkNeighbor(size_t location) + { + if (neighbors_[location]) + { + for (size_t i = 0; i < neighbors_[location]->neighbors_.size(); i++) + { + if (neighbors_[location]->neighbors_[i] == this) + neighbors_[location]->neighbors_[i] = NULL; + } + } + neighbors_[location] = NULL; + } + + bool DelaunayTriangulation::IsBoundaryVertex(Vertex* vert) + { + for (size_t i = 0, n = boundary_.size(); i < n; i++) + { + if (IsOn(vert->point, boundary_[i], boundary_[(i+1)%n]) != -1) + return true; + } + + return false; + } + + bool DelaunayTriangulation::IsBoundaryVertex(Vertex* vert, size_t location) + { + return IsOn(vert->point, boundary_[(location+1)%boundary_.size()], boundary_[location]) != -1; + } + + bool DelaunayTriangulation::IsBoundaryEdge(Edge* edge) + { + return cmap_.IsEdgeBound(edge,0); + } + + Vector DelaunayTriangulation::GetVertexNormal(Vertex* vert) + { + Vector normal = vert->getAreaWeightedNormal(); +/* + // Use any nearby triangulations data as well + for (int i = 0; i < 4; i++) + { + if (neighbors[i]) + { + if (IsBoundaryVertex(vert,Neighbor(i))) + { + Vertex* other = neighbors[i]->InsertPoint(vert->point); + Vector nextNormal = other->getAreaWeightedNormal(); + normal = nextNormal + normal; + } + } + } +*/ + return normal.normalize(); + } + + bool DelaunayTriangulation::IsBoundaryEdge(Edge* edge, size_t location) + { + return IsBoundaryVertex(edge->Org(),location) && IsBoundaryVertex(edge->Dest(),location); + } + +/****************************************************************************************************** + POINT AND TRIANGLE GATHERING ALGORITHMS +*******************************************************************************************************/ + +//! Recursively traverse the graph to gather all connected constrained edges + void DelaunayTriangulation::GatherConstraintEdges(Edge* edge, std::vector& edges, bool* marked, ID constraintID) + { + Edge* start = edge; + do + { + if (cmap_.IsEdgeBound(edge,constraintID)) + { + if (!marked[edge->getID()]) + { + marked[edge->getID()] = true; + edges.push_back(edge); + GatherConstraintEdges(edge->Sym(),edges,marked,constraintID); + } + } + edge = edge->Onext(); + } + while (edge != start); + } + +//! Gather all edges that cross the line between a and b + std::vector DelaunayTriangulation::GetCrossingEdges(Vertex* a, Vertex* b, bool bound, bool unbound) + { + std::vector edges; + + bool diverged = false; + int iteration = 0; + int iteration_limit = GetNumEdges(); + + auto EdgeNeeded = [&](Edge* e)-> bool + { + return e != nullptr && + ((bound && unbound) || + (bound && cmap_.IsEdgeBound(e)) || + (unbound && !cmap_.IsEdgeBound(e))); + }; + + Point alpha = a->point; + Point beta = b->point; + Edge* e = GetLeftEdge(a,beta); + while(e!=nullptr && e->Dest() != b) + { + if (iteration++ > iteration_limit) + { + diverged = true; + break; + } + + // Search + PointLineLocation loc = ctl::LocatePointOnLine(e->Dest()->point,alpha,beta, epsilon_); + if(loc==PL_LEFT_OF_LINE) + e = e->Rprev(); + else if(loc==PL_RIGHT_OF_LINE) + { + if(EdgeNeeded(e)) + edges.push_back(e); + e = e->Onext(); + } + else + { + if(IsRight(e->Lnext()->Dest()->point, alpha, beta)) + e = e->Onext(); + else + e = e->Lnext(); + } + } + + // smart search diverged, revert to brute force + if (diverged) + { + //ccl::ObjLog log; + //log << "DelaunayTriangulation::GetCrossingEdges() Smart search failed, reverting to brute force." << log.endl; + + edges.clear(); + Point ba = beta - alpha; + for (int i = 0; i < subdivision_->getMaxEdges(); i++) + { + Edge* edge = subdivision_->getEdge(i); + if (EdgeNeeded(edge)) + { + // If the edge vertices fall on the line, it does not cross the line + if (IsOn(edge->Org()->point, alpha, beta)!=-1 || IsOn(edge->Dest()->point, alpha, beta)!=-1) + continue; + Point dc = edge->Dest()->point - edge->Org()->point; + float denom = float(dc.x*ba.y - ba.x*dc.y); + if (denom) + { + Point ca = edge->Org()->point - alpha; + float s = float(dc.x*ca.y - ca.x*dc.y) / denom; + if (s < 0 || s > 1) + continue; + float t = float(ba.x*ca.y - ca.x*ba.y) / denom; + if (t < 0 || t > 1) + continue; + edges.push_back(edge); + } + } + } + } + + return edges; + } + +//! Gather all vertices that are on the line between a and b + std::vector DelaunayTriangulation::GetTouchingVerts(Vertex* a, Vertex* b) + { + std::vector verts; + + verts.push_back(a); + + bool diverged = false; + int iteration = 0; + int iteration_limit = GetNumEdges(); + + Point alpha = a->point; + Point beta = b->point; + Edge* e = GetLeftEdge(a,b->point); + while(e->Dest() != b) + { + if (iteration++ > iteration_limit) + { + diverged = true; + break; + } + + // Search + PointLineLocation loc = ctl::LocatePointOnLine(e->Dest()->point,alpha,beta, epsilon_); + if (loc==PL_LEFT_OF_LINE) + e = e->Rprev(); + else if (loc==PL_RIGHT_OF_LINE) + e = e->Onext(); + else + { + if (verts.back() != e->Dest()) verts.push_back(e->Dest()); + e = e->Onext(); + } + } + verts.push_back(b); + + if (diverged) + { + std::map vertmap; + + //ccl::ObjLog log; + //log << "DelaunayTriangulation::GetTouchingVerts() Smart search failed, reverting to brute force." << log.endl; + + vertmap[0] = a; + for (int i = 0; i < subdivision_->getMaxVerts(); i++) + { + Vertex* vert = subdivision_->getVertex(i); + if (vert) + { + PointLineLocation loc = LocatePointOnLine(vert->point, a->point, b->point, epsilon_); + if (loc == PL_BEGINS_LINE || loc == PL_ENDS_LINE || loc == PL_ON_LINE) + vertmap[(vert->point - a->point).length2D()] = vert; + } + } + vertmap[(b->point - a->point).length2D()] = b; + + verts.clear(); + for (std::map::iterator it = vertmap.begin(); it != vertmap.end(); it++) + verts.push_back(it->second); + } + + return verts; + } + + std::vector DelaunayTriangulation::GatherVertsLocal(const PointList & polygon, bool constrained, bool working) + { + Point minP, maxP; + + + GetBoundingRect(polygon, minP, maxP); + + std::vector verts; + verts.reserve( subdivision_->getMaxVerts() ); + + for (int i = 0; i < subdivision_->getMaxVerts(); i++) + { + Vertex* vert = subdivision_->getVertex(i); + if (vert && + ((constrained && working) || + (constrained && cmap_.IsVertexBound(vert)) || + (working && !cmap_.IsVertexBound(vert)))) + { + if (polygon.empty()) + verts.push_back(vert); + else if (vert->point.x < minP.x || + vert->point.x > maxP.x || + vert->point.y < minP.y || + vert->point.y > maxP.y) + continue; + if (PointInPolygon(vert->point, polygon, epsilon_)) + verts.push_back(vert); + } + } + + return verts; + } + + std::vector DelaunayTriangulation::GatherVerts(PointList polygon) + { + for (size_t i = 0; i < polygon.size(); i++) + polygon[i] = TransformPointToLocal(polygon[i]); + return GatherVertsLocal(polygon, true, true); + } + + std::vector DelaunayTriangulation::GatherWorkingVerts(PointList polygon) + { + for (size_t i = 0; i < polygon.size(); i++) + polygon[i] = TransformPointToLocal(polygon[i]); + return GatherVertsLocal(polygon, false, true); + } + + std::vector DelaunayTriangulation::GatherConstrainedVerts(PointList polygon) + { + for (size_t i = 0; i < polygon.size(); i++) + polygon[i] = TransformPointToLocal(polygon[i]); + return GatherVertsLocal(polygon, true, false); + } + + std::vector DelaunayTriangulation::GatherTriangles(PointList polygon) + { + for (size_t i = 0; i < polygon.size(); i++) + polygon[i] = TransformPointToLocal(polygon[i]); + Point minP, maxP; + GetBoundingRect(polygon, minP, maxP); + + std::unordered_set processedEdges; + std::vector edges; + + edges.reserve(subdivision_->getMaxEdges()*2); + for (int i = 0; i < 2*subdivision_->getMaxEdges(); i++) + { + Edge* edge = subdivision_->getEdge(i/2); + if (!edge) continue; + if (i % 2) edge = edge->Sym(); + + Point p1 = edge->Org()->point; + Point p2 = edge->Lnext()->Org()->point; + Point p3 = edge->Lprev()->Org()->point; + if (TArea2D(p1, p2, p3) < epsilon_) + continue; + + if (processedEdges.count(edge) != 0) + continue; + if (!polygon.empty()) + { + Point center = (p1 + p2 + p3) * (1.0/3.0); + if (center.x < minP.x || center.x > maxP.x || center.y < minP.y || center.y > maxP.y) + continue; + if (!PointInPolygon(center, polygon, epsilon_)) + continue; + } + + edges.push_back(edge); + processedEdges.insert(edge); + processedEdges.insert(edge->Lnext()); + processedEdges.insert(edge->Lprev()); + } + return edges; + } + +/****************************************************************************************************** + BOOLEAN FUNCTIONS +*******************************************************************************************************/ + + bool DelaunayTriangulation::IsRight(Vector vert, Vector a, Vector b) + { + return ctl::IsRight(vert, a, b, epsilon_); + } + + bool DelaunayTriangulation::IsRight(Vector vert, Edge* edge) + { + return ctl::IsRight(vert, edge->Org()->point, edge->Dest()->point, epsilon_); + } + + bool DelaunayTriangulation::IsLeft(Vector vert, Vector a, Vector b) + { + return ctl::IsLeft(vert, a, b, epsilon_); + } + + bool DelaunayTriangulation::IsLeft(Vector vert, Edge* edge) + { + return ctl::IsLeft(vert, edge->Org()->point, edge->Dest()->point, epsilon_); + } + + int DelaunayTriangulation::IsOn(Vector vert, Vector p0, Vector p1) + { + PointLineLocation result = ctl::LocatePointOnLine(vert, p0, p1, epsilon_); + return result <= PL_AFTER_LINE ? result : -1; + } + + int DelaunayTriangulation::IsOn(Vector vert, Edge* edge) + { + PointLineLocation result = ctl::LocatePointOnLine(vert, edge->Org()->point, edge->Dest()->point, epsilon_); + return result <= PL_AFTER_LINE ? result : -1; + } + + bool DelaunayTriangulation::InCircle(Vector a, Vector b, Vector c, Vector d) + { + return (a.x*a.x + a.y*a.y)*TArea2D(b,c,d) - + (b.x*b.x + b.y*b.y)*TArea2D(a,c,d) + + (c.x*c.x + c.y*c.y)*TArea2D(a,b,d) - + (d.x*d.x + d.y*d.y)*TArea2D(a,b,c) > areaEpsilon_; + } + + bool DelaunayTriangulation::IsFlipValid(Edge* edge) + { + Point a = edge->Org()->point; + Point b = edge->Dest()->point; + Point alpha = edge->Onext()->Dest()->point; + Point beta = edge->Oprev()->Dest()->point; + + if (!IsRight(a,alpha,beta)) return false; + else if (!IsLeft(b,alpha,beta)) return false; + + // Check for collapsed triangles + if (TArea2D(alpha,a,beta) < areaEpsilon_) + return false; + else if (TArea2D(alpha,beta,b) < areaEpsilon_) + return false; + else + return true; + } + + bool DelaunayTriangulation::IsDelaunay(Point p, Edge* edge) + { + Edge* temp = edge->Oprev(); + return !(IsRight(temp->Dest()->point,edge) && InCircle(edge->Org()->point,temp->Dest()->point,edge->Dest()->point,p)); + } + + bool DelaunayTriangulation::IsInside(Point point) + { + return PointInPolygon(point, boundary_, epsilon_); + } + + bool DelaunayTriangulation::IsInside(const PointList &points) + { + for (PointList::const_iterator it = points.begin(); it != points.end(); ++it) + { + if (!IsInside(*it)) return false; + } + return true; + } + + bool DelaunayTriangulation::Touches(const PointList &points) + { + for (PointList::const_iterator it = points.begin(); it != points.end(); ++it) + { + if (IsInside(*it)) return true; + } + return false; + } + +/****************************************************************************************************** + SUBDIVISION INTERFACE +*******************************************************************************************************/ + Edge* DelaunayTriangulation::Connect(Vertex* a, Vertex* b) + { + return subdivision_->Connect( + GetLeftEdge(a,b->point)->Sym(), + GetLeftEdge(b,a->point)->Oprev() + ); + } + + Edge* DelaunayTriangulation::GetConnection(Vertex* a, Vertex* b) + { + int iteration = 0; + int iteration_limit = GetNumEdges(); + + Edge* start = a->getEdges(); + Edge* next = start; + do + { + if (iteration++ > iteration_limit) + { +#ifdef CTL_DEBUG + if (GlobalCTLDebugEnabled) + { + glViewer::Clear(); + glViewer::AddPoint(a->point); + glViewer::AddPoint(b->point); + glViewer::AddCDT(this); + glViewer::Display(); + } +#endif + //ccl::ObjLog log; + //log << ccl::LERR << "DelaunayTriangulation::GetConnection() Edges do not form cycle around vertex." << log.endl; + error_ = CORRUPTION_DETECTED; + break; + } + + if (next->Dest() == b) return next; + else next = next->Onext(); + } + while (next != start); + return NULL; + } + + Edge* DelaunayTriangulation::GetLeftEdge(Vertex* a, Point p) + { + Edge* edge = a->getEdges(); + Edge* startEdge = edge; + int iteration = 0; + int iteration_limit = GetNumEdges(); + + // We need to return an edge so that the point is to the right of the edge. + // If the first point is to the right, search the previous edges. + // If the first points is to the left, search the next edges + // Note that we check for !IsLeft() and !IsRight() so that the function returns an edge + + if(IsRight(p, edge)) + { + while(!IsLeft(p, edge->Oprev())) + { + edge = edge->Oprev(); + if (iteration++ > iteration_limit || edge==startEdge) + { + //ccl::ObjLog log; + //log << ccl::LERR << "DelaunayTriangulation::GetLeftEdge() No 'left edge' found, this indicates graph corruption." << log.endl; +#ifdef CTL_DEBUG + if (GlobalCTLDebugEnabled) + { + glViewer::Clear(); + glViewer::AddPoint(a->point); + glViewer::AddPoint(p); + glViewer::AddCDT(this); + glViewer::Display(); + } +#endif + error_ = CORRUPTION_DETECTED; + + return edge; + + + + } + } + } + else + { + while(!IsRight(p, edge->Onext())) + { + edge = edge->Onext(); + if (iteration++ > iteration_limit || edge==startEdge) + { +#ifdef CTL_DEBUG + if (GlobalCTLDebugEnabled) + { + glViewer::Clear(); + glViewer::AddCDT(this); + glViewer::AddPoint(a->point); + glViewer::AddPoint(p); + glViewer::Display(); + } +#endif + error_ = CORRUPTION_DETECTED; + //ccl::ObjLog log; + //log << ccl::LERR << "DelaunayTriangulation::GetLeftEdge() No 'left edge' found, this indicates graph corruption." << log.endl; + return edge; + } + } + edge = edge->Onext(); + } + + return edge; + } + + void DelaunayTriangulation::Swap(Edge* edge) + { + Edge* a = edge->Oprev(); + Edge* b = edge->Sym()->Oprev(); + + edge->Org()->removeEdge(edge); + edge->Dest()->removeEdge(edge->Sym()); + + Edge::Splice(edge,a); + Edge::Splice(edge->Sym(),b); + Edge::Splice(edge,a->Lnext()); + Edge::Splice(edge->Sym(),b->Lnext()); + edge->setEndPoints(a->Dest(),b->Dest()); + } + + void DelaunayTriangulation::RemoveEdge(Edge* edge) + { + cmap_.FreeEdge(edge); + subdivision_->RemoveEdge(edge); + } + + void DelaunayTriangulation::RemoveVertex(Vertex* vert) + { + Edge* base = vert->getEdges(); + Edge* remaining = base->Lnext(); + + while (base->Onext() != base) + RemoveEdge(base->Onext()); + + RemoveEdge(base); + RetriangulateFace(remaining); + + subdivision_->RemoveVertex(vert); + } + +/****************************************************************************************************** + SEARCH AND INTERSECTION +*******************************************************************************************************/ + + LocationResult DelaunayTriangulation::LocatePoint(Point p, Edge* edge) + { + if (edge == NULL) + edge = subdivision_->getRandomEdge(); + + bool diverged = false; + int iteration = 0; + int iteration_limit = GetNumEdges(); + + while (true) + { + /* +#ifdef CTL_DEBUG + if (this->Enabled(VISUAL_DEBUG)){ + glViewer::Clear(); + glViewer::AddCDT(this); + glViewer::AddPoint(p); + glViewer::AddEdge(edge); + glViewer::Display(); + } +#endif + */ + if (iteration++ > iteration_limit) + { + diverged = true; + break; + } + + PointLineLocation result = ctl::LocatePointOnLine(p, edge->Org()->point, edge->Dest()->point, epsilon_); + if (result==PL_RIGHT_OF_LINE) + { + edge = edge->Sym(); + continue; + } + + if (result == PL_BEGINS_LINE) + return LocationResult(edge,LR_VERTEX); + else if (result == PL_ON_LINE) + return LocationResult(edge,LR_EDGE); + else if (result == PL_ENDS_LINE) + return LocationResult(edge->Sym(),LR_VERTEX); + else if (!IsRight(p,edge->Onext())) + { + // Changed by janghel on 9/21 to prevent cyclical problem when searching along a boundary. + // if (IsRight(edge->Onext()->Dest()->point, edge)) + if (!IsLeft(edge->Onext()->Dest()->point, edge)) + edge = edge->Rprev(); + else + edge = edge->Onext(); + } + else if (!IsRight(p,edge->Dprev())) + edge = edge->Dprev(); + else + return LocationResult(edge,LR_FACE); + } + + if (diverged) + { + //ccl::ObjLog log; + //log << "DelaunayTriangulation::LocatePoint() Smart search failed to converge, reverting to brute force." << log.endl; + for (int i = 0; i < subdivision_->getMaxEdges(); i++) + { + Edge* edge = subdivision_->getEdge(i); + if (edge) + { + int result = IsOn(p,edge); + if (result == PL_BEGINS_LINE) + return LocationResult(edge,LR_VERTEX); + else if (result == PL_ON_LINE) + return LocationResult(edge,LR_EDGE); + else if (result == PL_ENDS_LINE) + return LocationResult(edge->Sym(),LR_VERTEX); + else if (IsLeft(p, edge) && IsLeft(p, edge->Lnext()) && IsLeft(p, edge->Lprev())) + return LocationResult(edge,LR_FACE); + } + if (edge) + { + edge = edge->Sym(); + int result = IsOn(p,edge); + if (result == PL_BEGINS_LINE) + return LocationResult(edge,LR_VERTEX); + else if (result == PL_ON_LINE) + return LocationResult(edge,LR_EDGE); + else if (result == PL_ENDS_LINE) + return LocationResult(edge->Sym(),LR_VERTEX); + else if (IsLeft(p, edge) && IsLeft(p, edge->Lnext()) && IsLeft(p, edge->Lprev())) + return LocationResult(edge,LR_FACE); + } + } + //log << "DelaunayTriangulation::LocatePoint() Failed to locate point using brute force." << log.endl; + } + + return LocationResult(); + } + + Point DelaunayTriangulation::Intersection(Edge* edge,Point c, Point d) + { + Point a = edge->Org()->point; + Point b = edge->Dest()->point; + + Point u = b-a; + Point v = d-c; + + Point w = a - c; + + if (Enabled(INTERPOLATE_EDGES)) + { + double dist = ( v.x*w.y - v.y*w.x )/( v.y*u.x - v.x*u.y ); + return a + u*dist; + } + else + { + double dist = ( u.x*w.y - u.y*w.x )/( u.x*v.y - u.y*v.x ); + return c + v*dist; + } + } + + void DelaunayTriangulation::InterpolateZ(Vector O, Vector U, Vector V, Vertex *vert) + { + Point P = vert->point - O; + double denom = V.x*U.y - V.y*U.x; + double v = ( P.x*U.y - P.y*U.x )/denom; + double u = ( P.y*V.x - P.x*V.y )/denom; + vert->point.z = O.z + u*U.z + v*V.z; + } + +/****************************************************************************************************** + INSERTION +*******************************************************************************************************/ + + Vertex* DelaunayTriangulation::SnapPointToVertex(const Point& p) + { + return bsp->findSnapVertex(p); + //TODO - use BSP + for (int i = 0, n = subdivision_->getMaxVerts(); i < n; ++i) + { + Vertex* v = subdivision_->getVertex(i); + if (v && (v->point - p).length2D2() < 0.01) + return v; + } + return NULL; + } + + Vertex* DelaunayTriangulation::SnapPointToEdge(const Point& p) + { + //TODO - use BSP + for (int i = 0, n = subdivision_->getMaxEdges(); i < n; ++i) + { + Edge* e = subdivision_->getEdge(i); + if (e && cmap_.IsEdgeBound(e) && (LocatePointOnLine(p, e->Org()->point, e->Dest()->point, 0.01) == PL_ON_LINE)) + return InsertPointInEdge(p, e); + } + return NULL; + } + + Vertex* DelaunayTriangulation::InsertPoint(Point p) + { + if (Enabled(FLATTENING)) p.z = 0; + + LocationResult location = LocatePoint(p); + + Vertex *result = NULL; + if (location.getType() == LR_EDGE) + result = InsertPointInEdge(p,location.getEdge()); + else if (location.getType() == LR_FACE) + result = InsertPointInFace(p,location.getEdge()); + else if (location.getType() == LR_VERTEX) + { + result = location.getEdge()->Org(); + result->point.z = p.z; // Need to set the proper Z + return result; // Do not add to bsp -already included + } + if(result) + bsp->addVertex(result); + return result; + } + + Vertex* DelaunayTriangulation::InsertPointInEdge(Point p, Edge* edge) + { + // Snap point to edge exactly. This is fast approximation. + // Since the point is known to be very close to the edge the distance between + // the point and the edge origin is very close to the distance from the + // edge origin to the closest point on the edge. + Vector u = edge->Dest()->point - edge->Org()->point; + Vector v = p - edge->Org()->point; + + double z = p.z; + p = edge->Org()->point + u*(v.length2D()/u.length2D()); + if (!Enabled(INTERPOLATE_EDGES)) + p.z = z; + + // Insert point + if (IsBoundaryEdge(edge)) + return InsertPointInBoundary(p,edge); + + IDList constraints = cmap_.GetConstraints(edge); + edge = edge->Oprev(); + RemoveEdge(edge->Onext()); + + // Create new edge + Vertex* vert = subdivision_->CreateVertex(p); + Edge* base = subdivision_->CreateEdge(edge->Org(),vert); + cmap_.BindEdge(base,constraints); + Edge::Splice(base,edge); + + // Connect right side + base = subdivision_->Connect(edge,base->Sym()); + edge = base->Oprev(); + + // Connect other side + base = subdivision_->Connect(edge,base->Sym()); + edge = base->Oprev(); + cmap_.BindEdge(base,constraints); + + // Connect left side + base = subdivision_->Connect(edge,base->Sym()); + edge = base->Oprev(); + + FlipEdges(p,base); + return vert; + } + + Vertex* DelaunayTriangulation::InsertPointInBoundary(Point p, Edge* edge) + { + // Ensure edge is directed so that its left face is not outside the triangulation + for (size_t i = 0; i < boundary_.size(); i++) + { + if (IsRight(boundary_[i],edge)) + { + edge = edge->Sym(); + break; + } + } + + IDList constraints = cmap_.GetConstraints(edge); + edge = edge->Lnext(); + RemoveEdge(edge->Onext()); + + // Create new edge + Vertex* vert = subdivision_->CreateVertex(p); + + // Create first half of boundary edge + Edge* base = subdivision_->CreateEdge(edge->Org(),vert); + cmap_.BindEdge(base,constraints); + Edge::Splice(edge,base); + + // Connect right side + base = subdivision_->Connect(edge,base->Sym()); + edge = base->Oprev(); + + // Connect other side + base = subdivision_->Connect(edge, base->Sym()); + cmap_.BindEdge(base, constraints); + edge = base->Oprev(); + + FlipEdges(p,edge); + + // Insert this point as a working point in the any neighbors + for (size_t i = 0; i < neighbors_.size(); i++) + { + if (neighbors_[i]) + { + if (IsBoundaryVertex(vert,i)) + { + size_t l; + for (l = 0; l < neighbors_[i]->neighbors_.size(); l++) + if (neighbors_[i]->neighbors_[l] == this) + break; + + neighbors_[i]->neighbors_[l] = NULL; + neighbors_[i]->InsertWorkingPoint(p); + neighbors_[i]->neighbors_[l] = this; + } + } + } + + return vert; + } + + Vertex* DelaunayTriangulation::InsertPointInFace(Point p, Edge* edge) + { + Vertex* vert = subdivision_->CreateVertex(p); + + // Interpolate Z value if needed + if (Enabled(INTERPOLATE_FACES)) + { + Point O = edge->Org()->point; + Vector U = edge->Dest()->point - O; + Vector V = edge->Onext()->Dest()->point - O; + InterpolateZ(O,U,V,vert); + } + + Edge* base = subdivision_->CreateEdge(edge->Org(),vert); + Edge::Splice(base,edge); + + base = subdivision_->Connect(edge,base->Sym()); + + Edge* base2 = subdivision_->Connect(base->Oprev(),base->Sym()); + + FlipEdges(p,base); + return vert; + } + + void DelaunayTriangulation::SimplifyEdges(Vertex* vert) + { + INIT_CORRUPT_TEST + + if (!IsSimplifyValid(vert)) return; + + int n = cmap_.GetNumBoundEdges(vert); + if (n == 0) + RemoveVertex(vert); + else if (n == 2) + { + // Gather Left and Right + Edge* left = NULL; + Edge* right = NULL; + + Edge* edge = vert->getEdges(); + Edge* start = edge; + do + { + RUN_CORRUPT_TEST + + if (cmap_.IsEdgeBound(edge)) + { + if (left) right = edge; + else left = edge; + } + edge = edge->Onext(); + } + while (edge != start); + + // If Edge is collinear and the constraint maps are equal then merge + IDList left_cmap = cmap_.GetConstraints(left); + IDList right_cmap = cmap_.GetConstraints(right); + if (left_cmap.size() != right_cmap.size()) + return; + if (equal(left_cmap.begin(),left_cmap.end(),right_cmap.begin())) + { + if (IsOn(left->Dest()->point,right)!=-1) + { + Vertex* left_vert = left->Dest(); + Vertex* right_vert = right->Dest(); + + if (!IsBoundaryEdge(left)) + { + RemoveVertex(vert); + + Edge* edge = GetConnection(left_vert,right_vert); + if (!edge) + { + InsertSegment(left_vert,right_vert,1); + edge = GetConnection(left_vert,right_vert); + } + + cmap_.BindEdge(edge,left_cmap); + } + else // SPECIAL CASE OF BOUNDARY VERTEX REMOVAL + { + // Remove all Edges about the vertex + Edge* base = vert->getEdges(); + while (base->Onext() != base) + RemoveEdge(base->Onext()); + + RemoveEdge(base); + + // Delete Vertex + subdivision_->RemoveVertex(vert); + + // Make a new connection before retriangulating + base = Connect(left_vert,right_vert); + + // Constrain new edge + cmap_.BindEdge(base,left_cmap); + + // Retriangulate inner face only + if (!(IsLeft(boundary_[0],base) || IsLeft(boundary_[1],base))) base = base->Sym(); + RetriangulateFace(base); + + // Flip Edges to ensure retriangulation is Delaunay + + } + } + } + } + } + + bool DelaunayTriangulation::IsSimplifyValid(Vertex* vert) + { + if (cmap_.IsVertexBound(vert)) return false; + + for (size_t i = 0; i < neighbors_.size(); i++) + { + if (neighbors_[i]) + { + if (IsBoundaryVertex(vert,i)) + { + Vertex* other = neighbors_[i]->InsertPoint(vert->point); + if (!other) + return false; + int n = neighbors_[i]->cmap_.GetNumBoundEdges(other); + if (n > 0) return false; + } + } + } + + return true; + } + + void DelaunayTriangulation::FlipEdges(Point p, Edge* base) + { + if (Enabled(DISABLE_EDGE_FLIPS)) + return; + + Edge *e = base->Lprev(); + + int count = 0; + + do + { + if (count > maxEdgeFlips_) return; + count++; + + if (!IsDelaunay(p,e) && !cmap_.IsEdgeBound(e) && IsFlipValid(e)) + { + Swap(e); + e = e->Oprev(); + } + else if (e->Onext() == base) return; + else e = e->Onext()->Lprev(); + + } while (true); + } + + void DelaunayTriangulation::InsertSegment(Vertex* a, Vertex* b, ID constraintID) + { + if (a == b) return; + + std::vector edges; + std::vector verts; + + // Add intersection Points to constrained edges. + edges = GetCrossingEdges(a,b,true,false); + for (std::vector::iterator it = edges.begin(); it != edges.end(); ++it) + { + InsertPointInEdge(Intersection(*it,a->point,b->point),*it); + } + //edges.clear(); + + // Remove all non-constrained edges. Must research for crossing edges because of changes from inserting new points + edges = GetCrossingEdges(a,b,false,true); + for (std::vector::iterator it = edges.begin(); it != edges.end(); ++it) + { + RemoveEdge(*it); + } + //edges.clear(); + + // Handle all parallel edgese + verts = GetTouchingVerts(a,b); + for (int i = 1; i < int(verts.size()); i++) + { + Edge* connection = GetConnection(verts[i-1],verts[i]); + if (!connection) + { + connection = Connect(verts[i-1],verts[i]); + cmap_.BindEdge(connection,constraintID); + + RetriangulateFace(connection); + if (error_) break; + + RetriangulateFace(connection->Sym()); + if (error_) break; + } + else cmap_.BindEdge(connection,constraintID); + } + } + + void DelaunayTriangulation::RetriangulateFace(Edge* base) + { + if (!base) return; + + if (base->Org() != base->Lnext()->Lnext()->Dest()) + { + Edge* SplitPoint = base->Lnext(); + Edge* Next = SplitPoint; + + int iteration = 0; + int iteration_limit = GetNumEdges(); + + while (Next->Dest() != base->Org()) + { + if (iteration++ > iteration_limit) + { +#ifdef CTL_DEBUG + if (GlobalCTLDebugEnabled) + { + glViewer::Clear(); + glViewer::AddEdge(base); + glViewer::AddCDT(this); + glViewer::Display(); + } +#endif + error_ = CORRUPTION_DETECTED; + //ccl::ObjLog log; + //log << ccl::LERR << "DelaunayTriangulation::RetriangulateFace() Cannot retriangulate non-closed face." << log.endl; + return; + } + + if (InCircle(base->Org()->point,base->Dest()->point,SplitPoint->Dest()->point,Next->Dest()->point)) + SplitPoint = Next; + Next = Next->Lnext(); + } + + Edge* left = NULL; + Edge* right = NULL; + + // Create new edges only if they are valid (don't already exist) + if ( base->Lprev()->Lprev() != SplitPoint ) + left = subdivision_->Connect(base->Lprev(),SplitPoint->Lnext()); + if ( SplitPoint != base->Lnext() ) + right = subdivision_->Connect(SplitPoint,base->Lnext()); + + RetriangulateFace(left); + RetriangulateFace(right); + } + } + + Point DelaunayTriangulation::TransformPointToLocal(const Point& p) const + { + return p - origin_; + } + + Point DelaunayTriangulation::TransformPointToGlobal(const Point& p) const + { + return p + origin_; + } + +/****************************************************************************************************** + Mesh Simplification +*******************************************************************************************************/ + float DelaunayTriangulation::ComputeVertexError(Vertex* vert) const + { +#if 1 // Average Plane Computation + // Compute the average plane + Vector origin = vert->point; + Vector b_vector; + Vector n_vector; + double total_area = 0; + Edge* edge = vert->getEdges(); + Edge* end = edge->Oprev(); + while (edge != end) + { + Vector p1 = edge->Dest()->point; + Vector p2 = edge->Oprev()->Dest()->point; + + Vector c = (origin + p1 + p2) * (1.0/3.0); + Vector n = (p1 - origin).cross(p2 - origin); + n.normalize(); + double a = TArea3D(origin, p1, p2); + + b_vector += c*a; + n_vector += n*a; + total_area += a; + + edge = edge->Onext(); + } + + // The base point and normal of the plane + b_vector *= (1/total_area); + n_vector *= (1/total_area); + n_vector.normalize(); + + // Compute point to plane distance + return abs((origin - b_vector).dot(n_vector)); +#endif + return 0; + } + +#if 0 + void DelaunayTriangulation::Simplify(int targetPoints, float threshold) + { + // Create space to hold errors + std::multimap errors; + + // Compute initial error + for (int i=0; igetMaxVerts(); i++) + { + Vertex* vert = subdivision_->getVertex(i); + if (vert && !cmap_.IsVertexBound(vert)) + errors.insert(std::pair(ComputeVertexError(vert), vert)); + } + + // Main loop + // Remove the necessary points + int pointsRemoved = 0; + int pointsToRemove = GetNumVertices() - targetPoints; + for (std::multimap::iterator it = errors.begin(); it != errors.end(); it++) + { + if (pointsRemoved++ >= pointsToRemove) + return; + if (it->first > threshold) + return; + + RemoveVertex(it->second); + } + } +#else + void DelaunayTriangulation::Simplify(int targetFaces, float threshold) + { + // Create space to hold errors + std::multimap errors; + + // Compute initial error + for (int i=0; igetMaxVerts(); i++) + { + Vertex* vert = subdivision_->getVertex(i); + if (vert && !cmap_.IsVertexBound(vert)) + errors.insert(std::pair(ComputeVertexError(vert), vert)); + } + + // Main loop + // Remove the necessary points + for (std::multimap::iterator it = errors.begin(); it != errors.end(); it++) + { + if (GetNumTriangles(true) < targetFaces) + return; + if (it->first > threshold) + return; + + RemoveVertex(it->second); + } + } +#endif + + + + DelaunayBSP::~DelaunayBSP(void) + { + if(minChild) + delete minChild; + if(maxChild) + delete maxChild; + } + + DelaunayBSP::DelaunayBSP(const PointList &boundary) : depth(0), vertical(true), minChild(NULL), maxChild(NULL) + { + GetBoundingRect(boundary, minPoint, maxPoint); + } + + DelaunayBSP::DelaunayBSP(const Point &minPoint, const Point &maxPoint, size_t depth, bool vertical) : minPoint(minPoint), maxPoint(maxPoint), depth(depth + 1), vertical(vertical), minChild(NULL), maxChild(NULL) + { + } + + void DelaunayBSP::addVertex(Vertex *vertex) + { + if(minChild) + { + double split = vertical ? (minPoint.x + maxPoint.x) / 2 : (minPoint.y + maxPoint.y) / 2; + double axis = vertical ? vertex->point.x : vertex->point.y; + if(axis < split) + minChild->addVertex(vertex); + else if(axis > split) + maxChild->addVertex(vertex); + else + vertices.push_back(vertex); + return; + } + vertices.push_back(vertex); + if(depth >= 10) + return; + if(vertices.size() <= 10) + return; + + Point minMinPoint(minPoint); + Point minMaxPoint(maxPoint); + Point maxMinPoint(minPoint); + Point maxMaxPoint(maxPoint); + if(vertical) + { + double split = (minPoint.x + maxPoint.x) / 2; + minMaxPoint.x = split; + maxMinPoint.x = split; + } + else + { + double split = (minPoint.y + maxPoint.y) / 2; + minMaxPoint.y = split; + maxMinPoint.y = split; + } + minChild = new DelaunayBSP(minMinPoint, minMaxPoint, depth, !vertical); + maxChild = new DelaunayBSP(maxMinPoint, maxMaxPoint, depth, !vertical); + + std::list tmp = vertices; + vertices.clear(); + for(std::list::iterator it = tmp.begin(), end = tmp.end(); it != end; ++it) + addVertex(*it); + } + + Vertex *DelaunayBSP::findSnapVertex(const Point &point, double distance) + { + for(std::list::iterator it = vertices.begin(), end = vertices.end(); it != end; ++it) + { + if(((*it)->point - point).length2D() < 0.01) + return *it; + } + double split = vertical ? (minPoint.x + maxPoint.x) / 2 : (minPoint.y + maxPoint.y) / 2; + double axis = vertical ? point.x : point.y; + if(minChild && (axis < split)) + return minChild->findSnapVertex(point, distance); + if(maxChild && (axis > split)) + return maxChild->findSnapVertex(point, distance); + return NULL; + } + + + +} diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/source/DelaunayTriangulation.h b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/DelaunayTriangulation.h new file mode 100644 index 000000000..7f4d9a7d8 --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/DelaunayTriangulation.h @@ -0,0 +1,614 @@ +/**************************************************************************** +Copyright 2017, Cognitics Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ +/*! \file ctl/DelaunayTriangulation.h +\headerfile ctl/DelaunayTriangulation.h +\brief Provides ctl::DelaunayTriangulation. +\author Joshua Anghel +*/ +#pragma once + +#include "Subdivision.h" +#include "LocationResult.h" +#include "ConstraintMap.h" +#include "CGrid.h" +#include + + +namespace ctl { + + class DelaunayBSP + { + public: + size_t depth; + bool vertical; + ctl::Point minPoint; + ctl::Point maxPoint; + DelaunayBSP *minChild; + DelaunayBSP *maxChild; + std::list vertices; + + ~DelaunayBSP(void); + DelaunayBSP(const PointList &boundary); + DelaunayBSP(const Point &minPoint, const Point &maxPoint, size_t depth, bool vertical); + + void addVertex(Vertex *vertex); + Vertex *findSnapVertex(const Point &point, double distance = 0.01); + }; + + +/*! \class ctl::DelaunayTriangulation ctl/DelaunayTriangulation.h ctl/DelaunayTriangulation.h + \brief DelaunayTriangulation + + Provides a Dynamically Constrained Delaunay Triangulation system. Based on an incrimental Delaunay Triangulation algorithm + with the added feature of constraint insertion and removal. Capable of creating a point only Delaunay Triangulation in O(n^4/3) time + ( provided the points are inserted randomly - worst case time is n^2 and is encounted when inserting points of a grid in order, to counter + this worst case behaviour an even faster algorithm for generating DelaunayTringulations from a grid is provided). + + + + DelaunayTriangulation Construction: + + When creating a DelaunayTriangulation a few options must be specified. + + BoundingRegion: A DelaunayTriangulation must be initially constrainted to some bounding region (in this implementation a quad). + This must be specified by the user upon construction. + The user can specify 4 points of a bounding QUAD upon construction. + The user can specify a CGrid (which contains a bounding QUAD) upon construction. + Defaults to (NO DEFAULT - MUST BE SPECIFIED). + Must be counter-clockwise in orientation. + + DataBlockSize: The DelaunayTriangulation needs to know how large to make new Vertex and Edge data blocks if more Edges or Verts are needed. + This value will set the size (as in number of Edges or Verts to a block, not the number of bytes) per block. A larger size per + block will result in fewer blocks overall and thus less time spent on memory management, while a smaller block size will + result in less unused allocated memory at any given time, but result in longer processing times since more blocks must be managed. + Default to (100) + + Epsilon: A custom epsilon can be defined for comparisons in this DelaunayTriangulation. If the epsilon is set too small, some rounding + errors can lead to crashes or infinite loops. The default has been tested to work for a large number of cases. If undesired + results are present, try increasing the epsilon slightly. + Default to (3e-13). + + MaxEdgeFlips: The maximum number of Edge flips that will be performed for any call to FlipEdges by the DelaunayTriangulation. + This is important because a Constrained Delaunay Triangulation is not garunteed to be Delaunay since many Edges are + restricted from Edge flips and no extra Vertices (other than intersection points) are created. With this in mind + it is possible for the EdgeFlips to ripple outward from a new constraint for many itterations (which get increasingly + worse with a DelaunayTriangulation with many Edges). To avoid this, MaxEdgeFlips is specified which will constrain + the number of flips the DelaunayTriangulation will use in an attempt to correct the triangulation after inserting a new + constraint. + Defaults to (10000). + + Options: Additional Options may be specified or enabled for this DelaunayTriangulation (several options may be | together). + The Options allowed are: + + - CLIPPING + When Enabled, if a portion of a constraint lies outside of the bounding region, the DelaunayTriangulation will first try clipping + the constraint to see if any portion is inside the DelaunayTriangulation. When Disabled, if ANY portion of the constraint is + outside of the bouning region, the entire constraint will be ignored. + + - FLATTENING + When Enabled, all Z values of points added to this Triangulation will become 0. + + - INTERPOLATE_EDGES + When Enabled, any intersecting constrained Edges will create a new point with a Z value intepolated by the currently inserted + Edge. + + - INTERPOLATE_FACES + When Enabled, any Point inserted into a face, will have its Z value adjusted to match the face. + + + Constraints: + + A constraint is defined as a single Point or a single list of Points that form a line string. When a constraint is inserted into the DT it will force + all the segments of the constraint to appear in the DT regardless if they are Delaunay or not. + + If two constraints are found to intersect or overlap one another, a new Vertex point will be generated at the intersection and placed into the DT to + ensure that both constraints are satisfied. Note that this new Vertex will have a z value determined based on the ZInterpolationOption settings. Upon + removing one of the overlapping constraints, if it is found that the newly created Vertex is no longer necessary, the Vertex will be removed and the + DelaunayTriangulation will be simplified. + + + Insertion: + + WorkingPoint - + + When a working point is inserted, it is a temporary point that will only be gaurunteed to last until the next insertion or removal. + + ConstrainedPoint - + + When a constrained Point is inserted, the only way that point will ever be removed is by calling RemoveConstraint with its unique ID. Note that + ID values are unique even between Point constraints and LineString constraints, so no ID assigned to a Point will ever be given to a LineString or + vice versa. + + ConstrainedLineString - + + A constrained LineString inserts a series of constrained Edges into the DelaunayTriangualtion. The Z values of the constraints are handled by the + settings. + + ConstrainedPolygon - + + A constrained Polygon inserts a series of constrained Edges that form a single closed/simple area. After inserting a Polygon, all points and edges + inside the Polygon are simplified and removed if possible or else interpolated to the Z value of the Polygon by force. In this regard, the Z + interpolation settings are disregarded in this method and the Z values of the Polygon are used always. This method is great for inserting roads + if they already have the z values you want. + + + ConstraintID values: + + When inserting a Constraint, an ID value will always be returned. If this ID is 0, the insertion failed for some reason (the constraint may be outside of + this DelaunayTriangulation). The ID 0 is reserved internally for the boundary of the DelaunayTriangulation and will never be assigned to any constraint + that a user has any control over. + + ID values are unique within this DelaunayTriangulation. No ID assigned to a Point will be shared by any other Point OR LineString OR Polygon. Because of this + there is only one method to remove a constraint. It will determine what type the constraint is based on the ID. + + + Exporting the Data from a DelaunayTriangulation: + + A DelaunayTriangulation is capable of exporting the triangulation at any given moment as either a Subdivision or TIN. + + When retrieving the Subdivision of a DelaunayTriangulation, the actual raw data-structure used by the DelaunayTriangulation system itself will be returned. + This data is fragile and should not be changed outside the scope of the DelaunayTriangulation class itself. If using the Subdivision of a DelaunayTriangulation, + be careful not to change and data within a Vertex or Edge or the DelaunayTriangulation might (and most probably will) break. + + A TIN can also be retrieved. Note that all needed data is copied to the TIN and therefore no access to the original Subdivision is given to the TIN. A TIN can + be used if no topology information is needed. All normals are computed before hand for the TIN while the data is still within the Subdivision. See ctl::TIN for + more information on Creating a TIN out of a DelaunayTriangulation. + + + Linking multiple DelaunayTriangulations together: + + An interface for linking multiple neighbooring DelaunayTriangulations is provided. Note that no linker passes ownership and no memory is shared by either DelaunayTriangulation + (meaning no neighboors are deleted upong this DelaunayTriangulations destruction). Each DelaunayTriangulation has a left, right, up and down neighboor. These neighboors are + used when computing vertex normals + + + This implementation uses the quad-edge data structure presented by Guibas and Stolfi (1985) (See ctl::Subdivision and ctl::Edge for more information), and used + Graphics Gems IV (Paul S. Heckbert) as a reference for some of the basic Delaunay Triangulation code, while referencing a paper by Marcelo Kallmann for strategies + and algorithms for handling constrained edges within a DelaunayTriangulation. + + + Other Notes: + + A DelaunayTriangualtion cannot be copied or assigned due to the delicate data structures that hold the Edges and Vertices. No shared or referance pointer is + typedefed for a DelaunayTriangulation, but it is best to create some form of managed pointer if you plan on using a DelaunayTriangulation outside of a single + scope. + + Usage Examples: + + \code + +// Create the boundary of your triangulation + PointList boundary; + boundary.push_back(Point(0,0)); + boundary.push_back(Point(10,0)); + boundary.push_back(Point(10,10)); + boundary.push_back(Point(0,10)); + +// Create the triangulation + DelaunayTriangulation* DT = new DelaunayTriangulation(boundary); + +// Altering settings +// Disable and Enable clipping + DT->Disable( DelaunayTriangualtion::CLIPPING ); + DT->Enable( DelaunayTriangualtion::CLIPPING ); + +// Insert a working Point + DT->InsertWorkingPoint(Point(5,7,8)); + +// Insert a constrained Point + ID p0_id = DT->InsertConstrainedPoint(Point(5,7,8)); + if (p0_id == 0) + { + //... Handle failed point insertion + } + +// Inserting a constrained LineString or Polygon -> For Polygon the LineString MUST be defined CCW. + PointList points; + points.push_back(1,1,5); + points.push_back(2,1,5); + points.push_back(2,2,5); + points.push_back(2,1,5); + + ID l0_id = DT->InsertConstrainedLineString(points); + if (l0_id == 0) + { + //... Handle failed linestring insertion + } + +// a DT will close your polygon for you if you fail to close it yourself + ID poly0_id = DT->InsertConstrainedPolygon(points); + if (poly0_id == 0) + { + //... Handle failed polygon insertion + } + +// Removing the constraints + DT->RemoveConstraint(p0_id); + DT->RemoveConstraint(l0_id); + DT->RemoveConstraint(poly0_id); + + +// Linking a neighbor DelaunayTriangulation + DelaunayTriangulation *DT_2 = new DelaunayTriangulation( ...some boundary lines up with the right side of DT... ); + bool linked = DT->LinkNeighbor( DelaunayTriangulation::EAST, DT_2 ); + if (!linked) + { + //... Handle failed DelaunayTriangulation linking + } + +// Unlink + DT->UnlinkNeighbor( DelaunayTriangulation::EAST ); + +// Or you can simply wait till one of the DelaunayTriangulations is deleted and the link will be automatically broken. + +// Data Exporting + TIN* tin_all = new TIN(DT); // For entire DelaunayTriangulation ...or... + TIN* tin_some = new TIN( DT, DT->GetBoundedTriangled( ...some area... ) ); // For only the triangles within a given area (tested by point in polygon of their centroids + + delete tin_all; + delete tin_some; + +// Finished using DelaunayTriangulation + delete DT; // If the link still exists, it will be removed now + delete DT_2; + + \endcode + + \sa Fully Dynamic Constrained Delaunay Triangulations (Marcelo Kallmann et. al. 2003) + \sa Graphics Gems IV (Paul S. Heckbert 1994) + \sa Guibas and Stolfi (1985) + */ + class DelaunayTriangulation + { + public: + + enum Option + { + CLIPPING = 0x01, // Enable Constraint Clipping + FLATTENING = 0x02, // Enable Flattening + INTERPOLATE_EDGES = 0x04, // Interpolate Intersections between Constraints using current Constraint. + INTERPOLATE_FACES = 0x08, // Interpolate new face Vertex points using the current face. + VISUAL_DEBUG = 0x10, // Use visual debugging if possible + DISABLE_EDGE_FLIPS = 0x20 // Disable edge flipping. This prevents delaunay enforcement, but saves computations. + }; + + enum Error + { + INVALID_BOUNDARY = 0x01, // An invalid boundary was used to construct this DelaunayTriangulation + CORRUPTION_DETECTED = 0x02, // An unknown error has cased the graph to become corrupt + }; + + protected: + Point origin_; + PointList boundary_; + std::vector neighbors_; + + std::vector boundary_verts; + + double epsilon_; + double areaEpsilon_; + int maxEdgeFlips_; + int settings_; + Subdivision* subdivision_; + ConstraintMap cmap_; + int error_; + + DelaunayBSP *bsp; + + + + public: + +/****************************************************************************************************** + INITIALIZATION +*******************************************************************************************************/ + DelaunayTriangulation + ( + PointList boundary, + int resizeIncriment = 100000, + double epsilon = 1e-6, + double areaEpsilon = 3e-5, + int maxEdgeFlips = 10000, + int settings = CLIPPING + ); + + ~DelaunayTriangulation(void); + + // this removes the boundary vertices so that we can simplify to working points + // adding working points after this may be problematic + void removeBoundaryVerts(void); + + int error(void) const; + +/****************************************************************************************************** + BOUNDARY QUERIES +*******************************************************************************************************/ + +//! \return Returns a Point with the lowest x and y of this DelaunayTriangualtion. Effectively the lower envelope. + Point GetLowerBound(void); + +//! \return Returns a Point with the highest x and y of this DelaunayTriangulation. Effectively the upper envelope. + Point GetUpperBound(void); + +//! \return Returns a PointList of all 4 points ordered counter-clockwise starting at the bottom left. + PointList GetBoundary(void); + +/****************************************************************************************************** + SETTINGS CONTROL +*******************************************************************************************************/ + +//! \return Returns the current epsilon used by this DelaunayTriangulation. + double GetEpsilon(void) const; + +//! \brief Set the current epsilon used by this DelaunayTriangulation. + void SetEpsilon(double newEpsilon); + +//! \brief Returns the current epsilon used to define a collapsed triangle. + double GetAreaEpsilon(void) const; + +//! \brief Set the current epsilon used to define a collapsed triangle. + void SetAreaEpsilon(double newEpsilon); + +//! \return Returns the maximum number of Edge flips allowed per retriangulation in this DelaunayTriangulation. + int GetMaxEdgeFlips(void) const; + +//! \brief Set the maximum number of Edge flips allowed per retriangulation in this DelaunayTriangulation. + void SetMaxEdgeFlips(int MaxEdgeFlips); + +//! \brief Check if an Option is enabled by this DelaunayTriangulation. + bool Enabled(Option option) const; + +//! \brief Enable an Option in this DelaunayTriangulation. + void Enable(Option option); + +//! \brief Disable an Option in this DelaunayTriangulation. + void Disable(Option option); + +/****************************************************************************************************** + SIZE QUERIES +*******************************************************************************************************/ + +//! \return Return the number of Edges in this DelaunayTriangulation. + int GetNumEdges(void); + +//! \return Return the number of Constrained Edges in this DelaunayTriangulation. + int GetNumConstrainedEdges(void); + +//! \return Return the number of Vertices in this DelaunayTriangulation. + int GetNumVertices(void); + +//! \return Return the number of Constrained Vertices in this DelaunayTriangulation. + int GetNumConstrainedVertices(void); + +//! \return Return the number of triangles in this DelaunayTriangulation. +//! Uses a simlpe base computation that is O(1) time to compute an approximation. In order to be exact, +//! the number of boundary edges must be counted, which causes a O(E) check. Avoid calling frequently without rough + int GetNumTriangles(bool rough = true); + +/****************************************************************************************************** + POINT QUERIES +*******************************************************************************************************/ + +//! \return The nearest Point in this DelaunayTriagulation. Returns the same point is outside of this DelaunayTriangulation + Point GetNearestPoint(Point point); + +//! \return The z value of this Point within this DelaunayTriangulation. Interpolated based on the closest Edge or Face. Default if outside + double GetZValue(Point point, double outsideZ = 0); + +/****************************************************************************************************** + INSERTION AND REMOVAL +*******************************************************************************************************/ + protected: + ID InsertConstrainedLineStringPrivate(const PointList& constraint); + ID InsertConstrainedPolygonPrivate(const PointList& constraint); + + public: +//! \brief Inserts a new Point into the DelaunayTriangulation. A Working Point might be "simplified" away and thus its lifetime is unknown. + void InsertWorkingPoint(Point point); + +//! \brief Remove all working points that are inside the given polygon. Removes ALL working points in the polygon is empty. + void RemoveWorkingPoints(const PointList &polygon); + +/*! \brief Inserts a new Point into the DelaunayTriangulation and Constrains the Point. + \return ConstraintID of the inserted Point. 0 if the point could not be inserted. +*/ + ID InsertConstrainedPoint(Point point); + +/*! \brief Inserts a new cosntrained line string list into the DelaunayTriangulation. + + A constrained line string is defined as a collection of ordered points and the segments created by their ordering. + Also adds any needed intersection Points if and only if this constrained line string intersects another already + inserted in the DelaunayTriangulation. The intersection will be handled using the specified Z Interpolation Settings. + + If any portion of the constrained line string is outside of the DelaunayTriangulation, the constrained line string will + be handled using the Constraint Clipping Settings. + \param constraint PointList representing constrained line string to insert. + \return A unique ID representing the newly inserted constraint. 0 if the constraint failed to be inserted for some reason. +*/ + ID InsertConstrainedLineString(PointList constraint); + +/*! \brief Inserts a new constrained polygon into the DelaunayTriangulation. + + A constrained polygon is defined as a closed and simple collection of ordered points. This method is similar to inserting + a constrained line string, only after the boundary of the polygon is inserted, all points found to be inside the polygon + will be either removed or have their z values interpolated and forced by this polygon. + \param constraint PointList representing constrained polygon to insert (the first and last point should be equal). + \return A unique ID representing the newly inserted constraint. 0 if the constraint failed to be inserted for some reason. +*/ + ID InsertConstrainedPolygon(PointList constraint); + +/*! \brief Removes a constraint with the ID given. + + Will do nothing if no constraint with the given ID is found. + \param constraintID ID of the constraint to remove from this DelaunayTriangulation. +*/ + void RemoveConstraint(ID constraintID); + +/****************************************************************************************************** + DATA STRUCTURE EXPORTING +*******************************************************************************************************/ + public: +//! \return Returns the ConstraintMap of this DelaunayTriangulation. + const ConstraintMap* GetConstraintMap(void) const; + +//! \return Returns the Subdivision of this DelaunayTriangulation. + const Subdivision* GetSubdivision(void) const; + +/****************************************************************************************************** + NEIGHBOOR OPERATIONS +*******************************************************************************************************/ + public: +/*! \brief Link two DelaunayTriangulations together along their boundaries. + + Two Neighboor boundaries can only be linked if they both contain identical boundaries. + - The boundaries extend along the same line through space (including z values). + - The boundaries must have the same points along each other (including z values). + + Once linked, any changes along the boundary of one DelaunayTriangulation will be reflected in the other. + Note that this also means that a working point will never be deleted from one DelaunayTriangulation if it + is a Constrained point of the other DelaunayTriangulation. + + Destroying a DelaunayTriangulation will automatically undo any links that have been created to it. + \param location Location on this triangulation to link. + \param dt DelaunayTriangulation to link to this one. + \param dt_location Location on other triangulation to link to. + \return TRUE if linking was a success, FALSE otherwise. +*/ + bool LinkNeighbor(size_t location, DelaunayTriangulation* dt, size_t dt_location); + +//! \brief Remove any neighbor linking along the passed location. + void UnlinkNeighbor(size_t Location); + +//! \return TRUE if the Vertex lies on the boundary. + bool IsBoundaryVertex(Vertex* vert); + +//! \return TRUE if the Vertex is on the passed boundary. (If NONE, TRUE is returned). + bool IsBoundaryVertex(Vertex* vert, size_t Location); + +//! \return Returns TRUE if an Edge is part of the boundary. + bool IsBoundaryEdge(Edge* edge); + +//! \return Returns TRUE if an Edge is part of the passed boundary. (If NONE, TRUE is returned). + bool IsBoundaryEdge(Edge* edge, size_t Location); + +//! \return Returns the true Vertex normal of a Vertex in this DelaunayTriangulation. Will factor in linked DelaunayTriangulations if present. + Vector GetVertexNormal(Vertex* vert); + +/****************************************************************************************************** + POINT AND TRIANGLE GATHERING ALGORITHMS +*******************************************************************************************************/ + protected: + void GatherConstraintEdges(Edge* edge, std::vector& edges, bool* marked, ID constraintID); +//! \brief Collects all the edges that cross a line between vertics a and b +// It can select constrained and/or unconstrained edges + std::vector GetCrossingEdges(Vertex* a, Vertex* b, bool bound, bool unbound); + std::vector GetTouchingVerts(Vertex* a, Vertex* b); + +//! \brief Collects all the vertices, it can select the working and/or the constrained vertices. + std::vector GatherVertsLocal(const PointList &polygon, bool constrained, bool working); + public: + +//! \return Returns all vertices. If a non-empty polygon is given, only vertices inside it will be returned. + std::vector GatherVerts(PointList polygon); + +//! \return Returns all working Points. If a non-empty polygon is given, only vertices inside it will be returned. + std::vector GatherWorkingVerts(PointList polygon); + +//! \return Returns all bound vertices. If a non-empty polygon is given, only vertices inside it will be returned. + std::vector GatherConstrainedVerts(PointList polygon); + +//! \return Returns all triangles. If a non-empty polygon is given, only triangles with centroids inside the polygon will be returned. (Triangles are on the left of each Edge) + std::vector GatherTriangles(PointList polygon); + +/****************************************************************************************************** + BOOLEAN FUNCTIONS +*******************************************************************************************************/ + protected: + bool IsRight(Vector vert, Vector a, Vector b); + bool IsRight(Vector vert, Edge* edge); + bool IsLeft(Vector vert, Vector a, Vector b); + bool IsLeft(Vector vert, Edge* edge); + int IsOn(Vector vert, Vector p0, Vector p1); + int IsOn(Vector vert, Edge* edge); + bool InCircle(Vector a, Vector b, Vector c, Vector d); + bool IsFlipValid(Edge* edge); + bool IsDelaunay(Vector p, Edge* edge); + bool IsInside(Point point); + bool IsInside(const PointList &points); + bool Touches(const PointList &points); + +/****************************************************************************************************** + SUBDIVISION INTERFACE +*******************************************************************************************************/ + Edge* Connect(Vertex* a, Vertex* b); + Edge* GetConnection(Vertex* a, Vertex* b); + Edge* GetLeftEdge(Vertex* a, Vector p); + void Swap(Edge* edge); + void RemoveEdge(Edge* edge); + void RemoveVertex(Vertex* vert); + +/****************************************************************************************************** + SEARCH AND INTERSECTION +*******************************************************************************************************/ + LocationResult LocatePoint(Point p, Edge* edge = NULL); + Point Intersection(Edge* edge, Point c, Point d); + void InterpolateZ(Vector O, Vector U, Vector V, Vertex* vert); + +/****************************************************************************************************** + INSERTION +*******************************************************************************************************/ + Vertex* SnapPointToVertex(const Point& p); + Vertex* SnapPointToEdge(const Point& p); + Vertex* InsertPoint(Point p); + Vertex* InsertPointInEdge(Point p, Edge* edge); + Vertex* InsertPointInBoundary(Point p, Edge* edge); + Vertex* InsertPointInFace(Point p, Edge* edge); + void SimplifyEdges(Vertex* vert); + bool IsSimplifyValid(Vertex* vert); + void FlipEdges(Point p, Edge* base); + void InsertSegment(Vertex* a, Vertex* b, ID constraintID); + void RetriangulateFace(Edge* base); + +/****************************************************************************************************** + PROJECTION +*******************************************************************************************************/ + public: +//! Transforms a point from the global coordinate system to the local coordinate system + Point TransformPointToLocal(const Point& p) const; + +//! Transforms a point from the local coordinate system to the global coordinate system + Point TransformPointToGlobal(const Point& p) const; + +/****************************************************************************************************** + Mesh Simplification +*******************************************************************************************************/ + private: + float ComputeVertexError(Vertex* vert) const; + + public: +//! Simplify this DelaunayTriangulation by removing working points until the targetFaces have been reached +//! or until no other points can be removed. (No points with a saliency greater than threshold will be removed). + void Simplify(int targetFaces, float threshold); + + }; + +} \ No newline at end of file diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Edge.cpp b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Edge.cpp new file mode 100644 index 000000000..d5f953969 --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Edge.cpp @@ -0,0 +1,65 @@ +/**************************************************************************** +Copyright 2017, Cognitics Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ +#include "Edge.h" +#include "Vertex.h" + +namespace ctl { + + void Edge::Splice(Edge* a, Edge* b) + { + Edge* alpha = a->Onext()->Rot(); + Edge* beta = b->Onext()->Rot(); + + Edge* temp1 = b->Onext(); + Edge* temp2 = a->Onext(); + Edge* temp3 = beta->Onext(); + Edge* temp4 = alpha->Onext(); + + a->next = temp1; + b->next = temp2; + alpha->next = temp3; + beta->next = temp4; + } + + ID Edge::getID(void) const + { + return id; + } + + void Edge::setOrg(Vertex* vert) + { + point = vert; + if (vert != (Vertex*)0 && vert != (Vertex*)1) vert->addEdge(this); + } + + void Edge::setDest(Vertex* vert) + { + Sym()->setOrg(vert); + } + + void Edge::setEndPoints(Vertex* org, Vertex* dest) + { + setOrg(org); + setDest(dest); + } + +} \ No newline at end of file diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Edge.h b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Edge.h new file mode 100644 index 000000000..30c776a92 --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Edge.h @@ -0,0 +1,166 @@ +/**************************************************************************** +Copyright 2017, Cognitics Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ +/*! \file ctl/Edge.h +\headerfile ctl/Edge.h +\brief Provides ctl::Edge. +\author Joshua Anghel +*/ +#pragma once + +#include "ID.h" + +namespace ctl { + + class Vertex; + class Edge; + class Subdivision; + +/*! \class ctl::Edge ctl/Edge.h ctl.Edge.h + * \brief Edge + * + * A single directed Edge from one Vertex to another. Stores minimalistic information about adjacent Edges to allow + * Edge traversal in constant time. (Next and Previous Edge about the same Origin. +*/ + class Edge + { + friend class Subdivision; + + private: + ID id; + unsigned char num; + Vertex* point; + Edge* next; + + public: + Edge(void) { } + ~Edge(void) { } + + public: + +/*! \brief Splice two Edges together or apart. + * + * This operator affects the two edge rings around the origins of a and b, and , independently, the two edge + * rings around the left faces of a and b. In each case, (i) if the two rings are distinct, Splice will combine + * them into one; (ii) if the two are the same ring, Splice will break it into two separate pieces. + * Thus, Splice can be used both to attach the two edges together and to break them apart. + * + * \sa Guibus and Stolfi (1985 p.96) + * \param a First non-null Edge to Splice. + * \param b Second non-null Edge to Splice. + */ + static void Splice(Edge* a, Edge* b); + +/*! \brief Get the ID value shared by this Edge and all its sibling QuadEdge Edges. + * \return ID value of this Edge. + */ + ID getID(void) const; + +/*! \brief Set the origin Vertex of this Edge. + * \param vert Vertex to set Org to. + */ + void setOrg(Vertex* vert); + +/*! \brief Set the destination Vertex of this Edge. + * \param vert Vertex to set Dest to. + */ + void setDest(Vertex* vert); + +/*! \brief Simultaneously set the origin and destination Vertices of this Edge. + * \param org Vertex to set Org to. + * \param dest Vertex to set Dest to. + */ + void setEndPoints(Vertex* org, Vertex* dest); + +/*! \brief Returns the origin of this Edge. + * \return Origin of this Edge. + */ + inline Vertex* Org(void) { return point; } + +/*! \brief Returns the destination of this Edge. + * + * Equivalent to Sym()->Org() + * \return Destination of this Edge. + */ + inline Vertex* Dest(void) { return Sym()->point; } + +/* ================================================================================ */ +/* Edge Traversal Operators */ +/* ================================================================================ */ + +/*! \brief Returns the dual-edge pointing to the right. + * \return Dual-Edge pointing from the left face to the right face. + */ + Edge* Rot(void) { return (num < 3) ? this + 1 : this - 3; } + +/*! \brief Returns the Dual-Edge pointing to the left. + * \return Dual-Edge pointing from the right face to the left face. + */ + inline Edge* invRot(void) { return (num > 0) ? this - 1 : this + 3; } + +/*! \brief Returns the Edge symmetric to this one. + * \return Edge symmetric to this one. + */ + inline Edge* Sym(void) { return (num < 2) ? this + 2 : this - 2; } + +/*! \brief Returns the next Edge about the origin with the same origin. + * \return Next Edge about the origin with the same origin. + */ + inline Edge* Onext(void) { return next; } + +/*! \brief Returns the previous Edge about the origin with the same origin. + * \return Previous Edge about the origin with the same origin. + */ + inline Edge* Oprev(void) { return Rot()->Onext()->Rot(); } + +/*! \brief Returns the next Edge about the Right face with the same right face. + * \return Next Edge about the right face with the same right face. + */ + inline Edge* Rnext(void) { return Rot()->Onext()->invRot(); } + +/*! \brief Returns the previous Edge about the Right face with the same right face. + * \return Previous Edge about the right face with the same right face. + */ + inline Edge* Rprev(void) { return Sym()->Onext(); } + +/*! \brief Returns the next Edge about the destination with the same desination. + * \return Next Edge about the destination with the same destination. + */ + inline Edge* Dnext(void) { return Sym()->Onext()->Sym(); } + +/*! \brief Returns the previous Edge about the destination with the same destination. + * \return Previous Edge about the destination with the same destination. + */ + inline Edge* Dprev(void) { return invRot()->Onext()->invRot(); } + +/*! \brief Returns the next Edge about the left face with the same left face. + * \return Next Edge about the left face with the same left face. + */ + inline Edge* Lnext(void) { return invRot()->Onext()->Rot(); } + +/*! \brief Returns the previous Edge about the left face with the same left face. + * \return Previous Edge about the left face with the same left face. + */ + inline Edge* Lprev(void) { return Onext()->Sym(); } + + }; + +} \ No newline at end of file diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/source/ID.cpp b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/ID.cpp new file mode 100644 index 000000000..e7f910b46 --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/ID.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** +Copyright 2017, Cognitics Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ +#include "ID.h" + +namespace ctl { + + IDGenerator::IDGenerator(void) + { + AvailableIDs.push_back(0); + } + + ID IDGenerator::getID(void) + { + if (AvailableIDs.size() > 1) + { + ID id = AvailableIDs.back(); + AvailableIDs.pop_back(); + return id; + } + else + return (AvailableIDs.front()++); + } + + void IDGenerator::freeID(ID id) + { + AvailableIDs.push_back(id); + } + + bool IDGenerator::isIDUsed(ID id) const + { + for (int i = int(AvailableIDs.size())-1; i > 0; i--) + { + if (id == AvailableIDs[i]) return false; + } + if (id < AvailableIDs[0]) return true; + else return false; + } + + unsigned int IDGenerator::numUsedIDs(void) const + { + return AvailableIDs.front() - ((unsigned int)AvailableIDs.size()) + 1; + } + + unsigned int IDGenerator::numFreeIDs(void) const + { + return (unsigned int)(AvailableIDs.size()) - 1; + } + + unsigned int IDGenerator::peekNextID(void) const + { + return AvailableIDs[0]; + } + +} diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/source/ID.h b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/ID.h new file mode 100644 index 000000000..41a3b4124 --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/ID.h @@ -0,0 +1,81 @@ +/**************************************************************************** +Copyright 2017, Cognitics Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ +/*! \brief Provides ctl::IDGenerator +\author Joshua Anghel +*/ +#pragma once + +#include + +namespace ctl { + + typedef unsigned int ID; + typedef std::vector IDList; + +/*! \brief IDGenerator + +Provides a structure to maintain the allocation of unique int ID values to ensure keys are +always unique and to ensure the lowest ID values possible are used, so they can also double as index +values into an array if needed. + +The first ID value recieved when calling getID() for the first time after initialization is 0. +When feeID() is called, it places the newly available ID at the top of the stack and will be returned +on the next call to getID(). +*/ + class IDGenerator + { + private: + IDList AvailableIDs; + + public: + IDGenerator(void); + ~IDGenerator(void) { } + +/*! \brief Return a unique ID from this IDGenerator. + * \return Unique ID from this IDGenerator. + */ + ID getID(void); + +/*! \brief Free an ID to be used by this IDGenerator again. + * \param id ID to release for reassignment. + */ + void freeID(ID id); + + bool isIDUsed(ID id) const; + +/*! \brief Get the number of IDs currently in use. + * \return The number of IDs currently in use. + */ + unsigned int numUsedIDs(void) const; + +/*! \brief Get the number of IDs currently free to the IDGenerator. + * + * Does not count the next (highest available) + * \return The number of IDs that have been manually freed to the IDGenerator. + */ + unsigned int numFreeIDs(void) const; + + // get the next id (highest available, not a replacement) + unsigned int peekNextID(void) const; + }; + +} \ No newline at end of file diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/source/LocationResult.cpp b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/LocationResult.cpp new file mode 100644 index 000000000..108e5e852 --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/LocationResult.cpp @@ -0,0 +1,54 @@ +/**************************************************************************** +Copyright 2017, Cognitics Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ +#include "LocationResult.h" + +namespace ctl { + + LocationResult::LocationResult(void) : edge(0), type(LR_UNKNOWN) + { + } + + LocationResult::LocationResult(const LocationResult &rhs) : edge(rhs.edge), type(rhs.type) + { + } + + LocationResult &LocationResult::operator=(const LocationResult &rhs) + { + if(this != &rhs) + { + edge = rhs.edge; + type = rhs.type; + } + return *this; + } + + LocationResultType LocationResult::getType(void) + { + return type; + } + + Edge* LocationResult::getEdge(void) + { + return edge; + } + +} \ No newline at end of file diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/source/LocationResult.h b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/LocationResult.h new file mode 100644 index 000000000..0f3550ac4 --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/LocationResult.h @@ -0,0 +1,75 @@ +/**************************************************************************** +Copyright 2017, Cognitics Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ +/*! \file ctl/LocationResult.h +\headerfile ctl/LocationResult.h +\brief Provides ctl::LocationResult. +\author Joshua Anghel +*/ +#pragma once + +#include "Edge.h" + +namespace ctl { + + enum LocationResultType + { + LR_UNKNOWN = -1, + LR_VERTEX = 0, + LR_EDGE = 1, + LR_FACE = 2 + }; + +/*! \class ctl::LocationResult ctl/LocationResult.h ctl/LocationResult.h +\brief LocationResult + +A LocationResult provides information on the location of a Point in a QuadEdge and is used to quickly pass this +information between function calls in various algorithms. +*/ + class LocationResult + { + protected: + Edge* edge; + LocationResultType type; + + public: + LocationResult(Edge* e, LocationResultType t) : edge(e), type(t) { } + LocationResult(void); + LocationResult(const LocationResult &rhs); + LocationResult &operator=(const LocationResult &rhs); + ~LocationResult(void) { } + +/*! \brief Return the LocationResultType of this LocationResult. +\return LocationResultType of this LocationResult. +*/ + LocationResultType getType(void); + +/*! \brief Return the Edge representing the location of this LocationResult. + +If the LocationResultType is LR_VERTEX, the location is the origin of the Edge. +If the LocationResultType is LR_EDGE, the Location is the Edge. +If the LocationResultType is LR_FACE, the Location is the face to the left of the Edge. +\return Edge representing the Location of this LocationResult. +*/ + Edge* getEdge(void); + }; + +} \ No newline at end of file diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/source/QTriangulate.cpp b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/QTriangulate.cpp new file mode 100644 index 000000000..e10f296f9 --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/QTriangulate.cpp @@ -0,0 +1,110 @@ +/**************************************************************************** +Copyright 2017, Cognitics Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ +#include "QTriangulate.h" +#include "Util.h" + +namespace ctl { + + bool QTriangulate::snip(PointList contour, int u, int v, int w, int n, const std::vector& V, const Point& normal) + { + Point A = contour[V[u]]; + Point B = contour[V[v]]; + Point C = contour[V[w]]; + + if ( (B-A).cross(C-A).dot(normal) < 1e-10 ) + return false; + //TArea3D(A,B,C) < 1e-10) return false; + + for (int p = 0; p < n; p++) + { + if ( (p==u) || (p==v) || (p==w) ) continue; + Point P = contour[V[p]]; + + Vector v0 = C - A; + Vector v1 = B - A; + Vector v2 = P - A; + + double dot00 = v0 * v0; + double dot01 = v0 * v1; + double dot02 = v0 * v2; + double dot11 = v1 * v1; + double dot12 = v1 * v2; + + double invDenom = 1.0/ (dot00 * dot11 - dot01 * dot01); + double u = (dot11 * dot02 - dot01 * dot12) * invDenom; + double v = (dot00 * dot12 - dot01 * dot02) * invDenom; + + if ((u >= 0) && (v >= 0) && (u + v <= 1)) + return false; + } + + return true; + } + + PointList QTriangulate::apply(PointList contour) + { + int n = int(contour.size()); + if (n < 3) return PointList(); + + PointList result; + std::vector V(n); + + Point normal; + for (int i = 0; i < n; i++) + { + Point v0 = contour[i]; + Point v1 = contour[(i+1)%n]; + normal[0] += (v0.y - v1.y)*(v0.z + v1.z); + normal[1] += (v0.z - v1.z)*(v0.x + v1.x); + normal[2] += (v0.x - v1.x)*(v0.y + v1.y); + } + + for (int v = 0; v < n; v++) V[v] = v; + + int nv = n; + int count = 2*nv; + + for (int v = nv-1; nv>2;) + { + if (0 >= (count--)) // Bad polygon + return PointList(); + + int u = v; if (nv <= u) u = 0; + v = u+1; if (nv <= v) v = 0; + int w = v+1; if (nv <= w) w = 0; + + if (snip(contour,u,v,w,nv,V,normal)) + { + result.push_back(contour[V[u]]); + result.push_back(contour[V[v]]); + result.push_back(contour[V[w]]); + for (int s = v, t=v+1; t& V, const Point& normal); + + public: + static PointList apply(PointList contour); + }; + +} \ No newline at end of file diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/source/QuadEdge.cpp b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/QuadEdge.cpp new file mode 100644 index 000000000..18a683068 --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/QuadEdge.cpp @@ -0,0 +1,21 @@ +/**************************************************************************** +Copyright 2017, Cognitics Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/source/QuadEdge.h b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/QuadEdge.h new file mode 100644 index 000000000..18a683068 --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/QuadEdge.h @@ -0,0 +1,21 @@ +/**************************************************************************** +Copyright 2017, Cognitics Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Subdivision.cpp b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Subdivision.cpp new file mode 100644 index 000000000..9e77a8845 --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Subdivision.cpp @@ -0,0 +1,216 @@ +/**************************************************************************** +Copyright 2017, Cognitics Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ +#include "Subdivision.h" + +namespace ctl { + +//! Allocate more memory for Vertices + void Subdivision::allocVerts(void) + { + int start = int(verts.size()); + Block* _verts = new Block(resizeIncriment); + verts.PushBlock(_verts); + vertFlags.resize(start + resizeIncriment, false); + + for (unsigned int i = 0; i < resizeIncriment; i++) + _verts->data[i].id = start + i; + } + +//! Allocate more memory for Edges + void Subdivision::allocEdges(void) + { + int start = int(edges.size()/4); + Block* _edges = new Block(4*resizeIncriment); + edges.PushBlock(_edges); + edgeFlags.resize(start + resizeIncriment, false); + + for (size_t i = 0; i < resizeIncriment; i++) + { + _edges->data[ 4*i + 0 ].id = static_cast(start + i); + _edges->data[ 4*i + 1 ].id = static_cast(start + i); + _edges->data[ 4*i + 2 ].id = static_cast(start + i); + _edges->data[ 4*i + 3 ].id = static_cast(start + i); + _edges->data[ 4*i + 0 ].num = 0; + _edges->data[ 4*i + 1 ].num = 1; + _edges->data[ 4*i + 2 ].num = 2; + _edges->data[ 4*i + 3 ].num = 3; + } + } + + Subdivision::Subdivision(int _resizeIncriment) + { + resizeIncriment = _resizeIncriment; + allocVerts(); + allocEdges(); + } + + int Subdivision::getMaxVerts(void) const + { + return vertIDGen.peekNextID(); + } + + int Subdivision::getNumVerts(void) const { + return vertIDGen.numUsedIDs(); + } + + Vertex* Subdivision::getVertex(ID id) { + return vertFlags[id] ? verts[id] : NULL; + } + + Vertex* Subdivision::getRandomVertex(void) + { + if (getNumVerts() == 0) return NULL; + + int max = getMaxVerts(); + int n = rand()%max; + for (int i = 0; i < max; i++) + { + Vertex* vert = getVertex(n); + if (vert) + return vert; + else + n = (n+1)%max; + } + return NULL; + } + + Vertex* Subdivision::CreateVertex(Point point) + { + ID id = vertIDGen.getID(); + if (int(id) >= verts.size()) + allocVerts(); + vertFlags[id] = true; + Vertex* vert = verts[id]; + vert->clearEdge(); + vert->point = point; + return vert; + } + + void Subdivision::RemoveVertex(Vertex* vert) + { + if (!vert) return; + + vertFlags[vert->getID()] = false; + vertIDGen.freeID(vert->getID()); + + Edge* edge = vert->getEdges(); + if (edge) + { + Edge* next = edge; + do + { + next->setOrg(NULL); + next = next->Onext(); + } while (next != edge); + } + } + + int Subdivision::getMaxEdges(void) const { + return edgeIDGen.peekNextID(); + } + + int Subdivision::getNumEdges(void) const { + return edgeIDGen.numUsedIDs(); + } + + Edge* Subdivision::getEdge(ID id) { + return edgeFlags[id] ? edges[4*id] : NULL; + } + + Edge* Subdivision::getRandomEdge(void) + { + if (getNumEdges() == 0) return NULL; + + int max = getMaxEdges(); + int n = rand()%max; + for (int i = 0; i < max; i++) + { + Edge* edge = getEdge(n); + if (edge) + return edge; + else + n = (n+1)%max; + } + return NULL; + } + + Edge* Subdivision::CreateEdge(Vertex* a, Vertex* b) + { + ID id = edgeIDGen.getID(); + if (int(4*id) >= edges.size()) + allocEdges(); + edgeFlags[id] = true; + Edge* e0 = edges[ 4*id + 0 ]; + Edge* e1 = edges[ 4*id + 1 ]; + Edge* e2 = edges[ 4*id + 2 ]; + Edge* e3 = edges[ 4*id + 3 ]; + e0->next = e0; + e1->next = e3; + e2->next = e2; + e3->next = e1; + e0->setEndPoints(a,b); + e1->point = NULL; + e3->point = NULL; + return e0; + } + + void Subdivision::RemoveEdge(Edge* edge) + { + if (!edge) return; + + if (edge->Org()) edge->Org()->removeEdge(edge); + if (edge->Dest()) edge->Dest()->removeEdge(edge->Sym()); + Edge::Splice(edge,edge->Oprev()); + Edge::Splice(edge->Sym(),edge->Sym()->Oprev()); + + edgeIDGen.freeID( edge->getID() ); + edgeFlags[edge->getID()] = false; + } + + Edge* Subdivision::Connect(Edge* a, Edge* b) + { + Edge* edge = CreateEdge( a->Dest() , b->Org() ); + if (!edge) return NULL; + + Splice(edge,a->Lnext()); + Splice(edge->Sym(),b); + + return edge; + } + + void Subdivision::Splice(Edge* a, Edge* b) + { + Edge* alpha = a->Onext()->Rot(); + Edge* beta = b->Onext()->Rot(); + + Edge* temp1 = b->Onext(); + Edge* temp2 = a->Onext(); + Edge* temp3 = beta->Onext(); + Edge* temp4 = alpha->Onext(); + + a->next = temp1; + b->next = temp2; + alpha->next = temp3; + beta->next = temp4; + } + +} \ No newline at end of file diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Subdivision.h b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Subdivision.h new file mode 100644 index 000000000..00a62539d --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Subdivision.h @@ -0,0 +1,156 @@ +/**************************************************************************** +Copyright 2017, Cognitics Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ +/*! \file ctl/Subdivision.h +\headerfile ctl/Subdivision.h +\brief Provides ctl::Subdivision. +\author Joshua Anghel +*/ +#pragma once + +#include "Edge.h" +#include "Vertex.h" +#include "BlockList.h" + +namespace ctl { + +/*! \class ctl::Subdivision ctl/Subdivision.h ctl/Subdivision.h + \brief Subdivision + + Provides a class for storing Edges and Vertex points assossiated with a quad-edge system. + Assigns unique IDs to all Vertices and Edges and stores them in lists using they ID values as index values into the lists. + Automatically cleans up and used memory by all Vertices and Edges owned by it upon destruction. + Stores Edges and Vertices as blocks of data. When an Edge or Vertex is "deleted" it it instead flagged as inactive + and that memory will be used to construct future Edges/Vertices. This avoids constant calls to new/delete and avoids + fragmentation. + + Based on Guibus and Stolfi's quad-edge stucture and the code presented in Graphics Gems IV (Paul S. Heckbert). + \sa Guibus and Stolfi (1985 p.96) + \sa Graphics Gems IV (Paul S. Heckbert pg. 51) + */ + class Subdivision + { + private: + typedef BlockList EdgeList; + typedef BlockList VertexList; + + size_t resizeIncriment; //!< amount to resize a BlockList by on growth + + IDGenerator vertIDGen; //!< IDGenerator tracking ID's of active vertices + std::vector vertFlags; //!< flags indicating which vertices are active + VertexList verts; //!< container to store all vertices (active and non-active) + + IDGenerator edgeIDGen; //!< IDGenerator tracking ID's of active edges + std::vector edgeFlags; //!< flags indicating which edges are active + EdgeList edges; //!< container to store all edges (active and non-active) + + void allocVerts(void); + void allocEdges(void); + + public: + Subdivision(int resizeIncriment = 100); + ~Subdivision(void) { } + +/****************************************************************************************************** + VERTICES +*******************************************************************************************************/ + +//! \return Returns the maximum number of Vertices stored by this Subdivision. + int getMaxVerts(void) const; + +//! \return Returns the number of active Vertices in this Subdivision. + int getNumVerts(void) const; + +/*! \brief Return the Vertex with ID id in this Subdivision. + \param id ID value of Vertex to retrieve. + \return Vertex with ID value of id, NULL if that Vertex doesn't exist +*/ + Vertex* getVertex(ID id); + +//! \return Returns a random Vertex in this Subdivision. + Vertex* getRandomVertex(void); + +/*! \brief Create a Vertex within this Subdivision. + \param point Point to create Vertex at. + \return Pointer to new Vertex inside this Subdivision. +*/ + Vertex* CreateVertex(Point point = Point()); + +/*! \brief Free the memory used by a Vertex in this Subdivision. + \param vert Vertex to free. +*/ + void RemoveVertex(Vertex* vert); + +/****************************************************************************************************** + EDGES +*******************************************************************************************************/ + +//! \return Returns the maxmimum number of Edges stored by this Subdivision. + int getMaxEdges(void) const; + +//! \return Returns the number of active Edges in this Subdivision. + int getNumEdges(void) const; + +/*! \brief Return the Edge with ID id in this Subdivision. + \param id ID value of Edge to retrieve. + \return Edge with ID value of id, NULL if that Edge doesn't exist. +*/ + Edge* getEdge(ID id); + +//! \return A random Edge within this Subdivision. + Edge* getRandomEdge(void); + +/*! \brief Create a Edge in this Subdivision. + \param a Origin of new Edge. + \param b Destination of new Edge. + \return New Edge pointer. +*/ + Edge* CreateEdge(Vertex* a = NULL, Vertex* b = NULL); + +/*! \brief Free the memory used by an Edge in this Subdivision. + \param edge Edge to free. +*/ + void RemoveEdge(Edge* edge); + +/*! \brief Connects the destination of a to the origin of b. + Add a new Edge connecting the destination of a to the origin of b, in such a way that all three + have the same left face after the connection is complete. + \param a Destination of which will be the origin of the new Edge. + \param b Origin of which will be the destination of the new Edge. + \return A new Edge from the desination of a to the origin of b, NULL if not enough memory. +*/ + Edge* Connect(Edge* a, Edge* b); + +/*! \brief Splice two Edges together or apart. + * + * This operator affects the two edge rings around the origins of a and b, and , independently, the two edge + * rings around the left faces of a and b. In each case, (i) if the two rings are distinct, Splice will combine + * them into one; (ii) if the two are the same ring, Splice will break it into two separate pieces. + * Thus, Splice can be used both to attach the two edges together and to break them apart. + * + * \sa Guibus and Stolfi (1985 p.96) + * \param a First non-null Edge to Splice. + * \param b Second non-null Edge to Splice. + */ + void Splice(Edge* a, Edge* b); + }; + +} \ No newline at end of file diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/source/TIN.cpp b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/TIN.cpp new file mode 100644 index 000000000..18cf0fda0 --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/TIN.cpp @@ -0,0 +1,156 @@ +/**************************************************************************** +Copyright 2017, Cognitics Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ +#include "TIN.h" +#include "Util.h" +#include +#include + +namespace ctl { + + struct TriangleKey { + ID a; + ID b; + ID c; + + TriangleKey(void) + { + a = 0; + b = 0; + c = 0; + } + + TriangleKey(ID id1, ID id2, ID id3) + { + a = id1; + b = id2; + c = id3; + + if (a < b) + std::swap(a, b); + if (b < c) + std::swap(b, c); + if (a < b) + std::swap(a, b); + } + + bool operator<(const TriangleKey& other) const + { + if (a < other.a) + return true; + else if (a > other.a) + return false; + else if (b < other.b) + return true; + else if (b > other.b) + return false; + else if (c < other.c) + return true; + else if (c > other.c) + return false; + else + return false; + } + }; + + TIN::TIN(DelaunayTriangulation* DT) + { + CreateFromDT(DT,DT->GatherTriangles(PointList())); + } + + TIN::TIN(DelaunayTriangulation* DT, const std::vector &triangle_edges) + { + CreateFromDT(DT,triangle_edges); + } + + void TIN::CreateFromDT(DelaunayTriangulation* DT, const std::vector &triangle_edges) + { + const Subdivision* graph = DT->GetSubdivision(); + verts.resize(graph->getMaxVerts()); + normals.resize(graph->getMaxVerts()); + + ID invalid = graph->getMaxEdges(); + IDList VertexIDMap(invalid,invalid); + + int nextIndex = 0; + for (unsigned int i = 0 ; i < triangle_edges.size(); i++) + { + //For each vertex test if its already included (invalid means its not) + Vertex* a = triangle_edges[i]->Org(); + Vertex* b = triangle_edges[i]->Dest(); + Vertex* c = triangle_edges[i]->Onext()->Dest(); + + if ( VertexIDMap[a->getID()] == invalid ) + { + verts[nextIndex] = DT->TransformPointToGlobal(a->point); + normals[nextIndex] = DT->GetVertexNormal(a); + VertexIDMap[a->getID()] = nextIndex; + nextIndex++; + } + + if ( VertexIDMap[b->getID()] == invalid ) + { + verts[nextIndex] = DT->TransformPointToGlobal(b->point); + normals[nextIndex] = DT->GetVertexNormal(b); + VertexIDMap[b->getID()] = nextIndex; + nextIndex++; + } + + if ( VertexIDMap[c->getID()] == invalid ) + { + verts[nextIndex] = DT->TransformPointToGlobal(c->point); + normals[nextIndex] = DT->GetVertexNormal(c); + VertexIDMap[c->getID()] = nextIndex; + nextIndex++; + } + } + + // Resize Verts and normals array back to true size + verts.resize(nextIndex); + normals.resize(nextIndex); + + std::set processedEdges; + + // Add triangles + for (unsigned int i = 0; i < triangle_edges.size(); i++) + { + Edge* next = triangle_edges[i]; + + if (processedEdges.count(next) == 0) + { + processedEdges.insert(next); + processedEdges.insert(next->Lnext()); + processedEdges.insert(next->Lprev()); + + Vertex* a = next->Org(); + Vertex* b = next->Lnext()->Org(); + Vertex* c = next->Lprev()->Org(); + + if (abs(TArea2D(a->point, b->point, c->point)) > DT->GetAreaEpsilon()) + { + triangles.push_back(VertexIDMap[ a->getID() ]); + triangles.push_back(VertexIDMap[ b->getID() ]); + triangles.push_back(VertexIDMap[ c->getID() ]); + } + } + } + } +} \ No newline at end of file diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/source/TIN.h b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/TIN.h new file mode 100644 index 000000000..9e5d05536 --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/TIN.h @@ -0,0 +1,77 @@ +/**************************************************************************** +Copyright 2017, Cognitics Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ +/*! \file ctl/TIN.h +\headerfile ctl/TIN.h +\brief Provides ctl::TIN. +\author Joshua Anghel +*/ +#pragma once + +#include "Subdivision.h" +#include "DelaunayTriangulation.h" + + +namespace ctl { + +/*! \class ctl::TIN ctl/TIN.h ctl/TIN.h + * \brief TIN + * + * Provides a basic TIN data structure. + * Stores two Vector lists for points and their normals. + * Triangles are stored as a single IDList. + * Each 3 consecutive IDs in the list represents the locations of a single triangle's Vertex points inside + * the verts and normals lists. + * Triangles are stored CCW. + * + * Triangles can be created using the following code: + * + * \code + * for (int i = 0; i < int(tin.triangles.size()/3); i++) + * { + * Point a = tin.verts[tin.triangles[i*3 + 0]]; + * Point b = tin.verts[tin.triangles[i*3 + 1]]; + * Point c = tin.verts[tin.trianlges[i*3 + 2]]; + * + * // Normals are retrieved the same way, but call tin.normals[] instead of tin.verts[] + * // ..insert triangle handing code here + * } + * \endcode + */ + class TIN + { + public: + PointList verts; + std::vector normals; + IDList triangles; + + TIN(void) { } + + TIN(DelaunayTriangulation* DT); + + TIN(DelaunayTriangulation* DT, const std::vector &triangle_edges); + + ~TIN(void) { } + void CreateFromDT(DelaunayTriangulation* DT, const std::vector &triangle_edges); + + }; + +} \ No newline at end of file diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Util.cpp b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Util.cpp new file mode 100644 index 000000000..dc7af3058 --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Util.cpp @@ -0,0 +1,294 @@ +/**************************************************************************** +Copyright 2017, Cognitics Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ +#include "Util.h" + +namespace ctl { + +/****************************************************************************************************** + POINT OPERATIONS +*******************************************************************************************************/ + + PointLineLocation LocatePointOnLine(const Point& p, const Point& a, const Point& b, double epsilon) + { + Vector u = b - a; + Vector v = p - a; + + double du = abs(u.x) + abs(u.y); // Absolute value norm for distance + // Avoid the division and handle gracefully aligned points + double area = (v.x*u.y - v.y*u.x); + + // if area/du < -epsilon return PL_LEFT_OF_LINE + if (area<-du*epsilon) + return PL_LEFT_OF_LINE; + + // if (area/du > epsilon) return PL_RIGHT_OF_LINE + if (area>du*epsilon) + return PL_RIGHT_OF_LINE; + { + double da = abs(v.x) + abs(v.y); + Vector w = p - b; + double db = abs(w.x) + abs(w.y); + + if (da < epsilon) return PL_BEGINS_LINE; + else if (db < epsilon) return PL_ENDS_LINE; + else if (da > du) return PL_AFTER_LINE; + else if (db > du) return PL_BEFORE_LINE; + else return PL_ON_LINE; + } + } + + bool IsLeft(const Point& p, const Point& a, const Point& b, double epsilon) + { + Vector u = b - a; + Vector v = p - a; + + double du = abs(u.x) + abs(u.y); // Absolute value norm for distance + // Avoid the division and handle gracefully aligned points + double area = (v.x*u.y - v.y*u.x); + return area < -du*epsilon; + +// return area/du < -epsilon; + } + + bool IsOn(const Point& p, const Point& a, const Point& b, double epsilon) + { + Vector u = b - a; + Vector v = p - a; + + double du = abs(u.x) + abs(u.y); // Absolute value norm for distance + + // Avoid the division to handle gracefully aligned points + double area = (v.x*u.y - v.y*u.x); + + return abs(area) <= du*epsilon; + // return abs(area/du) <= epsilon; + } + + bool IsRight(const Point& p, const Point& a, const Point& b, double epsilon) + { + Vector u = b - a; + Vector v = p - a; + + double du = abs(u.x) + abs(u.y); // Absolute value norm for distance + + // Avoid the division and handle gracefully aligned points + double area = (v.x*u.y - v.y*u.x); + return area > du*epsilon; + +// return (area/du) > epsilon; + } + +/****************************************************************************************************** + TRIANGLE OPERATIONS +*******************************************************************************************************/ + Point TCentroid2D(const Point& a, const Point& b, const Point& c) + { + Point temp = (1.0/3.0)*(a+b+c); + temp.z = 0; + return temp; + } + + Point TCentroid3D(const Point& a, const Point& b, const Point& c) + { + return (1.0/3.0)*(a+b+c); + } + + double TArea2D(const Point& a, const Point& b, const Point& c) + { + return (b.x - a.x)*(c.y - a.y) - (b.y - a.y)*(c.x - a.x); + } + + double TArea3D(const Point& a, const Point& b, const Point& c) + { + return 0.5*((b-a).cross(c-a)).length(); + } + + +/****************************************************************************************************** + POLYGON OPERATIONS +*******************************************************************************************************/ + bool PointInPolygon(Point p, const PointList &polygon, double epsilon) + { + int Rcross = 0; + int Lcross = 0; + + // If the polygon is not closed, add a new edge from the last to the first point + int n = int(polygon.size()); + if ((n>0) && !(polygon[0]==polygon.back())) + n++; + for (int i = 1; i < n; i++) + { + Point p1 = polygon[i-1]; + int pointIndex = i < polygon.size() ? i : 0; + Point p2 = polygon[pointIndex]; + + if ( p.x == p1.x && p.y == p1.y) return true; + + double height = p.y; + double x; + bool Rstrad, Lstrad; + + //Rstrad is false if the point only touches ray, but is mostly below it + //Lstrad is false if the point only touches ray, but is mostly above it + Rstrad = ( p2.y > height - epsilon ) != ( p1.y > height - epsilon ); + Lstrad = ( p2.y < height + epsilon ) != ( p1.y < height + epsilon ); + + if (Rstrad || Lstrad) + { + x = ( (p2.x - p.x)*(p1.y - height) - (p1.x - p.x)*(p2.y - height) ) + / ( p1.y - p2.y ); + if ( Rstrad && x > epsilon ) Rcross++; + if ( Lstrad && x < -epsilon ) Lcross++; + // Point is on polygons edge + if (abs(x) < epsilon) + return true; + } + } + + //check cross countings to determine intersection + if ( (Rcross % 2) != (Lcross % 2) ) return true; + else if ( (Rcross % 2) == 1 ) return true; + else return false; + } + + PointList ClipToLine(const PointList &polygon, Point a, Point b, double epsilon) + { + PointList result; + if(polygon.size() < 3) return result; + + bool inside = !IsRight(a,b,polygon[0],epsilon); + if (inside) result.push_back(polygon[0]); + for (int i = 1; i < int(polygon.size()); i++) + { + bool next = !IsRight(a,b,polygon[i],epsilon); + if (next != inside) + { + /* Test if an edge (b-a) intersects a line (d-c). Finds the intersection by computing the normalized distance along the edge (b-a) the intersection + point is located at. This allows not only faster computation, but implicite linear interpolation of the z value. + + Assumes that b-a crosses d-c and is not collinear. + */ + double dx = b.x - a.x; + double dy = b.y - a.y; + double dist = ( dx*(polygon[i-1].y - a.y) - dy*(polygon[i-1].x - a.x) )/( dy*(polygon[i].x - polygon[i-1].x) - dx*(polygon[i].y - polygon[i-1].y) ); + if (dist > epsilon && dist < (1-epsilon)) result.push_back( Point( polygon[i-1].x + (polygon[i].x - polygon[i-1].x)*dist, polygon[i-1].y + (polygon[i].y - polygon[i-1].y)*dist, polygon[i-1].z + (polygon[i].z - polygon[i-1].z)*dist ) ); + } + if (next) + { + if (result.empty()) + result.push_back(polygon[i]); + else if ( (polygon[i] - result.back()).length() > epsilon) + result.push_back(polygon[i]); + } + inside = next; + } + + // At this point, the polygon might not be closed if it did not start off inside the polygon, so close it if not. + if (!result.empty()) + { + if (!(result.front() == result.back())) result.push_back(result.front()); + } + + return result; + } + + PointList ClipToPolygon(PointList polygon, const PointList &convex_region, double epsilon) + { + int n = int(convex_region.size()); + for (int i = 1; i < n; i++) + polygon = ClipToLine(polygon,convex_region[i-1],convex_region[i],epsilon); + + // If the convex region is open, just add one additional point + if ((n>1) && !(convex_region[0]==convex_region.back())) + polygon = ClipToLine(polygon, convex_region[n-1], convex_region[0], epsilon); + return polygon; + } + + double PArea2D(const PointList& contour) + { + double area = 0; + int n = int(contour.size()); + for (int i=0; i ay && ax > az) + coord = 1; + else if (ay > ax) + coord = 2; + else + coord = 3; + + int prev, current, next; + for (prev = n-1, current = 0, next = 1; current < n; prev=(prev+1)%n, current++, next=(next+1)%n) + { + switch(coord) + { + case 1: + area += (contour[current].y * (contour[next].z - contour[prev].z) ); + break; + case 2: + area += (contour[current].x * (contour[next].z - contour[prev].z) ); + break; + case 3: + area += (contour[current].x * (contour[next].y - contour[prev].y) ); + break; + default: + break; + } + } + + switch(coord) + { + case 1: + return area / (2.0*ax); + case 2: + return area / (2.0*ay); + case 3: + return area / (2.0*az); + default: + return 0; + } + } + +} \ No newline at end of file diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Util.h b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Util.h new file mode 100644 index 000000000..3f4cef7ca --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Util.h @@ -0,0 +1,82 @@ +/**************************************************************************** +Copyright 2017, Cognitics Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ +#pragma once + +#include "Vector.h" + +namespace ctl { + +/****************************************************************************************************** + POINT OPERATIONS +*******************************************************************************************************/ + enum PointLineLocation + { + PL_BEFORE_LINE = 0, + PL_BEGINS_LINE = 1, + PL_ON_LINE = 2, + PL_ENDS_LINE = 3, + PL_AFTER_LINE = 4, + PL_LEFT_OF_LINE = 5, + PL_RIGHT_OF_LINE = 6 + }; + + PointLineLocation LocatePointOnLine(const Point& p, const Point& a, const Point& b, double epsilon); + bool IsLeft(const Point& p, const Point& a, const Point& b, double epsilon); + bool IsOn(const Point& p, const Point& a, const Point& b, double epsilon); + bool IsRight(const Point& p, const Point& a, const Point& b, double epsilon); + inline bool IsOnLine(PointLineLocation loc) { return loc <= PL_AFTER_LINE; } + +/****************************************************************************************************** + TRIANGLE OPERATIONS +*******************************************************************************************************/ + Point TCentroid2D(const Point& a, const Point& b, const Point& c); + Point TCentroid3D(const Point& a, const Point& b, const Point& c); + double TArea2D(const Point& a, const Point& b, const Point& c); + double TArea3D(const Point& a, const Point& b, const Point& c); + +/****************************************************************************************************** + POLYGON OPERATIONS +*******************************************************************************************************/ + bool PointInPolygon(Point p, const PointList &polygon, double epsilon = 1e-10); + PointList ClipToLine(const PointList &polygon, Point a, Point b, double epsilon); + +/* + This implementation actually supports clipping any polygon - convex or concave (so long as its simple...and in fact it might even work for non- + simple polygons, but I'm not sure). The only constraint is that the clipping region be a closed convex polygon (ie triangle). It handles any case + of verticle lines while correctly finding all z values through linear interpolation along edges. + + Effectively, the following function will allow clipping an arbitrarily defined 3D polygon defined as a closed (first and last point equal) vector + of Points to any convex 2D region extruded upwards to infinity. + + Note that the convex_region MUST be defined CCW. + The polygon doesn't have to be a particular orientation CCW or CW are fine, but it will return the orientation it was given. + + If the convex_region is defined CW this algorithm will actually result in computing the intersection of the diference of the polygon with each half-plane. + Mathematically, since the convex_region is convex, that means that the funcation will always return nothing (empty vector). Its possible to prove this + mathematically and is actually the basis for many point in convex polygon detection systems. +*/ + PointList ClipToPolygon(PointList polygon, const PointList &convex_region, double epsilon); + + double PArea2D(const PointList& contour); + double PArea3D(const PointList& contour); + +} \ No newline at end of file diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Vector.cpp b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Vector.cpp new file mode 100644 index 000000000..b60420fcb --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Vector.cpp @@ -0,0 +1,194 @@ +/**************************************************************************** +Copyright 2017, Cognitics Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ +#include "Vector.h" +#include +#include +#include +namespace ctl { + + double& Vector::operator[](int index) + { + switch(index) + { + case 0: return x; + case 1: return y; + case 2: return z; + default: + throw std::runtime_error("Vector::operator[] Index out of bounds!"); + } + } + + double Vector::operator[](int index) const + { + switch(index) + { + case 0: return x; + case 1: return y; + case 2: return z; + default: + throw std::runtime_error("Vector::operator[] Index out of bounds!"); + } + } + + bool Vector::operator==(const Vector& other) const + { + if (x!=other.x) return false; + else if (y!=other.y) return false; + //else if (z!=other.z) return false; + else return true; + } + + bool Vector::operator!=(const Vector& other) const + { + return !((*this)==other); + } + + Vector Vector::operator+(const Vector &other) const + { + Vector vect = *this; + vect.x += other.x; + vect.y += other.y; + vect.z += other.z; + return vect; + } + + Vector& Vector::operator+=(const Vector& other) + { + x += other.x; + y += other.y; + z += other.z; + return *this; + } + + Vector Vector::operator-(const Vector& other) const + { + Vector vect = *this; + vect.x -= other.x; + vect.y -= other.y; + vect.z -= other.z; + return vect; + } + + Vector& Vector::operator-=(const Vector& other) + { + x -= other.x; + y -= other.y; + z -= other.z; + return *this; + } + + Vector& Vector::operator*=(double a) + { + x *= a; + y *= a; + z *= a; + return *this; + } + + double Vector::dot(const Vector& other) const + { + return x*other.x + y*other.y + z*other.z; + } + + Vector Vector::cross(const Vector& other) const + { + return (*this)^other; + } + + Vector Vector::operator^(const Vector& other) const + { + return Vector + ( + y*other.z - z*other.y, + z*other.x - x*other.z, + x*other.y - y*other.x + ); + } + + double Vector::length(void) const + { + return sqrt(x*x + y*y + z*z); + } + + double Vector::length2D(void) const + { + return sqrt(x*x + y*y); + } + + double Vector::length2D2(void) const + { + return x*x + y*y; + } + + Vector& Vector::normalize(void) + { + double l = 1.0/length(); + x *= l; + y *= l; + z *= l; + return *this; + } + + bool Vector::equals(Vector& other, double epsilon) const + { + if (epsilon == 0) + { + if (x != other.x) + return false; + else if (y != other.y) + return false; + else + return true; + } + else + { + double dist = std::abs(x-other.x) + std::abs(y-other.y); // Use L1 norm + return dist < epsilon; + } + } + + Vector operator*(double a, const Vector& b) + { + Vector v = b; + v.x *= a; + v.y *= a; + v.z *= a; + return v; + } + + Vector operator*(const Vector& a, double b) + { + return (b*a); + } + + double operator*(const Vector& a, const Vector& b) + { + return a.x*b.x + a.y*b.y + a.z*b.z; + } + + void Vector::set(double x, double y, double z) + { + this->x = x; + this->y = y; + this->z = z; + } +} \ No newline at end of file diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Vector.h b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Vector.h new file mode 100644 index 000000000..f246ca8bf --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Vector.h @@ -0,0 +1,85 @@ +/**************************************************************************** +Copyright 2017, Cognitics Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ +/*! \file ctl/Vector.h +\headerfile ctl/Vector.h +\brief Provides ctl::Vector. +\author Joshua Anghel +*/ +#pragma once + +#include + +namespace ctl { + +/*! \class ctl::Vector ctl/Vector.h ctl/Vector.h +\brief Vector + +3D coordinate for ctl, with ability to perform normalization and other common vector operations. +*/ + class Vector + { + public: + double x; + double y; + double z; + + Vector(double _x = 0, double _y = 0, double _z = 0) : x(_x), y(_y), z(_z) { } + ~Vector(void) { } + + double& operator[](int index); + double operator[](int index) const; + + bool operator==(const Vector& other) const; + bool operator!=(const Vector& other) const; + Vector operator+(const Vector& other) const; + Vector& operator+=(const Vector& other); + Vector operator-(const Vector& other) const; + Vector& operator-=(const Vector& other); + + Vector& operator*=(double a); + +/* Dot Product */ + double dot(const Vector& other) const; + +/* Cross Product */ + Vector cross(const Vector& other) const; + Vector operator^(const Vector& other) const; + +/* Length and Normalization */ + double length(void) const; + double length2D(void) const; + double length2D2(void) const; + Vector& normalize(void); + +/* Equal check with epsilon */ + bool equals(Vector& other, double epsilon) const; + + void set(double x, double y, double z); + }; + + Vector operator*(double a, const Vector& b); + Vector operator*(const Vector& a, double b); + double operator*(const Vector& a, const Vector& b); + + typedef Vector Point; + typedef std::vector PointList; +} \ No newline at end of file diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Vertex.cpp b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Vertex.cpp new file mode 100644 index 000000000..2e21a3516 --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Vertex.cpp @@ -0,0 +1,100 @@ +/**************************************************************************** +Copyright 2017, Cognitics Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ +#include "Vertex.h" + +namespace ctl { + + ID Vertex::getID(void) + { + return id; + } + + void Vertex::addEdge(Edge* edge) + { + this->edge = edge; + } + + void Vertex::removeEdge(Edge* edge) + { + Edge* next = edge->Onext(); + this->edge = (next != edge) ? next : NULL; + } + + Edge* Vertex::getEdges(void) + { + return edge; + } + + void Vertex::clearEdge(void) + { + edge = NULL; + } + + Vector Vertex::getAreaWeightedNormal(void) + { + Vector up(0,0,1); + if (!edge) return up; + if (edge->Onext() == edge) return up; + + Vector normal; + + Edge* start = edge; + Edge* next = start; + + do + { + if (!next->Dest() || !next->Onext()->Dest()) break; + + Vector u = next->Dest()->point - point; + Vector v = next->Onext()->Dest()->point - point; + + Vector nextNorm = u.cross(v); + if (nextNorm.dot(up) > 0) + normal += nextNorm; + + next = next->Onext(); + } + while (next != start); + + return normal; + } + + void Vertex::Reset(Vertex* vert) + { + id = vert->id; + point = vert->point; + edge = vert->edge; + + // Replace all links to old vert with this new one + if (edge) + { + Edge* start = edge; + Edge* next = edge; + do + { + next->setOrg(this); + next = next->Onext(); + } while( next != start ); + } + } + +} diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Vertex.h b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Vertex.h new file mode 100644 index 000000000..a4f9e73ad --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/Vertex.h @@ -0,0 +1,92 @@ +/**************************************************************************** +Copyright 2017, Cognitics Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ +/*! \file ctl/Vertex.h +\headerfile ctl/Vertex.h +\brief Provides ctl::Vertex. +\author Joshua Anghel +*/ +#pragma once + +#include "Edge.h" +#include "Vector.h" + +namespace ctl { + +/*! \class ctl::Vertex ctl/Vertex.h ctl/Vertex.h + \brief Vertex + + ID Unique ID value for this Vertex. + Point Location of this Vertex. + Edges Edges radiating outword from this Vertex. + +*/ + class Vertex + { + friend class Subdivision; + + private: + ID id; + Edge* edge; + + public: + Vertex(void) { } + ~Vertex(void) { } + + Vector point; + +/*! \brief Get the ID of this Vertex. + * \return The unique ID assigned to this Vertex. + */ + ID getID(void); + +/*! \brief Link an Edge to this Vertex. + * \param edge Edge to link to this Vertex. + */ + void addEdge(Edge* edge); + +/*! \brief Remove an Edge linked to this Vertex. + * \param edge Edge to unlink from this Vertex. + */ + void removeEdge(Edge* edge); + + void clearEdge(void); + +/*! \brief Returns an arbitrary Edge linked to this Vertex. + * + * All Edges linked to this Vertex can be found by iterating around the returned Edge using Edge::Onext(). + * \return An arbitrary Edge linked to this Vertex. + */ + Edge* getEdges(void); + +/*! \brief Returns the area weighted normal of this Vertex. + * + * Uses the linked Edges of this Vertex to compute the normals of all adjacent triangles. If there are no + * Adjacent Edges, the normal will be (0,0,0). + * \return The area weighted normal of this Vertex. + */ + Vector getAreaWeightedNormal(void); + +//! \brief Replace the other Vertex with this + void Reset(Vertex* vert); + }; + +} \ No newline at end of file diff --git a/prog/3rdPartyLibs/math/DelaunayTriangulator/source/ctl.h b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/ctl.h new file mode 100644 index 000000000..cfa17e5c0 --- /dev/null +++ b/prog/3rdPartyLibs/math/DelaunayTriangulator/source/ctl.h @@ -0,0 +1,52 @@ +/**************************************************************************** +Copyright 2017, Cognitics Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ +/*! \file ctl/ctl.h +\headerfile ctl/ctl.h +\brief Cognitics Triangulation Library +\author Joshua Anghel + +\page ctl_page Cognitics Triangulation Library (CTL) + +\section Description + +\section Usage + +\section Notes + +*/ +#pragma once + +#define CONGITICS_CTL_VERSION 1.0 + +#include "ID.h" +#include "Vector.h" +#include "Vertex.h" +#include "Subdivision.h" +#include "Edge.h" +#include "LocationResult.h" +#include "TIN.h" +#include "DelaunayTriangulation.h" +#include "CGrid.h" +#include "Util.h" + +//! \namespace ctl Cognitics Triangualtion Library +namespace ctl { } diff --git a/prog/3rdPartyLibs/reflexStats/reflexstats.h b/prog/3rdPartyLibs/reflexStats/reflexstats.h deleted file mode 100644 index 575a19c79..000000000 --- a/prog/3rdPartyLibs/reflexStats/reflexstats.h +++ /dev/null @@ -1,156 +0,0 @@ -/** Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.* -* NVIDIA CORPORATION and its licensors retain all intellectual property -* and proprietary rights in and to this software, related documentation -* and any modifications thereto. Any use, reproduction, disclosure or -* distribution of this software and related documentation without an express -* license agreement from NVIDIA CORPORATION is strictly prohibited.*/ - -#include -#include -#include -#include - -#pragma comment(lib, "advapi32.lib") -#pragma comment(lib, "user32.lib") - -typedef enum _NVSTATS_LATENCY_MARKER_TYPE -{ - NVSTATS_SIMULATION_START = 0, - NVSTATS_SIMULATION_END = 1, - NVSTATS_RENDERSUBMIT_START = 2, - NVSTATS_RENDERSUBMIT_END = 3, - NVSTATS_PRESENT_START = 4, - NVSTATS_PRESENT_END = 5, - NVSTATS_INPUT_SAMPLE = 6, - NVSTATS_TRIGGER_FLASH = 7, - NVSTATS_PC_LATENCY_PING = 8, -} NVSTATS_LATENCY_MARKER_TYPE; - -typedef enum _NVSTATS_FLAGS -{ - NVSTATS_NO_PRESENT_MARKERS = 0x00000001, -} NVSTATS_FLAGS; - -TRACELOGGING_DECLARE_PROVIDER(g_hReflexStatsComponentProvider); - -#define NVSTATS_DEFINE() \ - TRACELOGGING_DEFINE_PROVIDER( \ - g_hReflexStatsComponentProvider, \ - "ReflexStatsTraceLoggingProvider", \ - (0x0d216f06, 0x82a6, 0x4d49, 0xbc, 0x4f, 0x8f, 0x38, 0xae, 0x56, 0xef, 0xab)); \ - UINT g_ReflexStatsWindowMessage = 0; \ - WORD g_ReflexStatsVirtualKey = 0; \ - HANDLE g_ReflexStatsQuitEvent = NULL; \ - HANDLE g_ReflexStatsPingThread = NULL; \ - bool g_ReflexStatsEnable = false; \ - UINT g_ReflexStatsFlags = 0; \ - DWORD ReflexStatsPingThreadProc(LPVOID lpThreadParameter) \ - { \ - DWORD minPingInterval = 100 /*ms*/; \ - DWORD maxPingInterval = 300 /*ms*/; \ - while (WAIT_TIMEOUT == WaitForSingleObject(g_ReflexStatsQuitEvent, minPingInterval + (rand() % (maxPingInterval - minPingInterval)))) \ - { \ - if (!g_ReflexStatsEnable) \ - { \ - continue; \ - } \ - HWND hWnd = GetForegroundWindow(); \ - if (hWnd) \ - { \ - DWORD dwProcessId = 0; \ - (void)GetWindowThreadProcessId(hWnd, &dwProcessId); \ - if (GetCurrentProcessId() == dwProcessId) \ - { \ - if ((g_ReflexStatsVirtualKey == VK_F13) || \ - (g_ReflexStatsVirtualKey == VK_F14) || \ - (g_ReflexStatsVirtualKey == VK_F15)) \ - { \ - TraceLoggingWrite(g_hReflexStatsComponentProvider, "ReflexStatsInput"); \ - PostMessageW(hWnd, WM_KEYDOWN, g_ReflexStatsVirtualKey, 0x00000001); \ - PostMessageW(hWnd, WM_KEYUP, g_ReflexStatsVirtualKey, 0xC0000001); \ - } \ - else if (g_ReflexStatsWindowMessage) \ - { \ - TraceLoggingWrite(g_hReflexStatsComponentProvider, "ReflexStatsInput"); \ - PostMessageW(hWnd, g_ReflexStatsWindowMessage, 0, 0); \ - } \ - else \ - { \ - break; \ - } \ - } \ - } \ - } \ - return S_OK; \ - } \ - void WINAPI ReflexStatsComponentProviderCb(LPCGUID, ULONG ControlCode, UCHAR, ULONGLONG, ULONGLONG, PEVENT_FILTER_DESCRIPTOR, PVOID) \ - { \ - switch (ControlCode) \ - { \ - case EVENT_CONTROL_CODE_ENABLE_PROVIDER: \ - g_ReflexStatsEnable = true; \ - break; \ - case EVENT_CONTROL_CODE_DISABLE_PROVIDER: \ - g_ReflexStatsEnable = false; \ - break; \ - case EVENT_CONTROL_CODE_CAPTURE_STATE: \ - TraceLoggingWrite(g_hReflexStatsComponentProvider, "ReflexStatsFlags", TraceLoggingUInt32(g_ReflexStatsFlags, "Flags")); \ - break; \ - default: \ - break; \ - } \ - } - -#define NVSTATS_INIT(vk, flags) \ - if (((vk) == 0) && (g_ReflexStatsWindowMessage == 0)) \ - { \ - g_ReflexStatsWindowMessage = RegisterWindowMessageW(L"NVIDIA_Reflex_PC_Latency_Ping"); \ - } \ - g_ReflexStatsVirtualKey = (vk); \ - g_ReflexStatsFlags = (flags); \ - if (!g_ReflexStatsQuitEvent) \ - { \ - g_ReflexStatsQuitEvent = CreateEventW(NULL, 1, 0, NULL); \ - } \ - if (g_ReflexStatsQuitEvent) \ - { \ - TraceLoggingRegisterEx(g_hReflexStatsComponentProvider, ReflexStatsComponentProviderCb, NULL); \ - TraceLoggingWrite(g_hReflexStatsComponentProvider, "ReflexStatsInit"); \ - if (!g_ReflexStatsPingThread) \ - { \ - g_ReflexStatsPingThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ReflexStatsPingThreadProc, NULL, 0, NULL); \ - } \ - } - -#define NVSTATS_MARKER(mrk,frid) TraceLoggingWrite(g_hReflexStatsComponentProvider, "ReflexStatsEvent", TraceLoggingUInt32((mrk), "Marker"), TraceLoggingUInt64((frid), "FrameID")) -#define NVSTATS_MARKER_V2(mrk,frid) TraceLoggingWrite(g_hReflexStatsComponentProvider, "ReflexStatsEventV2", TraceLoggingUInt32((mrk), "Marker"), TraceLoggingUInt64((frid), "FrameID"), TraceLoggingUInt32(g_ReflexStatsFlags, "Flags")) - -#define NVSTATS_SHUTDOWN() \ - if (g_ReflexStatsPingThread) \ - { \ - if (g_ReflexStatsQuitEvent) \ - { \ - SetEvent(g_ReflexStatsQuitEvent); \ - } \ - (void)WaitForSingleObject(g_ReflexStatsPingThread, 1000); \ - g_ReflexStatsPingThread = NULL; \ - } \ - TraceLoggingWrite(g_hReflexStatsComponentProvider, "ReflexStatsShutdown"); \ - TraceLoggingUnregister(g_hReflexStatsComponentProvider); \ - if (g_ReflexStatsQuitEvent) \ - { \ - CloseHandle(g_ReflexStatsQuitEvent); \ - g_ReflexStatsQuitEvent = NULL; \ - } - -#define NVSTATS_IS_PING_MSG_ID(msgId) ((msgId) == g_ReflexStatsWindowMessage) - -extern "C" UINT g_ReflexStatsWindowMessage; -extern "C" WORD g_ReflexStatsVirtualKey; -extern "C" HANDLE g_ReflexStatsQuitEvent; -extern "C" HANDLE g_ReflexStatsPingThread; -extern "C" bool g_ReflexStatsEnable; -extern "C" UINT g_ReflexStatsFlags; - -DWORD ReflexStatsPingThreadProc(LPVOID lpThreadParameter); -void WINAPI ReflexStatsComponentProviderCb(LPCGUID, ULONG ControlCode, UCHAR, ULONGLONG, ULONGLONG, PEVENT_FILTER_DESCRIPTOR, PVOID); diff --git a/prog/3rdPartyLibs/removed_code.txt b/prog/3rdPartyLibs/removed_code.txt index 8643bf9b4..1e55e6e96 100644 --- a/prog/3rdPartyLibs/removed_code.txt +++ b/prog/3rdPartyLibs/removed_code.txt @@ -1,3 +1,6 @@ +removed on 2023/10/29: + dagor4/prog/3rdPartyLibs/wtl-8.1 + removed on 2023/08/09: dagor4/prog/3rdPartyLibs/math/quickDelaunay diff --git a/prog/3rdPartyLibs/ska_hash_map/flat_hash_map2.hpp b/prog/3rdPartyLibs/ska_hash_map/flat_hash_map2.hpp index 47caaeb80..fa705816c 100644 --- a/prog/3rdPartyLibs/ska_hash_map/flat_hash_map2.hpp +++ b/prog/3rdPartyLibs/ska_hash_map/flat_hash_map2.hpp @@ -1124,7 +1124,7 @@ class flat_hash_map typename Table::EntryPointer it = Table::entries + ptrdiff_t(index); for (int8_t distance = 0; it->distance_from_desired >= distance; ++distance, ++it) { - if (predicate(key, it->value.first)) + if (predicate(it->value.first, key)) return { it }; } return Table::end(); @@ -1217,7 +1217,7 @@ class flat_hash_set typename Table::EntryPointer it = Table::entries + ptrdiff_t(index); for (int8_t distance = 0; it->distance_from_desired >= distance; ++distance, ++it) { - if (predicate(key, it->value)) + if (predicate(it->value, key)) return { it }; } return Table::end(); diff --git a/prog/3rdPartyLibs/winpixeventruntime/Include/WinPixEventRuntime/PIXEvents.h b/prog/3rdPartyLibs/winpixeventruntime/Include/WinPixEventRuntime/PIXEvents.h deleted file mode 100644 index 94240e6e4..000000000 --- a/prog/3rdPartyLibs/winpixeventruntime/Include/WinPixEventRuntime/PIXEvents.h +++ /dev/null @@ -1,661 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. - -/*==========================================================================; - * - * Copyright (C) Microsoft Corporation. All Rights Reserved. - * - * File: PIXEvents.h - * Content: PIX include file - * Don't include this file directly - use pix3.h - * - ****************************************************************************/ -#pragma once - -#ifndef _PixEvents_H_ -#define _PixEvents_H_ - -#ifndef _PIX3_H_ -# error Do not include this file directly - use pix3.h -#endif - -#include "PIXEventsCommon.h" - -#if _MSC_VER < 1800 -# error This version of pix3.h is only supported on Visual Studio 2013 or higher -#elif _MSC_VER < 1900 -# ifndef constexpr // Visual Studio 2013 doesn't support constexpr -# define constexpr -# define PIX3__DEFINED_CONSTEXPR -# endif -#endif - -// Xbox does not support CPU events for retail scenarios -#if defined(USE_PIX) || !defined(PIX_XBOX) -#define PIX_CONTEXT_EMIT_CPU_EVENTS -#endif - -namespace PIXEventsDetail -{ - template - struct PIXEventTypeInferer - { - static constexpr PIXEventType Begin() { return PIXEvent_BeginEvent_VarArgs; } - static constexpr PIXEventType SetMarker() { return PIXEvent_SetMarker_VarArgs; } - static constexpr PIXEventType BeginOnContext() { return PIXEvent_BeginEvent_OnContext_VarArgs; } - static constexpr PIXEventType SetMarkerOnContext() { return PIXEvent_SetMarker_OnContext_VarArgs; } - - // Xbox and Windows store different types of events for context events. - // On Xbox these include a context argument, while on Windows they do - // not. It is important not to change the event types used on the - // Windows version as there are OS components (eg debug layer & DRED) - // that decode event structs. -#ifdef PIX_XBOX - static constexpr PIXEventType GpuBeginOnContext() { return PIXEvent_BeginEvent_OnContext_VarArgs; } - static constexpr PIXEventType GpuSetMarkerOnContext() { return PIXEvent_SetMarker_OnContext_VarArgs; } -#else - static constexpr PIXEventType GpuBeginOnContext() { return PIXEvent_BeginEvent_VarArgs; } - static constexpr PIXEventType GpuSetMarkerOnContext() { return PIXEvent_SetMarker_VarArgs; } -#endif - }; - - template<> - struct PIXEventTypeInferer - { - static constexpr PIXEventType Begin() { return PIXEvent_BeginEvent_NoArgs; } - static constexpr PIXEventType SetMarker() { return PIXEvent_SetMarker_NoArgs; } - static constexpr PIXEventType BeginOnContext() { return PIXEvent_BeginEvent_OnContext_NoArgs; } - static constexpr PIXEventType SetMarkerOnContext() { return PIXEvent_SetMarker_OnContext_NoArgs; } - -#ifdef PIX_XBOX - static constexpr PIXEventType GpuBeginOnContext() { return PIXEvent_BeginEvent_OnContext_NoArgs; } - static constexpr PIXEventType GpuSetMarkerOnContext() { return PIXEvent_SetMarker_OnContext_NoArgs; } -#else - static constexpr PIXEventType GpuBeginOnContext() { return PIXEvent_BeginEvent_NoArgs; } - static constexpr PIXEventType GpuSetMarkerOnContext() { return PIXEvent_SetMarker_NoArgs; } -#endif - }; - - inline void PIXCopyEventArguments(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit) - { - // nothing - UNREFERENCED_PARAMETER(destination); - UNREFERENCED_PARAMETER(limit); - } - - template - void PIXCopyEventArguments(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, ARG const& arg, ARGS const&... args) - { - PIXCopyEventArgument(destination, limit, arg); - PIXCopyEventArguments(destination, limit, args...); - } - - template - __declspec(noinline) void PIXBeginEventAllocate(PIXEventsThreadInfo* threadInfo, UINT64 color, STR formatString, ARGS... args) - { -#ifdef PIX_XBOX - UINT64 time = PIXEventsReplaceBlock(false); -#else - UINT64 time = PIXEventsReplaceBlock(threadInfo, false); -#endif - if (!time) - return; - - UINT64* destination = threadInfo->destination; - UINT64* limit = threadInfo->biasedLimit; - if (destination >= limit) - return; - - limit += PIXEventsSafeFastCopySpaceQwords; - *destination++ = PIXEncodeEventInfo(time, PIXEventTypeInferer::Begin()); - *destination++ = color; - - PIXCopyEventArguments(destination, limit, formatString, args...); - - *destination = PIXEventsBlockEndMarker; - threadInfo->destination = destination; - } - - template - void PIXBeginEvent(UINT64 color, STR formatString, ARGS... args) - { - PIXEventsThreadInfo* threadInfo = PIXGetThreadInfo(); - UINT64* limit = threadInfo->biasedLimit; - if (limit != nullptr) - { - UINT64* destination = threadInfo->destination; - if (destination < limit) - { - limit += PIXEventsSafeFastCopySpaceQwords; - UINT64 time = PIXGetTimestampCounter(); - *destination++ = PIXEncodeEventInfo(time, PIXEventTypeInferer::Begin()); - *destination++ = color; - - PIXCopyEventArguments(destination, limit, formatString, args...); - - *destination = PIXEventsBlockEndMarker; - threadInfo->destination = destination; - } - else - { - PIXBeginEventAllocate(threadInfo, color, formatString, args...); - } - } - } - - template - __declspec(noinline) void PIXSetMarkerAllocate(PIXEventsThreadInfo* threadInfo, UINT64 color, STR formatString, ARGS... args) - { -#ifdef PIX_XBOX - UINT64 time = PIXEventsReplaceBlock(false); -#else - UINT64 time = PIXEventsReplaceBlock(threadInfo, false); -#endif - if (!time) - return; - - UINT64* destination = threadInfo->destination; - UINT64* limit = threadInfo->biasedLimit; - - if (destination >= limit) - return; - - limit += PIXEventsSafeFastCopySpaceQwords; - *destination++ = PIXEncodeEventInfo(time, PIXEventTypeInferer::SetMarker()); - *destination++ = color; - - PIXCopyEventArguments(destination, limit, formatString, args...); - - *destination = PIXEventsBlockEndMarker; - threadInfo->destination = destination; - } - - template - void PIXSetMarker(UINT64 color, STR formatString, ARGS... args) - { - PIXEventsThreadInfo* threadInfo = PIXGetThreadInfo(); - UINT64* limit = threadInfo->biasedLimit; - if (limit != nullptr) - { - UINT64* destination = threadInfo->destination; - if (destination < limit) - { - limit += PIXEventsSafeFastCopySpaceQwords; - UINT64 time = PIXGetTimestampCounter(); - *destination++ = PIXEncodeEventInfo(time, PIXEventTypeInferer::SetMarker()); - *destination++ = color; - - PIXCopyEventArguments(destination, limit, formatString, args...); - - *destination = PIXEventsBlockEndMarker; - threadInfo->destination = destination; - } - else - { - PIXSetMarkerAllocate(threadInfo, color, formatString, args...); - } - } - } - - template - __declspec(noinline) void PIXBeginEventOnContextCpuAllocate(PIXEventsThreadInfo* threadInfo, void* context, UINT64 color, STR formatString, ARGS... args) - { -#ifdef PIX_XBOX - UINT64 time = PIXEventsReplaceBlock(false); -#else - UINT64 time = PIXEventsReplaceBlock(threadInfo, false); -#endif - if (!time) - return; - - UINT64* destination = threadInfo->destination; - UINT64* limit = threadInfo->biasedLimit; - - if (destination >= limit) - return; - - limit += PIXEventsSafeFastCopySpaceQwords; - *destination++ = PIXEncodeEventInfo(time, PIXEventTypeInferer::BeginOnContext()); - *destination++ = color; - -#ifdef PIX_XBOX - UNREFERENCED_PARAMETER(context); - PIXCopyEventArguments(destination, limit, formatString, args...); -#else - PIXCopyEventArguments(destination, limit, context, formatString, args...); -#endif - - *destination = PIXEventsBlockEndMarker; - threadInfo->destination = destination; - } - - template - void PIXBeginEventOnContextCpu(void* context, UINT64 color, STR formatString, ARGS... args) - { - PIXEventsThreadInfo* threadInfo = PIXGetThreadInfo(); - UINT64* limit = threadInfo->biasedLimit; - if (limit != nullptr) - { - UINT64* destination = threadInfo->destination; - if (destination < limit) - { - limit += PIXEventsSafeFastCopySpaceQwords; - UINT64 time = PIXGetTimestampCounter(); - *destination++ = PIXEncodeEventInfo(time, PIXEventTypeInferer::BeginOnContext()); - *destination++ = color; - -#ifdef PIX_XBOX - PIXCopyEventArguments(destination, limit, formatString, args...); -#else - PIXCopyEventArguments(destination, limit, context, formatString, args...); -#endif - - *destination = PIXEventsBlockEndMarker; - threadInfo->destination = destination; - } - else - { - PIXBeginEventOnContextCpuAllocate(threadInfo, context, color, formatString, args...); - } - } - } - - template - void PIXBeginEvent(CONTEXT* context, UINT64 color, STR formatString, ARGS... args) - { -#ifdef PIX_CONTEXT_EMIT_CPU_EVENTS - PIXBeginEventOnContextCpu(context, color, formatString, args...); -#endif - - // TODO: we've already encoded this once for the CPU event - figure out way to avoid doing it again - UINT64 buffer[PIXEventsGraphicsRecordSpaceQwords]; - UINT64* destination = buffer; - UINT64* limit = buffer + PIXEventsGraphicsRecordSpaceQwords - PIXEventsReservedTailSpaceQwords; - - *destination++ = PIXEncodeEventInfo(0, PIXEventTypeInferer::GpuBeginOnContext()); - *destination++ = color; - - PIXCopyEventArguments(destination, limit, formatString, args...); - *destination = 0ull; - - PIXBeginGPUEventOnContext(context, static_cast(buffer), static_cast(reinterpret_cast(destination) - reinterpret_cast(buffer))); - } - - template - __declspec(noinline) void PIXSetMarkerOnContextCpuAllocate(PIXEventsThreadInfo* threadInfo, void* context, UINT64 color, STR formatString, ARGS... args) - { -#ifdef PIX_XBOX - UINT64 time = PIXEventsReplaceBlock(false); -#else - UINT64 time = PIXEventsReplaceBlock(threadInfo, false); -#endif - if (!time) - return; - - UINT64* destination = threadInfo->destination; - UINT64* limit = threadInfo->biasedLimit; - - if (destination >= limit) - return; - - limit += PIXEventsSafeFastCopySpaceQwords; - *destination++ = PIXEncodeEventInfo(time, PIXEventTypeInferer::SetMarkerOnContext()); - *destination++ = color; - -#ifdef PIX_XBOX - UNREFERENCED_PARAMETER(context); - PIXCopyEventArguments(destination, limit, formatString, args...); -#else - PIXCopyEventArguments(destination, limit, context, formatString, args...); -#endif - - *destination = PIXEventsBlockEndMarker; - threadInfo->destination = destination; - } - - template - void PIXSetMarkerOnContextCpu(void* context, UINT64 color, STR formatString, ARGS... args) - { - PIXEventsThreadInfo* threadInfo = PIXGetThreadInfo(); - UINT64* limit = threadInfo->biasedLimit; - if (limit != nullptr) - { - UINT64* destination = threadInfo->destination; - if (destination < limit) - { - limit += PIXEventsSafeFastCopySpaceQwords; - UINT64 time = PIXGetTimestampCounter(); - *destination++ = PIXEncodeEventInfo(time, PIXEventTypeInferer::SetMarkerOnContext()); - *destination++ = color; - -#ifdef PIX_XBOX - PIXCopyEventArguments(destination, limit, formatString, args...); -#else - PIXCopyEventArguments(destination, limit, context, formatString, args...); -#endif - - *destination = PIXEventsBlockEndMarker; - threadInfo->destination = destination; - } - else - { - PIXSetMarkerOnContextCpuAllocate(threadInfo, context, color, formatString, args...); - } - } - } - - template - void PIXSetMarker(CONTEXT* context, UINT64 color, STR formatString, ARGS... args) - { -#ifdef PIX_CONTEXT_EMIT_CPU_EVENTS - PIXSetMarkerOnContextCpu(context, color, formatString, args...); -#endif - - UINT64 buffer[PIXEventsGraphicsRecordSpaceQwords]; - UINT64* destination = buffer; - UINT64* limit = buffer + PIXEventsGraphicsRecordSpaceQwords - PIXEventsReservedTailSpaceQwords; - - *destination++ = PIXEncodeEventInfo(0, PIXEventTypeInferer::GpuSetMarkerOnContext()); - *destination++ = color; - - PIXCopyEventArguments(destination, limit, formatString, args...); - *destination = 0ull; - - PIXSetGPUMarkerOnContext(context, static_cast(buffer), static_cast(reinterpret_cast(destination) - reinterpret_cast(buffer))); - } - - __declspec(noinline) inline void PIXEndEventAllocate(PIXEventsThreadInfo* threadInfo) - { -#ifdef PIX_XBOX - UINT64 time = PIXEventsReplaceBlock(true); -#else - UINT64 time = PIXEventsReplaceBlock(threadInfo, true); -#endif - if (!time) - return; - - UINT64* destination = threadInfo->destination; - UINT64* limit = threadInfo->biasedLimit; - - if (destination >= limit) - return; - - limit += PIXEventsSafeFastCopySpaceQwords; - *destination++ = PIXEncodeEventInfo(time, PIXEvent_EndEvent); - *destination = PIXEventsBlockEndMarker; - threadInfo->destination = destination; - } - - inline void PIXEndEvent() - { - PIXEventsThreadInfo* threadInfo = PIXGetThreadInfo(); - UINT64* limit = threadInfo->biasedLimit; - if (limit != nullptr) - { - UINT64* destination = threadInfo->destination; - if (destination < limit) - { - limit += PIXEventsSafeFastCopySpaceQwords; - UINT64 time = PIXGetTimestampCounter(); - *destination++ = PIXEncodeEventInfo(time, PIXEvent_EndEvent); - *destination = PIXEventsBlockEndMarker; - threadInfo->destination = destination; - } - else - { - PIXEndEventAllocate(threadInfo); - } - } - } - - __declspec(noinline) inline void PIXEndEventOnContextCpuAllocate(PIXEventsThreadInfo* threadInfo, void* context) - { -#ifdef PIX_XBOX - UINT64 time = PIXEventsReplaceBlock(true); -#else - UINT64 time = PIXEventsReplaceBlock(threadInfo, true); -#endif - if (!time) - return; - - UINT64* destination = threadInfo->destination; - UINT64* limit = threadInfo->biasedLimit; - - if (destination >= limit) - return; - - limit += PIXEventsSafeFastCopySpaceQwords; - *destination++ = PIXEncodeEventInfo(time, PIXEvent_EndEvent_OnContext); -#ifdef PIX_XBOX - UNREFERENCED_PARAMETER(context); -#else - PIXCopyEventArgument(destination, limit, context); -#endif - *destination = PIXEventsBlockEndMarker; - threadInfo->destination = destination; - } - - inline void PIXEndEventOnContextCpu(void* context) - { - PIXEventsThreadInfo* threadInfo = PIXGetThreadInfo(); - UINT64* limit = threadInfo->biasedLimit; - if (limit != nullptr) - { - UINT64* destination = threadInfo->destination; - if (destination < limit) - { - limit += PIXEventsSafeFastCopySpaceQwords; - UINT64 time = PIXGetTimestampCounter(); - *destination++ = PIXEncodeEventInfo(time, PIXEvent_EndEvent_OnContext); -#ifndef PIX_XBOX - PIXCopyEventArgument(destination, limit, context); -#endif - *destination = PIXEventsBlockEndMarker; - threadInfo->destination = destination; - } - else - { - PIXEndEventOnContextCpuAllocate(threadInfo, context); - } - } - } - - template - void PIXEndEvent(CONTEXT* context) - { -#ifdef PIX_CONTEXT_EMIT_CPU_EVENTS - PIXEndEventOnContextCpu(context); -#endif - PIXEndGPUEventOnContext(context); - } -} - -#if defined(USE_PIX) - -template -void PIXBeginEvent(UINT64 color, PCWSTR formatString, ARGS... args) -{ - PIXEventsDetail::PIXBeginEvent(color, formatString, args...); -} - -template -void PIXBeginEvent(UINT64 color, PCSTR formatString, ARGS... args) -{ - PIXEventsDetail::PIXBeginEvent(color, formatString, args...); -} - -template -void PIXSetMarker(UINT64 color, PCWSTR formatString, ARGS... args) -{ - PIXEventsDetail::PIXSetMarker(color, formatString, args...); -} - -template -void PIXSetMarker(UINT64 color, PCSTR formatString, ARGS... args) -{ - PIXEventsDetail::PIXSetMarker(color, formatString, args...); -} - -template -void PIXBeginEvent(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args) -{ - PIXEventsDetail::PIXBeginEvent(context, color, formatString, args...); -} - -template -void PIXBeginEvent(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args) -{ - PIXEventsDetail::PIXBeginEvent(context, color, formatString, args...); -} - -template -void PIXSetMarker(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args) -{ - PIXEventsDetail::PIXSetMarker(context, color, formatString, args...); -} - -template -void PIXSetMarker(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args) -{ - PIXEventsDetail::PIXSetMarker(context, color, formatString, args...); -} - -inline void PIXEndEvent() -{ - PIXEventsDetail::PIXEndEvent(); -} - -template -void PIXEndEvent(CONTEXT* context) -{ - PIXEventsDetail::PIXEndEvent(context); -} - -#else // USE_PIX_RETAIL - -inline void PIXBeginEvent(UINT64, _In_ PCSTR, ...) {} -inline void PIXBeginEvent(UINT64, _In_ PCWSTR, ...) {} -inline void PIXBeginEvent(void*, UINT64, _In_ PCSTR, ...) {} -inline void PIXBeginEvent(void*, UINT64, _In_ PCWSTR, ...) {} -inline void PIXEndEvent() {} -inline void PIXEndEvent(void*) {} -inline void PIXSetMarker(UINT64, _In_ PCSTR, ...) {} -inline void PIXSetMarker(UINT64, _In_ PCWSTR, ...) {} -inline void PIXSetMarker(void*, UINT64, _In_ PCSTR, ...) {} -inline void PIXSetMarker(void*, UINT64, _In_ PCWSTR, ...) {} - -#endif // USE_PIX - -template -void PIXBeginRetailEvent(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args) -{ - PIXEventsDetail::PIXBeginEvent(context, color, formatString, args...); -} - -template -void PIXBeginRetailEvent(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args) -{ - PIXEventsDetail::PIXBeginEvent(context, color, formatString, args...); -} - -template -void PIXSetRetailMarker(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args) -{ - PIXEventsDetail::PIXSetMarker(context, color, formatString, args...); -} - -template -void PIXSetRetailMarker(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args) -{ - PIXEventsDetail::PIXSetMarker(context, color, formatString, args...); -} - -template -void PIXEndRetailEvent(CONTEXT* context) -{ - PIXEventsDetail::PIXEndEvent(context); -} - -template -class PIXScopedEventObject -{ - CONTEXT* m_context; - -public: - template - PIXScopedEventObject(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args) - : m_context(context) - { - PIXBeginEvent(m_context, color, formatString, args...); - } - - template - PIXScopedEventObject(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args) - : m_context(context) - { - PIXBeginEvent(m_context, color, formatString, args...); - } - - ~PIXScopedEventObject() - { - PIXEndEvent(m_context); - } -}; - -template -class PIXScopedRetailEventObject -{ - CONTEXT* m_context; - -public: - template - PIXScopedRetailEventObject(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args) - : m_context(context) - { - PIXBeginRetailEvent(m_context, color, formatString, args...); - } - - template - PIXScopedRetailEventObject(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args) - : m_context(context) - { - PIXBeginRetailEvent(m_context, color, formatString, args...); - } - - ~PIXScopedRetailEventObject() - { - PIXEndRetailEvent(m_context); - } -}; - -template<> -class PIXScopedEventObject -{ -public: - template - PIXScopedEventObject(UINT64 color, PCWSTR formatString, ARGS... args) - { - PIXBeginEvent(color, formatString, args...); - } - - template - PIXScopedEventObject(UINT64 color, PCSTR formatString, ARGS... args) - { - PIXBeginEvent(color, formatString, args...); - } - - ~PIXScopedEventObject() - { - PIXEndEvent(); - } -}; - -#define PIXConcatenate(a, b) a ## b -#define PIXGetScopedEventVariableName(a, b) PIXConcatenate(a, b) -#define PIXScopedEvent(context, ...) PIXScopedEventObject::Type> PIXGetScopedEventVariableName(pixEvent, __LINE__)(context, __VA_ARGS__) - -#ifdef PIX3__DEFINED_CONSTEXPR -#undef constexpr -#undef PIX3__DEFINED_CONSTEXPR -#endif - -#endif // _PIXEvents_H__ diff --git a/prog/3rdPartyLibs/winpixeventruntime/Include/WinPixEventRuntime/PIXEventsCommon.h b/prog/3rdPartyLibs/winpixeventruntime/Include/WinPixEventRuntime/PIXEventsCommon.h deleted file mode 100644 index a9c21d97f..000000000 --- a/prog/3rdPartyLibs/winpixeventruntime/Include/WinPixEventRuntime/PIXEventsCommon.h +++ /dev/null @@ -1,605 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. - -/*==========================================================================; -* -* Copyright (C) Microsoft Corporation. All Rights Reserved. -* -* File: PIXEventsCommon.h -* Content: PIX include file -* Don't include this file directly - use pix3.h -* -****************************************************************************/ -#pragma once - -#ifndef _PIXEventsCommon_H_ -#define _PIXEventsCommon_H_ - -#if defined(XBOX) || defined(_XBOX_ONE) || defined(_DURANGO) || defined(_GAMING_XBOX) || defined(_GAMING_XBOX_SCARLETT) -#define PIX_XBOX -#endif - -#include - -#if defined(_M_X64) || defined(_M_IX86) -#include -#endif - -// -// The PIXBeginEvent and PIXSetMarker functions have an optimized path for -// copying strings that work by copying 128-bit or 64-bits at a time. In some -// circumstances this may result in PIX logging the remaining memory after the -// null terminator. -// -// By default this optimization is enabled unless Address Sanitizer is enabled, -// since this optimization can trigger a global-buffer-overflow when copying -// string literals. -// -// The PIX_ENABLE_BLOCK_ARGUMENT_COPY controls whether or not this optimization -// is enabled. Applications may also explicitly set this macro to 0 to disable -// the optimization if necessary. -// - -// Check for Address Sanitizer on either Clang or MSVC - -#if defined(__has_feature) -#if __has_feature(address_sanitizer) -#define PIX_ASAN_ENABLED -#endif -#elif defined(__SANITIZE_ADDRESS__) -#define PIX_ASAN_ENABLED -#endif - -#if defined(PIX_ENABLE_BLOCK_ARGUMENT_COPY) -// Previously set values override everything -# define PIX_ENABLE_BLOCK_ARGUMENT_COPY_SET 0 -#elif defined(PIX_ASAN_ENABLED) -// Disable block argument copy when address sanitizer is enabled -#define PIX_ENABLE_BLOCK_ARGUMENT_COPY 0 -#define PIX_ENABLE_BLOCK_ARGUMENT_COPY_SET 1 -#endif - -#if !defined(PIX_ENABLE_BLOCK_ARGUMENT_COPY) -// Default to enabled. -#define PIX_ENABLE_BLOCK_ARGUMENT_COPY 1 -#define PIX_ENABLE_BLOCK_ARGUMENT_COPY_SET 1 -#endif - -struct PIXEventsBlockInfo; - -struct PIXEventsThreadInfo -{ - PIXEventsBlockInfo* block; - UINT64* biasedLimit; - UINT64* destination; -}; - -#ifdef PIX_XBOX -extern "C" UINT64 WINAPI PIXEventsReplaceBlock(bool getEarliestTime) noexcept; -#else -extern "C" UINT64 WINAPI PIXEventsReplaceBlock(PIXEventsThreadInfo * threadInfo, bool getEarliestTime) noexcept; -#endif - -enum PIXEventType -{ - PIXEvent_EndEvent = 0x000, - PIXEvent_BeginEvent_VarArgs = 0x001, - PIXEvent_BeginEvent_NoArgs = 0x002, - PIXEvent_SetMarker_VarArgs = 0x007, - PIXEvent_SetMarker_NoArgs = 0x008, - - PIXEvent_EndEvent_OnContext = 0x010, - PIXEvent_BeginEvent_OnContext_VarArgs = 0x011, - PIXEvent_BeginEvent_OnContext_NoArgs = 0x012, - PIXEvent_SetMarker_OnContext_VarArgs = 0x017, - PIXEvent_SetMarker_OnContext_NoArgs = 0x018, -}; - -static const UINT64 PIXEventsReservedRecordSpaceQwords = 64; -//this is used to make sure SSE string copy always will end 16-byte write in the current block -//this way only a check if destination < limit can be performed, instead of destination < limit - 1 -//since both these are UINT64* and SSE writes in 16 byte chunks, 8 bytes are kept in reserve -//so even if SSE overwrites 8 extra bytes, those will still belong to the correct block -//on next iteration check destination will be greater than limit -//this is used as well for fixed size UMD events and PIXEndEvent since these require less space -//than other variable length user events and do not need big reserved space -static const UINT64 PIXEventsReservedTailSpaceQwords = 2; -static const UINT64 PIXEventsSafeFastCopySpaceQwords = PIXEventsReservedRecordSpaceQwords - PIXEventsReservedTailSpaceQwords; -static const UINT64 PIXEventsGraphicsRecordSpaceQwords = 64; - -//Bits 7-19 (13 bits) -static const UINT64 PIXEventsBlockEndMarker = 0x00000000000FFF80; - -//Bits 10-19 (10 bits) -static const UINT64 PIXEventsTypeReadMask = 0x00000000000FFC00; -static const UINT64 PIXEventsTypeWriteMask = 0x00000000000003FF; -static const UINT64 PIXEventsTypeBitShift = 10; - -//Bits 20-63 (44 bits) -static const UINT64 PIXEventsTimestampReadMask = 0xFFFFFFFFFFF00000; -static const UINT64 PIXEventsTimestampWriteMask = 0x00000FFFFFFFFFFF; -static const UINT64 PIXEventsTimestampBitShift = 20; - -inline UINT64 PIXEncodeEventInfo(UINT64 timestamp, PIXEventType eventType) -{ - return ((timestamp & PIXEventsTimestampWriteMask) << PIXEventsTimestampBitShift) | - (((UINT64)eventType & PIXEventsTypeWriteMask) << PIXEventsTypeBitShift); -} - -//Bits 60-63 (4) -static const UINT64 PIXEventsStringAlignmentWriteMask = 0x000000000000000F; -static const UINT64 PIXEventsStringAlignmentReadMask = 0xF000000000000000; -static const UINT64 PIXEventsStringAlignmentBitShift = 60; - -//Bits 55-59 (5) -static const UINT64 PIXEventsStringCopyChunkSizeWriteMask = 0x000000000000001F; -static const UINT64 PIXEventsStringCopyChunkSizeReadMask = 0x0F80000000000000; -static const UINT64 PIXEventsStringCopyChunkSizeBitShift = 55; - -//Bit 54 -static const UINT64 PIXEventsStringIsANSIWriteMask = 0x0000000000000001; -static const UINT64 PIXEventsStringIsANSIReadMask = 0x0040000000000000; -static const UINT64 PIXEventsStringIsANSIBitShift = 54; - -//Bit 53 -static const UINT64 PIXEventsStringIsShortcutWriteMask = 0x0000000000000001; -static const UINT64 PIXEventsStringIsShortcutReadMask = 0x0020000000000000; -static const UINT64 PIXEventsStringIsShortcutBitShift = 53; - -inline UINT64 PIXEncodeStringInfo(UINT64 alignment, UINT64 copyChunkSize, BOOL isANSI, BOOL isShortcut) -{ - return ((alignment & PIXEventsStringAlignmentWriteMask) << PIXEventsStringAlignmentBitShift) | - ((copyChunkSize & PIXEventsStringCopyChunkSizeWriteMask) << PIXEventsStringCopyChunkSizeBitShift) | - (((UINT64)isANSI & PIXEventsStringIsANSIWriteMask) << PIXEventsStringIsANSIBitShift) | - (((UINT64)isShortcut & PIXEventsStringIsShortcutWriteMask) << PIXEventsStringIsShortcutBitShift); -} - -template -inline bool PIXIsPointerAligned(T* pointer) -{ - return !(((UINT64)pointer) & (alignment - 1)); -} - -// Generic template version slower because of the additional clear write -template -inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, T argument) -{ - if (destination < limit) - { - *destination = 0ull; - *((T*)destination) = argument; - ++destination; - } -} - -// int32 specialization to avoid slower double memory writes -template<> -inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, INT32 argument) -{ - if (destination < limit) - { - *reinterpret_cast(destination) = static_cast(argument); - ++destination; - } -} - -// unsigned int32 specialization to avoid slower double memory writes -template<> -inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, UINT32 argument) -{ - if (destination < limit) - { - *destination = static_cast(argument); - ++destination; - } -} - -// int64 specialization to avoid slower double memory writes -template<> -inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, INT64 argument) -{ - if (destination < limit) - { - *reinterpret_cast(destination) = argument; - ++destination; - } -} - -// unsigned int64 specialization to avoid slower double memory writes -template<> -inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, UINT64 argument) -{ - if (destination < limit) - { - *destination = argument; - ++destination; - } -} - -//floats must be cast to double during writing the data to be properly printed later when reading the data -//this is needed because when float is passed to varargs function it's cast to double -template<> -inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, float argument) -{ - if (destination < limit) - { - *reinterpret_cast(destination) = static_cast(argument); - ++destination; - } -} - -//char has to be cast to a longer signed integer type -//this is due to printf not ignoring correctly the upper bits of unsigned long long for a char format specifier -template<> -inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, char argument) -{ - if (destination < limit) - { - *reinterpret_cast(destination) = static_cast(argument); - ++destination; - } -} - -//unsigned char has to be cast to a longer unsigned integer type -//this is due to printf not ignoring correctly the upper bits of unsigned long long for a char format specifier -template<> -inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, unsigned char argument) -{ - if (destination < limit) - { - *destination = static_cast(argument); - ++destination; - } -} - -//bool has to be cast to an integer since it's not explicitly supported by string format routines -//there's no format specifier for bool type, but it should work with integer format specifiers -template<> -inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, bool argument) -{ - if (destination < limit) - { - *destination = static_cast(argument); - ++destination; - } -} - -inline void PIXCopyEventArgumentSlowest(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCSTR argument) -{ - *destination++ = PIXEncodeStringInfo(0, 8, TRUE, FALSE); - while (destination < limit) - { - UINT64 c = static_cast(argument[0]); - if (!c) - { - *destination++ = 0; - return; - } - UINT64 x = c; - c = static_cast(argument[1]); - if (!c) - { - *destination++ = x; - return; - } - x |= c << 8; - c = static_cast(argument[2]); - if (!c) - { - *destination++ = x; - return; - } - x |= c << 16; - c = static_cast(argument[3]); - if (!c) - { - *destination++ = x; - return; - } - x |= c << 24; - c = static_cast(argument[4]); - if (!c) - { - *destination++ = x; - return; - } - x |= c << 32; - c = static_cast(argument[5]); - if (!c) - { - *destination++ = x; - return; - } - x |= c << 40; - c = static_cast(argument[6]); - if (!c) - { - *destination++ = x; - return; - } - x |= c << 48; - c = static_cast(argument[7]); - if (!c) - { - *destination++ = x; - return; - } - x |= c << 56; - *destination++ = x; - argument += 8; - } -} - -inline void PIXCopyEventArgumentSlow(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCSTR argument) -{ -#if PIX_ENABLE_BLOCK_ARGUMENT_COPY - if (PIXIsPointerAligned<8>(argument)) - { - *destination++ = PIXEncodeStringInfo(0, 8, TRUE, FALSE); - UINT64* source = (UINT64*)argument; - while (destination < limit) - { - UINT64 qword = *source++; - *destination++ = qword; - //check if any of the characters is a terminating zero - if (!((qword & 0xFF00000000000000) && - (qword & 0xFF000000000000) && - (qword & 0xFF0000000000) && - (qword & 0xFF00000000) && - (qword & 0xFF000000) && - (qword & 0xFF0000) && - (qword & 0xFF00) && - (qword & 0xFF))) - { - break; - } - } - } - else -#endif // PIX_ENABLE_BLOCK_ARGUMENT_COPY - { - PIXCopyEventArgumentSlowest(destination, limit, argument); - } -} - -template<> -inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCSTR argument) -{ - if (destination < limit) - { - if (argument != nullptr) - { -#if (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY - if (PIXIsPointerAligned<16>(argument)) - { - *destination++ = PIXEncodeStringInfo(0, 16, TRUE, FALSE); - __m128i zero = _mm_setzero_si128(); - if (PIXIsPointerAligned<16>(destination)) - { - while (destination < limit) - { - __m128i mem = _mm_load_si128((__m128i*)argument); - _mm_store_si128((__m128i*)destination, mem); - //check if any of the characters is a terminating zero - __m128i res = _mm_cmpeq_epi8(mem, zero); - destination += 2; - if (_mm_movemask_epi8(res)) - break; - argument += 16; - } - } - else - { - while (destination < limit) - { - __m128i mem = _mm_load_si128((__m128i*)argument); - _mm_storeu_si128((__m128i*)destination, mem); - //check if any of the characters is a terminating zero - __m128i res = _mm_cmpeq_epi8(mem, zero); - destination += 2; - if (_mm_movemask_epi8(res)) - break; - argument += 16; - } - } - } - else -#endif // (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY - { - PIXCopyEventArgumentSlow(destination, limit, argument); - } - } - else - { - *destination++ = 0ull; - } - } -} - -template<> -inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PSTR argument) -{ - PIXCopyEventArgument(destination, limit, (PCSTR)argument); -} - -inline void PIXCopyEventArgumentSlowest(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCWSTR argument) -{ - *destination++ = PIXEncodeStringInfo(0, 8, FALSE, FALSE); - while (destination < limit) - { - UINT64 c = static_cast(argument[0]); - if (!c) - { - *destination++ = 0; - return; - } - UINT64 x = c; - c = static_cast(argument[1]); - if (!c) - { - *destination++ = x; - return; - } - x |= c << 16; - c = static_cast(argument[2]); - if (!c) - { - *destination++ = x; - return; - } - x |= c << 32; - c = static_cast(argument[3]); - if (!c) - { - *destination++ = x; - return; - } - x |= c << 48; - *destination++ = x; - argument += 4; - } -} - -inline void PIXCopyEventArgumentSlow(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCWSTR argument) -{ -#if PIX_ENABLE_BLOCK_ARGUMENT_COPY - if (PIXIsPointerAligned<8>(argument)) - { - *destination++ = PIXEncodeStringInfo(0, 8, FALSE, FALSE); - UINT64* source = (UINT64*)argument; - while (destination < limit) - { - UINT64 qword = *source++; - *destination++ = qword; - //check if any of the characters is a terminating zero - //TODO: check if reversed condition is faster - if (!((qword & 0xFFFF000000000000) && - (qword & 0xFFFF00000000) && - (qword & 0xFFFF0000) && - (qword & 0xFFFF))) - { - break; - } - } - } - else -#endif // PIX_ENABLE_BLOCK_ARGUMENT_COPY - { - PIXCopyEventArgumentSlowest(destination, limit, argument); - } -} - -template<> -inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCWSTR argument) -{ - if (destination < limit) - { - if (argument != nullptr) - { -#if (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY - if (PIXIsPointerAligned<16>(argument)) - { - *destination++ = PIXEncodeStringInfo(0, 16, FALSE, FALSE); - __m128i zero = _mm_setzero_si128(); - if (PIXIsPointerAligned<16>(destination)) - { - while (destination < limit) - { - __m128i mem = _mm_load_si128((__m128i*)argument); - _mm_store_si128((__m128i*)destination, mem); - //check if any of the characters is a terminating zero - __m128i res = _mm_cmpeq_epi16(mem, zero); - destination += 2; - if (_mm_movemask_epi8(res)) - break; - argument += 8; - } - } - else - { - while (destination < limit) - { - __m128i mem = _mm_load_si128((__m128i*)argument); - _mm_storeu_si128((__m128i*)destination, mem); - //check if any of the characters is a terminating zero - __m128i res = _mm_cmpeq_epi16(mem, zero); - destination += 2; - if (_mm_movemask_epi8(res)) - break; - argument += 8; - } - } - } - else -#endif // (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY - { - PIXCopyEventArgumentSlow(destination, limit, argument); - } - } - else - { - *destination++ = 0ull; - } - } -} - -template<> -inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PWSTR argument) -{ - PIXCopyEventArgument(destination, limit, (PCWSTR)argument); -}; - -#if defined(__d3d12_x_h__) || defined(__d3d12_xs_h__) || defined(__d3d12_h__) - -inline void PIXSetGPUMarkerOnContext(_In_ ID3D12GraphicsCommandList* commandList, _In_reads_bytes_(size) void* data, UINT size) -{ - commandList->SetMarker(D3D12_EVENT_METADATA, data, size); -} - -inline void PIXSetGPUMarkerOnContext(_In_ ID3D12CommandQueue* commandQueue, _In_reads_bytes_(size) void* data, UINT size) -{ - commandQueue->SetMarker(D3D12_EVENT_METADATA, data, size); -} - -inline void PIXBeginGPUEventOnContext(_In_ ID3D12GraphicsCommandList* commandList, _In_reads_bytes_(size) void* data, UINT size) -{ - commandList->BeginEvent(D3D12_EVENT_METADATA, data, size); -} - -inline void PIXBeginGPUEventOnContext(_In_ ID3D12CommandQueue* commandQueue, _In_reads_bytes_(size) void* data, UINT size) -{ - commandQueue->BeginEvent(D3D12_EVENT_METADATA, data, size); -} - -inline void PIXEndGPUEventOnContext(_In_ ID3D12GraphicsCommandList* commandList) -{ - commandList->EndEvent(); -} - -inline void PIXEndGPUEventOnContext(_In_ ID3D12CommandQueue* commandQueue) -{ - commandQueue->EndEvent(); -} - -#endif //__d3d12_h__ - -template struct PIXInferScopedEventType { typedef T Type; }; -template struct PIXInferScopedEventType { typedef T Type; }; -template struct PIXInferScopedEventType { typedef T Type; }; -template struct PIXInferScopedEventType { typedef T Type; }; -template<> struct PIXInferScopedEventType { typedef void Type; }; -template<> struct PIXInferScopedEventType { typedef void Type; }; -template<> struct PIXInferScopedEventType { typedef void Type; }; -template<> struct PIXInferScopedEventType { typedef void Type; }; -template<> struct PIXInferScopedEventType { typedef void Type; }; -template<> struct PIXInferScopedEventType { typedef void Type; }; -template<> struct PIXInferScopedEventType { typedef void Type; }; -template<> struct PIXInferScopedEventType { typedef void Type; }; - - -#if PIX_ENABLE_BLOCK_ARGUMENT_COPY_SET -#undef PIX_ENABLE_BLOCK_ARGUMENT_COPY -#endif - -#undef PIX_ENABLE_BLOCK_ARGUMENT_COPY_SET - -#endif //_PIXEventsCommon_H_ diff --git a/prog/3rdPartyLibs/winpixeventruntime/Include/WinPixEventRuntime/pix3.h b/prog/3rdPartyLibs/winpixeventruntime/Include/WinPixEventRuntime/pix3.h deleted file mode 100644 index 56d3142a3..000000000 --- a/prog/3rdPartyLibs/winpixeventruntime/Include/WinPixEventRuntime/pix3.h +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. - -/*==========================================================================; - * - * Copyright (C) Microsoft Corporation. All Rights Reserved. - * - * File: pix3.h - * Content: PIX include file - * - ****************************************************************************/ -#pragma once - -#ifndef _PIX3_H_ -#define _PIX3_H_ - -#include - -#ifndef __cplusplus -#error "Only C++ files can include pix3.h. C is not supported." -#endif - -#if !defined(USE_PIX_SUPPORTED_ARCHITECTURE) -#if defined(_M_X64) || defined(USE_PIX_ON_ALL_ARCHITECTURES) || defined(_M_ARM64) -#define USE_PIX_SUPPORTED_ARCHITECTURE -#endif -#endif - -#if !defined(USE_PIX) -#if defined(USE_PIX_SUPPORTED_ARCHITECTURE) && (defined(_DEBUG) || DBG || defined(PROFILE) || defined(PROFILE_BUILD)) && !defined(_PREFAST_) -#define USE_PIX -#endif -#endif - -#if defined(USE_PIX) && !defined(USE_PIX_SUPPORTED_ARCHITECTURE) -#pragma message("Warning: Pix markers are only supported on AMD64 and ARM64") -#endif - - -// These flags are used by both PIXBeginCapture and PIXGetCaptureState -#define PIX_CAPTURE_TIMING (1 << 0) -#define PIX_CAPTURE_GPU (1 << 1) -#define PIX_CAPTURE_FUNCTION_SUMMARY (1 << 2) -#define PIX_CAPTURE_FUNCTION_DETAILS (1 << 3) -#define PIX_CAPTURE_CALLGRAPH (1 << 4) -#define PIX_CAPTURE_INSTRUCTION_TRACE (1 << 5) -#define PIX_CAPTURE_SYSTEM_MONITOR_COUNTERS (1 << 6) -#define PIX_CAPTURE_VIDEO (1 << 7) -#define PIX_CAPTURE_AUDIO (1 << 8) -#define PIX_CAPTURE_RESERVED (1 << 15) - -union PIXCaptureParameters -{ - enum PIXCaptureStorage - { - Memory = 0, - }; - - struct GpuCaptureParameters - { - PCWSTR FileName; - } GpuCaptureParameters; - - struct TimingCaptureParameters - { - PCWSTR FileName; - UINT32 MaximumToolingMemorySizeMb; - PIXCaptureStorage CaptureStorage; - - BOOL CaptureGpuTiming; - - BOOL CaptureCallstacks; - BOOL CaptureCpuSamples; - UINT32 CpuSamplesPerSecond; - - BOOL CaptureFileIO; - - BOOL CaptureVirtualAllocEvents; - BOOL CaptureHeapAllocEvents; - BOOL CaptureXMemEvents; // Xbox only - BOOL CapturePixMemEvents; // Xbox only - } TimingCaptureParameters; -}; - -typedef PIXCaptureParameters* PPIXCaptureParameters; - -#if defined(XBOX) || defined(_XBOX_ONE) || defined(_DURANGO) || defined(_GAMING_XBOX) || defined(_GAMING_XBOX_SCARLETT) -#include "pix3_xbox.h" -#else -#include "pix3_win.h" -#endif - -#if defined(USE_PIX_SUPPORTED_ARCHITECTURE) && (defined(USE_PIX) || defined(USE_PIX_RETAIL)) - -#define PIX_EVENTS_ARE_TURNED_ON - -#include "PIXEventsCommon.h" -#include "PIXEvents.h" - -#ifdef USE_PIX -// Starts a programmatically controlled capture. -// captureFlags uses the PIX_CAPTURE_* family of flags to specify the type of capture to take -extern "C" HRESULT WINAPI PIXBeginCapture2(DWORD captureFlags, _In_opt_ const PPIXCaptureParameters captureParameters); -inline HRESULT PIXBeginCapture(DWORD captureFlags, _In_opt_ const PPIXCaptureParameters captureParameters) { return PIXBeginCapture2(captureFlags, captureParameters); } - -// Stops a programmatically controlled capture -// If discard == TRUE, the captured data is discarded -// If discard == FALSE, the captured data is saved -// discard parameter is not supported on Windows -extern "C" HRESULT WINAPI PIXEndCapture(BOOL discard); - -extern "C" DWORD WINAPI PIXGetCaptureState(); - -extern "C" void WINAPI PIXReportCounter(_In_ PCWSTR name, float value); - -#endif // USE_PIX - -#endif // (USE_PIX_SUPPORTED_ARCHITECTURE) && (USE_PIX || USE_PIX_RETAIL) - -#if !defined(USE_PIX_SUPPORTED_ARCHITECTURE) || !defined(USE_PIX) - -// Eliminate these APIs when not using PIX -inline HRESULT PIXBeginCapture2(DWORD, _In_opt_ const PIXCaptureParameters*) { return S_OK; } -inline HRESULT PIXBeginCapture(DWORD, _In_opt_ const PIXCaptureParameters*) { return S_OK; } -inline HRESULT PIXEndCapture(BOOL) { return S_OK; } -inline HRESULT PIXGpuCaptureNextFrames(PCWSTR, UINT32) { return S_OK; } -inline HRESULT PIXSetTargetWindow(HWND) { return S_OK; } -inline HRESULT PIXForceD3D11On12() { return S_OK; } -inline HRESULT WINAPI PIXSetHUDOptions(PIXHUDOptions) { return S_OK; } -inline HMODULE PIXLoadLatestWinPixGpuCapturerLibrary() { return nullptr; } -inline DWORD PIXGetCaptureState() { return 0; } -inline void PIXReportCounter(_In_ PCWSTR, float) {} -inline void PIXNotifyWakeFromFenceSignal(_In_ HANDLE) {} - -#if !defined(USE_PIX_RETAIL) - -inline void PIXBeginEvent(UINT64, _In_ PCSTR, ...) {} -inline void PIXBeginEvent(UINT64, _In_ PCWSTR, ...) {} -inline void PIXBeginEvent(void*, UINT64, _In_ PCSTR, ...) {} -inline void PIXBeginEvent(void*, UINT64, _In_ PCWSTR, ...) {} -inline void PIXEndEvent() {} -inline void PIXEndEvent(void*) {} -inline void PIXSetMarker(UINT64, _In_ PCSTR, ...) {} -inline void PIXSetMarker(UINT64, _In_ PCWSTR, ...) {} -inline void PIXSetMarker(void*, UINT64, _In_ PCSTR, ...) {} -inline void PIXSetMarker(void*, UINT64, _In_ PCWSTR, ...) {} -inline void PIXBeginRetailEvent(void*, UINT64, _In_ PCSTR, ...) {} -inline void PIXBeginRetailEvent(void*, UINT64, _In_ PCWSTR, ...) {} -inline void PIXEndRetailEvent(void*) {} -inline void PIXSetRetailMarker(void*, UINT64, _In_ PCSTR, ...) {} -inline void PIXSetRetailMarker(void*, UINT64, _In_ PCWSTR, ...) {} -inline void PIXScopedEvent(UINT64, _In_ PCSTR, ...) {} -inline void PIXScopedEvent(UINT64, _In_ PCWSTR, ...) {} -inline void PIXScopedEvent(void*, UINT64, _In_ PCSTR, ...) {} -inline void PIXScopedEvent(void*, UINT64, _In_ PCWSTR, ...) {} - -#endif // !USE_PIX_RETAIL - -// don't show warnings about expressions with no effect -#pragma warning(disable:4548) -#pragma warning(disable:4555) - -#endif // !USE_PIX_SUPPORTED_ARCHITECTURE || !USE_PIX - -// Use these functions to specify colors to pass as metadata to a PIX event/marker API. -// Use PIX_COLOR() to specify a particular color for an event. -// Or, use PIX_COLOR_INDEX() to specify a set of unique event categories, and let PIX choose -// the colors to represent each category. -inline UINT PIX_COLOR(BYTE r, BYTE g, BYTE b) { return 0xff000000 | (r << 16) | (g << 8) | b; } -inline UINT PIX_COLOR_INDEX(BYTE i) { return i; } -const UINT PIX_COLOR_DEFAULT = PIX_COLOR_INDEX(0); - -#endif // _PIX3_H_ diff --git a/prog/3rdPartyLibs/winpixeventruntime/Include/WinPixEventRuntime/pix3_win.h b/prog/3rdPartyLibs/winpixeventruntime/Include/WinPixEventRuntime/pix3_win.h deleted file mode 100644 index 84479ef38..000000000 --- a/prog/3rdPartyLibs/winpixeventruntime/Include/WinPixEventRuntime/pix3_win.h +++ /dev/null @@ -1,287 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. - -/*==========================================================================; - * - * Copyright (C) Microsoft Corporation. All Rights Reserved. - * - * File: PIX3_win.h - * Content: PIX include file - * Don't include this file directly - use pix3.h - * - ****************************************************************************/ - -#pragma once - -#ifndef _PIX3_H_ -#error Don't include this file directly - use pix3.h -#endif - -#ifndef _PIX3_WIN_H_ -#define _PIX3_WIN_H_ - -// PIXEventsThreadInfo is defined in PIXEventsCommon.h -struct PIXEventsThreadInfo; - -extern "C" PIXEventsThreadInfo* WINAPI PIXGetThreadInfo() noexcept; - -#if defined(USE_PIX) && defined(USE_PIX_SUPPORTED_ARCHITECTURE) -// Notifies PIX that an event handle was set as a result of a D3D12 fence being signaled. -// The event specified must have the same handle value as the handle -// used in ID3D12Fence::SetEventOnCompletion. -extern "C" void WINAPI PIXNotifyWakeFromFenceSignal(_In_ HANDLE event); -#endif - -// The following defines denote the different metadata values that have been used -// by tools to denote how to parse pix marker event data. The first two values -// are legacy values. -#define WINPIX_EVENT_UNICODE_VERSION 0 -#define WINPIX_EVENT_ANSI_VERSION 1 -#define WINPIX_EVENT_PIX3BLOB_VERSION 2 - -#define D3D12_EVENT_METADATA WINPIX_EVENT_PIX3BLOB_VERSION - -__forceinline UINT64 PIXGetTimestampCounter() -{ - LARGE_INTEGER time = {}; - QueryPerformanceCounter(&time); - return static_cast(time.QuadPart); -} - -enum PIXHUDOptions -{ - PIX_HUD_SHOW_ON_ALL_WINDOWS = 0x1, - PIX_HUD_SHOW_ON_TARGET_WINDOW_ONLY = 0x2, - PIX_HUD_SHOW_ON_NO_WINDOWS = 0x4 -}; -DEFINE_ENUM_FLAG_OPERATORS(PIXHUDOptions); - -#if defined(USE_PIX_SUPPORTED_ARCHITECTURE) && defined(USE_PIX) - -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) - -namespace PixImpl -{ - __forceinline void * GetFunctionPtr(LPCSTR fnName) noexcept - { - HMODULE module = GetModuleHandleW(L"WinPixGpuCapturer.dll"); - if (module == NULL) - { - return nullptr; - } - - auto fn = GetProcAddress(module, fnName); - if (fn == nullptr) - { - return nullptr; - } - - return fn; - } -} - -#include -#include -#include - -#define PIXERRORCHECK(value) do { \ - if (FAILED(value)) \ - return nullptr; \ - } while(0) - -__forceinline HMODULE PIXLoadLatestWinPixGpuCapturerLibrary() -{ - HMODULE libHandle{}; - - if (GetModuleHandleExW(0, L"WinPixGpuCapturer.dll", &libHandle)) - { - return libHandle; - } - - LPWSTR programFilesPath = nullptr; - if (FAILED(SHGetKnownFolderPath(FOLDERID_ProgramFiles, KF_FLAG_DEFAULT, NULL, &programFilesPath))) - { - CoTaskMemFree(programFilesPath); - return nullptr; - } - - wchar_t pixSearchPath[MAX_PATH]; - - if (FAILED(StringCchCopyW(pixSearchPath, MAX_PATH, programFilesPath))) - { - CoTaskMemFree(programFilesPath); - return nullptr; - } - CoTaskMemFree(programFilesPath); - - PIXERRORCHECK(StringCchCatW(pixSearchPath, MAX_PATH, L"\\Microsoft PIX\\*")); - - WIN32_FIND_DATAW findData; - bool foundPixInstallation = false; - wchar_t newestVersionFound[MAX_PATH]; - wchar_t output[MAX_PATH]; - wchar_t possibleOutput[MAX_PATH]; - - HANDLE hFind = FindFirstFileW(pixSearchPath, &findData); - if (hFind != INVALID_HANDLE_VALUE) - { - do - { - if (((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY) && - (findData.cFileName[0] != '.')) - { - if (!foundPixInstallation || wcscmp(newestVersionFound, findData.cFileName) <= 0) - { - // length - 1 to get rid of the wildcard character in the search path - PIXERRORCHECK(StringCchCopyNW(possibleOutput, MAX_PATH, pixSearchPath, wcslen(pixSearchPath) - 1)); - PIXERRORCHECK(StringCchCatW(possibleOutput, MAX_PATH, findData.cFileName)); - PIXERRORCHECK(StringCchCatW(possibleOutput, MAX_PATH, L"\\WinPixGpuCapturer.dll")); - - DWORD result = GetFileAttributesW(possibleOutput); - - if (result != INVALID_FILE_ATTRIBUTES && !(result & FILE_ATTRIBUTE_DIRECTORY)) - { - foundPixInstallation = true; - PIXERRORCHECK(StringCchCopyW(newestVersionFound, _countof(newestVersionFound), findData.cFileName)); - PIXERRORCHECK(StringCchCopyW(output, _countof(possibleOutput), possibleOutput)); - } - } - } - } while (FindNextFileW(hFind, &findData) != 0); - } - - FindClose(hFind); - - if (!foundPixInstallation) - { - SetLastError(ERROR_FILE_NOT_FOUND); - return nullptr; - } - - return LoadLibraryW(output); -} - -#undef PIXERRORCHECK - -__forceinline HRESULT WINAPI PIXSetTargetWindow(HWND hwnd) -{ - typedef void(WINAPI* SetGlobalTargetWindowFn)(HWND); - - auto fn = (SetGlobalTargetWindowFn)PixImpl::GetFunctionPtr("SetGlobalTargetWindow"); - if (fn == nullptr) - { - return HRESULT_FROM_WIN32(GetLastError()); - } - - fn(hwnd); - return S_OK; -} - -__forceinline HRESULT WINAPI PIXGpuCaptureNextFrames(PCWSTR fileName, UINT32 numFrames) -{ - typedef HRESULT(WINAPI* CaptureNextFrameFn)(PCWSTR, UINT32); - - auto fn = (CaptureNextFrameFn)PixImpl::GetFunctionPtr("CaptureNextFrame"); - if (fn == nullptr) - { - return HRESULT_FROM_WIN32(GetLastError()); - } - - return fn(fileName, numFrames); -} - -extern "C" __forceinline HRESULT WINAPI PIXBeginCapture2(DWORD captureFlags, _In_opt_ const PPIXCaptureParameters captureParameters) -{ - if (captureFlags == PIX_CAPTURE_GPU) - { - typedef HRESULT(WINAPI* BeginProgrammaticGpuCaptureFn)(const PPIXCaptureParameters); - - auto fn = (BeginProgrammaticGpuCaptureFn)PixImpl::GetFunctionPtr("BeginProgrammaticGpuCapture"); - if (fn == nullptr) - { - return HRESULT_FROM_WIN32(GetLastError()); - } - - return fn(captureParameters); - } - else - { - return E_NOTIMPL; - } -} - -extern "C" __forceinline HRESULT WINAPI PIXEndCapture(BOOL discard) -{ - UNREFERENCED_PARAMETER(discard); - - typedef HRESULT(WINAPI* EndProgrammaticGpuCaptureFn)(void); - - auto fn = (EndProgrammaticGpuCaptureFn)PixImpl::GetFunctionPtr("EndProgrammaticGpuCapture"); - if (fn == NULL) - { - return HRESULT_FROM_WIN32(GetLastError()); - } - - return fn(); -} - -__forceinline HRESULT WINAPI PIXForceD3D11On12() -{ - typedef HRESULT (WINAPI* ForceD3D11On12Fn)(void); - - auto fn = (ForceD3D11On12Fn)PixImpl::GetFunctionPtr("ForceD3D11On12"); - if (fn == NULL) - { - return HRESULT_FROM_WIN32(GetLastError()); - } - - return fn(); -} - -__forceinline HRESULT WINAPI PIXSetHUDOptions(PIXHUDOptions hudOptions) -{ - typedef HRESULT(WINAPI* SetHUDOptionsFn)(PIXHUDOptions); - - auto fn = (SetHUDOptionsFn)PixImpl::GetFunctionPtr("SetHUDOptions"); - if (fn == NULL) - { - return HRESULT_FROM_WIN32(GetLastError()); - } - - return fn(hudOptions); -} - -#else -__forceinline HMODULE PIXLoadLatestWinPixGpuCapturerLibrary() -{ - return nullptr; -} -__forceinline HRESULT WINAPI PIXSetTargetWindow(HWND) -{ - return E_NOTIMPL; -} - -__forceinline HRESULT WINAPI PIXGpuCaptureNextFrames(PCWSTR, UINT32) -{ - return E_NOTIMPL; -} -extern "C" __forceinline HRESULT WINAPI PIXBeginCapture2(DWORD, _In_opt_ const PPIXCaptureParameters) -{ - return E_NOTIMPL; -} -extern "C" __forceinline HRESULT WINAPI PIXEndCapture(BOOL) -{ - return E_NOTIMPL; -} -__forceinline HRESULT WINAPI PIXForceD3D11On12() -{ - return E_NOTIMPL; -} -__forceinline HRESULT WINAPI PIXSetHUDOptions(PIXHUDOptions) -{ - return E_NOTIMPL; -} -#endif // WINAPI_PARTITION - -#endif // USE_PIX_SUPPORTED_ARCHITECTURE || USE_PIX - -#endif //_PIX3_WIN_H_ diff --git a/prog/3rdPartyLibs/winpixeventruntime/bin/x64/WinPixEventRuntime.lib b/prog/3rdPartyLibs/winpixeventruntime/bin/x64/WinPixEventRuntime.lib deleted file mode 100644 index 18450a210..000000000 Binary files a/prog/3rdPartyLibs/winpixeventruntime/bin/x64/WinPixEventRuntime.lib and /dev/null differ diff --git a/prog/3rdPartyLibs/winpixeventruntime/version.txt b/prog/3rdPartyLibs/winpixeventruntime/version.txt deleted file mode 100644 index 2271bedde..000000000 --- a/prog/3rdPartyLibs/winpixeventruntime/version.txt +++ /dev/null @@ -1 +0,0 @@ -1.0.220124001 stripped \ No newline at end of file diff --git a/prog/3rdPartyLibs/wtl-8.1/include/atlapp.h b/prog/3rdPartyLibs/wtl-8.1/include/atlapp.h deleted file mode 100644 index c94f7978e..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/atlapp.h +++ /dev/null @@ -1,1690 +0,0 @@ -// Windows Template Library - WTL version 8.1 -// Copyright (C) Microsoft Corporation. All rights reserved. -// -// This file is a part of the Windows Template Library. -// The use and distribution terms for this software are covered by the -// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php) -// which can be found in the file CPL.TXT at the root of this distribution. -// By using this software in any fashion, you are agreeing to be bound by -// the terms of this license. You must not remove this notice, or -// any other, from this software. - -#ifndef __ATLAPP_H__ -#define __ATLAPP_H__ - -#pragma once - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#ifndef __ATLBASE_H__ - #error atlapp.h requires atlbase.h to be included first -#endif - -#ifndef _WIN32_WCE - #if (WINVER < 0x0400) - #error WTL requires Windows version 4.0 or higher - #endif - - #if (_WIN32_IE < 0x0300) - #error WTL requires IE version 3.0 or higher - #endif -#endif - -#ifdef _ATL_NO_COMMODULE - #error WTL requires that _ATL_NO_COMMODULE is not defined -#endif // _ATL_NO_COMMODULE - -#if defined(_WIN32_WCE) && defined(_ATL_MIN_CRT) - #pragma message("Warning: WTL for Windows CE doesn't use _ATL_MIN_CRT") -#endif // defined(_WIN32_WCE) && defined(_ATL_MIN_CRT) - -#include -#if !defined(_ATL_MIN_CRT) && defined(_MT) && !defined(_WIN32_WCE) - #include // for _beginthreadex -#endif - -#if (_ATL_VER < 0x0800) && !defined(_DEBUG) - #include -#endif - -#include -#ifndef _WIN32_WCE -#pragma comment(lib, "comctl32.lib") -#endif // !_WIN32_WCE - -#ifndef _WIN32_WCE - #include "atlres.h" -#else // CE specific - #include "atlresce.h" -#endif // _WIN32_WCE - -// We need to disable this warning because of template class arguments -#pragma warning(disable: 4127) - - -/////////////////////////////////////////////////////////////////////////////// -// WTL version number - -#define _WTL_VER 0x0810 - - -/////////////////////////////////////////////////////////////////////////////// -// Classes in this file: -// -// CMessageFilter -// CIdleHandler -// CMessageLoop -// -// CAppModule -// CServerAppModule -// -// Global functions: -// AtlGetDefaultGuiFont() -// AtlCreateBoldFont() -// AtlInitCommonControls() - - -/////////////////////////////////////////////////////////////////////////////// -// Global support for Windows CE - -#ifdef _WIN32_WCE - -#ifndef SW_SHOWDEFAULT - #define SW_SHOWDEFAULT SW_SHOWNORMAL -#endif // !SW_SHOWDEFAULT - -// These get's OR-ed in a constant and will have no effect. -// Defining them reduces the number of #ifdefs required for CE. -#define LR_DEFAULTSIZE 0 -#define LR_LOADFROMFILE 0 - -#ifndef SM_CXCURSOR - #define SM_CXCURSOR 13 -#endif -#ifndef SM_CYCURSOR - #define SM_CYCURSOR 14 -#endif - -inline BOOL IsMenu(HMENU hMenu) -{ - MENUITEMINFO mii = { sizeof(MENUITEMINFO) }; - ::SetLastError(0); - BOOL bRet = ::GetMenuItemInfo(hMenu, 0, TRUE, &mii); - if(!bRet) - bRet = (::GetLastError() != ERROR_INVALID_MENU_HANDLE) ? TRUE : FALSE; - return bRet; -} - -#if (_WIN32_WCE >= 410) -extern "C" void WINAPI ListView_SetItemSpacing(HWND hwndLV, int iHeight); -#endif // (_WIN32_WCE >= 410) - -inline int MulDiv(IN int nNumber, IN int nNumerator, IN int nDenominator) -{ - __int64 multiple = nNumber * nNumerator; - return static_cast(multiple / nDenominator); -} - -#if (_ATL_VER >= 0x0800) - -#ifndef _WTL_KEEP_WS_OVERLAPPEDWINDOW - #ifdef WS_OVERLAPPEDWINDOW - #undef WS_OVERLAPPEDWINDOW - #define WS_OVERLAPPEDWINDOW 0 - #endif // WS_OVERLAPPEDWINDOW -#endif // !_WTL_KEEP_WS_OVERLAPPEDWINDOW - -#ifndef RDW_FRAME - #define RDW_FRAME 0 -#endif // !RDW_FRAME - -#ifndef WM_WINDOWPOSCHANGING - #define WM_WINDOWPOSCHANGING 0 -#endif // !WM_WINDOWPOSCHANGING - -#define FreeResource(x) -#define UnlockResource(x) - -namespace ATL -{ - inline HRESULT CComModule::RegisterClassObjects(DWORD /*dwClsContext*/, DWORD /*dwFlags*/) throw() - { return E_NOTIMPL; } - inline HRESULT CComModule::RevokeClassObjects() throw() - { return E_NOTIMPL; } -}; // namespace ATL - -#ifndef lstrlenW - #define lstrlenW (int)ATL::lstrlenW -#endif // lstrlenW - -inline int WINAPI lstrlenA(LPCSTR lpszString) -{ return ATL::lstrlenA(lpszString); } - -#ifdef lstrcpyn - #undef lstrcpyn - #define lstrcpyn ATL::lstrcpynW -#endif // lstrcpyn - -#ifndef SetWindowLongPtrW - inline LONG_PTR tmp_SetWindowLongPtrW( HWND hWnd, int nIndex, LONG_PTR dwNewLong ) - { - return( ::SetWindowLongW( hWnd, nIndex, LONG( dwNewLong ) ) ); - } - #define SetWindowLongPtrW tmp_SetWindowLongPtrW -#endif - -#ifndef GetWindowLongPtrW - inline LONG_PTR tmp_GetWindowLongPtrW( HWND hWnd, int nIndex ) - { - return( ::GetWindowLongW( hWnd, nIndex ) ); - } - #define GetWindowLongPtrW tmp_GetWindowLongPtrW -#endif - -#ifndef LongToPtr - #define LongToPtr(x) ((void*)x) -#endif - -#ifndef PtrToInt - #define PtrToInt( p ) ((INT)(INT_PTR) (p) ) -#endif - -#else // !(_ATL_VER >= 0x0800) - -#ifdef lstrlenW - #undef lstrlenW - #define lstrlenW (int)::wcslen -#endif // lstrlenW - -#define lstrlenA (int)strlen - -#ifndef lstrcpyn - inline LPTSTR lstrcpyn(LPTSTR lpstrDest, LPCTSTR lpstrSrc, int nLength) - { - if(lpstrDest == NULL || lpstrSrc == NULL || nLength <= 0) - return NULL; - int nLen = min(lstrlen(lpstrSrc), nLength - 1); - LPTSTR lpstrRet = (LPTSTR)memcpy(lpstrDest, lpstrSrc, nLen * sizeof(TCHAR)); - lpstrDest[nLen] = 0; - return lpstrRet; - } -#endif // !lstrcpyn - -#ifndef lstrcpynW - inline LPWSTR lstrcpynW(LPWSTR lpstrDest, LPCWSTR lpstrSrc, int nLength) - { - return lstrcpyn(lpstrDest, lpstrSrc, nLength); // WinCE is Unicode only - } -#endif // !lstrcpynW - -#ifndef lstrcpynA - inline LPSTR lstrcpynA(LPSTR lpstrDest, LPCSTR lpstrSrc, int nLength) - { - if(lpstrDest == NULL || lpstrSrc == NULL || nLength <= 0) - return NULL; - int nLen = min(lstrlenA(lpstrSrc), nLength - 1); - LPSTR lpstrRet = (LPSTR)memcpy(lpstrDest, lpstrSrc, nLen * sizeof(char)); - lpstrDest[nLen] = 0; - return lpstrRet; - } -#endif // !lstrcpyn - -#ifdef TrackPopupMenu - #undef TrackPopupMenu -#endif // TrackPopupMenu - -#define DECLARE_WND_CLASS_EX(WndClassName, style, bkgnd) \ -static CWndClassInfo& GetWndClassInfo() \ -{ \ - static CWndClassInfo wc = \ - { \ - { style, StartWindowProc, \ - 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName }, \ - NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \ - }; \ - return wc; \ -} - -#ifndef _MAX_FNAME - #define _MAX_FNAME _MAX_PATH -#endif // _MAX_FNAME - -#if (_WIN32_WCE < 400) - #define MAKEINTATOM(i) (LPTSTR)((ULONG_PTR)((WORD)(i))) -#endif // (_WIN32_WCE < 400) - -#if (_WIN32_WCE < 410) - #define WHEEL_PAGESCROLL (UINT_MAX) - #define WHEEL_DELTA 120 -#endif // (_WIN32_WCE < 410) - -#ifdef DrawIcon - #undef DrawIcon -#endif - -#ifndef VARCMP_LT - #define VARCMP_LT 0 -#endif -#ifndef VARCMP_EQ - #define VARCMP_EQ 1 -#endif -#ifndef VARCMP_GT - #define VARCMP_GT 2 -#endif -#ifndef VARCMP_NULL - #define VARCMP_NULL 3 -#endif - -#ifndef RDW_ALLCHILDREN - #define RDW_ALLCHILDREN 0 -#endif - -#endif // !(_ATL_VER >= 0x0800) - -#endif // _WIN32_WCE - - -/////////////////////////////////////////////////////////////////////////////// -// Global support for using original VC++ 6.0 headers with WTL - -#ifndef _ATL_NO_OLD_HEADERS_WIN64 -#if !defined(_WIN64) && (_ATL_VER < 0x0700) - - #ifndef PSM_INSERTPAGE - #define PSM_INSERTPAGE (WM_USER + 119) - #endif // !PSM_INSERTPAGE - - #ifndef GetClassLongPtr - #define GetClassLongPtrA GetClassLongA - #define GetClassLongPtrW GetClassLongW - #ifdef UNICODE - #define GetClassLongPtr GetClassLongPtrW - #else - #define GetClassLongPtr GetClassLongPtrA - #endif // !UNICODE - #endif // !GetClassLongPtr - - #ifndef GCLP_HICONSM - #define GCLP_HICONSM (-34) - #endif // !GCLP_HICONSM - - #ifndef GetWindowLongPtr - #define GetWindowLongPtrA GetWindowLongA - #define GetWindowLongPtrW GetWindowLongW - #ifdef UNICODE - #define GetWindowLongPtr GetWindowLongPtrW - #else - #define GetWindowLongPtr GetWindowLongPtrA - #endif // !UNICODE - #endif // !GetWindowLongPtr - - #ifndef SetWindowLongPtr - #define SetWindowLongPtrA SetWindowLongA - #define SetWindowLongPtrW SetWindowLongW - #ifdef UNICODE - #define SetWindowLongPtr SetWindowLongPtrW - #else - #define SetWindowLongPtr SetWindowLongPtrA - #endif // !UNICODE - #endif // !SetWindowLongPtr - - #ifndef GWLP_WNDPROC - #define GWLP_WNDPROC (-4) - #endif - #ifndef GWLP_HINSTANCE - #define GWLP_HINSTANCE (-6) - #endif - #ifndef GWLP_HWNDPARENT - #define GWLP_HWNDPARENT (-8) - #endif - #ifndef GWLP_USERDATA - #define GWLP_USERDATA (-21) - #endif - #ifndef GWLP_ID - #define GWLP_ID (-12) - #endif - - #ifndef DWLP_MSGRESULT - #define DWLP_MSGRESULT 0 - #endif - - typedef long LONG_PTR; - typedef unsigned long ULONG_PTR; - typedef ULONG_PTR DWORD_PTR; - - #ifndef HandleToUlong - #define HandleToUlong( h ) ((ULONG)(ULONG_PTR)(h) ) - #endif - #ifndef HandleToLong - #define HandleToLong( h ) ((LONG)(LONG_PTR) (h) ) - #endif - #ifndef LongToHandle - #define LongToHandle( h) ((HANDLE)(LONG_PTR) (h)) - #endif - #ifndef PtrToUlong - #define PtrToUlong( p ) ((ULONG)(ULONG_PTR) (p) ) - #endif - #ifndef PtrToLong - #define PtrToLong( p ) ((LONG)(LONG_PTR) (p) ) - #endif - #ifndef PtrToUint - #define PtrToUint( p ) ((UINT)(UINT_PTR) (p) ) - #endif - #ifndef PtrToInt - #define PtrToInt( p ) ((INT)(INT_PTR) (p) ) - #endif - #ifndef PtrToUshort - #define PtrToUshort( p ) ((unsigned short)(ULONG_PTR)(p) ) - #endif - #ifndef PtrToShort - #define PtrToShort( p ) ((short)(LONG_PTR)(p) ) - #endif - #ifndef IntToPtr - #define IntToPtr( i ) ((VOID *)(INT_PTR)((int)i)) - #endif - #ifndef UIntToPtr - #define UIntToPtr( ui ) ((VOID *)(UINT_PTR)((unsigned int)ui)) - #endif - #ifndef LongToPtr - #define LongToPtr( l ) ((VOID *)(LONG_PTR)((long)l)) - #endif - #ifndef ULongToPtr - #define ULongToPtr( ul ) ((VOID *)(ULONG_PTR)((unsigned long)ul)) - #endif - -#endif // !defined(_WIN64) && (_ATL_VER < 0x0700) -#endif // !_ATL_NO_OLD_HEADERS_WIN64 - - -/////////////////////////////////////////////////////////////////////////////// -// Global support for SecureHelper functions - -#ifndef _TRUNCATE - #define _TRUNCATE ((size_t)-1) -#endif - -#ifndef _ERRCODE_DEFINED - #define _ERRCODE_DEFINED - typedef int errno_t; -#endif - -#ifndef _SECURECRT_ERRCODE_VALUES_DEFINED - #define _SECURECRT_ERRCODE_VALUES_DEFINED - #define EINVAL 22 - #define STRUNCATE 80 -#endif - -#ifndef _countof - #define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0])) -#endif - - -/////////////////////////////////////////////////////////////////////////////// -// Miscellaneous global support - -// define useful macros from winuser.h -#ifndef IS_INTRESOURCE - #define IS_INTRESOURCE(_r) (((ULONG_PTR)(_r) >> 16) == 0) -#endif // IS_INTRESOURCE - -// protect template members from windowsx.h macros -#ifdef _INC_WINDOWSX - #undef SubclassWindow -#endif // _INC_WINDOWSX - -// define useful macros from windowsx.h -#ifndef GET_X_LPARAM - #define GET_X_LPARAM(lParam) ((int)(short)LOWORD(lParam)) -#endif -#ifndef GET_Y_LPARAM - #define GET_Y_LPARAM(lParam) ((int)(short)HIWORD(lParam)) -#endif - -// Dummy structs for compiling with /CLR -#if (_MSC_VER >= 1300) && defined(_MANAGED) - __if_not_exists(_IMAGELIST::_IMAGELIST) { struct _IMAGELIST { }; } - __if_not_exists(_TREEITEM::_TREEITEM) { struct _TREEITEM { }; } - __if_not_exists(_PSP::_PSP) { struct _PSP { }; } -#endif - -// Define ATLVERIFY macro for ATL3 -#if (_ATL_VER < 0x0700) - #ifndef ATLVERIFY - #ifdef _DEBUG - #define ATLVERIFY(expr) ATLASSERT(expr) - #else - #define ATLVERIFY(expr) (expr) - #endif // DEBUG - #endif // ATLVERIFY -#endif // (_ATL_VER < 0x0700) - -// Forward declaration for ATL3 fix -#if (_ATL_VER < 0x0700) && defined(_ATL_DLL) && !defined(_WIN32_WCE) - namespace ATL { HRESULT AtlGetCommCtrlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor); }; -#endif - - -namespace WTL -{ - -#if (_ATL_VER >= 0x0700) - DECLARE_TRACE_CATEGORY(atlTraceUI); - #ifdef _DEBUG - __declspec(selectany) ATL::CTraceCategory atlTraceUI(_T("atlTraceUI")); - #endif // _DEBUG -#else // !(_ATL_VER >= 0x0700) - enum wtlTraceFlags - { - atlTraceUI = 0x10000000 - }; -#endif // !(_ATL_VER >= 0x0700) - -// Windows version helper -inline bool AtlIsOldWindows() -{ - OSVERSIONINFO ovi = { 0 }; - ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - BOOL bRet = ::GetVersionEx(&ovi); - return (!bRet || !((ovi.dwMajorVersion >= 5) || (ovi.dwMajorVersion == 4 && ovi.dwMinorVersion >= 90))); -} - -// default GUI font helper -inline HFONT AtlGetDefaultGuiFont() -{ -#ifndef _WIN32_WCE - return (HFONT)::GetStockObject(DEFAULT_GUI_FONT); -#else // CE specific - return (HFONT)::GetStockObject(SYSTEM_FONT); -#endif // _WIN32_WCE -} - -// bold font helper (NOTE: Caller owns the font, and should destroy it when done using it) -inline HFONT AtlCreateBoldFont(HFONT hFont = NULL) -{ - if(hFont == NULL) - hFont = AtlGetDefaultGuiFont(); - ATLASSERT(hFont != NULL); - HFONT hFontBold = NULL; - LOGFONT lf = { 0 }; - if(::GetObject(hFont, sizeof(LOGFONT), &lf) == sizeof(LOGFONT)) - { - lf.lfWeight = FW_BOLD; - hFontBold = ::CreateFontIndirect(&lf); - ATLASSERT(hFontBold != NULL); - } - else - { - ATLASSERT(FALSE); - } - return hFontBold; -} - -// Common Controls initialization helper -inline BOOL AtlInitCommonControls(DWORD dwFlags) -{ - INITCOMMONCONTROLSEX iccx = { sizeof(INITCOMMONCONTROLSEX), dwFlags }; - BOOL bRet = ::InitCommonControlsEx(&iccx); - ATLASSERT(bRet); - return bRet; -} - - -/////////////////////////////////////////////////////////////////////////////// -// RunTimeHelper - helper functions for Windows version and structure sizes - -// Not for Windows CE -#if defined(_WIN32_WCE) && !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) - #define _WTL_NO_RUNTIME_STRUCT_SIZE -#endif - -#ifndef _WTL_NO_RUNTIME_STRUCT_SIZE - -#ifndef _SIZEOF_STRUCT - #define _SIZEOF_STRUCT(structname, member) (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member)) -#endif - -#if (_WIN32_WINNT >= 0x0600) && !defined(REBARBANDINFO_V6_SIZE) - #define REBARBANDINFO_V6_SIZE _SIZEOF_STRUCT(REBARBANDINFO, cxHeader) -#endif // (_WIN32_WINNT >= 0x0600) && !defined(REBARBANDINFO_V6_SIZE) - -#if (_WIN32_WINNT >= 0x0600) && !defined(LVGROUP_V5_SIZE) - #define LVGROUP_V5_SIZE _SIZEOF_STRUCT(LVGROUP, uAlign) -#endif // (_WIN32_WINNT >= 0x0600) && !defined(LVGROUP_V5_SIZE) - -#if (_WIN32_WINNT >= 0x0600) && !defined(LVTILEINFO_V5_SIZE) - #define LVTILEINFO_V5_SIZE _SIZEOF_STRUCT(LVTILEINFO, puColumns) -#endif // (_WIN32_WINNT >= 0x0600) && !defined(LVTILEINFO_V5_SIZE) - -#if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) && !defined(MCHITTESTINFO_V1_SIZE) - #define MCHITTESTINFO_V1_SIZE _SIZEOF_STRUCT(MCHITTESTINFO, st) -#endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) && !defined(MCHITTESTINFO_V1_SIZE) - -#if !defined(_WIN32_WCE) && (WINVER >= 0x0600) && !defined(NONCLIENTMETRICS_V1_SIZE) - #define NONCLIENTMETRICS_V1_SIZE _SIZEOF_STRUCT(NONCLIENTMETRICS, lfMessageFont) -#endif // !defined(_WIN32_WCE) && (WINVER >= 0x0600) && !defined(NONCLIENTMETRICS_V1_SIZE) - -#endif // !_WTL_NO_RUNTIME_STRUCT_SIZE - -namespace RunTimeHelper -{ -#ifndef _WIN32_WCE - inline bool IsCommCtrl6() - { - DWORD dwMajor = 0, dwMinor = 0; - HRESULT hRet = ATL::AtlGetCommCtrlVersion(&dwMajor, &dwMinor); - return (SUCCEEDED(hRet) && (dwMajor >= 6)); - } - - inline bool IsVista() - { - OSVERSIONINFO ovi = { sizeof(OSVERSIONINFO) }; - BOOL bRet = ::GetVersionEx(&ovi); - return ((bRet != FALSE) && (ovi.dwMajorVersion >= 6)); - } -#endif // !_WIN32_WCE - - inline int SizeOf_REBARBANDINFO() - { - int nSize = sizeof(REBARBANDINFO); -#if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600) - if(!(IsVista() && IsCommCtrl6())) - nSize = REBARBANDINFO_V6_SIZE; -#endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600) - return nSize; - } - -#if (_WIN32_WINNT >= 0x501) - inline int SizeOf_LVGROUP() - { - int nSize = sizeof(LVGROUP); -#if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600) - if(!IsVista()) - nSize = LVGROUP_V5_SIZE; -#endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600) - return nSize; - } - - inline int SizeOf_LVTILEINFO() - { - int nSize = sizeof(LVTILEINFO); -#if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600) - if(!IsVista()) - nSize = LVTILEINFO_V5_SIZE; -#endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600) - return nSize; - } -#endif // (_WIN32_WINNT >= 0x501) - - inline int SizeOf_MCHITTESTINFO() - { - int nSize = sizeof(MCHITTESTINFO); -#if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) - if(!(IsVista() && IsCommCtrl6())) - nSize = MCHITTESTINFO_V1_SIZE; -#endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) - return nSize; - } - -#ifndef _WIN32_WCE - inline int SizeOf_NONCLIENTMETRICS() - { - int nSize = sizeof(NONCLIENTMETRICS); -#if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (WINVER >= 0x0600) - if(!IsVista()) - nSize = NONCLIENTMETRICS_V1_SIZE; -#endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (WINVER >= 0x0600) - return nSize; - } -#endif // !_WIN32_WCE -}; - - -/////////////////////////////////////////////////////////////////////////////// -// ModuleHelper - helper functions for ATL3 and ATL7 module classes - -namespace ModuleHelper -{ - inline HINSTANCE GetModuleInstance() - { -#if (_ATL_VER >= 0x0700) - return ATL::_AtlBaseModule.GetModuleInstance(); -#else // !(_ATL_VER >= 0x0700) - return ATL::_pModule->GetModuleInstance(); -#endif // !(_ATL_VER >= 0x0700) - } - - inline HINSTANCE GetResourceInstance() - { -#if (_ATL_VER >= 0x0700) - return ATL::_AtlBaseModule.GetResourceInstance(); -#else // !(_ATL_VER >= 0x0700) - return ATL::_pModule->GetResourceInstance(); -#endif // !(_ATL_VER >= 0x0700) - } - - inline void AddCreateWndData(ATL::_AtlCreateWndData* pData, void* pObject) - { -#if (_ATL_VER >= 0x0700) - ATL::_AtlWinModule.AddCreateWndData(pData, pObject); -#else // !(_ATL_VER >= 0x0700) - ATL::_pModule->AddCreateWndData(pData, pObject); -#endif // !(_ATL_VER >= 0x0700) - } - - inline void* ExtractCreateWndData() - { -#if (_ATL_VER >= 0x0700) - return ATL::_AtlWinModule.ExtractCreateWndData(); -#else // !(_ATL_VER >= 0x0700) - return ATL::_pModule->ExtractCreateWndData(); -#endif // !(_ATL_VER >= 0x0700) - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// SecureHelper - helper functions for VS2005 secure CRT - -namespace SecureHelper -{ - inline void strcpyA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc) - { -#if _SECURE_ATL - ATL::Checked::strcpy_s(lpstrDest, cchDest, lpstrSrc); -#else - if(cchDest > (size_t)lstrlenA(lpstrSrc)) - ATLVERIFY(lstrcpyA(lpstrDest, lpstrSrc) != NULL); - else - ATLASSERT(FALSE); -#endif - } - - inline void strcpyW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc) - { -#if _SECURE_ATL - ATL::Checked::wcscpy_s(lpstrDest, cchDest, lpstrSrc); -#else - if(cchDest > (size_t)lstrlenW(lpstrSrc)) - ATLVERIFY(lstrcpyW(lpstrDest, lpstrSrc) != NULL); - else - ATLASSERT(FALSE); -#endif - } - - inline void strcpy_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc) - { -#ifdef _UNICODE - strcpyW_x(lpstrDest, cchDest, lpstrSrc); -#else - strcpyA_x(lpstrDest, cchDest, lpstrSrc); -#endif - } - - inline errno_t strncpyA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc, size_t cchCount) - { -#if _SECURE_ATL - return ATL::Checked::strncpy_s(lpstrDest, cchDest, lpstrSrc, cchCount); -#else - errno_t nRet = 0; - if(lpstrDest == NULL || cchDest == 0 || lpstrSrc == NULL) - { - nRet = EINVAL; - } - else if(cchCount == _TRUNCATE) - { - cchCount = min(cchDest - 1, size_t(lstrlenA(lpstrSrc))); - nRet = STRUNCATE; - } - else if(cchDest <= cchCount) - { - lpstrDest[0] = 0; - nRet = EINVAL; - } - if(nRet == 0 || nRet == STRUNCATE) - nRet = (lstrcpynA(lpstrDest, lpstrSrc, (int)cchCount + 1) != NULL) ? nRet : EINVAL; - ATLASSERT(nRet == 0 || nRet == STRUNCATE); - return nRet; -#endif - } - - inline errno_t strncpyW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc, size_t cchCount) - { -#if _SECURE_ATL - return ATL::Checked::wcsncpy_s(lpstrDest, cchDest, lpstrSrc, cchCount); -#else - errno_t nRet = 0; - if(lpstrDest == NULL || cchDest == 0 || lpstrSrc == NULL) - { - nRet = EINVAL; - } - else if(cchCount == _TRUNCATE) - { - cchCount = min(cchDest - 1, size_t(lstrlenW(lpstrSrc))); - nRet = STRUNCATE; - } - else if(cchDest <= cchCount) - { - lpstrDest[0] = 0; - nRet = EINVAL; - } - if(nRet == 0 || nRet == STRUNCATE) - nRet = (lstrcpynW(lpstrDest, lpstrSrc, (int)cchCount + 1) != NULL) ? nRet : EINVAL; - ATLASSERT(nRet == 0 || nRet == STRUNCATE); - return nRet; -#endif - } - - inline errno_t strncpy_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc, size_t cchCount) - { -#ifdef _UNICODE - return strncpyW_x(lpstrDest, cchDest, lpstrSrc, cchCount); -#else - return strncpyA_x(lpstrDest, cchDest, lpstrSrc, cchCount); -#endif - } - - inline void strcatA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc) - { -#if _SECURE_ATL - ATL::Checked::strcat_s(lpstrDest, cchDest, lpstrSrc); -#else - if(cchDest > (size_t)lstrlenA(lpstrSrc)) - ATLVERIFY(lstrcatA(lpstrDest, lpstrSrc) != NULL); - else - ATLASSERT(FALSE); -#endif - } - - inline void strcatW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc) - { -#if _SECURE_ATL - ATL::Checked::wcscat_s(lpstrDest, cchDest, lpstrSrc); -#else - if(cchDest > (size_t)lstrlenW(lpstrSrc)) - ATLVERIFY(lstrcatW(lpstrDest, lpstrSrc) != NULL); - else - ATLASSERT(FALSE); -#endif - } - - inline void strcat_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc) - { -#ifdef _UNICODE - strcatW_x(lpstrDest, cchDest, lpstrSrc); -#else - strcatA_x(lpstrDest, cchDest, lpstrSrc); -#endif - } - - inline void memcpy_x(void* pDest, size_t cbDest, const void* pSrc, size_t cbSrc) - { -#if _SECURE_ATL - ATL::Checked::memcpy_s(pDest, cbDest, pSrc, cbSrc); -#else - if(cbDest >= cbSrc) - memcpy(pDest, pSrc, cbSrc); - else - ATLASSERT(FALSE); -#endif - } - - inline void memmove_x(void* pDest, size_t cbDest, const void* pSrc, size_t cbSrc) - { -#if _SECURE_ATL - ATL::Checked::memmove_s(pDest, cbDest, pSrc, cbSrc); -#else - if(cbDest >= cbSrc) - memmove(pDest, pSrc, cbSrc); - else - ATLASSERT(FALSE); -#endif - } - - inline int vsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, va_list args) - { -#if _SECURE_ATL && !defined(_ATL_MIN_CRT) && !defined(_WIN32_WCE) - return _vstprintf_s(lpstrBuff, cchBuff, lpstrFormat, args); -#else - cchBuff; // Avoid unused argument warning -#pragma warning(disable: 4996) - return _vstprintf(lpstrBuff, lpstrFormat, args); -#pragma warning(default: 4996) -#endif - } - - inline int wvsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, va_list args) - { -#if _SECURE_ATL && !defined(_ATL_MIN_CRT) && !defined(_WIN32_WCE) - return _vstprintf_s(lpstrBuff, cchBuff, lpstrFormat, args); -#else - cchBuff; // Avoid unused argument warning - return ::wvsprintf(lpstrBuff, lpstrFormat, args); -#endif - } - - inline int sprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, ...) - { - va_list args; - va_start(args, lpstrFormat); - int nRes = vsprintf_x(lpstrBuff, cchBuff, lpstrFormat, args); - va_end(args); - return nRes; - } - - inline int wsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, ...) - { - va_list args; - va_start(args, lpstrFormat); - int nRes = wvsprintf_x(lpstrBuff, cchBuff, lpstrFormat, args); - va_end(args); - return nRes; - } -}; // namespace SecureHelper - - -/////////////////////////////////////////////////////////////////////////////// -// CMessageFilter - Interface for message filter support - -class CMessageFilter -{ -public: - virtual BOOL PreTranslateMessage(MSG* pMsg) = 0; -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CIdleHandler - Interface for idle processing - -class CIdleHandler -{ -public: - virtual BOOL OnIdle() = 0; -}; - -#ifndef _ATL_NO_OLD_NAMES - // for compatilibility with old names only - typedef CIdleHandler CUpdateUIObject; - #define DoUpdate OnIdle -#endif // !_ATL_NO_OLD_NAMES - - -/////////////////////////////////////////////////////////////////////////////// -// CMessageLoop - message loop implementation - -class CMessageLoop -{ -public: - ATL::CSimpleArray m_aMsgFilter; - ATL::CSimpleArray m_aIdleHandler; - MSG m_msg; - -// Message filter operations - BOOL AddMessageFilter(CMessageFilter* pMessageFilter) - { - return m_aMsgFilter.Add(pMessageFilter); - } - - BOOL RemoveMessageFilter(CMessageFilter* pMessageFilter) - { - return m_aMsgFilter.Remove(pMessageFilter); - } - -// Idle handler operations - BOOL AddIdleHandler(CIdleHandler* pIdleHandler) - { - return m_aIdleHandler.Add(pIdleHandler); - } - - BOOL RemoveIdleHandler(CIdleHandler* pIdleHandler) - { - return m_aIdleHandler.Remove(pIdleHandler); - } - -#ifndef _ATL_NO_OLD_NAMES - // for compatilibility with old names only - BOOL AddUpdateUI(CIdleHandler* pIdleHandler) - { - ATLTRACE2(atlTraceUI, 0, _T("CUpdateUIObject and AddUpdateUI are deprecated. Please change your code to use CIdleHandler and OnIdle\n")); - return AddIdleHandler(pIdleHandler); - } - - BOOL RemoveUpdateUI(CIdleHandler* pIdleHandler) - { - ATLTRACE2(atlTraceUI, 0, _T("CUpdateUIObject and RemoveUpdateUI are deprecated. Please change your code to use CIdleHandler and OnIdle\n")); - return RemoveIdleHandler(pIdleHandler); - } -#endif // !_ATL_NO_OLD_NAMES - -// message loop - int Run() - { - BOOL bDoIdle = TRUE; - int nIdleCount = 0; - BOOL bRet; - - for(;;) - { - while(bDoIdle && !::PeekMessage(&m_msg, NULL, 0, 0, PM_NOREMOVE)) - { - if(!OnIdle(nIdleCount++)) - bDoIdle = FALSE; - } - - bRet = ::GetMessage(&m_msg, NULL, 0, 0); - - if(bRet == -1) - { - ATLTRACE2(atlTraceUI, 0, _T("::GetMessage returned -1 (error)\n")); - continue; // error, don't process - } - else if(!bRet) - { - ATLTRACE2(atlTraceUI, 0, _T("CMessageLoop::Run - exiting\n")); - break; // WM_QUIT, exit message loop - } - - if(!PreTranslateMessage(&m_msg)) - { - ::TranslateMessage(&m_msg); - ::DispatchMessage(&m_msg); - } - - if(IsIdleMessage(&m_msg)) - { - bDoIdle = TRUE; - nIdleCount = 0; - } - } - - return (int)m_msg.wParam; - } - - static BOOL IsIdleMessage(MSG* pMsg) - { - // These messages should NOT cause idle processing - switch(pMsg->message) - { - case WM_MOUSEMOVE: -#ifndef _WIN32_WCE - case WM_NCMOUSEMOVE: -#endif // !_WIN32_WCE - case WM_PAINT: - case 0x0118: // WM_SYSTIMER (caret blink) - return FALSE; - } - - return TRUE; - } - -// Overrideables - // Override to change message filtering - virtual BOOL PreTranslateMessage(MSG* pMsg) - { - // loop backwards - for(int i = m_aMsgFilter.GetSize() - 1; i >= 0; i--) - { - CMessageFilter* pMessageFilter = m_aMsgFilter[i]; - if(pMessageFilter != NULL && pMessageFilter->PreTranslateMessage(pMsg)) - return TRUE; - } - return FALSE; // not translated - } - - // override to change idle processing - virtual BOOL OnIdle(int /*nIdleCount*/) - { - for(int i = 0; i < m_aIdleHandler.GetSize(); i++) - { - CIdleHandler* pIdleHandler = m_aIdleHandler[i]; - if(pIdleHandler != NULL) - pIdleHandler->OnIdle(); - } - return FALSE; // don't continue - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CStaticDataInitCriticalSectionLock and CWindowCreateCriticalSectionLock -// internal classes to manage critical sections for both ATL3 and ATL7 - -class CStaticDataInitCriticalSectionLock -{ -public: -#if (_ATL_VER >= 0x0700) - ATL::CComCritSecLock m_cslock; - - CStaticDataInitCriticalSectionLock() : m_cslock(ATL::_pAtlModule->m_csStaticDataInitAndTypeInfo, false) - { } -#endif // (_ATL_VER >= 0x0700) - - HRESULT Lock() - { -#if (_ATL_VER >= 0x0700) - return m_cslock.Lock(); -#else // !(_ATL_VER >= 0x0700) - ::EnterCriticalSection(&ATL::_pModule->m_csStaticDataInit); - return S_OK; -#endif // !(_ATL_VER >= 0x0700) - } - - void Unlock() - { -#if (_ATL_VER >= 0x0700) - m_cslock.Unlock(); -#else // !(_ATL_VER >= 0x0700) - ::LeaveCriticalSection(&ATL::_pModule->m_csStaticDataInit); -#endif // !(_ATL_VER >= 0x0700) - } -}; - - -class CWindowCreateCriticalSectionLock -{ -public: -#if (_ATL_VER >= 0x0700) - ATL::CComCritSecLock m_cslock; - - CWindowCreateCriticalSectionLock() : m_cslock(ATL::_AtlWinModule.m_csWindowCreate, false) - { } -#endif // (_ATL_VER >= 0x0700) - - HRESULT Lock() - { -#if (_ATL_VER >= 0x0700) - return m_cslock.Lock(); -#else // !(_ATL_VER >= 0x0700) - ::EnterCriticalSection(&ATL::_pModule->m_csWindowCreate); - return S_OK; -#endif // !(_ATL_VER >= 0x0700) - } - - void Unlock() - { -#if (_ATL_VER >= 0x0700) - m_cslock.Unlock(); -#else // !(_ATL_VER >= 0x0700) - ::LeaveCriticalSection(&ATL::_pModule->m_csWindowCreate); -#endif // !(_ATL_VER >= 0x0700) - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CTempBuffer - helper class for stack allocations for ATL3 - -#ifndef _WTL_STACK_ALLOC_THRESHOLD - #define _WTL_STACK_ALLOC_THRESHOLD 512 -#endif - -#if (_ATL_VER >= 0x0700) - -using ATL::CTempBuffer; - -#else // !(_ATL_VER >= 0x0700) - -#ifndef SIZE_MAX - #ifdef _WIN64 - #define SIZE_MAX _UI64_MAX - #else - #define SIZE_MAX UINT_MAX - #endif -#endif - -#pragma warning(disable: 4284) // warning for operator -> - -template -class CTempBuffer -{ -public: - CTempBuffer() : m_p(NULL) - { - } - - CTempBuffer(size_t nElements) : m_p(NULL) - { - Allocate(nElements); - } - - ~CTempBuffer() - { - if(m_p != reinterpret_cast(m_abFixedBuffer)) - free(m_p); - } - - operator T*() const - { - return m_p; - } - - T* operator ->() const - { - ATLASSERT(m_p != NULL); - return m_p; - } - - T* Allocate(size_t nElements) - { - ATLASSERT(nElements <= (SIZE_MAX / sizeof(T))); - return AllocateBytes(nElements * sizeof(T)); - } - - T* AllocateBytes(size_t nBytes) - { - ATLASSERT(m_p == NULL); - if(nBytes > t_nFixedBytes) - m_p = static_cast(malloc(nBytes)); - else - m_p = reinterpret_cast(m_abFixedBuffer); - - return m_p; - } - -private: - T* m_p; - BYTE m_abFixedBuffer[t_nFixedBytes]; -}; - -#pragma warning(default: 4284) - -#endif // !(_ATL_VER >= 0x0700) - - -/////////////////////////////////////////////////////////////////////////////// -// CAppModule - module class for an application - -class CAppModule : public ATL::CComModule -{ -public: - DWORD m_dwMainThreadID; - ATL::CSimpleMap* m_pMsgLoopMap; - ATL::CSimpleArray* m_pSettingChangeNotify; - -// Overrides of CComModule::Init and Term - HRESULT Init(ATL::_ATL_OBJMAP_ENTRY* pObjMap, HINSTANCE hInstance, const GUID* pLibID = NULL) - { - HRESULT hRet = CComModule::Init(pObjMap, hInstance, pLibID); - if(FAILED(hRet)) - return hRet; - - m_dwMainThreadID = ::GetCurrentThreadId(); - typedef ATL::CSimpleMap _mapClass; - m_pMsgLoopMap = NULL; - ATLTRY(m_pMsgLoopMap = new _mapClass); - if(m_pMsgLoopMap == NULL) - return E_OUTOFMEMORY; - m_pSettingChangeNotify = NULL; - - return hRet; - } - - void Term() - { - TermSettingChangeNotify(); - delete m_pMsgLoopMap; - CComModule::Term(); - } - -// Message loop map methods - BOOL AddMessageLoop(CMessageLoop* pMsgLoop) - { - CStaticDataInitCriticalSectionLock lock; - if(FAILED(lock.Lock())) - { - ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::AddMessageLoop.\n")); - ATLASSERT(FALSE); - return FALSE; - } - - ATLASSERT(pMsgLoop != NULL); - ATLASSERT(m_pMsgLoopMap->Lookup(::GetCurrentThreadId()) == NULL); // not in map yet - - BOOL bRet = m_pMsgLoopMap->Add(::GetCurrentThreadId(), pMsgLoop); - - lock.Unlock(); - - return bRet; - } - - BOOL RemoveMessageLoop() - { - CStaticDataInitCriticalSectionLock lock; - if(FAILED(lock.Lock())) - { - ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::RemoveMessageLoop.\n")); - ATLASSERT(FALSE); - return FALSE; - } - - BOOL bRet = m_pMsgLoopMap->Remove(::GetCurrentThreadId()); - - lock.Unlock(); - - return bRet; - } - - CMessageLoop* GetMessageLoop(DWORD dwThreadID = ::GetCurrentThreadId()) const - { - CStaticDataInitCriticalSectionLock lock; - if(FAILED(lock.Lock())) - { - ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::GetMessageLoop.\n")); - ATLASSERT(FALSE); - return NULL; - } - - CMessageLoop* pLoop = m_pMsgLoopMap->Lookup(dwThreadID); - - lock.Unlock(); - - return pLoop; - } - -// Setting change notify methods - // Note: Call this from the main thread for MSDI apps - BOOL InitSettingChangeNotify(DLGPROC pfnDlgProc = _SettingChangeDlgProc) - { - CStaticDataInitCriticalSectionLock lock; - if(FAILED(lock.Lock())) - { - ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::InitSettingChangeNotify.\n")); - ATLASSERT(FALSE); - return FALSE; - } - - if(m_pSettingChangeNotify == NULL) - { - typedef ATL::CSimpleArray _notifyClass; - ATLTRY(m_pSettingChangeNotify = new _notifyClass); - ATLASSERT(m_pSettingChangeNotify != NULL); - } - - BOOL bRet = (m_pSettingChangeNotify != NULL); - if(bRet && m_pSettingChangeNotify->GetSize() == 0) - { - // init everything - _ATL_EMPTY_DLGTEMPLATE templ; - HWND hNtfWnd = ::CreateDialogIndirect(GetModuleInstance(), &templ, NULL, pfnDlgProc); - ATLASSERT(::IsWindow(hNtfWnd)); - if(::IsWindow(hNtfWnd)) - { -// need conditional code because types don't match in winuser.h -#ifdef _WIN64 - ::SetWindowLongPtr(hNtfWnd, GWLP_USERDATA, (LONG_PTR)this); -#else - ::SetWindowLongPtr(hNtfWnd, GWLP_USERDATA, PtrToLong(this)); -#endif - bRet = m_pSettingChangeNotify->Add(hNtfWnd); - } - else - { - bRet = FALSE; - } - } - - lock.Unlock(); - - return bRet; - } - - void TermSettingChangeNotify() - { - CStaticDataInitCriticalSectionLock lock; - if(FAILED(lock.Lock())) - { - ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::TermSettingChangeNotify.\n")); - ATLASSERT(FALSE); - return; - } - - if(m_pSettingChangeNotify != NULL && m_pSettingChangeNotify->GetSize() > 0) - ::DestroyWindow((*m_pSettingChangeNotify)[0]); - delete m_pSettingChangeNotify; - m_pSettingChangeNotify = NULL; - - lock.Unlock(); - } - - BOOL AddSettingChangeNotify(HWND hWnd) - { - CStaticDataInitCriticalSectionLock lock; - if(FAILED(lock.Lock())) - { - ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::AddSettingChangeNotify.\n")); - ATLASSERT(FALSE); - return FALSE; - } - - ATLASSERT(::IsWindow(hWnd)); - BOOL bRet = FALSE; - if(InitSettingChangeNotify() != FALSE) - bRet = m_pSettingChangeNotify->Add(hWnd); - - lock.Unlock(); - - return bRet; - } - - BOOL RemoveSettingChangeNotify(HWND hWnd) - { - CStaticDataInitCriticalSectionLock lock; - if(FAILED(lock.Lock())) - { - ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::RemoveSettingChangeNotify.\n")); - ATLASSERT(FALSE); - return FALSE; - } - - BOOL bRet = FALSE; - if(m_pSettingChangeNotify != NULL) - bRet = m_pSettingChangeNotify->Remove(hWnd); - - lock.Unlock(); - - return bRet; - } - -// Implementation - setting change notify dialog template and dialog procedure - struct _ATL_EMPTY_DLGTEMPLATE : DLGTEMPLATE - { - _ATL_EMPTY_DLGTEMPLATE() - { - memset(this, 0, sizeof(_ATL_EMPTY_DLGTEMPLATE)); - style = WS_POPUP; - } - WORD wMenu, wClass, wTitle; - }; - -#ifdef _WIN64 - static INT_PTR CALLBACK _SettingChangeDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -#else - static BOOL CALLBACK _SettingChangeDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -#endif - { - if(uMsg == WM_SETTINGCHANGE) - { -// need conditional code because types don't match in winuser.h -#ifdef _WIN64 - CAppModule* pModule = (CAppModule*)::GetWindowLongPtr(hWnd, GWLP_USERDATA); -#else - CAppModule* pModule = (CAppModule*)LongToPtr(::GetWindowLongPtr(hWnd, GWLP_USERDATA)); -#endif - ATLASSERT(pModule != NULL); - ATLASSERT(pModule->m_pSettingChangeNotify != NULL); - const UINT uTimeout = 1500; // ms - for(int i = 1; i < pModule->m_pSettingChangeNotify->GetSize(); i++) - { -#if !defined(_WIN32_WCE) - ::SendMessageTimeout((*pModule->m_pSettingChangeNotify)[i], uMsg, wParam, lParam, SMTO_ABORTIFHUNG, uTimeout, NULL); -#elif(_WIN32_WCE >= 400) // CE specific - ::SendMessageTimeout((*pModule->m_pSettingChangeNotify)[i], uMsg, wParam, lParam, SMTO_NORMAL, uTimeout, NULL); -#else // _WIN32_WCE < 400 specific - uTimeout; - ::SendMessage((*pModule->m_pSettingChangeNotify)[i], uMsg, wParam, lParam); -#endif - } - return TRUE; - } - return FALSE; - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CServerAppModule - module class for a COM server application - -class CServerAppModule : public CAppModule -{ -public: - HANDLE m_hEventShutdown; - bool m_bActivity; - DWORD m_dwTimeOut; - DWORD m_dwPause; - -// Override of CAppModule::Init - HRESULT Init(ATL::_ATL_OBJMAP_ENTRY* pObjMap, HINSTANCE hInstance, const GUID* pLibID = NULL) - { - m_dwTimeOut = 5000; - m_dwPause = 1000; - return CAppModule::Init(pObjMap, hInstance, pLibID); - } - - void Term() - { - if(m_hEventShutdown != NULL && ::CloseHandle(m_hEventShutdown)) - m_hEventShutdown = NULL; - CAppModule::Term(); - } - -// COM Server methods - LONG Unlock() - { - LONG lRet = CComModule::Unlock(); - if(lRet == 0) - { - m_bActivity = true; - ::SetEvent(m_hEventShutdown); // tell monitor that we transitioned to zero - } - return lRet; - } - - void MonitorShutdown() - { - for(;;) - { - ::WaitForSingleObject(m_hEventShutdown, INFINITE); - DWORD dwWait = 0; - do - { - m_bActivity = false; - dwWait = ::WaitForSingleObject(m_hEventShutdown, m_dwTimeOut); - } - while(dwWait == WAIT_OBJECT_0); - // timed out - if(!m_bActivity && m_nLockCnt == 0) // if no activity let's really bail - { -#if ((_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM)) && defined(_ATL_FREE_THREADED) && !defined(_WIN32_WCE) - ::CoSuspendClassObjects(); - if(!m_bActivity && m_nLockCnt == 0) -#endif - break; - } - } - // This handle should be valid now. If it isn't, - // check if _Module.Term was called first (it shouldn't) - if(::CloseHandle(m_hEventShutdown)) - m_hEventShutdown = NULL; - ::PostThreadMessage(m_dwMainThreadID, WM_QUIT, 0, 0); - } - - bool StartMonitor() - { - m_hEventShutdown = ::CreateEvent(NULL, false, false, NULL); - if(m_hEventShutdown == NULL) - return false; - DWORD dwThreadID = 0; -#if !defined(_ATL_MIN_CRT) && defined(_MT) && !defined(_WIN32_WCE) - HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, (UINT (WINAPI*)(void*))MonitorProc, this, 0, (UINT*)&dwThreadID); -#else - HANDLE hThread = ::CreateThread(NULL, 0, MonitorProc, this, 0, &dwThreadID); -#endif - bool bRet = (hThread != NULL); - if(bRet) - ::CloseHandle(hThread); - return bRet; - } - - static DWORD WINAPI MonitorProc(void* pv) - { - CServerAppModule* p = (CServerAppModule*)pv; - p->MonitorShutdown(); - return 0; - } - -#if (_ATL_VER < 0x0700) - // search for an occurence of string p2 in string p1 - static LPCTSTR FindOneOf(LPCTSTR p1, LPCTSTR p2) - { - while(p1 != NULL && *p1 != NULL) - { - LPCTSTR p = p2; - while(p != NULL && *p != NULL) - { - if(*p1 == *p) - return ::CharNext(p1); - p = ::CharNext(p); - } - p1 = ::CharNext(p1); - } - return NULL; - } -#endif // (_ATL_VER < 0x0700) -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CString forward reference (enables CString use in atluser.h and atlgdi.h) - -#if defined(_WTL_FORWARD_DECLARE_CSTRING) && !defined(_WTL_USE_CSTRING) - #define _WTL_USE_CSTRING -#endif // defined(_WTL_FORWARD_DECLARE_CSTRING) && !defined(_WTL_USE_CSTRING) - -#ifdef _WTL_USE_CSTRING - class CString; // forward declaration (include atlmisc.h for the whole class) -#endif // _WTL_USE_CSTRING - -// CString namespace -#ifndef _CSTRING_NS - #ifdef __ATLSTR_H__ - #define _CSTRING_NS ATL - #else - #define _CSTRING_NS WTL - #endif -#endif // _CSTRING_NS - -// Type classes namespace -#ifndef _WTYPES_NS - #ifdef __ATLTYPES_H__ - #define _WTYPES_NS - #else - #define _WTYPES_NS WTL - #endif -#endif // _WTYPES_NS - -}; // namespace WTL - - -/////////////////////////////////////////////////////////////////////////////// -// General DLL version helpers (excluded from atlbase.h if _ATL_DLL is defined) - -#if (_ATL_VER < 0x0700) && defined(_ATL_DLL) && !defined(_WIN32_WCE) - -namespace ATL -{ - -inline HRESULT AtlGetDllVersion(HINSTANCE hInstDLL, DLLVERSIONINFO* pDllVersionInfo) -{ - ATLASSERT(pDllVersionInfo != NULL); - if(pDllVersionInfo == NULL) - return E_INVALIDARG; - - // We must get this function explicitly because some DLLs don't implement it. - DLLGETVERSIONPROC pfnDllGetVersion = (DLLGETVERSIONPROC)::GetProcAddress(hInstDLL, "DllGetVersion"); - if(pfnDllGetVersion == NULL) - return E_NOTIMPL; - - return (*pfnDllGetVersion)(pDllVersionInfo); -} - -inline HRESULT AtlGetDllVersion(LPCTSTR lpstrDllName, DLLVERSIONINFO* pDllVersionInfo) -{ - HINSTANCE hInstDLL = ::LoadLibrary(lpstrDllName); - if(hInstDLL == NULL) - return E_FAIL; - HRESULT hRet = AtlGetDllVersion(hInstDLL, pDllVersionInfo); - ::FreeLibrary(hInstDLL); - return hRet; -} - -// Common Control Versions: -// Win95/WinNT 4.0 maj=4 min=00 -// IE 3.x maj=4 min=70 -// IE 4.0 maj=4 min=71 -inline HRESULT AtlGetCommCtrlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor) -{ - ATLASSERT(pdwMajor != NULL && pdwMinor != NULL); - if(pdwMajor == NULL || pdwMinor == NULL) - return E_INVALIDARG; - - DLLVERSIONINFO dvi; - ::ZeroMemory(&dvi, sizeof(dvi)); - dvi.cbSize = sizeof(dvi); - HRESULT hRet = AtlGetDllVersion(_T("comctl32.dll"), &dvi); - - if(SUCCEEDED(hRet)) - { - *pdwMajor = dvi.dwMajorVersion; - *pdwMinor = dvi.dwMinorVersion; - } - else if(hRet == E_NOTIMPL) - { - // If DllGetVersion is not there, then the DLL is a version - // previous to the one shipped with IE 3.x - *pdwMajor = 4; - *pdwMinor = 0; - hRet = S_OK; - } - - return hRet; -} - -// Shell Versions: -// Win95/WinNT 4.0 maj=4 min=00 -// IE 3.x, IE 4.0 without Web Integrated Desktop maj=4 min=00 -// IE 4.0 with Web Integrated Desktop maj=4 min=71 -// IE 4.01 with Web Integrated Desktop maj=4 min=72 -inline HRESULT AtlGetShellVersion(LPDWORD pdwMajor, LPDWORD pdwMinor) -{ - ATLASSERT(pdwMajor != NULL && pdwMinor != NULL); - if(pdwMajor == NULL || pdwMinor == NULL) - return E_INVALIDARG; - - DLLVERSIONINFO dvi; - ::ZeroMemory(&dvi, sizeof(dvi)); - dvi.cbSize = sizeof(dvi); - HRESULT hRet = AtlGetDllVersion(_T("shell32.dll"), &dvi); - - if(SUCCEEDED(hRet)) - { - *pdwMajor = dvi.dwMajorVersion; - *pdwMinor = dvi.dwMinorVersion; - } - else if(hRet == E_NOTIMPL) - { - // If DllGetVersion is not there, then the DLL is a version - // previous to the one shipped with IE 4.x - *pdwMajor = 4; - *pdwMinor = 0; - hRet = S_OK; - } - - return hRet; -} - -}; // namespace ATL - -#endif // (_ATL_VER < 0x0700) && defined(_ATL_DLL) && !defined(_WIN32_WCE) - - -// These are always included -#include "atlwinx.h" -#include "atluser.h" -#include "atlgdi.h" - -#ifndef _WTL_NO_AUTOMATIC_NAMESPACE -using namespace WTL; -#endif // !_WTL_NO_AUTOMATIC_NAMESPACE - -#endif // __ATLAPP_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/atlcrack.h b/prog/3rdPartyLibs/wtl-8.1/include/atlcrack.h deleted file mode 100644 index 90f756003..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/atlcrack.h +++ /dev/null @@ -1,2380 +0,0 @@ -// Windows Template Library - WTL version 8.1 -// Copyright (C) Microsoft Corporation. All rights reserved. -// -// This file is a part of the Windows Template Library. -// The use and distribution terms for this software are covered by the -// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php) -// which can be found in the file CPL.TXT at the root of this distribution. -// By using this software in any fashion, you are agreeing to be bound by -// the terms of this license. You must not remove this notice, or -// any other, from this software. - -#ifndef __ATLCRACK_H__ -#define __ATLCRACK_H__ - -#pragma once - - -/////////////////////////////////////////////////////////////////////////////// -// Message map macro for cracked handlers - -// Note about message maps with cracked handlers: -// For ATL 3.0, a message map using cracked handlers MUST use BEGIN_MSG_MAP_EX. -// For ATL 7.0 or higher, you can use BEGIN_MSG_MAP for CWindowImpl/CDialogImpl derived classes, -// but must use BEGIN_MSG_MAP_EX for classes that don't derive from CWindowImpl/CDialogImpl. - -#define BEGIN_MSG_MAP_EX(theClass) \ -public: \ - BOOL m_bMsgHandled; \ - /* "handled" management for cracked handlers */ \ - BOOL IsMsgHandled() const \ - { \ - return m_bMsgHandled; \ - } \ - void SetMsgHandled(BOOL bHandled) \ - { \ - m_bMsgHandled = bHandled; \ - } \ - BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) \ - { \ - BOOL bOldMsgHandled = m_bMsgHandled; \ - BOOL bRet = _ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, dwMsgMapID); \ - m_bMsgHandled = bOldMsgHandled; \ - return bRet; \ - } \ - BOOL _ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID) \ - { \ - BOOL bHandled = TRUE; \ - hWnd; \ - uMsg; \ - wParam; \ - lParam; \ - lResult; \ - bHandled; \ - switch(dwMsgMapID) \ - { \ - case 0: - - -/////////////////////////////////////////////////////////////////////////////// -// Standard Windows message macros - -// int OnCreate(LPCREATESTRUCT lpCreateStruct) -#define MSG_WM_CREATE(func) \ - if (uMsg == WM_CREATE) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((LPCREATESTRUCT)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam) -#define MSG_WM_INITDIALOG(func) \ - if (uMsg == WM_INITDIALOG) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((HWND)wParam, lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// BOOL OnCopyData(CWindow wnd, PCOPYDATASTRUCT pCopyDataStruct) -#define MSG_WM_COPYDATA(func) \ - if (uMsg == WM_COPYDATA) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((HWND)wParam, (PCOPYDATASTRUCT)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnDestroy() -#define MSG_WM_DESTROY(func) \ - if (uMsg == WM_DESTROY) \ - { \ - SetMsgHandled(TRUE); \ - func(); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnMove(CPoint ptPos) -#define MSG_WM_MOVE(func) \ - if (uMsg == WM_MOVE) \ - { \ - SetMsgHandled(TRUE); \ - func(_WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnSize(UINT nType, CSize size) -#define MSG_WM_SIZE(func) \ - if (uMsg == WM_SIZE) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, _WTYPES_NS::CSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnActivate(UINT nState, BOOL bMinimized, CWindow wndOther) -#define MSG_WM_ACTIVATE(func) \ - if (uMsg == WM_ACTIVATE) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)LOWORD(wParam), (BOOL)HIWORD(wParam), (HWND)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnSetFocus(CWindow wndOld) -#define MSG_WM_SETFOCUS(func) \ - if (uMsg == WM_SETFOCUS) \ - { \ - SetMsgHandled(TRUE); \ - func((HWND)wParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnKillFocus(CWindow wndFocus) -#define MSG_WM_KILLFOCUS(func) \ - if (uMsg == WM_KILLFOCUS) \ - { \ - SetMsgHandled(TRUE); \ - func((HWND)wParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnEnable(BOOL bEnable) -#define MSG_WM_ENABLE(func) \ - if (uMsg == WM_ENABLE) \ - { \ - SetMsgHandled(TRUE); \ - func((BOOL)wParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnPaint(CDCHandle dc) -#define MSG_WM_PAINT(func) \ - if (uMsg == WM_PAINT) \ - { \ - SetMsgHandled(TRUE); \ - func((HDC)wParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnClose() -#define MSG_WM_CLOSE(func) \ - if (uMsg == WM_CLOSE) \ - { \ - SetMsgHandled(TRUE); \ - func(); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// BOOL OnQueryEndSession(UINT nSource, UINT uLogOff) -#define MSG_WM_QUERYENDSESSION(func) \ - if (uMsg == WM_QUERYENDSESSION) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((UINT)wParam, (UINT)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// BOOL OnQueryOpen() -#define MSG_WM_QUERYOPEN(func) \ - if (uMsg == WM_QUERYOPEN) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func(); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// BOOL OnEraseBkgnd(CDCHandle dc) -#define MSG_WM_ERASEBKGND(func) \ - if (uMsg == WM_ERASEBKGND) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((HDC)wParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnSysColorChange() -#define MSG_WM_SYSCOLORCHANGE(func) \ - if (uMsg == WM_SYSCOLORCHANGE) \ - { \ - SetMsgHandled(TRUE); \ - func(); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnEndSession(BOOL bEnding, UINT uLogOff) -#define MSG_WM_ENDSESSION(func) \ - if (uMsg == WM_ENDSESSION) \ - { \ - SetMsgHandled(TRUE); \ - func((BOOL)wParam, (UINT)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnShowWindow(BOOL bShow, UINT nStatus) -#define MSG_WM_SHOWWINDOW(func) \ - if (uMsg == WM_SHOWWINDOW) \ - { \ - SetMsgHandled(TRUE); \ - func((BOOL)wParam, (int)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// HBRUSH OnCtlColorEdit(CDCHandle dc, CEdit edit) -#define MSG_WM_CTLCOLOREDIT(func) \ - if (uMsg == WM_CTLCOLOREDIT) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// HBRUSH OnCtlColorListBox(CDCHandle dc, CListBox listBox) -#define MSG_WM_CTLCOLORLISTBOX(func) \ - if (uMsg == WM_CTLCOLORLISTBOX) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// HBRUSH OnCtlColorBtn(CDCHandle dc, CButton button) -#define MSG_WM_CTLCOLORBTN(func) \ - if (uMsg == WM_CTLCOLORBTN) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// HBRUSH OnCtlColorDlg(CDCHandle dc, CWindow wnd) -#define MSG_WM_CTLCOLORDLG(func) \ - if (uMsg == WM_CTLCOLORDLG) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// HBRUSH OnCtlColorScrollBar(CDCHandle dc, CScrollBar scrollBar) -#define MSG_WM_CTLCOLORSCROLLBAR(func) \ - if (uMsg == WM_CTLCOLORSCROLLBAR) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// HBRUSH OnCtlColorStatic(CDCHandle dc, CStatic wndStatic) -#define MSG_WM_CTLCOLORSTATIC(func) \ - if (uMsg == WM_CTLCOLORSTATIC) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnSettingChange(UINT uFlags, LPCTSTR lpszSection) -#define MSG_WM_SETTINGCHANGE(func) \ - if (uMsg == WM_SETTINGCHANGE) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, (LPCTSTR)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnDevModeChange(LPCTSTR lpDeviceName) -#define MSG_WM_DEVMODECHANGE(func) \ - if (uMsg == WM_DEVMODECHANGE) \ - { \ - SetMsgHandled(TRUE); \ - func((LPCTSTR)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnActivateApp(BOOL bActive, DWORD dwThreadID) -#define MSG_WM_ACTIVATEAPP(func) \ - if (uMsg == WM_ACTIVATEAPP) \ - { \ - SetMsgHandled(TRUE); \ - func((BOOL)wParam, (DWORD)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnFontChange() -#define MSG_WM_FONTCHANGE(func) \ - if (uMsg == WM_FONTCHANGE) \ - { \ - SetMsgHandled(TRUE); \ - func(); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnTimeChange() -#define MSG_WM_TIMECHANGE(func) \ - if (uMsg == WM_TIMECHANGE) \ - { \ - SetMsgHandled(TRUE); \ - func(); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnCancelMode() -#define MSG_WM_CANCELMODE(func) \ - if (uMsg == WM_CANCELMODE) \ - { \ - SetMsgHandled(TRUE); \ - func(); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// BOOL OnSetCursor(CWindow wnd, UINT nHitTest, UINT message) -#define MSG_WM_SETCURSOR(func) \ - if (uMsg == WM_SETCURSOR) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((HWND)wParam, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// int OnMouseActivate(CWindow wndTopLevel, UINT nHitTest, UINT message) -#define MSG_WM_MOUSEACTIVATE(func) \ - if (uMsg == WM_MOUSEACTIVATE) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((HWND)wParam, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnChildActivate() -#define MSG_WM_CHILDACTIVATE(func) \ - if (uMsg == WM_CHILDACTIVATE) \ - { \ - SetMsgHandled(TRUE); \ - func(); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnGetMinMaxInfo(LPMINMAXINFO lpMMI) -#define MSG_WM_GETMINMAXINFO(func) \ - if (uMsg == WM_GETMINMAXINFO) \ - { \ - SetMsgHandled(TRUE); \ - func((LPMINMAXINFO)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnIconEraseBkgnd(CDCHandle dc) -#define MSG_WM_ICONERASEBKGND(func) \ - if (uMsg == WM_ICONERASEBKGND) \ - { \ - SetMsgHandled(TRUE); \ - func((HDC)wParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnSpoolerStatus(UINT nStatus, UINT nJobs) -#define MSG_WM_SPOOLERSTATUS(func) \ - if (uMsg == WM_SPOOLERSTATUS) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, (UINT)LOWORD(lParam)); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) -#define MSG_WM_DRAWITEM(func) \ - if (uMsg == WM_DRAWITEM) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, (LPDRAWITEMSTRUCT)lParam); \ - lResult = TRUE; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct) -#define MSG_WM_MEASUREITEM(func) \ - if (uMsg == WM_MEASUREITEM) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, (LPMEASUREITEMSTRUCT)lParam); \ - lResult = TRUE; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnDeleteItem(int nIDCtl, LPDELETEITEMSTRUCT lpDeleteItemStruct) -#define MSG_WM_DELETEITEM(func) \ - if (uMsg == WM_DELETEITEM) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, (LPDELETEITEMSTRUCT)lParam); \ - lResult = TRUE; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -//int OnCharToItem(UINT nChar, UINT nIndex, CListBox listBox) -#define MSG_WM_CHARTOITEM(func) \ - if (uMsg == WM_CHARTOITEM) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), (HWND)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// int OnVKeyToItem(UINT nKey, UINT nIndex, CListBox listBox) -#define MSG_WM_VKEYTOITEM(func) \ - if (uMsg == WM_VKEYTOITEM) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), (HWND)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// HCURSOR OnQueryDragIcon() -#define MSG_WM_QUERYDRAGICON(func) \ - if (uMsg == WM_QUERYDRAGICON) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func(); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// int OnCompareItem(int nIDCtl, LPCOMPAREITEMSTRUCT lpCompareItemStruct) -#define MSG_WM_COMPAREITEM(func) \ - if (uMsg == WM_COMPAREITEM) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((UINT)wParam, (LPCOMPAREITEMSTRUCT)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnCompacting(UINT nCpuTime) -#define MSG_WM_COMPACTING(func) \ - if (uMsg == WM_COMPACTING) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// BOOL OnNcCreate(LPCREATESTRUCT lpCreateStruct) -#define MSG_WM_NCCREATE(func) \ - if (uMsg == WM_NCCREATE) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((LPCREATESTRUCT)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnNcDestroy() -#define MSG_WM_NCDESTROY(func) \ - if (uMsg == WM_NCDESTROY) \ - { \ - SetMsgHandled(TRUE); \ - func(); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// LRESULT OnNcCalcSize(BOOL bCalcValidRects, LPARAM lParam) -#define MSG_WM_NCCALCSIZE(func) \ - if (uMsg == WM_NCCALCSIZE) \ - { \ - SetMsgHandled(TRUE); \ - lResult = func((BOOL)wParam, lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// UINT OnNcHitTest(CPoint point) -#define MSG_WM_NCHITTEST(func) \ - if (uMsg == WM_NCHITTEST) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func(_WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnNcPaint(CRgn rgn) -#define MSG_WM_NCPAINT(func) \ - if (uMsg == WM_NCPAINT) \ - { \ - SetMsgHandled(TRUE); \ - func((HRGN)wParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// BOOL OnNcActivate(BOOL bActive) -#define MSG_WM_NCACTIVATE(func) \ - if (uMsg == WM_NCACTIVATE) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((BOOL)wParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// UINT OnGetDlgCode(LPMSG lpMsg) -#define MSG_WM_GETDLGCODE(func) \ - if (uMsg == WM_GETDLGCODE) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((LPMSG)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnNcMouseMove(UINT nHitTest, CPoint point) -#define MSG_WM_NCMOUSEMOVE(func) \ - if (uMsg == WM_NCMOUSEMOVE) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnNcLButtonDown(UINT nHitTest, CPoint point) -#define MSG_WM_NCLBUTTONDOWN(func) \ - if (uMsg == WM_NCLBUTTONDOWN) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnNcLButtonUp(UINT nHitTest, CPoint point) -#define MSG_WM_NCLBUTTONUP(func) \ - if (uMsg == WM_NCLBUTTONUP) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnNcLButtonDblClk(UINT nHitTest, CPoint point) -#define MSG_WM_NCLBUTTONDBLCLK(func) \ - if (uMsg == WM_NCLBUTTONDBLCLK) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnNcRButtonDown(UINT nHitTest, CPoint point) -#define MSG_WM_NCRBUTTONDOWN(func) \ - if (uMsg == WM_NCRBUTTONDOWN) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnNcRButtonUp(UINT nHitTest, CPoint point) -#define MSG_WM_NCRBUTTONUP(func) \ - if (uMsg == WM_NCRBUTTONUP) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnNcRButtonDblClk(UINT nHitTest, CPoint point) -#define MSG_WM_NCRBUTTONDBLCLK(func) \ - if (uMsg == WM_NCRBUTTONDBLCLK) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnNcMButtonDown(UINT nHitTest, CPoint point) -#define MSG_WM_NCMBUTTONDOWN(func) \ - if (uMsg == WM_NCMBUTTONDOWN) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnNcMButtonUp(UINT nHitTest, CPoint point) -#define MSG_WM_NCMBUTTONUP(func) \ - if (uMsg == WM_NCMBUTTONUP) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnNcMButtonDblClk(UINT nHitTest, CPoint point) -#define MSG_WM_NCMBUTTONDBLCLK(func) \ - if (uMsg == WM_NCMBUTTONDBLCLK) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) -#define MSG_WM_KEYDOWN(func) \ - if (uMsg == WM_KEYDOWN) \ - { \ - SetMsgHandled(TRUE); \ - func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) -#define MSG_WM_KEYUP(func) \ - if (uMsg == WM_KEYUP) \ - { \ - SetMsgHandled(TRUE); \ - func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) -#define MSG_WM_CHAR(func) \ - if (uMsg == WM_CHAR) \ - { \ - SetMsgHandled(TRUE); \ - func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnDeadChar(UINT nChar, UINT nRepCnt, UINT nFlags) -#define MSG_WM_DEADCHAR(func) \ - if (uMsg == WM_DEADCHAR) \ - { \ - SetMsgHandled(TRUE); \ - func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) -#define MSG_WM_SYSKEYDOWN(func) \ - if (uMsg == WM_SYSKEYDOWN) \ - { \ - SetMsgHandled(TRUE); \ - func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnSysKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) -#define MSG_WM_SYSKEYUP(func) \ - if (uMsg == WM_SYSKEYUP) \ - { \ - SetMsgHandled(TRUE); \ - func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnSysChar(UINT nChar, UINT nRepCnt, UINT nFlags) -#define MSG_WM_SYSCHAR(func) \ - if (uMsg == WM_SYSCHAR) \ - { \ - SetMsgHandled(TRUE); \ - func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnSysDeadChar(UINT nChar, UINT nRepCnt, UINT nFlags) -#define MSG_WM_SYSDEADCHAR(func) \ - if (uMsg == WM_SYSDEADCHAR) \ - { \ - SetMsgHandled(TRUE); \ - func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnSysCommand(UINT nID, LPARAM lParam) -#define MSG_WM_SYSCOMMAND(func) \ - if (uMsg == WM_SYSCOMMAND) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnTCard(UINT idAction, DWORD dwActionData) -#define MSG_WM_TCARD(func) \ - if (uMsg == WM_TCARD) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, (DWORD)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnTimer(UINT_PTR nIDEvent) -#define MSG_WM_TIMER(func) \ - if (uMsg == WM_TIMER) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT_PTR)wParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar) -#define MSG_WM_HSCROLL(func) \ - if (uMsg == WM_HSCROLL) \ - { \ - SetMsgHandled(TRUE); \ - func((int)LOWORD(wParam), (short)HIWORD(wParam), (HWND)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar) -#define MSG_WM_VSCROLL(func) \ - if (uMsg == WM_VSCROLL) \ - { \ - SetMsgHandled(TRUE); \ - func((int)LOWORD(wParam), (short)HIWORD(wParam), (HWND)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnInitMenu(CMenu menu) -#define MSG_WM_INITMENU(func) \ - if (uMsg == WM_INITMENU) \ - { \ - SetMsgHandled(TRUE); \ - func((HMENU)wParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnInitMenuPopup(CMenu menuPopup, UINT nIndex, BOOL bSysMenu) -#define MSG_WM_INITMENUPOPUP(func) \ - if (uMsg == WM_INITMENUPOPUP) \ - { \ - SetMsgHandled(TRUE); \ - func((HMENU)wParam, (UINT)LOWORD(lParam), (BOOL)HIWORD(lParam)); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnMenuSelect(UINT nItemID, UINT nFlags, CMenu menu) -#define MSG_WM_MENUSELECT(func) \ - if (uMsg == WM_MENUSELECT) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), (HMENU)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// LRESULT OnMenuChar(UINT nChar, UINT nFlags, CMenu menu) -#define MSG_WM_MENUCHAR(func) \ - if (uMsg == WM_MENUCHAR) \ - { \ - SetMsgHandled(TRUE); \ - lResult = func((TCHAR)LOWORD(wParam), (UINT)HIWORD(wParam), (HMENU)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// LRESULT OnNotify(int idCtrl, LPNMHDR pnmh) -#define MSG_WM_NOTIFY(func) \ - if (uMsg == WM_NOTIFY) \ - { \ - SetMsgHandled(TRUE); \ - lResult = func((int)wParam, (LPNMHDR)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnEnterIdle(UINT nWhy, CWindow wndWho) -#define MSG_WM_ENTERIDLE(func) \ - if (uMsg == WM_ENTERIDLE) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, (HWND)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnMouseMove(UINT nFlags, CPoint point) -#define MSG_WM_MOUSEMOVE(func) \ - if (uMsg == WM_MOUSEMOVE) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) -#define MSG_WM_MOUSEWHEEL(func) \ - if (uMsg == WM_MOUSEWHEEL) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((UINT)LOWORD(wParam), (short)HIWORD(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnLButtonDown(UINT nFlags, CPoint point) -#define MSG_WM_LBUTTONDOWN(func) \ - if (uMsg == WM_LBUTTONDOWN) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnLButtonUp(UINT nFlags, CPoint point) -#define MSG_WM_LBUTTONUP(func) \ - if (uMsg == WM_LBUTTONUP) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnLButtonDblClk(UINT nFlags, CPoint point) -#define MSG_WM_LBUTTONDBLCLK(func) \ - if (uMsg == WM_LBUTTONDBLCLK) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnRButtonDown(UINT nFlags, CPoint point) -#define MSG_WM_RBUTTONDOWN(func) \ - if (uMsg == WM_RBUTTONDOWN) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnRButtonUp(UINT nFlags, CPoint point) -#define MSG_WM_RBUTTONUP(func) \ - if (uMsg == WM_RBUTTONUP) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnRButtonDblClk(UINT nFlags, CPoint point) -#define MSG_WM_RBUTTONDBLCLK(func) \ - if (uMsg == WM_RBUTTONDBLCLK) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnMButtonDown(UINT nFlags, CPoint point) -#define MSG_WM_MBUTTONDOWN(func) \ - if (uMsg == WM_MBUTTONDOWN) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnMButtonUp(UINT nFlags, CPoint point) -#define MSG_WM_MBUTTONUP(func) \ - if (uMsg == WM_MBUTTONUP) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnMButtonDblClk(UINT nFlags, CPoint point) -#define MSG_WM_MBUTTONDBLCLK(func) \ - if (uMsg == WM_MBUTTONDBLCLK) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnParentNotify(UINT message, UINT nChildID, LPARAM lParam) -#define MSG_WM_PARENTNOTIFY(func) \ - if (uMsg == WM_PARENTNOTIFY) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnMDIActivate(CWindow wndActivate, CWindow wndDeactivate) -#define MSG_WM_MDIACTIVATE(func) \ - if (uMsg == WM_MDIACTIVATE) \ - { \ - SetMsgHandled(TRUE); \ - func((HWND)wParam, (HWND)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnRenderFormat(UINT nFormat) -#define MSG_WM_RENDERFORMAT(func) \ - if (uMsg == WM_RENDERFORMAT) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnRenderAllFormats() -#define MSG_WM_RENDERALLFORMATS(func) \ - if (uMsg == WM_RENDERALLFORMATS) \ - { \ - SetMsgHandled(TRUE); \ - func(); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnDestroyClipboard() -#define MSG_WM_DESTROYCLIPBOARD(func) \ - if (uMsg == WM_DESTROYCLIPBOARD) \ - { \ - SetMsgHandled(TRUE); \ - func(); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnDrawClipboard() -#define MSG_WM_DRAWCLIPBOARD(func) \ - if (uMsg == WM_DRAWCLIPBOARD) \ - { \ - SetMsgHandled(TRUE); \ - func(); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnPaintClipboard(CWindow wndViewer, const LPPAINTSTRUCT lpPaintStruct) -#define MSG_WM_PAINTCLIPBOARD(func) \ - if (uMsg == WM_PAINTCLIPBOARD) \ - { \ - SetMsgHandled(TRUE); \ - func((HWND)wParam, (const LPPAINTSTRUCT)::GlobalLock((HGLOBAL)lParam)); \ - ::GlobalUnlock((HGLOBAL)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnVScrollClipboard(CWindow wndViewer, UINT nSBCode, UINT nPos) -#define MSG_WM_VSCROLLCLIPBOARD(func) \ - if (uMsg == WM_VSCROLLCLIPBOARD) \ - { \ - SetMsgHandled(TRUE); \ - func((HWND)wParam, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnContextMenu(CWindow wnd, CPoint point) -#define MSG_WM_CONTEXTMENU(func) \ - if (uMsg == WM_CONTEXTMENU) \ - { \ - SetMsgHandled(TRUE); \ - func((HWND)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnSizeClipboard(CWindow wndViewer, const LPRECT lpRect) -#define MSG_WM_SIZECLIPBOARD(func) \ - if (uMsg == WM_SIZECLIPBOARD) \ - { \ - SetMsgHandled(TRUE); \ - func((HWND)wParam, (const LPRECT)::GlobalLock((HGLOBAL)lParam)); \ - ::GlobalUnlock((HGLOBAL)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnAskCbFormatName(UINT nMaxCount, LPTSTR lpszString) -#define MSG_WM_ASKCBFORMATNAME(func) \ - if (uMsg == WM_ASKCBFORMATNAME) \ - { \ - SetMsgHandled(TRUE); \ - func((DWORD)wParam, (LPTSTR)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnChangeCbChain(CWindow wndRemove, CWindow wndAfter) -#define MSG_WM_CHANGECBCHAIN(func) \ - if (uMsg == WM_CHANGECBCHAIN) \ - { \ - SetMsgHandled(TRUE); \ - func((HWND)wParam, (HWND)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnHScrollClipboard(CWindow wndViewer, UINT nSBCode, UINT nPos) -#define MSG_WM_HSCROLLCLIPBOARD(func) \ - if (uMsg == WM_HSCROLLCLIPBOARD) \ - { \ - SetMsgHandled(TRUE); \ - func((HWND)wParam, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// BOOL OnQueryNewPalette() -#define MSG_WM_QUERYNEWPALETTE(func) \ - if (uMsg == WM_QUERYNEWPALETTE) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func(); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnPaletteChanged(CWindow wndFocus) -#define MSG_WM_PALETTECHANGED(func) \ - if (uMsg == WM_PALETTECHANGED) \ - { \ - SetMsgHandled(TRUE); \ - func((HWND)wParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnPaletteIsChanging(CWindow wndPalChg) -#define MSG_WM_PALETTEISCHANGING(func) \ - if (uMsg == WM_PALETTEISCHANGING) \ - { \ - SetMsgHandled(TRUE); \ - func((HWND)wParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnDropFiles(HDROP hDropInfo) -#define MSG_WM_DROPFILES(func) \ - if (uMsg == WM_DROPFILES) \ - { \ - SetMsgHandled(TRUE); \ - func((HDROP)wParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnWindowPosChanging(LPWINDOWPOS lpWndPos) -#define MSG_WM_WINDOWPOSCHANGING(func) \ - if (uMsg == WM_WINDOWPOSCHANGING) \ - { \ - SetMsgHandled(TRUE); \ - func((LPWINDOWPOS)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnWindowPosChanged(LPWINDOWPOS lpWndPos) -#define MSG_WM_WINDOWPOSCHANGED(func) \ - if (uMsg == WM_WINDOWPOSCHANGED) \ - { \ - SetMsgHandled(TRUE); \ - func((LPWINDOWPOS)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnExitMenuLoop(BOOL fIsTrackPopupMenu) -#define MSG_WM_EXITMENULOOP(func) \ - if (uMsg == WM_EXITMENULOOP) \ - { \ - SetMsgHandled(TRUE); \ - func((BOOL)wParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnEnterMenuLoop(BOOL fIsTrackPopupMenu) -#define MSG_WM_ENTERMENULOOP(func) \ - if (uMsg == WM_ENTERMENULOOP) \ - { \ - SetMsgHandled(TRUE); \ - func((BOOL)wParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnStyleChanged(int nStyleType, LPSTYLESTRUCT lpStyleStruct) -#define MSG_WM_STYLECHANGED(func) \ - if (uMsg == WM_STYLECHANGED) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, (LPSTYLESTRUCT)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnStyleChanging(int nStyleType, LPSTYLESTRUCT lpStyleStruct) -#define MSG_WM_STYLECHANGING(func) \ - if (uMsg == WM_STYLECHANGING) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, (LPSTYLESTRUCT)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnSizing(UINT fwSide, LPRECT pRect) -#define MSG_WM_SIZING(func) \ - if (uMsg == WM_SIZING) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, (LPRECT)lParam); \ - lResult = TRUE; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnMoving(UINT fwSide, LPRECT pRect) -#define MSG_WM_MOVING(func) \ - if (uMsg == WM_MOVING) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, (LPRECT)lParam); \ - lResult = TRUE; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnCaptureChanged(CWindow wnd) -#define MSG_WM_CAPTURECHANGED(func) \ - if (uMsg == WM_CAPTURECHANGED) \ - { \ - SetMsgHandled(TRUE); \ - func((HWND)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// BOOL OnDeviceChange(UINT nEventType, DWORD dwData) -#define MSG_WM_DEVICECHANGE(func) \ - if (uMsg == WM_DEVICECHANGE) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((UINT)wParam, (DWORD)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnCommand(UINT uNotifyCode, int nID, CWindow wndCtl) -#define MSG_WM_COMMAND(func) \ - if (uMsg == WM_COMMAND) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnDisplayChange(UINT uBitsPerPixel, CSize sizeScreen) -#define MSG_WM_DISPLAYCHANGE(func) \ - if (uMsg == WM_DISPLAYCHANGE) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, _WTYPES_NS::CSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnEnterSizeMove() -#define MSG_WM_ENTERSIZEMOVE(func) \ - if (uMsg == WM_ENTERSIZEMOVE) \ - { \ - SetMsgHandled(TRUE); \ - func(); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnExitSizeMove() -#define MSG_WM_EXITSIZEMOVE(func) \ - if (uMsg == WM_EXITSIZEMOVE) \ - { \ - SetMsgHandled(TRUE); \ - func(); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// HFONT OnGetFont() -#define MSG_WM_GETFONT(func) \ - if (uMsg == WM_GETFONT) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func(); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// LRESULT OnGetHotKey() -#define MSG_WM_GETHOTKEY(func) \ - if (uMsg == WM_GETHOTKEY) \ - { \ - SetMsgHandled(TRUE); \ - lResult = func(); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// HICON OnGetIcon() -#define MSG_WM_GETICON(func) \ - if (uMsg == WM_GETICON) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((UINT)wParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// int OnGetText(int cchTextMax, LPTSTR lpszText) -#define MSG_WM_GETTEXT(func) \ - if (uMsg == WM_GETTEXT) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((int)wParam, (LPTSTR)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// int OnGetTextLength() -#define MSG_WM_GETTEXTLENGTH(func) \ - if (uMsg == WM_GETTEXTLENGTH) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func(); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnHelp(LPHELPINFO lpHelpInfo) -#define MSG_WM_HELP(func) \ - if (uMsg == WM_HELP) \ - { \ - SetMsgHandled(TRUE); \ - func((LPHELPINFO)lParam); \ - lResult = TRUE; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnHotKey(int nHotKeyID, UINT uModifiers, UINT uVirtKey) -#define MSG_WM_HOTKEY(func) \ - if (uMsg == WM_HOTKEY) \ - { \ - SetMsgHandled(TRUE); \ - func((int)wParam, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnInputLangChange(DWORD dwCharSet, HKL hKbdLayout) -#define MSG_WM_INPUTLANGCHANGE(func) \ - if (uMsg == WM_INPUTLANGCHANGE) \ - { \ - SetMsgHandled(TRUE); \ - func((DWORD)wParam, (HKL)lParam); \ - lResult = TRUE; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnInputLangChangeRequest(BOOL bSysCharSet, HKL hKbdLayout) -#define MSG_WM_INPUTLANGCHANGEREQUEST(func) \ - if (uMsg == WM_INPUTLANGCHANGEREQUEST) \ - { \ - SetMsgHandled(TRUE); \ - func((BOOL)wParam, (HKL)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnNextDlgCtl(BOOL bHandle, WPARAM wCtlFocus) -#define MSG_WM_NEXTDLGCTL(func) \ - if (uMsg == WM_NEXTDLGCTL) \ - { \ - SetMsgHandled(TRUE); \ - func((BOOL)LOWORD(lParam), wParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnNextMenu(int nVirtKey, LPMDINEXTMENU lpMdiNextMenu) -#define MSG_WM_NEXTMENU(func) \ - if (uMsg == WM_NEXTMENU) \ - { \ - SetMsgHandled(TRUE); \ - func((int)wParam, (LPMDINEXTMENU)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// int OnNotifyFormat(CWindow wndFrom, int nCommand) -#define MSG_WM_NOTIFYFORMAT(func) \ - if (uMsg == WM_NOTIFYFORMAT) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((HWND)wParam, (int)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// BOOL OnPowerBroadcast(DWORD dwPowerEvent, DWORD dwData) -#define MSG_WM_POWERBROADCAST(func) \ - if (uMsg == WM_POWERBROADCAST) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((DWORD)wParam, (DWORD)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnPrint(CDCHandle dc, UINT uFlags) -#define MSG_WM_PRINT(func) \ - if (uMsg == WM_PRINT) \ - { \ - SetMsgHandled(TRUE); \ - func((HDC)wParam, (UINT)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnPrintClient(CDCHandle dc, UINT uFlags) -#define MSG_WM_PRINTCLIENT(func) \ - if (uMsg == WM_PRINTCLIENT) \ - { \ - SetMsgHandled(TRUE); \ - func((HDC)wParam, (UINT)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnRasDialEvent(RASCONNSTATE rasconnstate, DWORD dwError) -#define MSG_WM_RASDIALEVENT(func) \ - if (uMsg == WM_RASDIALEVENT) \ - { \ - SetMsgHandled(TRUE); \ - func((RASCONNSTATE)wParam, (DWORD)lParam); \ - lResult = TRUE; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnSetFont(CFont font, BOOL bRedraw) -#define MSG_WM_SETFONT(func) \ - if (uMsg == WM_SETFONT) \ - { \ - SetMsgHandled(TRUE); \ - func((HFONT)wParam, (BOOL)LOWORD(lParam)); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// int OnSetHotKey(int nVirtKey, UINT uFlags) -#define MSG_WM_SETHOTKEY(func) \ - if (uMsg == WM_SETHOTKEY) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((int)LOBYTE(LOWORD(wParam)), (UINT)HIBYTE(LOWORD(wParam))); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// HICON OnSetIcon(UINT uType, HICON hIcon) -#define MSG_WM_SETICON(func) \ - if (uMsg == WM_SETICON) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((UINT)wParam, (HICON)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnSetRedraw(BOOL bRedraw) -#define MSG_WM_SETREDRAW(func) \ - if (uMsg == WM_SETREDRAW) \ - { \ - SetMsgHandled(TRUE); \ - func((BOOL)wParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// int OnSetText(LPCTSTR lpstrText) -#define MSG_WM_SETTEXT(func) \ - if (uMsg == WM_SETTEXT) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((LPCTSTR)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnUserChanged() -#define MSG_WM_USERCHANGED(func) \ - if (uMsg == WM_USERCHANGED) \ - { \ - SetMsgHandled(TRUE); \ - func(); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -/////////////////////////////////////////////////////////////////////////////// -// New NT4 & NT5 messages - -#if(_WIN32_WINNT >= 0x0400) - -// void OnMouseHover(WPARAM wParam, CPoint ptPos) -#define MSG_WM_MOUSEHOVER(func) \ - if (uMsg == WM_MOUSEHOVER) \ - { \ - SetMsgHandled(TRUE); \ - func(wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnMouseLeave() -#define MSG_WM_MOUSELEAVE(func) \ - if (uMsg == WM_MOUSELEAVE) \ - { \ - SetMsgHandled(TRUE); \ - func(); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -#endif /* _WIN32_WINNT >= 0x0400 */ - -#if(WINVER >= 0x0500) - -// void OnMenuRButtonUp(WPARAM wParam, CMenu menu) -#define MSG_WM_MENURBUTTONUP(func) \ - if (uMsg == WM_MENURBUTTONUP) \ - { \ - SetMsgHandled(TRUE); \ - func(wParam, (HMENU)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// LRESULT OnMenuDrag(WPARAM wParam, CMenu menu) -#define MSG_WM_MENUDRAG(func) \ - if (uMsg == WM_MENUDRAG) \ - { \ - SetMsgHandled(TRUE); \ - lResult = func(wParam, (HMENU)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// LRESULT OnMenuGetObject(PMENUGETOBJECTINFO info) -#define MSG_WM_MENUGETOBJECT(func) \ - if (uMsg == WM_MENUGETOBJECT) \ - { \ - SetMsgHandled(TRUE); \ - lResult = func((PMENUGETOBJECTINFO)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnUnInitMenuPopup(UINT nID, CMenu menu) -#define MSG_WM_UNINITMENUPOPUP(func) \ - if (uMsg == WM_UNINITMENUPOPUP) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)HIWORD(lParam), (HMENU)wParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnMenuCommand(WPARAM nIndex, CMenu menu) -#define MSG_WM_MENUCOMMAND(func) \ - if (uMsg == WM_MENUCOMMAND) \ - { \ - SetMsgHandled(TRUE); \ - func(wParam, (HMENU)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -#endif /* WINVER >= 0x0500 */ - -#if(_WIN32_WINNT >= 0x0500) - -// BOOL OnAppCommand(CWindow wndFocus, short cmd, WORD uDevice, int dwKeys) -#define MSG_WM_APPCOMMAND(func) \ - if (uMsg == WM_APPCOMMAND) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((HWND)wParam, GET_APPCOMMAND_LPARAM(lParam), GET_DEVICE_LPARAM(lParam), GET_KEYSTATE_LPARAM(lParam)); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnNCXButtonDown(int fwButton, short nHittest, CPoint ptPos) -#define MSG_WM_NCXBUTTONDOWN(func) \ - if (uMsg == WM_NCXBUTTONDOWN) \ - { \ - SetMsgHandled(TRUE); \ - func(GET_XBUTTON_WPARAM(wParam), GET_NCHITTEST_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnNCXButtonUp(int fwButton, short nHittest, CPoint ptPos) -#define MSG_WM_NCXBUTTONUP(func) \ - if (uMsg == WM_NCXBUTTONUP) \ - { \ - SetMsgHandled(TRUE); \ - func(GET_XBUTTON_WPARAM(wParam), GET_NCHITTEST_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnNCXButtonDblClk(int fwButton, short nHittest, CPoint ptPos) -#define MSG_WM_NCXBUTTONDBLCLK(func) \ - if (uMsg == WM_NCXBUTTONDBLCLK) \ - { \ - SetMsgHandled(TRUE); \ - func(GET_XBUTTON_WPARAM(wParam), GET_NCHITTEST_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnXButtonDown(int fwButton, int dwKeys, CPoint ptPos) -#define MSG_WM_XBUTTONDOWN(func) \ - if (uMsg == WM_XBUTTONDOWN) \ - { \ - SetMsgHandled(TRUE); \ - func(GET_XBUTTON_WPARAM(wParam), GET_KEYSTATE_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnXButtonUp(int fwButton, int dwKeys, CPoint ptPos) -#define MSG_WM_XBUTTONUP(func) \ - if (uMsg == WM_XBUTTONUP) \ - { \ - SetMsgHandled(TRUE); \ - func(GET_XBUTTON_WPARAM(wParam), GET_KEYSTATE_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnXButtonDblClk(int fwButton, int dwKeys, CPoint ptPos) -#define MSG_WM_XBUTTONDBLCLK(func) \ - if (uMsg == WM_XBUTTONDBLCLK) \ - { \ - SetMsgHandled(TRUE); \ - func(GET_XBUTTON_WPARAM(wParam), GET_KEYSTATE_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnChangeUIState(WORD nAction, WORD nState) -#define MSG_WM_CHANGEUISTATE(func) \ - if (uMsg == WM_CHANGEUISTATE) \ - { \ - SetMsgHandled(TRUE); \ - func(LOWORD(wParam), HIWORD(wParam)); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnUpdateUIState(WORD nAction, WORD nState) -#define MSG_WM_UPDATEUISTATE(func) \ - if (uMsg == WM_UPDATEUISTATE) \ - { \ - SetMsgHandled(TRUE); \ - func(LOWORD(wParam), HIWORD(wParam)); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// LRESULT OnQueryUIState() -#define MSG_WM_QUERYUISTATE(func) \ - if (uMsg == WM_QUERYUISTATE) \ - { \ - SetMsgHandled(TRUE); \ - lResult = func(); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -#endif // (_WIN32_WINNT >= 0x0500) - -#if(_WIN32_WINNT >= 0x0501) - -// void OnInput(WPARAM RawInputCode, HRAWINPUT hRawInput) -#define MSG_WM_INPUT(func) \ - if (uMsg == WM_INPUT) \ - { \ - SetMsgHandled(TRUE); \ - func(GET_RAWINPUT_CODE_WPARAM(wParam), (HRAWINPUT)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnUniChar(TCHAR nChar, UINT nRepCnt, UINT nFlags) -#define MSG_WM_UNICHAR(func) \ - if (uMsg == WM_UNICHAR) \ - { \ - SetMsgHandled(TRUE); \ - func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \ - if(IsMsgHandled()) \ - { \ - lResult = (wParam == UNICODE_NOCHAR) ? TRUE : FALSE; \ - return TRUE; \ - } \ - } - -// void OnWTSSessionChange(WPARAM nStatusCode, PWTSSESSION_NOTIFICATION nSessionID) -#define MSG_WM_WTSSESSION_CHANGE(func) \ - if (uMsg == WM_WTSSESSION_CHANGE) \ - { \ - SetMsgHandled(TRUE); \ - func(wParam, (PWTSSESSION_NOTIFICATION)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// OnThemeChanged() -#define MSG_WM_THEMECHANGED(func) \ - if (uMsg == WM_THEMECHANGED) \ - { \ - SetMsgHandled(TRUE); \ - func(); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -#endif /* _WIN32_WINNT >= 0x0501 */ - -/////////////////////////////////////////////////////////////////////////////// -// ATL defined messages - -// BOOL OnForwardMsg(LPMSG Msg, DWORD nUserData) -#define MSG_WM_FORWARDMSG(func) \ - if (uMsg == WM_FORWARDMSG) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((LPMSG)lParam, (DWORD)wParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -/////////////////////////////////////////////////////////////////////////////// -// Dialog specific messages - -// LRESULT OnDMGetDefID() -#define MSG_DM_GETDEFID(func) \ - if (uMsg == DM_GETDEFID) \ - { \ - SetMsgHandled(TRUE); \ - lResult = func(); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnDMSetDefID(UINT DefID) -#define MSG_DM_SETDEFID(func) \ - if (uMsg == DM_SETDEFID) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam); \ - lResult = TRUE; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnDMReposition() -#define MSG_DM_REPOSITION(func) \ - if (uMsg == DM_REPOSITION) \ - { \ - SetMsgHandled(TRUE); \ - func(); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -/////////////////////////////////////////////////////////////////////////////// -// Reflected messages - -// void OnReflectedCommand(UINT uNotifyCode, int nID, CWindow wndCtl) -#define MSG_OCM_COMMAND(func) \ - if (uMsg == OCM_COMMAND) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// LRESULT OnReflectedNotify(int idCtrl, LPNMHDR pnmh) -#define MSG_OCM_NOTIFY(func) \ - if (uMsg == OCM_NOTIFY) \ - { \ - SetMsgHandled(TRUE); \ - lResult = func((int)wParam, (LPNMHDR)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnReflectedParentNotify(UINT message, UINT nChildID, LPARAM lParam) -#define MSG_OCM_PARENTNOTIFY(func) \ - if (uMsg == OCM_PARENTNOTIFY) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnReflectedDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) -#define MSG_OCM_DRAWITEM(func) \ - if (uMsg == OCM_DRAWITEM) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, (LPDRAWITEMSTRUCT)lParam); \ - lResult = TRUE; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnReflectedMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct) -#define MSG_OCM_MEASUREITEM(func) \ - if (uMsg == OCM_MEASUREITEM) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, (LPMEASUREITEMSTRUCT)lParam); \ - lResult = TRUE; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// int OnReflectedCompareItem(int nIDCtl, LPCOMPAREITEMSTRUCT lpCompareItemStruct) -#define MSG_OCM_COMPAREITEM(func) \ - if (uMsg == OCM_COMPAREITEM) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((UINT)wParam, (LPCOMPAREITEMSTRUCT)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnReflectedDeleteItem(int nIDCtl, LPDELETEITEMSTRUCT lpDeleteItemStruct) -#define MSG_OCM_DELETEITEM(func) \ - if (uMsg == OCM_DELETEITEM) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)wParam, (LPDELETEITEMSTRUCT)lParam); \ - lResult = TRUE; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// int OnReflectedVKeyToItem(UINT nKey, UINT nIndex, CListBox listBox) -#define MSG_OCM_VKEYTOITEM(func) \ - if (uMsg == OCM_VKEYTOITEM) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), (HWND)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -//int OnReflectedCharToItem(UINT nChar, UINT nIndex, CListBox listBox) -#define MSG_OCM_CHARTOITEM(func) \ - if (uMsg == OCM_CHARTOITEM) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), (HWND)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnReflectedHScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar) -#define MSG_OCM_HSCROLL(func) \ - if (uMsg == OCM_HSCROLL) \ - { \ - SetMsgHandled(TRUE); \ - func((int)LOWORD(wParam), (short)HIWORD(wParam), (HWND)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnReflectedVScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar) -#define MSG_OCM_VSCROLL(func) \ - if (uMsg == OCM_VSCROLL) \ - { \ - SetMsgHandled(TRUE); \ - func((int)LOWORD(wParam), (short)HIWORD(wParam), (HWND)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// HBRUSH OnReflectedCtlColorEdit(CDCHandle dc, CEdit edit) -#define MSG_OCM_CTLCOLOREDIT(func) \ - if (uMsg == OCM_CTLCOLOREDIT) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// HBRUSH OnReflectedCtlColorListBox(CDCHandle dc, CListBox listBox) -#define MSG_OCM_CTLCOLORLISTBOX(func) \ - if (uMsg == OCM_CTLCOLORLISTBOX) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// HBRUSH OnReflectedCtlColorBtn(CDCHandle dc, CButton button) -#define MSG_OCM_CTLCOLORBTN(func) \ - if (uMsg == OCM_CTLCOLORBTN) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// HBRUSH OnReflectedCtlColorDlg(CDCHandle dc, CWindow wnd) -#define MSG_OCM_CTLCOLORDLG(func) \ - if (uMsg == OCM_CTLCOLORDLG) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// HBRUSH OnReflectedCtlColorScrollBar(CDCHandle dc, CScrollBar scrollBar) -#define MSG_OCM_CTLCOLORSCROLLBAR(func) \ - if (uMsg == OCM_CTLCOLORSCROLLBAR) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// HBRUSH OnReflectedCtlColorStatic(CDCHandle dc, CStatic wndStatic) -#define MSG_OCM_CTLCOLORSTATIC(func) \ - if (uMsg == OCM_CTLCOLORSTATIC) \ - { \ - SetMsgHandled(TRUE); \ - lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -/////////////////////////////////////////////////////////////////////////////// -// Edit specific messages - -// void OnClear() -#define MSG_WM_CLEAR(func) \ - if (uMsg == WM_CLEAR) \ - { \ - SetMsgHandled(TRUE); \ - func(); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnCopy() -#define MSG_WM_COPY(func) \ - if (uMsg == WM_COPY) \ - { \ - SetMsgHandled(TRUE); \ - func(); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnCut() -#define MSG_WM_CUT(func) \ - if (uMsg == WM_CUT) \ - { \ - SetMsgHandled(TRUE); \ - func(); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnPaste() -#define MSG_WM_PASTE(func) \ - if (uMsg == WM_PASTE) \ - { \ - SetMsgHandled(TRUE); \ - func(); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnUndo() -#define MSG_WM_UNDO(func) \ - if (uMsg == WM_UNDO) \ - { \ - SetMsgHandled(TRUE); \ - func(); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -/////////////////////////////////////////////////////////////////////////////// -// Generic message handlers - -// LRESULT OnMessageHandlerEX(UINT uMsg, WPARAM wParam, LPARAM lParam) -#define MESSAGE_HANDLER_EX(msg, func) \ - if(uMsg == msg) \ - { \ - SetMsgHandled(TRUE); \ - lResult = func(uMsg, wParam, lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// LRESULT OnMessageRangeHandlerEX(UINT uMsg, WPARAM wParam, LPARAM lParam) -#define MESSAGE_RANGE_HANDLER_EX(msgFirst, msgLast, func) \ - if(uMsg >= msgFirst && uMsg <= msgLast) \ - { \ - SetMsgHandled(TRUE); \ - lResult = func(uMsg, wParam, lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -/////////////////////////////////////////////////////////////////////////////// -// Commands and notifications - -// void OnCommandHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl) -#define COMMAND_HANDLER_EX(id, code, func) \ - if (uMsg == WM_COMMAND && code == HIWORD(wParam) && id == LOWORD(wParam)) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnCommandIDHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl) -#define COMMAND_ID_HANDLER_EX(id, func) \ - if (uMsg == WM_COMMAND && id == LOWORD(wParam)) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnCommandCodeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl) -#define COMMAND_CODE_HANDLER_EX(code, func) \ - if (uMsg == WM_COMMAND && code == HIWORD(wParam)) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// LRESULT OnNotifyHandlerEX(LPNMHDR pnmh) -#define NOTIFY_HANDLER_EX(id, cd, func) \ - if (uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code && id == ((LPNMHDR)lParam)->idFrom) \ - { \ - SetMsgHandled(TRUE); \ - lResult = func((LPNMHDR)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// LRESULT OnNotifyIDHandlerEX(LPNMHDR pnmh) -#define NOTIFY_ID_HANDLER_EX(id, func) \ - if (uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) \ - { \ - SetMsgHandled(TRUE); \ - lResult = func((LPNMHDR)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// LRESULT OnNotifyCodeHandlerEX(LPNMHDR pnmh) -#define NOTIFY_CODE_HANDLER_EX(cd, func) \ - if (uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \ - { \ - SetMsgHandled(TRUE); \ - lResult = func((LPNMHDR)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnCommandRangeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl) -#define COMMAND_RANGE_HANDLER_EX(idFirst, idLast, func) \ - if(uMsg == WM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnCommandRangeCodeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl) -#define COMMAND_RANGE_CODE_HANDLER_EX(idFirst, idLast, code, func) \ - if(uMsg == WM_COMMAND && code == HIWORD(wParam) && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// LRESULT OnNotifyRangeHandlerEX(LPNMHDR pnmh) -#define NOTIFY_RANGE_HANDLER_EX(idFirst, idLast, func) \ - if(uMsg == WM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \ - { \ - SetMsgHandled(TRUE); \ - lResult = func((LPNMHDR)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// LRESULT OnNotifyRangeCodeHandlerEX(LPNMHDR pnmh) -#define NOTIFY_RANGE_CODE_HANDLER_EX(idFirst, idLast, cd, func) \ - if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \ - { \ - SetMsgHandled(TRUE); \ - lResult = func((LPNMHDR)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// LRESULT OnReflectedCommandHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl) -#define REFLECTED_COMMAND_HANDLER_EX(id, code, func) \ - if (uMsg == OCM_COMMAND && code == HIWORD(wParam) && id == LOWORD(wParam)) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// LRESULT OnReflectedCommandIDHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl) -#define REFLECTED_COMMAND_ID_HANDLER_EX(id, func) \ - if (uMsg == OCM_COMMAND && id == LOWORD(wParam)) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// LRESULT OnReflectedCommandCodeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl) -#define REFLECTED_COMMAND_CODE_HANDLER_EX(code, func) \ - if (uMsg == OCM_COMMAND && code == HIWORD(wParam)) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// LRESULT OnReflectedNotifyHandlerEX(LPNMHDR pnmh) -#define REFLECTED_NOTIFY_HANDLER_EX(id, cd, func) \ - if (uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code && id == ((LPNMHDR)lParam)->idFrom) \ - { \ - SetMsgHandled(TRUE); \ - lResult = func((LPNMHDR)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// LRESULT OnReflectedNotifyIDHandlerEX(LPNMHDR pnmh) -#define REFLECTED_NOTIFY_ID_HANDLER_EX(id, func) \ - if (uMsg == OCM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) \ - { \ - SetMsgHandled(TRUE); \ - lResult = func((LPNMHDR)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// LRESULT OnReflectedNotifyCodeHandlerEX(LPNMHDR pnmh) -#define REFLECTED_NOTIFY_CODE_HANDLER_EX(cd, func) \ - if (uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \ - { \ - SetMsgHandled(TRUE); \ - lResult = func((LPNMHDR)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnReflectedCommandRangeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl) -#define REFLECTED_COMMAND_RANGE_HANDLER_EX(idFirst, idLast, func) \ - if(uMsg == OCM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// void OnReflectedCommandRangeCodeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl) -#define REFLECTED_COMMAND_RANGE_CODE_HANDLER_EX(idFirst, idLast, code, func) \ - if(uMsg == OCM_COMMAND && code == HIWORD(wParam) && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \ - { \ - SetMsgHandled(TRUE); \ - func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \ - lResult = 0; \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// LRESULT OnReflectedNotifyRangeHandlerEX(LPNMHDR pnmh) -#define REFLECTED_NOTIFY_RANGE_HANDLER_EX(idFirst, idLast, func) \ - if(uMsg == OCM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \ - { \ - SetMsgHandled(TRUE); \ - lResult = func((LPNMHDR)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -// LRESULT OnReflectedNotifyRangeCodeHandlerEX(LPNMHDR pnmh) -#define REFLECTED_NOTIFY_RANGE_CODE_HANDLER_EX(idFirst, idLast, cd, func) \ - if(uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \ - { \ - SetMsgHandled(TRUE); \ - lResult = func((LPNMHDR)lParam); \ - if(IsMsgHandled()) \ - return TRUE; \ - } - -#endif // __ATLCRACK_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/atlctrls.h b/prog/3rdPartyLibs/wtl-8.1/include/atlctrls.h deleted file mode 100644 index 7aa925465..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/atlctrls.h +++ /dev/null @@ -1,10039 +0,0 @@ -// Windows Template Library - WTL version 8.1 -// Copyright (C) Microsoft Corporation. All rights reserved. -// -// This file is a part of the Windows Template Library. -// The use and distribution terms for this software are covered by the -// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php) -// which can be found in the file CPL.TXT at the root of this distribution. -// By using this software in any fashion, you are agreeing to be bound by -// the terms of this license. You must not remove this notice, or -// any other, from this software. - -#ifndef __ATLCTRLS_H__ -#define __ATLCTRLS_H__ - -#pragma once - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#ifndef __ATLAPP_H__ - #error atlctrls.h requires atlapp.h to be included first -#endif - -#ifndef __ATLWIN_H__ - #error atlctrls.h requires atlwin.h to be included first -#endif - -#if (_WIN32_IE < 0x0300) - #error atlctrls.h requires IE Version 3.0 or higher -#endif - -#ifndef _WIN32_WCE - #include - #include -#elif defined(WIN32_PLATFORM_WFSP) && !defined(_WINUSERM_H_) - #include -#endif // !_WIN32_WCE - -// protect template members from windowsx.h macros -#ifdef _INC_WINDOWSX - #undef GetNextSibling - #undef GetPrevSibling -#endif // _INC_WINDOWSX - - -/////////////////////////////////////////////////////////////////////////////// -// Classes in this file: -// -// CStaticT - CStatic -// CButtonT - CButton -// CListBoxT - CListBox -// CComboBoxT - CComboBox -// CEditT - CEdit -// CEditCommands -// CScrollBarT - CScrollBar -// -// CImageList -// CListViewCtrlT - CListViewCtrl -// CTreeViewCtrlT - CTreeViewCtrl -// CTreeItemT - CTreeItem -// CTreeViewCtrlExT - CTreeViewCtrlEx -// CHeaderCtrlT - CHeaderCtrl -// CToolBarCtrlT - CToolBarCtrl -// CStatusBarCtrlT - CStatusBarCtrl -// CTabCtrlT - CTabCtrl -// CToolInfo -// CToolTipCtrlT - CToolTipCtrl -// CTrackBarCtrlT - CTrackBarCtrl -// CUpDownCtrlT - CUpDownCtrl -// CProgressBarCtrlT - CProgressBarCtrl -// CHotKeyCtrlT - CHotKeyCtrl -// CAnimateCtrlT - CAnimateCtrl -// CRichEditCtrlT - CRichEditCtrl -// CRichEditCommands -// CDragListBoxT - CDragListBox -// CDragListNotifyImpl -// CReBarCtrlT - CReBarCtrl -// CComboBoxExT - CComboBoxEx -// CDateTimePickerCtrlT - CDateTimePickerCtrl -// CMonthCalendarCtrlT - CMonthCalendarCtrl -// CFlatScrollBarImpl -// CFlatScrollBarT - CFlatScrollBar -// CIPAddressCtrlT - CIPAddressCtrl -// CPagerCtrlT - CPagerCtrl -// CLinkCtrlT - CLinkCtrl -// -// CCustomDraw -// -// CCECommandBarCtrlT - CCECommandBarCtrl -// CCECommandBandsCtrlT - CCECommandBandsCtrl - - -namespace WTL -{ - -// These are wrapper classes for Windows standard and common controls. -// To implement a window based on a control, use following: -// Example: Implementing a window based on a list box -// -// class CMyListBox : CWindowImpl -// { -// public: -// BEGIN_MSG_MAP(CMyListBox) -// // put your message handler entries here -// END_MSG_MAP() -// }; - - - -// --- Standard Windows controls --- - -/////////////////////////////////////////////////////////////////////////////// -// CStatic - client side for a Windows STATIC control - -template -class CStaticT : public TBase -{ -public: -// Constructors - CStaticT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CStaticT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return _T("STATIC"); - } - -#ifndef _WIN32_WCE - HICON GetIcon() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HICON)::SendMessage(m_hWnd, STM_GETICON, 0, 0L); - } - - HICON SetIcon(HICON hIcon) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HICON)::SendMessage(m_hWnd, STM_SETICON, (WPARAM)hIcon, 0L); - } - - HENHMETAFILE GetEnhMetaFile() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HENHMETAFILE)::SendMessage(m_hWnd, STM_GETIMAGE, IMAGE_ENHMETAFILE, 0L); - } - - HENHMETAFILE SetEnhMetaFile(HENHMETAFILE hMetaFile) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HENHMETAFILE)::SendMessage(m_hWnd, STM_SETIMAGE, IMAGE_ENHMETAFILE, (LPARAM)hMetaFile); - } -#else // CE specific - HICON GetIcon() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HICON)::SendMessage(m_hWnd, STM_GETIMAGE, IMAGE_ICON, 0L); - } - - HICON SetIcon(HICON hIcon) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HICON)::SendMessage(m_hWnd, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); - } -#endif // _WIN32_WCE - - CBitmapHandle GetBitmap() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return CBitmapHandle((HBITMAP)::SendMessage(m_hWnd, STM_GETIMAGE, IMAGE_BITMAP, 0L)); - } - - CBitmapHandle SetBitmap(HBITMAP hBitmap) - { - ATLASSERT(::IsWindow(m_hWnd)); - return CBitmapHandle((HBITMAP)::SendMessage(m_hWnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap)); - } - - HCURSOR GetCursor() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HCURSOR)::SendMessage(m_hWnd, STM_GETIMAGE, IMAGE_CURSOR, 0L); - } - - HCURSOR SetCursor(HCURSOR hCursor) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HCURSOR)::SendMessage(m_hWnd, STM_SETIMAGE, IMAGE_CURSOR, (LPARAM)hCursor); - } -}; - -typedef CStaticT CStatic; - - -/////////////////////////////////////////////////////////////////////////////// -// CButton - client side for a Windows BUTTON control - -template -class CButtonT : public TBase -{ -public: -// Constructors - CButtonT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CButtonT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return _T("BUTTON"); - } - - UINT GetState() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::SendMessage(m_hWnd, BM_GETSTATE, 0, 0L); - } - - void SetState(BOOL bHighlight) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, BM_SETSTATE, bHighlight, 0L); - } - - int GetCheck() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, BM_GETCHECK, 0, 0L); - } - - void SetCheck(int nCheck) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, BM_SETCHECK, nCheck, 0L); - } - - UINT GetButtonStyle() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::GetWindowLong(m_hWnd, GWL_STYLE) & 0xFFFF; - } - - void SetButtonStyle(UINT nStyle, BOOL bRedraw = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, BM_SETSTYLE, nStyle, (LPARAM)bRedraw); - } - -#ifndef _WIN32_WCE - HICON GetIcon() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HICON)::SendMessage(m_hWnd, BM_GETIMAGE, IMAGE_ICON, 0L); - } - - HICON SetIcon(HICON hIcon) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HICON)::SendMessage(m_hWnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); - } - - CBitmapHandle GetBitmap() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return CBitmapHandle((HBITMAP)::SendMessage(m_hWnd, BM_GETIMAGE, IMAGE_BITMAP, 0L)); - } - - CBitmapHandle SetBitmap(HBITMAP hBitmap) - { - ATLASSERT(::IsWindow(m_hWnd)); - return CBitmapHandle((HBITMAP)::SendMessage(m_hWnd, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap)); - } -#endif // !_WIN32_WCE - -#if (_WIN32_WINNT >= 0x0501) - BOOL GetIdealSize(LPSIZE lpSize) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, BCM_GETIDEALSIZE, 0, (LPARAM)lpSize); - } - - BOOL GetImageList(PBUTTON_IMAGELIST pButtonImagelist) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, BCM_GETIMAGELIST, 0, (LPARAM)pButtonImagelist); - } - - BOOL SetImageList(PBUTTON_IMAGELIST pButtonImagelist) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, BCM_SETIMAGELIST, 0, (LPARAM)pButtonImagelist); - } - - BOOL GetTextMargin(LPRECT lpRect) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, BCM_GETTEXTMARGIN, 0, (LPARAM)lpRect); - } - - BOOL SetTextMargin(LPRECT lpRect) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, BCM_SETTEXTMARGIN, 0, (LPARAM)lpRect); - } -#endif // (_WIN32_WINNT >= 0x0501) - -#if (WINVER >= 0x0600) - void SetDontClick(BOOL bDontClick) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, BM_SETDONTCLICK, (WPARAM)bDontClick, 0L); - } -#endif // (WINVER >= 0x0600) - -#if (_WIN32_WINNT >= 0x0600) - BOOL SetDropDownState(BOOL bDropDown) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetStyle() & (BS_SPLITBUTTON | BS_DEFSPLITBUTTON)) != 0); - return (BOOL)::SendMessage(m_hWnd, BCM_SETDROPDOWNSTATE, (WPARAM)bDropDown, 0L); - } - - BOOL GetSplitInfo(PBUTTON_SPLITINFO pSplitInfo) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetStyle() & (BS_SPLITBUTTON | BS_DEFSPLITBUTTON)) != 0); - return (BOOL)::SendMessage(m_hWnd, BCM_GETSPLITINFO, 0, (LPARAM)pSplitInfo); - } - - BOOL SetSplitInfo(PBUTTON_SPLITINFO pSplitInfo) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetStyle() & (BS_SPLITBUTTON | BS_DEFSPLITBUTTON)) != 0); - return (BOOL)::SendMessage(m_hWnd, BCM_SETSPLITINFO, 0, (LPARAM)pSplitInfo); - } - - int GetNoteLength() const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetStyle() & (BS_COMMANDLINK | BS_DEFCOMMANDLINK)) != 0); - return (int)::SendMessage(m_hWnd, BCM_GETNOTELENGTH, 0, 0L); - } - - BOOL GetNote(LPWSTR lpstrNoteText, int cchNoteText) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetStyle() & (BS_COMMANDLINK | BS_DEFCOMMANDLINK)) != 0); - return (BOOL)::SendMessage(m_hWnd, BCM_GETNOTE, cchNoteText, (LPARAM)lpstrNoteText); - } - - BOOL SetNote(LPCWSTR lpstrNoteText) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetStyle() & (BS_COMMANDLINK | BS_DEFCOMMANDLINK)) != 0); - return (BOOL)::SendMessage(m_hWnd, BCM_SETNOTE, 0, (LPARAM)lpstrNoteText); - } - - LRESULT SetElevationRequiredState(BOOL bSet) - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SendMessage(m_hWnd, BCM_SETSHIELD, 0, (LPARAM)bSet); - } -#endif // (_WIN32_WINNT >= 0x0600) - -// Operations - void Click() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, BM_CLICK, 0, 0L); - } -}; - -typedef CButtonT CButton; - - -/////////////////////////////////////////////////////////////////////////////// -// CListBox - client side for a Windows LISTBOX control - -template -class CListBoxT : public TBase -{ -public: -// Constructors - CListBoxT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CListBoxT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return _T("LISTBOX"); - } - - // for entire listbox - int GetCount() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LB_GETCOUNT, 0, 0L); - } - -#ifndef _WIN32_WCE - int SetCount(int cItems) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(((GetStyle() & LBS_NODATA) != 0) && ((GetStyle() & LBS_HASSTRINGS) == 0)); - return (int)::SendMessage(m_hWnd, LB_SETCOUNT, cItems, 0L); - } -#endif // !_WIN32_WCE - - int GetHorizontalExtent() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LB_GETHORIZONTALEXTENT, 0, 0L); - } - - void SetHorizontalExtent(int cxExtent) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, LB_SETHORIZONTALEXTENT, cxExtent, 0L); - } - - int GetTopIndex() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LB_GETTOPINDEX, 0, 0L); - } - - int SetTopIndex(int nIndex) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LB_SETTOPINDEX, nIndex, 0L); - } - - LCID GetLocale() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (LCID)::SendMessage(m_hWnd, LB_GETLOCALE, 0, 0L); - } - - LCID SetLocale(LCID nNewLocale) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (LCID)::SendMessage(m_hWnd, LB_SETLOCALE, (WPARAM)nNewLocale, 0L); - } - -#if (WINVER >= 0x0500) && !defined(_WIN32_WCE) - DWORD GetListBoxInfo() const - { - ATLASSERT(::IsWindow(m_hWnd)); -#if (_WIN32_WINNT >= 0x0501) - return (DWORD)::SendMessage(m_hWnd, LB_GETLISTBOXINFO, 0, 0L); -#else // !(_WIN32_WINNT >= 0x0501) - return ::GetListBoxInfo(m_hWnd); -#endif // !(_WIN32_WINNT >= 0x0501) - } -#endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE) - - // for single-selection listboxes - int GetCurSel() const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) == 0); - return (int)::SendMessage(m_hWnd, LB_GETCURSEL, 0, 0L); - } - - int SetCurSel(int nSelect) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) == 0); - return (int)::SendMessage(m_hWnd, LB_SETCURSEL, nSelect, 0L); - } - - // for multiple-selection listboxes - int GetSel(int nIndex) const // also works for single-selection - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LB_GETSEL, nIndex, 0L); - } - - int SetSel(int nIndex, BOOL bSelect = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0); - return (int)::SendMessage(m_hWnd, LB_SETSEL, bSelect, nIndex); - } - - int GetSelCount() const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0); - return (int)::SendMessage(m_hWnd, LB_GETSELCOUNT, 0, 0L); - } - - int GetSelItems(int nMaxItems, LPINT rgIndex) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0); - return (int)::SendMessage(m_hWnd, LB_GETSELITEMS, nMaxItems, (LPARAM)rgIndex); - } - - int GetAnchorIndex() const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0); - return (int)::SendMessage(m_hWnd, LB_GETANCHORINDEX, 0, 0L); - } - - void SetAnchorIndex(int nIndex) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0); - ::SendMessage(m_hWnd, LB_SETANCHORINDEX, nIndex, 0L); - } - - int GetCaretIndex() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LB_GETCARETINDEX, 0, 0); - } - - int SetCaretIndex(int nIndex, BOOL bScroll = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LB_SETCARETINDEX, nIndex, MAKELONG(bScroll, 0)); - } - - // for listbox items - DWORD_PTR GetItemData(int nIndex) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD_PTR)::SendMessage(m_hWnd, LB_GETITEMDATA, nIndex, 0L); - } - - int SetItemData(int nIndex, DWORD_PTR dwItemData) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LB_SETITEMDATA, nIndex, (LPARAM)dwItemData); - } - - void* GetItemDataPtr(int nIndex) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (void*)::SendMessage(m_hWnd, LB_GETITEMDATA, nIndex, 0L); - } - - int SetItemDataPtr(int nIndex, void* pData) - { - ATLASSERT(::IsWindow(m_hWnd)); - return SetItemData(nIndex, (DWORD_PTR)pData); - } - - int GetItemRect(int nIndex, LPRECT lpRect) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LB_GETITEMRECT, nIndex, (LPARAM)lpRect); - } - - int GetText(int nIndex, LPTSTR lpszBuffer) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LB_GETTEXT, nIndex, (LPARAM)lpszBuffer); - } - -#ifndef _ATL_NO_COM -#ifdef _OLEAUTO_H_ - BOOL GetTextBSTR(int nIndex, BSTR& bstrText) const - { - USES_CONVERSION; - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(bstrText == NULL); - - int nLen = GetTextLen(nIndex); - if(nLen == LB_ERR) - return FALSE; - - CTempBuffer buff; - LPTSTR lpstrText = buff.Allocate(nLen + 1); - if(lpstrText == NULL) - return FALSE; - - if(GetText(nIndex, lpstrText) == LB_ERR) - return FALSE; - - bstrText = ::SysAllocString(T2OLE(lpstrText)); - return (bstrText != NULL) ? TRUE : FALSE; - } -#endif // _OLEAUTO_H_ -#endif // !_ATL_NO_COM - -#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - int GetText(int nIndex, _CSTRING_NS::CString& strText) const - { - ATLASSERT(::IsWindow(m_hWnd)); - int cchLen = GetTextLen(nIndex); - if(cchLen == LB_ERR) - return LB_ERR; - int nRet = LB_ERR; - LPTSTR lpstr = strText.GetBufferSetLength(cchLen); - if(lpstr != NULL) - { - nRet = GetText(nIndex, lpstr); - strText.ReleaseBuffer(); - } - return nRet; - } -#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - - int GetTextLen(int nIndex) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LB_GETTEXTLEN, nIndex, 0L); - } - - int GetItemHeight(int nIndex) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LB_GETITEMHEIGHT, nIndex, 0L); - } - - int SetItemHeight(int nIndex, UINT cyItemHeight) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LB_SETITEMHEIGHT, nIndex, MAKELONG(cyItemHeight, 0)); - } - - // Settable only attributes - void SetColumnWidth(int cxWidth) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, LB_SETCOLUMNWIDTH, cxWidth, 0L); - } - - BOOL SetTabStops(int nTabStops, LPINT rgTabStops) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetStyle() & LBS_USETABSTOPS) != 0); - return (BOOL)::SendMessage(m_hWnd, LB_SETTABSTOPS, nTabStops, (LPARAM)rgTabStops); - } - - BOOL SetTabStops() - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetStyle() & LBS_USETABSTOPS) != 0); - return (BOOL)::SendMessage(m_hWnd, LB_SETTABSTOPS, 0, 0L); - } - - BOOL SetTabStops(const int& cxEachStop) // takes an 'int' - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetStyle() & LBS_USETABSTOPS) != 0); - return (BOOL)::SendMessage(m_hWnd, LB_SETTABSTOPS, 1, (LPARAM)(LPINT)&cxEachStop); - } - -// Operations - int InitStorage(int nItems, UINT nBytes) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LB_INITSTORAGE, (WPARAM)nItems, nBytes); - } - - void ResetContent() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, LB_RESETCONTENT, 0, 0L); - } - - UINT ItemFromPoint(POINT pt, BOOL& bOutside) const - { - ATLASSERT(::IsWindow(m_hWnd)); - DWORD dw = (DWORD)::SendMessage(m_hWnd, LB_ITEMFROMPOINT, 0, MAKELPARAM(pt.x, pt.y)); - bOutside = (BOOL)HIWORD(dw); - return (UINT)LOWORD(dw); - } - - // manipulating listbox items - int AddString(LPCTSTR lpszItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LB_ADDSTRING, 0, (LPARAM)lpszItem); - } - - int DeleteString(UINT nIndex) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LB_DELETESTRING, nIndex, 0L); - } - - int InsertString(int nIndex, LPCTSTR lpszItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LB_INSERTSTRING, nIndex, (LPARAM)lpszItem); - } - -#ifndef _WIN32_WCE - int Dir(UINT attr, LPCTSTR lpszWildCard) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LB_DIR, attr, (LPARAM)lpszWildCard); - } - - int AddFile(LPCTSTR lpstrFileName) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LB_ADDFILE, 0, (LPARAM)lpstrFileName); - } -#endif // !_WIN32_WCE - - // selection helpers - int FindString(int nStartAfter, LPCTSTR lpszItem) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LB_FINDSTRING, nStartAfter, (LPARAM)lpszItem); - } - - int FindStringExact(int nIndexStart, LPCTSTR lpszFind) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LB_FINDSTRINGEXACT, nIndexStart, (LPARAM)lpszFind); - } - - int SelectString(int nStartAfter, LPCTSTR lpszItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LB_SELECTSTRING, nStartAfter, (LPARAM)lpszItem); - } - - int SelItemRange(BOOL bSelect, int nFirstItem, int nLastItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0); - ATLASSERT(nFirstItem <= nLastItem); - return bSelect ? (int)::SendMessage(m_hWnd, LB_SELITEMRANGEEX, nFirstItem, nLastItem) : (int)::SendMessage(m_hWnd, LB_SELITEMRANGEEX, nLastItem, nFirstItem); - } - -#ifdef WIN32_PLATFORM_WFSP // SmartPhone only messages - DWORD GetInputMode(BOOL bCurrentMode = TRUE) - { - return SendMessage(LB_GETINPUTMODE, 0, (LPARAM)bCurrentMode); - } - - BOOL SetInputMode(DWORD dwMode) - { - return SendMessage(LB_SETINPUTMODE, 0, (LPARAM)dwMode); - } -#endif // WIN32_PLATFORM_WFSP -}; - -typedef CListBoxT CListBox; - - -/////////////////////////////////////////////////////////////////////////////// -// CComboBox - client side for a Windows COMBOBOX control - -#ifndef WIN32_PLATFORM_WFSP // No COMBOBOX on SmartPhones - -template -class CComboBoxT : public TBase -{ -public: -// Constructors - CComboBoxT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CComboBoxT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return _T("COMBOBOX"); - } - - // for entire combo box - int GetCount() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, CB_GETCOUNT, 0, 0L); - } - - int GetCurSel() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, CB_GETCURSEL, 0, 0L); - } - - int SetCurSel(int nSelect) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, CB_SETCURSEL, nSelect, 0L); - } - - LCID GetLocale() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (LCID)::SendMessage(m_hWnd, CB_GETLOCALE, 0, 0L); - } - - LCID SetLocale(LCID nNewLocale) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (LCID)::SendMessage(m_hWnd, CB_SETLOCALE, (WPARAM)nNewLocale, 0L); - } - - int GetTopIndex() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, CB_GETTOPINDEX, 0, 0L); - } - - int SetTopIndex(int nIndex) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, CB_SETTOPINDEX, nIndex, 0L); - } - - UINT GetHorizontalExtent() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::SendMessage(m_hWnd, CB_GETHORIZONTALEXTENT, 0, 0L); - } - - void SetHorizontalExtent(UINT nExtent) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, CB_SETHORIZONTALEXTENT, nExtent, 0L); - } - - int GetDroppedWidth() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, CB_GETDROPPEDWIDTH, 0, 0L); - } - - int SetDroppedWidth(UINT nWidth) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, CB_SETDROPPEDWIDTH, nWidth, 0L); - } - -#if ((WINVER >= 0x0500) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 420)) - BOOL GetComboBoxInfo(PCOMBOBOXINFO pComboBoxInfo) const - { - ATLASSERT(::IsWindow(m_hWnd)); -#if ((_WIN32_WINNT >= 0x0501) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 420)) - return (BOOL)::SendMessage(m_hWnd, CB_GETCOMBOBOXINFO, 0, (LPARAM)pComboBoxInfo); -#else // !((_WIN32_WINNT >= 0x0501) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 420)) - return ::GetComboBoxInfo(m_hWnd, pComboBoxInfo); -#endif // !((_WIN32_WINNT >= 0x0501) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 420)) - } -#endif // ((WINVER >= 0x0500) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 420)) - - // for edit control - DWORD GetEditSel() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, CB_GETEDITSEL, 0, 0L); - } - - BOOL SetEditSel(int nStartChar, int nEndChar) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, CB_SETEDITSEL, 0, MAKELONG(nStartChar, nEndChar)); - } - - // for combobox item - DWORD_PTR GetItemData(int nIndex) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD_PTR)::SendMessage(m_hWnd, CB_GETITEMDATA, nIndex, 0L); - } - - int SetItemData(int nIndex, DWORD_PTR dwItemData) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, CB_SETITEMDATA, nIndex, (LPARAM)dwItemData); - } - - void* GetItemDataPtr(int nIndex) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (void*)GetItemData(nIndex); - } - - int SetItemDataPtr(int nIndex, void* pData) - { - ATLASSERT(::IsWindow(m_hWnd)); - return SetItemData(nIndex, (DWORD_PTR)pData); - } - - int GetLBText(int nIndex, LPTSTR lpszText) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, CB_GETLBTEXT, nIndex, (LPARAM)lpszText); - } - -#ifndef _ATL_NO_COM - BOOL GetLBTextBSTR(int nIndex, BSTR& bstrText) const - { - USES_CONVERSION; - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(bstrText == NULL); - - int nLen = GetLBTextLen(nIndex); - if(nLen == CB_ERR) - return FALSE; - - CTempBuffer buff; - LPTSTR lpstrText = buff.Allocate(nLen + 1); - if(lpstrText == NULL) - return FALSE; - - if(GetLBText(nIndex, lpstrText) == CB_ERR) - return FALSE; - - bstrText = ::SysAllocString(T2OLE(lpstrText)); - return (bstrText != NULL) ? TRUE : FALSE; - } -#endif // !_ATL_NO_COM - -#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - int GetLBText(int nIndex, _CSTRING_NS::CString& strText) const - { - ATLASSERT(::IsWindow(m_hWnd)); - int cchLen = GetLBTextLen(nIndex); - if(cchLen == CB_ERR) - return CB_ERR; - int nRet = CB_ERR; - LPTSTR lpstr = strText.GetBufferSetLength(cchLen); - if(lpstr != NULL) - { - nRet = GetLBText(nIndex, lpstr); - strText.ReleaseBuffer(); - } - return nRet; - } -#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - - int GetLBTextLen(int nIndex) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, CB_GETLBTEXTLEN, nIndex, 0L); - } - - int GetItemHeight(int nIndex) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, CB_GETITEMHEIGHT, nIndex, 0L); - } - - int SetItemHeight(int nIndex, UINT cyItemHeight) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, CB_SETITEMHEIGHT, nIndex, MAKELONG(cyItemHeight, 0)); - } - - BOOL GetExtendedUI() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, CB_GETEXTENDEDUI, 0, 0L); - } - - int SetExtendedUI(BOOL bExtended = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, CB_SETEXTENDEDUI, bExtended, 0L); - } - - void GetDroppedControlRect(LPRECT lprect) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)lprect); - } - - BOOL GetDroppedState() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, CB_GETDROPPEDSTATE, 0, 0L); - } - -#if (_WIN32_WINNT >= 0x0501) - int GetMinVisible() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, CB_GETMINVISIBLE, 0, 0L); - } - - BOOL SetMinVisible(int nMinVisible) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, CB_SETMINVISIBLE, nMinVisible, 0L); - } - - // Vista only - BOOL GetCueBannerText(LPWSTR lpwText, int cchText) const - { -#ifndef CB_GETCUEBANNER - const UINT CB_GETCUEBANNER = (CBM_FIRST + 4); -#endif - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, CB_GETCUEBANNER, (WPARAM)lpwText, cchText); - } - - // Vista only - BOOL SetCueBannerText(LPCWSTR lpcwText) - { -#ifndef CB_SETCUEBANNER - const UINT CB_SETCUEBANNER = (CBM_FIRST + 3); -#endif - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, CB_SETCUEBANNER, 0, (LPARAM)lpcwText); - } -#endif // (_WIN32_WINNT >= 0x0501) - -// Operations - int InitStorage(int nItems, UINT nBytes) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, CB_INITSTORAGE, (WPARAM)nItems, nBytes); - } - - void ResetContent() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, CB_RESETCONTENT, 0, 0L); - } - - // for edit control - BOOL LimitText(int nMaxChars) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, CB_LIMITTEXT, nMaxChars, 0L); - } - - // for drop-down combo boxes - void ShowDropDown(BOOL bShowIt = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, CB_SHOWDROPDOWN, bShowIt, 0L); - } - - // manipulating listbox items - int AddString(LPCTSTR lpszString) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, CB_ADDSTRING, 0, (LPARAM)lpszString); - } - - int DeleteString(UINT nIndex) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, CB_DELETESTRING, nIndex, 0L); - } - - int InsertString(int nIndex, LPCTSTR lpszString) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, CB_INSERTSTRING, nIndex, (LPARAM)lpszString); - } - -#ifndef _WIN32_WCE - int Dir(UINT attr, LPCTSTR lpszWildCard) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, CB_DIR, attr, (LPARAM)lpszWildCard); - } -#endif // !_WIN32_WCE - - // selection helpers - int FindString(int nStartAfter, LPCTSTR lpszString) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, CB_FINDSTRING, nStartAfter, (LPARAM)lpszString); - } - - int FindStringExact(int nIndexStart, LPCTSTR lpszFind) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, CB_FINDSTRINGEXACT, nIndexStart, (LPARAM)lpszFind); - } - - int SelectString(int nStartAfter, LPCTSTR lpszString) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, CB_SELECTSTRING, nStartAfter, (LPARAM)lpszString); - } - - // Clipboard operations - void Clear() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_CLEAR, 0, 0L); - } - - void Copy() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_COPY, 0, 0L); - } - - void Cut() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_CUT, 0, 0L); - } - - void Paste() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_PASTE, 0, 0L); - } -}; - -typedef CComboBoxT CComboBox; - -#endif // !WIN32_PLATFORM_WFSP - -/////////////////////////////////////////////////////////////////////////////// -// CEdit - client side for a Windows EDIT control - -template -class CEditT : public TBase -{ -public: -// Constructors - CEditT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CEditT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return _T("EDIT"); - } - - BOOL CanUndo() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_CANUNDO, 0, 0L); - } - - int GetLineCount() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, EM_GETLINECOUNT, 0, 0L); - } - - BOOL GetModify() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_GETMODIFY, 0, 0L); - } - - void SetModify(BOOL bModified = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_SETMODIFY, bModified, 0L); - } - - void GetRect(LPRECT lpRect) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_GETRECT, 0, (LPARAM)lpRect); - } - - DWORD GetSel() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, EM_GETSEL, 0, 0L); - } - - void GetSel(int& nStartChar, int& nEndChar) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_GETSEL, (WPARAM)&nStartChar, (LPARAM)&nEndChar); - } - -#ifndef _WIN32_WCE - HLOCAL GetHandle() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HLOCAL)::SendMessage(m_hWnd, EM_GETHANDLE, 0, 0L); - } - - void SetHandle(HLOCAL hBuffer) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_SETHANDLE, (WPARAM)hBuffer, 0L); - } -#endif // !_WIN32_WCE - - DWORD GetMargins() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, EM_GETMARGINS, 0, 0L); - } - - void SetMargins(UINT nLeft, UINT nRight) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_SETMARGINS, EC_LEFTMARGIN|EC_RIGHTMARGIN, MAKELONG(nLeft, nRight)); - } - - UINT GetLimitText() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::SendMessage(m_hWnd, EM_GETLIMITTEXT, 0, 0L); - } - - void SetLimitText(UINT nMax) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_SETLIMITTEXT, nMax, 0L); - } - - POINT PosFromChar(UINT nChar) const - { - ATLASSERT(::IsWindow(m_hWnd)); - DWORD dwRet = (DWORD)::SendMessage(m_hWnd, EM_POSFROMCHAR, nChar, 0); - POINT point = { GET_X_LPARAM(dwRet), GET_Y_LPARAM(dwRet) }; - return point; - } - - int CharFromPos(POINT pt, int* pLine = NULL) const - { - ATLASSERT(::IsWindow(m_hWnd)); - DWORD dwRet = (DWORD)::SendMessage(m_hWnd, EM_CHARFROMPOS, 0, MAKELPARAM(pt.x, pt.y)); - if(pLine != NULL) - *pLine = (int)(short)HIWORD(dwRet); - return (int)(short)LOWORD(dwRet); - } - - // NOTE: first word in lpszBuffer must contain the size of the buffer! - int GetLine(int nIndex, LPTSTR lpszBuffer) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, EM_GETLINE, nIndex, (LPARAM)lpszBuffer); - } - - int GetLine(int nIndex, LPTSTR lpszBuffer, int nMaxLength) const - { - ATLASSERT(::IsWindow(m_hWnd)); - *(LPWORD)lpszBuffer = (WORD)nMaxLength; - return (int)::SendMessage(m_hWnd, EM_GETLINE, nIndex, (LPARAM)lpszBuffer); - } - - TCHAR GetPasswordChar() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (TCHAR)::SendMessage(m_hWnd, EM_GETPASSWORDCHAR, 0, 0L); - } - - void SetPasswordChar(TCHAR ch) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_SETPASSWORDCHAR, ch, 0L); - } - -#ifndef _WIN32_WCE - EDITWORDBREAKPROC GetWordBreakProc() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (EDITWORDBREAKPROC)::SendMessage(m_hWnd, EM_GETWORDBREAKPROC, 0, 0L); - } - - void SetWordBreakProc(EDITWORDBREAKPROC ewbprc) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_SETWORDBREAKPROC, 0, (LPARAM)ewbprc); - } -#endif // !_WIN32_WCE - - int GetFirstVisibleLine() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, EM_GETFIRSTVISIBLELINE, 0, 0L); - } - -#ifndef _WIN32_WCE - int GetThumb() const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetStyle() & ES_MULTILINE) != 0); - return (int)::SendMessage(m_hWnd, EM_GETTHUMB, 0, 0L); - } -#endif // !_WIN32_WCE - - BOOL SetReadOnly(BOOL bReadOnly = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_SETREADONLY, bReadOnly, 0L); - } - -#if (WINVER >= 0x0500) && !defined(_WIN32_WCE) - UINT GetImeStatus(UINT uStatus) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::SendMessage(m_hWnd, EM_GETIMESTATUS, uStatus, 0L); - } - - UINT SetImeStatus(UINT uStatus, UINT uData) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::SendMessage(m_hWnd, EM_SETIMESTATUS, uStatus, uData); - } -#endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE) - -#if (_WIN32_WINNT >= 0x0501) - BOOL GetCueBannerText(LPCWSTR lpstrText, int cchText) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_GETCUEBANNER, (WPARAM)lpstrText, cchText); - } - - // bKeepWithFocus - Vista only - BOOL SetCueBannerText(LPCWSTR lpstrText, BOOL bKeepWithFocus = FALSE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_SETCUEBANNER, (WPARAM)bKeepWithFocus, (LPARAM)(lpstrText)); - } -#endif // (_WIN32_WINNT >= 0x0501) - -// Operations - void EmptyUndoBuffer() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_EMPTYUNDOBUFFER, 0, 0L); - } - - BOOL FmtLines(BOOL bAddEOL) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_FMTLINES, bAddEOL, 0L); - } - - void LimitText(int nChars = 0) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_LIMITTEXT, nChars, 0L); - } - - int LineFromChar(int nIndex = -1) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, EM_LINEFROMCHAR, nIndex, 0L); - } - - int LineIndex(int nLine = -1) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, EM_LINEINDEX, nLine, 0L); - } - - int LineLength(int nLine = -1) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, EM_LINELENGTH, nLine, 0L); - } - - void LineScroll(int nLines, int nChars = 0) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_LINESCROLL, nChars, nLines); - } - - void ReplaceSel(LPCTSTR lpszNewText, BOOL bCanUndo = FALSE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_REPLACESEL, (WPARAM) bCanUndo, (LPARAM)lpszNewText); - } - - void SetRect(LPCRECT lpRect) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_SETRECT, 0, (LPARAM)lpRect); - } - - void SetRectNP(LPCRECT lpRect) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_SETRECTNP, 0, (LPARAM)lpRect); - } - - void SetSel(DWORD dwSelection, BOOL bNoScroll = FALSE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_SETSEL, LOWORD(dwSelection), HIWORD(dwSelection)); - if(!bNoScroll) - ::SendMessage(m_hWnd, EM_SCROLLCARET, 0, 0L); - } - - void SetSel(int nStartChar, int nEndChar, BOOL bNoScroll = FALSE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_SETSEL, nStartChar, nEndChar); - if(!bNoScroll) - ::SendMessage(m_hWnd, EM_SCROLLCARET, 0, 0L); - } - - void SetSelAll(BOOL bNoScroll = FALSE) - { - SetSel(0, -1, bNoScroll); - } - - void SetSelNone(BOOL bNoScroll = FALSE) - { - SetSel(-1, 0, bNoScroll); - } - - BOOL SetTabStops(int nTabStops, LPINT rgTabStops) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, nTabStops, (LPARAM)rgTabStops); - } - - BOOL SetTabStops() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, 0, 0L); - } - - BOOL SetTabStops(const int& cxEachStop) // takes an 'int' - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, 1, (LPARAM)(LPINT)&cxEachStop); - } - - void ScrollCaret() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_SCROLLCARET, 0, 0L); - } - - int Scroll(int nScrollAction) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetStyle() & ES_MULTILINE) != 0); - LRESULT lRet = ::SendMessage(m_hWnd, EM_SCROLL, nScrollAction, 0L); - if(!(BOOL)HIWORD(lRet)) - return -1; // failed - return (int)(short)LOWORD(lRet); - - } - - void InsertText(int nInsertAfterChar, LPCTSTR lpstrText, BOOL bNoScroll = FALSE, BOOL bCanUndo = FALSE) - { - SetSel(nInsertAfterChar, nInsertAfterChar, bNoScroll); - ReplaceSel(lpstrText, bCanUndo); - } - - void AppendText(LPCTSTR lpstrText, BOOL bNoScroll = FALSE, BOOL bCanUndo = FALSE) - { - InsertText(GetWindowTextLength(), lpstrText, bNoScroll, bCanUndo); - } - -#if (_WIN32_WINNT >= 0x0501) - BOOL ShowBalloonTip(PEDITBALLOONTIP pEditBaloonTip) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_SHOWBALLOONTIP, 0, (LPARAM)pEditBaloonTip); - } - - BOOL HideBalloonTip() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_HIDEBALLOONTIP, 0, 0L); - } -#endif // (_WIN32_WINNT >= 0x0501) - -#if (_WIN32_WINNT >= 0x0600) - DWORD GetHilite() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, EM_GETHILITE, 0, 0L); - } - - void GetHilite(int& nStartChar, int& nEndChar) const - { - ATLASSERT(::IsWindow(m_hWnd)); - DWORD dwRet = (DWORD)::SendMessage(m_hWnd, EM_GETHILITE, 0, 0L); - nStartChar = (int)(short)LOWORD(dwRet); - nEndChar = (int)(short)HIWORD(dwRet); - } - - void SetHilite(int nStartChar, int nEndChar) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_SETHILITE, nStartChar, nEndChar); - } -#endif // (_WIN32_WINNT >= 0x0600) - - // Clipboard operations - BOOL Undo() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_UNDO, 0, 0L); - } - - void Clear() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_CLEAR, 0, 0L); - } - - void Copy() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_COPY, 0, 0L); - } - - void Cut() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_CUT, 0, 0L); - } - - void Paste() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_PASTE, 0, 0L); - } - -#ifdef WIN32_PLATFORM_WFSP // SmartPhone only messages - DWORD GetExtendedStyle() - { - return SendMessage(EM_GETEXTENDEDSTYLE); - } - - DWORD SetExtendedStyle(DWORD dwMask, DWORD dwExStyle) - { - return SendMessage(EM_SETEXTENDEDSTYLE, (WPARAM)dwMask, (LPARAM)dwExStyle); - } - - DWORD GetInputMode(BOOL bCurrentMode = TRUE) - { - return SendMessage(EM_GETINPUTMODE, 0, (LPARAM)bCurrentMode); - } - - BOOL SetInputMode(DWORD dwMode) - { - return SendMessage(EM_SETINPUTMODE, 0, (LPARAM)dwMode); - } - - BOOL SetSymbols(LPCTSTR szSymbols) - { - return SendMessage(EM_SETSYMBOLS, 0, (LPARAM)szSymbols); - } - - BOOL ResetSymbols() - { - return SendMessage(EM_SETSYMBOLS); - } -#endif // WIN32_PLATFORM_WFSP -}; - -typedef CEditT CEdit; - - -/////////////////////////////////////////////////////////////////////////////// -// CEditCommands - message handlers for standard EDIT commands - -// Chain to CEditCommands message map. Your class must also derive from CEdit. -// Example: -// class CMyEdit : public CWindowImpl, -// public CEditCommands -// { -// public: -// BEGIN_MSG_MAP(CMyEdit) -// // your handlers... -// CHAIN_MSG_MAP_ALT(CEditCommands, 1) -// END_MSG_MAP() -// // other stuff... -// }; - -template -class CEditCommands -{ -public: - BEGIN_MSG_MAP(CEditCommands< T >) - ALT_MSG_MAP(1) - COMMAND_ID_HANDLER(ID_EDIT_CLEAR, OnEditClear) - COMMAND_ID_HANDLER(ID_EDIT_CLEAR_ALL, OnEditClearAll) - COMMAND_ID_HANDLER(ID_EDIT_COPY, OnEditCopy) - COMMAND_ID_HANDLER(ID_EDIT_CUT, OnEditCut) - COMMAND_ID_HANDLER(ID_EDIT_PASTE, OnEditPaste) - COMMAND_ID_HANDLER(ID_EDIT_SELECT_ALL, OnEditSelectAll) - COMMAND_ID_HANDLER(ID_EDIT_UNDO, OnEditUndo) - END_MSG_MAP() - - LRESULT OnEditClear(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - pT->Clear(); - return 0; - } - - LRESULT OnEditClearAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - pT->SetSel(0, -1); - pT->Clear(); - return 0; - } - - LRESULT OnEditCopy(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - pT->Copy(); - return 0; - } - - LRESULT OnEditCut(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - pT->Cut(); - return 0; - } - - LRESULT OnEditPaste(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - pT->Paste(); - return 0; - } - - LRESULT OnEditSelectAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - pT->SetSel(0, -1); - return 0; - } - - LRESULT OnEditUndo(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - pT->Undo(); - return 0; - } - -// State (update UI) helpers - BOOL CanCut() const - { return HasSelection(); } - - BOOL CanCopy() const - { return HasSelection(); } - - BOOL CanClear() const - { return HasSelection(); } - - BOOL CanSelectAll() const - { return HasText(); } - - BOOL CanFind() const - { return HasText(); } - - BOOL CanRepeat() const - { return HasText(); } - - BOOL CanReplace() const - { return HasText(); } - - BOOL CanClearAll() const - { return HasText(); } - -// Implementation - BOOL HasSelection() const - { - const T* pT = static_cast(this); - int nMin, nMax; - ::SendMessage(pT->m_hWnd, EM_GETSEL, (WPARAM)&nMin, (LPARAM)&nMax); - return (nMin != nMax); - } - - BOOL HasText() const - { - const T* pT = static_cast(this); - return (pT->GetWindowTextLength() > 0); - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CScrollBar - client side for a Windows SCROLLBAR control - -template -class CScrollBarT : public TBase -{ -public: -// Constructors - CScrollBarT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CScrollBarT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return _T("SCROLLBAR"); - } - -#ifndef _WIN32_WCE - int GetScrollPos() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetScrollPos(m_hWnd, SB_CTL); - } -#endif // !_WIN32_WCE - - int SetScrollPos(int nPos, BOOL bRedraw = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetScrollPos(m_hWnd, SB_CTL, nPos, bRedraw); - } - -#ifndef _WIN32_WCE - void GetScrollRange(LPINT lpMinPos, LPINT lpMaxPos) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ::GetScrollRange(m_hWnd, SB_CTL, lpMinPos, lpMaxPos); - } -#endif // !_WIN32_WCE - - void SetScrollRange(int nMinPos, int nMaxPos, BOOL bRedraw = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SetScrollRange(m_hWnd, SB_CTL, nMinPos, nMaxPos, bRedraw); - } - - BOOL GetScrollInfo(LPSCROLLINFO lpScrollInfo) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetScrollInfo(m_hWnd, SB_CTL, lpScrollInfo); - } - - int SetScrollInfo(LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetScrollInfo(m_hWnd, SB_CTL, lpScrollInfo, bRedraw); - } - -#ifndef _WIN32_WCE - int GetScrollLimit() const - { - int nMin = 0, nMax = 0; - ::GetScrollRange(m_hWnd, SB_CTL, &nMin, &nMax); - SCROLLINFO info = { 0 }; - info.cbSize = sizeof(SCROLLINFO); - info.fMask = SIF_PAGE; - if(::GetScrollInfo(m_hWnd, SB_CTL, &info)) - nMax -= ((info.nPage - 1) > 0) ? (info.nPage - 1) : 0; - - return nMax; - } - -#if (WINVER >= 0x0500) - BOOL GetScrollBarInfo(PSCROLLBARINFO pScrollBarInfo) const - { - ATLASSERT(::IsWindow(m_hWnd)); -#if (_WIN32_WINNT >= 0x0501) - return (BOOL)::SendMessage(m_hWnd, SBM_GETSCROLLBARINFO, 0, (LPARAM)pScrollBarInfo); -#else // !(_WIN32_WINNT >= 0x0501) - return ::GetScrollBarInfo(m_hWnd, OBJID_CLIENT, pScrollBarInfo); -#endif // !(_WIN32_WINNT >= 0x0501) - } -#endif // (WINVER >= 0x0500) - -// Operations - void ShowScrollBar(BOOL bShow = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::ShowScrollBar(m_hWnd, SB_CTL, bShow); - } - - BOOL EnableScrollBar(UINT nArrowFlags = ESB_ENABLE_BOTH) - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::EnableScrollBar(m_hWnd, SB_CTL, nArrowFlags); - } -#endif // !_WIN32_WCE -}; - -typedef CScrollBarT CScrollBar; - - -// --- Windows Common Controls --- - -/////////////////////////////////////////////////////////////////////////////// -// CImageList - -class CImageList -{ -public: - HIMAGELIST m_hImageList; - -// Constructor - CImageList(HIMAGELIST hImageList = NULL) : m_hImageList(hImageList) - { } - -// Operators, etc. - CImageList& operator =(HIMAGELIST hImageList) - { - m_hImageList = hImageList; - return *this; - } - - operator HIMAGELIST() const { return m_hImageList; } - - void Attach(HIMAGELIST hImageList) - { - ATLASSERT(m_hImageList == NULL); - ATLASSERT(hImageList != NULL); - m_hImageList = hImageList; - } - - HIMAGELIST Detach() - { - HIMAGELIST hImageList = m_hImageList; - m_hImageList = NULL; - return hImageList; - } - - bool IsNull() const { return (m_hImageList == NULL); } - -// Attributes - int GetImageCount() const - { - ATLASSERT(m_hImageList != NULL); - return ImageList_GetImageCount(m_hImageList); - } - - COLORREF GetBkColor() const - { - ATLASSERT(m_hImageList != NULL); - return ImageList_GetBkColor(m_hImageList); - } - - COLORREF SetBkColor(COLORREF cr) - { - ATLASSERT(m_hImageList != NULL); - return ImageList_SetBkColor(m_hImageList, cr); - } - - BOOL GetImageInfo(int nImage, IMAGEINFO* pImageInfo) const - { - ATLASSERT(m_hImageList != NULL); - return ImageList_GetImageInfo(m_hImageList, nImage, pImageInfo); - } - - HICON GetIcon(int nIndex, UINT uFlags = ILD_NORMAL) const - { - ATLASSERT(m_hImageList != NULL); - return ImageList_GetIcon(m_hImageList, nIndex, uFlags); - } - - BOOL GetIconSize(int& cx, int& cy) const - { - ATLASSERT(m_hImageList != NULL); - return ImageList_GetIconSize(m_hImageList, &cx, &cy); - } - - BOOL GetIconSize(SIZE& size) const - { - ATLASSERT(m_hImageList != NULL); - return ImageList_GetIconSize(m_hImageList, (int*)&size.cx, (int*)&size.cy); - } - - BOOL SetIconSize(int cx, int cy) - { - ATLASSERT(m_hImageList != NULL); - return ImageList_SetIconSize(m_hImageList, cx, cy); - } - - BOOL SetIconSize(SIZE size) - { - ATLASSERT(m_hImageList != NULL); - return ImageList_SetIconSize(m_hImageList, size.cx, size.cy); - } - - BOOL SetImageCount(UINT uNewCount) - { - ATLASSERT(m_hImageList != NULL); - return ImageList_SetImageCount(m_hImageList, uNewCount); - } - - BOOL SetOverlayImage(int nImage, int nOverlay) - { - ATLASSERT(m_hImageList != NULL); - return ImageList_SetOverlayImage(m_hImageList, nImage, nOverlay); - } - -// Operations - BOOL Create(int cx, int cy, UINT nFlags, int nInitial, int nGrow) - { - ATLASSERT(m_hImageList == NULL); - m_hImageList = ImageList_Create(cx, cy, nFlags, nInitial, nGrow); - return (m_hImageList != NULL) ? TRUE : FALSE; - } - - BOOL Create(ATL::_U_STRINGorID bitmap, int cx, int nGrow, COLORREF crMask) - { - ATLASSERT(m_hImageList == NULL); - m_hImageList = ImageList_LoadBitmap(ModuleHelper::GetResourceInstance(), bitmap.m_lpstr, cx, nGrow, crMask); - return (m_hImageList != NULL) ? TRUE : FALSE; - } - - BOOL CreateFromImage(ATL::_U_STRINGorID image, int cx, int nGrow, COLORREF crMask, UINT uType, UINT uFlags = LR_DEFAULTCOLOR | LR_DEFAULTSIZE) - { - ATLASSERT(m_hImageList == NULL); - m_hImageList = ImageList_LoadImage(ModuleHelper::GetResourceInstance(), image.m_lpstr, cx, nGrow, crMask, uType, uFlags); - return (m_hImageList != NULL) ? TRUE : FALSE; - } - - BOOL Merge(HIMAGELIST hImageList1, int nImage1, HIMAGELIST hImageList2, int nImage2, int dx, int dy) - { - ATLASSERT(m_hImageList == NULL); - m_hImageList = ImageList_Merge(hImageList1, nImage1, hImageList2, nImage2, dx, dy); - return (m_hImageList != NULL) ? TRUE : FALSE; - } - -#ifndef _WIN32_WCE -#ifdef __IStream_INTERFACE_DEFINED__ - BOOL CreateFromStream(LPSTREAM lpStream) - { - ATLASSERT(m_hImageList == NULL); - m_hImageList = ImageList_Read(lpStream); - return (m_hImageList != NULL) ? TRUE : FALSE; - } -#endif // __IStream_INTERFACE_DEFINED__ -#endif // !_WIN32_WCE - - BOOL Destroy() - { - if (m_hImageList == NULL) - return FALSE; - BOOL bRet = ImageList_Destroy(m_hImageList); - if(bRet) - m_hImageList = NULL; - return bRet; - } - - int Add(HBITMAP hBitmap, HBITMAP hBitmapMask = NULL) - { - ATLASSERT(m_hImageList != NULL); - return ImageList_Add(m_hImageList, hBitmap, hBitmapMask); - } - - int Add(HBITMAP hBitmap, COLORREF crMask) - { - ATLASSERT(m_hImageList != NULL); - return ImageList_AddMasked(m_hImageList, hBitmap, crMask); - } - - BOOL Remove(int nImage) - { - ATLASSERT(m_hImageList != NULL); - return ImageList_Remove(m_hImageList, nImage); - } - - BOOL RemoveAll() - { - ATLASSERT(m_hImageList != NULL); - return ImageList_RemoveAll(m_hImageList); - } - - BOOL Replace(int nImage, HBITMAP hBitmap, HBITMAP hBitmapMask) - { - ATLASSERT(m_hImageList != NULL); - return ImageList_Replace(m_hImageList, nImage, hBitmap, hBitmapMask); - } - - int AddIcon(HICON hIcon) - { - ATLASSERT(m_hImageList != NULL); - return ImageList_AddIcon(m_hImageList, hIcon); - } - - int ReplaceIcon(int nImage, HICON hIcon) - { - ATLASSERT(m_hImageList != NULL); - return ImageList_ReplaceIcon(m_hImageList, nImage, hIcon); - } - - HICON ExtractIcon(int nImage) - { - ATLASSERT(m_hImageList != NULL); - return ImageList_ExtractIcon(NULL, m_hImageList, nImage); - } - - BOOL Draw(HDC hDC, int nImage, int x, int y, UINT nStyle) - { - ATLASSERT(m_hImageList != NULL); - ATLASSERT(hDC != NULL); - return ImageList_Draw(m_hImageList, nImage, hDC, x, y, nStyle); - } - - BOOL Draw(HDC hDC, int nImage, POINT pt, UINT nStyle) - { - ATLASSERT(m_hImageList != NULL); - ATLASSERT(hDC != NULL); - return ImageList_Draw(m_hImageList, nImage, hDC, pt.x, pt.y, nStyle); - } - - BOOL DrawEx(int nImage, HDC hDC, int x, int y, int dx, int dy, COLORREF rgbBk, COLORREF rgbFg, UINT fStyle) - { - ATLASSERT(m_hImageList != NULL); - ATLASSERT(hDC != NULL); - return ImageList_DrawEx(m_hImageList, nImage, hDC, x, y, dx, dy, rgbBk, rgbFg, fStyle); - } - - BOOL DrawEx(int nImage, HDC hDC, RECT& rect, COLORREF rgbBk, COLORREF rgbFg, UINT fStyle) - { - ATLASSERT(m_hImageList != NULL); - ATLASSERT(hDC != NULL); - return ImageList_DrawEx(m_hImageList, nImage, hDC, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, rgbBk, rgbFg, fStyle); - } - - static BOOL DrawIndirect(IMAGELISTDRAWPARAMS* pimldp) - { - return ImageList_DrawIndirect(pimldp); - } - - BOOL Copy(int nSrc, int nDst, UINT uFlags = ILCF_MOVE) - { - ATLASSERT(m_hImageList != NULL); - return ImageList_Copy(m_hImageList, nDst, m_hImageList, nSrc, uFlags); - } - -#ifdef __IStream_INTERFACE_DEFINED__ -#ifndef _WIN32_WCE - static HIMAGELIST Read(LPSTREAM lpStream) - { - return ImageList_Read(lpStream); - } - - BOOL Write(LPSTREAM lpStream) - { - ATLASSERT(m_hImageList != NULL); - return ImageList_Write(m_hImageList, lpStream); - } -#endif // !_WIN32_WCE - -#if (_WIN32_WINNT >= 0x0501) - static HRESULT ReadEx(DWORD dwFlags, LPSTREAM lpStream, REFIID riid, PVOID* ppv) - { - return ImageList_ReadEx(dwFlags, lpStream, riid, ppv); - } - - HRESULT WriteEx(DWORD dwFlags, LPSTREAM lpStream) - { - ATLASSERT(m_hImageList != NULL); - return ImageList_WriteEx(m_hImageList, dwFlags, lpStream); - } -#endif // (_WIN32_WINNT >= 0x0501) -#endif // __IStream_INTERFACE_DEFINED__ - - // Drag operations - BOOL BeginDrag(int nImage, POINT ptHotSpot) - { - ATLASSERT(m_hImageList != NULL); - return ImageList_BeginDrag(m_hImageList, nImage, ptHotSpot.x, ptHotSpot.y); - } - - BOOL BeginDrag(int nImage, int xHotSpot, int yHotSpot) - { - ATLASSERT(m_hImageList != NULL); - return ImageList_BeginDrag(m_hImageList, nImage, xHotSpot, yHotSpot); - } - - static void EndDrag() - { - ImageList_EndDrag(); - } - - static BOOL DragMove(POINT pt) - { - return ImageList_DragMove(pt.x, pt.y); - } - - static BOOL DragMove(int x, int y) - { - return ImageList_DragMove(x, y); - } - - BOOL SetDragCursorImage(int nDrag, POINT ptHotSpot) - { - ATLASSERT(m_hImageList != NULL); - return ImageList_SetDragCursorImage(m_hImageList, nDrag, ptHotSpot.x, ptHotSpot.y); - } - - BOOL SetDragCursorImage(int nDrag, int xHotSpot, int yHotSpot) - { - ATLASSERT(m_hImageList != NULL); - return ImageList_SetDragCursorImage(m_hImageList, nDrag, xHotSpot, yHotSpot); - } - - static BOOL DragShowNolock(BOOL bShow = TRUE) - { - return ImageList_DragShowNolock(bShow); - } - - static CImageList GetDragImage(LPPOINT lpPoint, LPPOINT lpPointHotSpot) - { - return CImageList(ImageList_GetDragImage(lpPoint, lpPointHotSpot)); - } - - static BOOL DragEnter(HWND hWnd, POINT point) - { - return ImageList_DragEnter(hWnd, point.x, point.y); - } - - static BOOL DragEnter(HWND hWnd, int x, int y) - { - return ImageList_DragEnter(hWnd, x, y); - } - - static BOOL DragLeave(HWND hWnd) - { - return ImageList_DragLeave(hWnd); - } - -#if (_WIN32_IE >= 0x0400) - CImageList Duplicate() const - { - ATLASSERT(m_hImageList != NULL); - return CImageList(ImageList_Duplicate(m_hImageList)); - } - - static CImageList Duplicate(HIMAGELIST hImageList) - { - ATLASSERT(hImageList != NULL); - return CImageList(ImageList_Duplicate(hImageList)); - } -#endif // (_WIN32_IE >= 0x0400) -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CToolTipCtrl - -#ifndef _WIN32_WCE - -class CToolInfo : public TOOLINFO -{ -public: - CToolInfo(UINT nFlags, HWND hWnd, UINT nIDTool = 0, LPRECT lpRect = NULL, LPTSTR lpstrText = LPSTR_TEXTCALLBACK, LPARAM lUserParam = NULL) - { - Init(nFlags, hWnd, nIDTool, lpRect, lpstrText, lUserParam); - } - - operator LPTOOLINFO() { return this; } - - operator LPARAM() { return (LPARAM)this; } - - void Init(UINT nFlags, HWND hWnd, UINT nIDTool = 0, LPRECT lpRect = NULL, LPTSTR lpstrText = LPSTR_TEXTCALLBACK, LPARAM lUserParam = NULL) - { - ATLASSERT(::IsWindow(hWnd)); - memset(this, 0, sizeof(TOOLINFO)); - cbSize = sizeof(TOOLINFO); - uFlags = nFlags; - if(nIDTool == 0) - { - hwnd = ::GetParent(hWnd); - uFlags |= TTF_IDISHWND; - uId = (UINT_PTR)hWnd; - } - else - { - hwnd = hWnd; - uId = nIDTool; - } - if(lpRect != NULL) - rect = *lpRect; - hinst = ModuleHelper::GetResourceInstance(); - lpszText = lpstrText; - lParam = lUserParam; - } -}; - -template -class CToolTipCtrlT : public TBase -{ -public: -// Constructors - CToolTipCtrlT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CToolTipCtrlT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return TOOLTIPS_CLASS; - } - - void GetText(LPTOOLINFO lpToolInfo) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TTM_GETTEXT, 0, (LPARAM)&lpToolInfo); - } - - void GetText(LPTSTR lpstrText, HWND hWnd, UINT nIDTool = 0) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(hWnd != NULL); - CToolInfo ti(0, hWnd, nIDTool, NULL, lpstrText); - ::SendMessage(m_hWnd, TTM_GETTEXT, 0, ti); - } - - BOOL GetToolInfo(LPTOOLINFO lpToolInfo) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TTM_GETTOOLINFO, 0, (LPARAM)lpToolInfo); - } - - BOOL GetToolInfo(HWND hWnd, UINT nIDTool, UINT* puFlags, LPRECT lpRect, LPTSTR lpstrText) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(hWnd != NULL); - ATLASSERT(puFlags != NULL); - ATLASSERT(lpRect != NULL); - CToolInfo ti(0, hWnd, nIDTool, NULL, lpstrText); - BOOL bRet = (BOOL)::SendMessage(m_hWnd, TTM_GETTOOLINFO, 0, ti); - if(bRet != FALSE) - { - *puFlags = ti.uFlags; - *lpRect = ti.rect; - } - return bRet; - } - - void SetToolInfo(LPTOOLINFO lpToolInfo) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TTM_SETTOOLINFO, 0, (LPARAM)lpToolInfo); - } - - void SetToolRect(LPTOOLINFO lpToolInfo) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TTM_NEWTOOLRECT, 0, (LPARAM)lpToolInfo); - } - - void SetToolRect(HWND hWnd, UINT nIDTool, LPCRECT lpRect) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(hWnd != NULL); - ATLASSERT(nIDTool != 0); - - CToolInfo ti(0, hWnd, nIDTool, (LPRECT)lpRect, NULL); - ::SendMessage(m_hWnd, TTM_NEWTOOLRECT, 0, ti); - } - - int GetToolCount() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TTM_GETTOOLCOUNT, 0, 0L); - } - - int GetDelayTime(DWORD dwType) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TTM_GETDELAYTIME, dwType, 0L); - } - - void SetDelayTime(DWORD dwType, int nTime) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TTM_SETDELAYTIME, dwType, MAKELPARAM(nTime, 0)); - } - - void GetMargin(LPRECT lpRect) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TTM_GETMARGIN, 0, (LPARAM)lpRect); - } - - void SetMargin(LPRECT lpRect) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TTM_SETMARGIN, 0, (LPARAM)lpRect); - } - - int GetMaxTipWidth() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TTM_GETMAXTIPWIDTH, 0, 0L); - } - - int SetMaxTipWidth(int nWidth) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TTM_SETMAXTIPWIDTH, 0, nWidth); - } - - COLORREF GetTipBkColor() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, TTM_GETTIPBKCOLOR, 0, 0L); - } - - void SetTipBkColor(COLORREF clr) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TTM_SETTIPBKCOLOR, (WPARAM)clr, 0L); - } - - COLORREF GetTipTextColor() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, TTM_GETTIPTEXTCOLOR, 0, 0L); - } - - void SetTipTextColor(COLORREF clr) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TTM_SETTIPTEXTCOLOR, (WPARAM)clr, 0L); - } - - BOOL GetCurrentTool(LPTOOLINFO lpToolInfo) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TTM_GETCURRENTTOOL, 0, (LPARAM)lpToolInfo); - } - -#if (_WIN32_IE >= 0x0500) - SIZE GetBubbleSize(LPTOOLINFO lpToolInfo) const - { - ATLASSERT(::IsWindow(m_hWnd)); - DWORD dwRet = (DWORD)::SendMessage(m_hWnd, TTM_GETBUBBLESIZE, 0, (LPARAM)lpToolInfo); - SIZE size = { GET_X_LPARAM(dwRet), GET_Y_LPARAM(dwRet) }; - return size; - } - - BOOL SetTitle(UINT uIcon, LPCTSTR lpstrTitle) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TTM_SETTITLE, uIcon, (LPARAM)lpstrTitle); - } -#endif // (_WIN32_IE >= 0x0500) - -#if (_WIN32_WINNT >= 0x0501) - void GetTitle(PTTGETTITLE pTTGetTitle) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TTM_GETTITLE, 0, (LPARAM)pTTGetTitle); - } - - void SetWindowTheme(LPCWSTR lpstrTheme) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TTM_SETWINDOWTHEME, 0, (LPARAM)lpstrTheme); - } -#endif // (_WIN32_WINNT >= 0x0501) - -// Operations - void Activate(BOOL bActivate) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TTM_ACTIVATE, bActivate, 0L); - } - - BOOL AddTool(LPTOOLINFO lpToolInfo) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TTM_ADDTOOL, 0, (LPARAM)lpToolInfo); - } - - BOOL AddTool(HWND hWnd, ATL::_U_STRINGorID text = LPSTR_TEXTCALLBACK, LPCRECT lpRectTool = NULL, UINT nIDTool = 0) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(hWnd != NULL); - // the toolrect and toolid must both be zero or both valid - ATLASSERT((lpRectTool != NULL && nIDTool != 0) || (lpRectTool == NULL && nIDTool == 0)); - - CToolInfo ti(0, hWnd, nIDTool, (LPRECT)lpRectTool, (LPTSTR)text.m_lpstr); - return (BOOL)::SendMessage(m_hWnd, TTM_ADDTOOL, 0, ti); - } - - void DelTool(LPTOOLINFO lpToolInfo) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TTM_DELTOOL, 0, (LPARAM)lpToolInfo); - } - - void DelTool(HWND hWnd, UINT nIDTool = 0) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(hWnd != NULL); - - CToolInfo ti(0, hWnd, nIDTool, NULL, NULL); - ::SendMessage(m_hWnd, TTM_DELTOOL, 0, ti); - } - - BOOL HitTest(LPTTHITTESTINFO lpHitTestInfo) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TTM_HITTEST, 0, (LPARAM)lpHitTestInfo); - } - - BOOL HitTest(HWND hWnd, POINT pt, LPTOOLINFO lpToolInfo) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(hWnd != NULL); - ATLASSERT(lpToolInfo != NULL); - - TTHITTESTINFO hti = { 0 }; - hti.ti.cbSize = sizeof(TOOLINFO); - hti.hwnd = hWnd; - hti.pt.x = pt.x; - hti.pt.y = pt.y; - if((BOOL)::SendMessage(m_hWnd, TTM_HITTEST, 0, (LPARAM)&hti) != FALSE) - { - *lpToolInfo = hti.ti; - return TRUE; - } - return FALSE; - } - - void RelayEvent(LPMSG lpMsg) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TTM_RELAYEVENT, 0, (LPARAM)lpMsg); - } - - void UpdateTipText(LPTOOLINFO lpToolInfo) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TTM_UPDATETIPTEXT, 0, (LPARAM)lpToolInfo); - } - - void UpdateTipText(ATL::_U_STRINGorID text, HWND hWnd, UINT nIDTool = 0) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(hWnd != NULL); - - CToolInfo ti(0, hWnd, nIDTool, NULL, (LPTSTR)text.m_lpstr); - ::SendMessage(m_hWnd, TTM_UPDATETIPTEXT, 0, ti); - } - - BOOL EnumTools(UINT nTool, LPTOOLINFO lpToolInfo) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TTM_ENUMTOOLS, nTool, (LPARAM)lpToolInfo); - } - - void Pop() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TTM_POP, 0, 0L); - } - - void TrackActivate(LPTOOLINFO lpToolInfo, BOOL bActivate) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TTM_TRACKACTIVATE, bActivate, (LPARAM)lpToolInfo); - } - - void TrackPosition(int xPos, int yPos) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TTM_TRACKPOSITION, 0, MAKELPARAM(xPos, yPos)); - } - -#if (_WIN32_IE >= 0x0400) - void Update() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TTM_UPDATE, 0, 0L); - } -#endif // (_WIN32_IE >= 0x0400) - -#if (_WIN32_IE >= 0x0500) - BOOL AdjustRect(LPRECT lpRect, BOOL bLarger /*= TRUE*/) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TTM_ADJUSTRECT, bLarger, (LPARAM)lpRect); - } -#endif // (_WIN32_IE >= 0x0500) - -#if (_WIN32_WINNT >= 0x0501) - void Popup() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TTM_POPUP, 0, 0L); - } -#endif // (_WIN32_WINNT >= 0x0501) -}; - -typedef CToolTipCtrlT CToolTipCtrl; - -#endif // !_WIN32_WCE - - -/////////////////////////////////////////////////////////////////////////////// -// CHeaderCtrl - -template -class CHeaderCtrlT : public TBase -{ -public: -// Constructors - CHeaderCtrlT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CHeaderCtrlT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return WC_HEADER; - } - - int GetItemCount() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, HDM_GETITEMCOUNT, 0, 0L); - } - - BOOL GetItem(int nIndex, LPHDITEM pHeaderItem) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, HDM_GETITEM, nIndex, (LPARAM)pHeaderItem); - } - - BOOL SetItem(int nIndex, LPHDITEM pHeaderItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, HDM_SETITEM, nIndex, (LPARAM)pHeaderItem); - } - - CImageList GetImageList() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return CImageList((HIMAGELIST)::SendMessage(m_hWnd, HDM_GETIMAGELIST, 0, 0L)); - } - - CImageList SetImageList(HIMAGELIST hImageList) - { - ATLASSERT(::IsWindow(m_hWnd)); - return CImageList((HIMAGELIST)::SendMessage(m_hWnd, HDM_SETIMAGELIST, 0, (LPARAM)hImageList)); - } - - BOOL GetOrderArray(int nSize, int* lpnArray) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, HDM_GETORDERARRAY, nSize, (LPARAM)lpnArray); - } - - BOOL SetOrderArray(int nSize, int* lpnArray) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, HDM_SETORDERARRAY, nSize, (LPARAM)lpnArray); - } - - BOOL GetItemRect(int nIndex, LPRECT lpItemRect) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, HDM_GETITEMRECT, nIndex, (LPARAM)lpItemRect); - } - - int SetHotDivider(BOOL bPos, DWORD dwInputValue) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, HDM_SETHOTDIVIDER, bPos, dwInputValue); - } - -#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) - BOOL GetUnicodeFormat() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, HDM_GETUNICODEFORMAT, 0, 0L); - } - - BOOL SetUnicodeFormat(BOOL bUnicode = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, HDM_SETUNICODEFORMAT, bUnicode, 0L); - } -#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) - -#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) - int GetBitmapMargin() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, HDM_GETBITMAPMARGIN, 0, 0L); - } - - int SetBitmapMargin(int nWidth) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, HDM_SETBITMAPMARGIN, nWidth, 0L); - } - - int SetFilterChangeTimeout(DWORD dwTimeOut) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, HDM_SETFILTERCHANGETIMEOUT, 0, dwTimeOut); - } -#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) - -#if (_WIN32_WINNT >= 0x0600) - BOOL GetItemDropDownRect(int nIndex, LPRECT lpRect) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, HDM_GETITEMDROPDOWNRECT, nIndex, (LPARAM)lpRect); - } - - BOOL GetOverflowRect(LPRECT lpRect) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, HDM_GETOVERFLOWRECT, 0, (LPARAM)lpRect); - } - - int GetFocusedItem() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, HDM_GETFOCUSEDITEM, 0, 0L); - } - - BOOL SetFocusedItem(int nIndex) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, HDM_SETFOCUSEDITEM, 0, nIndex); - } -#endif // (_WIN32_WINNT >= 0x0600) - -// Operations - int InsertItem(int nIndex, LPHDITEM phdi) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, HDM_INSERTITEM, nIndex, (LPARAM)phdi); - } - - int AddItem(LPHDITEM phdi) - { - return InsertItem(GetItemCount(), phdi); - } - - BOOL DeleteItem(int nIndex) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, HDM_DELETEITEM, nIndex, 0L); - } - - BOOL Layout(HD_LAYOUT* pHeaderLayout) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, HDM_LAYOUT, 0, (LPARAM)pHeaderLayout); - } - - int HitTest(LPHDHITTESTINFO lpHitTestInfo) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, HDM_HITTEST, 0, (LPARAM)lpHitTestInfo); - } - - int OrderToIndex(int nOrder) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, HDM_ORDERTOINDEX, nOrder, 0L); - } - - CImageList CreateDragImage(int nIndex) - { - ATLASSERT(::IsWindow(m_hWnd)); - return CImageList((HIMAGELIST)::SendMessage(m_hWnd, HDM_CREATEDRAGIMAGE, nIndex, 0L)); - } - -#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) - int EditFilter(int nColumn, BOOL bDiscardChanges) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, HDM_EDITFILTER, nColumn, MAKELPARAM(bDiscardChanges, 0)); - } - - int ClearFilter(int nColumn) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, HDM_CLEARFILTER, nColumn, 0L); - } - - int ClearAllFilters() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, HDM_CLEARFILTER, (WPARAM)-1, 0L); - } -#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) -}; - -typedef CHeaderCtrlT CHeaderCtrl; - - -/////////////////////////////////////////////////////////////////////////////// -// CListViewCtrl - -template -class CListViewCtrlT : public TBase -{ -public: -// Constructors - CListViewCtrlT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CListViewCtrlT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return WC_LISTVIEW; - } - - COLORREF GetBkColor() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, LVM_GETBKCOLOR, 0, 0L); - } - - BOOL SetBkColor(COLORREF cr) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_SETBKCOLOR, 0, cr); - } - - CImageList GetImageList(int nImageListType) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return CImageList((HIMAGELIST)::SendMessage(m_hWnd, LVM_GETIMAGELIST, nImageListType, 0L)); - } - - CImageList SetImageList(HIMAGELIST hImageList, int nImageList) - { - ATLASSERT(::IsWindow(m_hWnd)); - return CImageList((HIMAGELIST)::SendMessage(m_hWnd, LVM_SETIMAGELIST, nImageList, (LPARAM)hImageList)); - } - - int GetItemCount() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_GETITEMCOUNT, 0, 0L); - } - - BOOL SetItemCount(int nItems) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMCOUNT, nItems, 0L); - } - - BOOL GetItem(LPLVITEM pItem) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_GETITEM, 0, (LPARAM)pItem); - } - - BOOL SetItem(const LVITEM* pItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_SETITEM, 0, (LPARAM)pItem); - } - - BOOL SetItem(int nItem, int nSubItem, UINT nMask, LPCTSTR lpszItem, - int nImage, UINT nState, UINT nStateMask, LPARAM lParam) - { - ATLASSERT(::IsWindow(m_hWnd)); - LVITEM lvi = { 0 }; - lvi.mask = nMask; - lvi.iItem = nItem; - lvi.iSubItem = nSubItem; - lvi.stateMask = nStateMask; - lvi.state = nState; - lvi.pszText = (LPTSTR) lpszItem; - lvi.iImage = nImage; - lvi.lParam = lParam; - return (BOOL)::SendMessage(m_hWnd, LVM_SETITEM, 0, (LPARAM)&lvi); - } - - UINT GetItemState(int nItem, UINT nMask) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::SendMessage(m_hWnd, LVM_GETITEMSTATE, nItem, nMask); - } - - BOOL SetItemState(int nItem, UINT nState, UINT nStateMask) - { - ATLASSERT(::IsWindow(m_hWnd)); - LVITEM lvi = { 0 }; - lvi.state = nState; - lvi.stateMask = nStateMask; - return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMSTATE, nItem, (LPARAM)&lvi); - } - - BOOL SetItemState(int nItem, LPLVITEM pItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMSTATE, nItem, (LPARAM)pItem); - } - -#ifndef _ATL_NO_COM - BOOL GetItemText(int nItem, int nSubItem, BSTR& bstrText) const - { - USES_CONVERSION; - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(bstrText == NULL); - LVITEM lvi = { 0 }; - lvi.iSubItem = nSubItem; - - LPTSTR lpstrText = NULL; - int nRes = 0; - for(int nLen = 256; ; nLen *= 2) - { - ATLTRY(lpstrText = new TCHAR[nLen]); - if(lpstrText == NULL) - break; - lpstrText[0] = NULL; - lvi.cchTextMax = nLen; - lvi.pszText = lpstrText; - nRes = (int)::SendMessage(m_hWnd, LVM_GETITEMTEXT, (WPARAM)nItem, (LPARAM)&lvi); - if(nRes < nLen - 1) - break; - delete [] lpstrText; - lpstrText = NULL; - } - - if(lpstrText != NULL) - { - if(nRes != 0) - bstrText = ::SysAllocString(T2OLE(lpstrText)); - delete [] lpstrText; - } - - return (bstrText != NULL) ? TRUE : FALSE; - } -#endif // !_ATL_NO_COM - -#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - int GetItemText(int nItem, int nSubItem, _CSTRING_NS::CString& strText) const - { - ATLASSERT(::IsWindow(m_hWnd)); - LVITEM lvi = { 0 }; - lvi.iSubItem = nSubItem; - - strText.Empty(); - int nRes = 0; - for(int nLen = 256; ; nLen *= 2) - { - lvi.cchTextMax = nLen; - lvi.pszText = strText.GetBufferSetLength(nLen); - if(lvi.pszText == NULL) - { - nRes = 0; - break; - } - nRes = (int)::SendMessage(m_hWnd, LVM_GETITEMTEXT, (WPARAM)nItem, (LPARAM)&lvi); - if(nRes < nLen - 1) - break; - } - strText.ReleaseBuffer(); - return nRes; - } -#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - - int GetItemText(int nItem, int nSubItem, LPTSTR lpszText, int nLen) const - { - ATLASSERT(::IsWindow(m_hWnd)); - LVITEM lvi = { 0 }; - lvi.iSubItem = nSubItem; - lvi.cchTextMax = nLen; - lvi.pszText = lpszText; - return (int)::SendMessage(m_hWnd, LVM_GETITEMTEXT, (WPARAM)nItem, (LPARAM)&lvi); - } - - BOOL SetItemText(int nItem, int nSubItem, LPCTSTR lpszText) - { - ATLASSERT(::IsWindow(m_hWnd)); - return SetItem(nItem, nSubItem, LVIF_TEXT, lpszText, 0, 0, 0, 0); - } - - DWORD_PTR GetItemData(int nItem) const - { - ATLASSERT(::IsWindow(m_hWnd)); - LVITEM lvi = { 0 }; - lvi.iItem = nItem; - lvi.mask = LVIF_PARAM; - BOOL bRet = (BOOL)::SendMessage(m_hWnd, LVM_GETITEM, 0, (LPARAM)&lvi); - return (DWORD_PTR)(bRet ? lvi.lParam : NULL); - } - - BOOL SetItemData(int nItem, DWORD_PTR dwData) - { - ATLASSERT(::IsWindow(m_hWnd)); - return SetItem(nItem, 0, LVIF_PARAM, NULL, 0, 0, 0, (LPARAM)dwData); - } - - UINT GetCallbackMask() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::SendMessage(m_hWnd, LVM_GETCALLBACKMASK, 0, 0L); - } - - BOOL SetCallbackMask(UINT nMask) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_SETCALLBACKMASK, nMask, 0L); - } - - BOOL GetItemPosition(int nItem, LPPOINT lpPoint) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_GETITEMPOSITION, nItem, (LPARAM)lpPoint); - } - - BOOL SetItemPosition(int nItem, POINT pt) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(((GetStyle() & LVS_TYPEMASK) == LVS_ICON) || ((GetStyle() & LVS_TYPEMASK) == LVS_SMALLICON)); - return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMPOSITION32, nItem, (LPARAM)&pt); - } - - BOOL SetItemPosition(int nItem, int x, int y) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(((GetStyle() & LVS_TYPEMASK) == LVS_ICON) || ((GetStyle() & LVS_TYPEMASK) == LVS_SMALLICON)); - POINT pt = { x, y }; - return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMPOSITION32, nItem, (LPARAM)&pt); - } - - int GetStringWidth(LPCTSTR lpsz) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_GETSTRINGWIDTH, 0, (LPARAM)lpsz); - } - - CEdit GetEditControl() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return CEdit((HWND)::SendMessage(m_hWnd, LVM_GETEDITCONTROL, 0, 0L)); - } - - BOOL GetColumn(int nCol, LVCOLUMN* pColumn) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_GETCOLUMN, nCol, (LPARAM)pColumn); - } - - BOOL SetColumn(int nCol, const LVCOLUMN* pColumn) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_SETCOLUMN, nCol, (LPARAM)pColumn); - } - - int GetColumnWidth(int nCol) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_GETCOLUMNWIDTH, nCol, 0L); - } - - BOOL SetColumnWidth(int nCol, int cx) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_SETCOLUMNWIDTH, nCol, MAKELPARAM(cx, 0)); - } - - BOOL GetViewRect(LPRECT lpRect) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_GETVIEWRECT, 0, (LPARAM)lpRect); - } - - COLORREF GetTextColor() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, LVM_GETTEXTCOLOR, 0, 0L); - } - - BOOL SetTextColor(COLORREF cr) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_SETTEXTCOLOR, 0, cr); - } - - COLORREF GetTextBkColor() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, LVM_GETTEXTBKCOLOR, 0, 0L); - } - - BOOL SetTextBkColor(COLORREF cr) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_SETTEXTBKCOLOR, 0, cr); - } - - int GetTopIndex() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_GETTOPINDEX, 0, 0L); - } - - int GetCountPerPage() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_GETCOUNTPERPAGE, 0, 0L); - } - - BOOL GetOrigin(LPPOINT lpPoint) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_GETORIGIN, 0, (LPARAM)lpPoint); - } - - UINT GetSelectedCount() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::SendMessage(m_hWnd, LVM_GETSELECTEDCOUNT, 0, 0L); - } - - BOOL GetItemRect(int nItem, LPRECT lpRect, UINT nCode) const - { - ATLASSERT(::IsWindow(m_hWnd)); - lpRect->left = nCode; - return (BOOL)::SendMessage(m_hWnd, LVM_GETITEMRECT, (WPARAM)nItem, (LPARAM)lpRect); - } - -#ifndef _WIN32_WCE - HCURSOR GetHotCursor() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HCURSOR)::SendMessage(m_hWnd, LVM_GETHOTCURSOR, 0, 0L); - } - - HCURSOR SetHotCursor(HCURSOR hHotCursor) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HCURSOR)::SendMessage(m_hWnd, LVM_SETHOTCURSOR, 0, (LPARAM)hHotCursor); - } - - int GetHotItem() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_GETHOTITEM, 0, 0L); - } - - int SetHotItem(int nIndex) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_SETHOTITEM, nIndex, 0L); - } -#endif // !_WIN32_WCE - - BOOL GetColumnOrderArray(int nCount, int* lpnArray) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_GETCOLUMNORDERARRAY, nCount, (LPARAM)lpnArray); - } - - BOOL SetColumnOrderArray(int nCount, int* lpnArray) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_SETCOLUMNORDERARRAY, nCount, (LPARAM)lpnArray); - } - - CHeaderCtrl GetHeader() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return CHeaderCtrl((HWND)::SendMessage(m_hWnd, LVM_GETHEADER, 0, 0L)); - } - - BOOL GetSubItemRect(int nItem, int nSubItem, int nFlag, LPRECT lpRect) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetStyle() & LVS_TYPEMASK) == LVS_REPORT); - ATLASSERT(lpRect != NULL); - lpRect->top = nSubItem; - lpRect->left = nFlag; - return (BOOL)::SendMessage(m_hWnd, LVM_GETSUBITEMRECT, nItem, (LPARAM)lpRect); - } - - DWORD SetIconSpacing(int cx, int cy) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetStyle() & LVS_TYPEMASK) == LVS_ICON); - return (DWORD)::SendMessage(m_hWnd, LVM_SETICONSPACING, 0, MAKELPARAM(cx, cy)); - } - - int GetISearchString(LPTSTR lpstr) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_GETISEARCHSTRING, 0, (LPARAM)lpstr); - } - - void GetItemSpacing(SIZE& sizeSpacing, BOOL bSmallIconView = FALSE) const - { - ATLASSERT(::IsWindow(m_hWnd)); - DWORD dwRet = (DWORD)::SendMessage(m_hWnd, LVM_GETITEMSPACING, bSmallIconView, 0L); - sizeSpacing.cx = GET_X_LPARAM(dwRet); - sizeSpacing.cy = GET_Y_LPARAM(dwRet); - } - -#if (_WIN32_WCE >= 410) - void SetItemSpacing(INT cySpacing) - { - ATLASSERT(::IsWindow(m_hWnd)); - ListView_SetItemSpacing(m_hWnd, cySpacing); - } -#endif // (_WIN32_WCE >= 410) - - // single-selection only - int GetSelectedIndex() const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetStyle() & LVS_SINGLESEL) != 0); - return (int)::SendMessage(m_hWnd, LVM_GETNEXTITEM, (WPARAM)-1, MAKELPARAM(LVNI_ALL | LVNI_SELECTED, 0)); - } - - BOOL GetSelectedItem(LPLVITEM pItem) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetStyle() & LVS_SINGLESEL) != 0); - ATLASSERT(pItem != NULL); - pItem->iItem = (int)::SendMessage(m_hWnd, LVM_GETNEXTITEM, (WPARAM)-1, MAKELPARAM(LVNI_ALL | LVNI_SELECTED, 0)); - if(pItem->iItem == -1) - return FALSE; - return (BOOL)::SendMessage(m_hWnd, LVM_GETITEM, 0, (LPARAM)pItem); - } - - // extended list view styles - DWORD GetExtendedListViewStyle() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0L); - } - - // dwExMask = 0 means all styles - DWORD SetExtendedListViewStyle(DWORD dwExStyle, DWORD dwExMask = 0) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, LVM_SETEXTENDEDLISTVIEWSTYLE, dwExMask, dwExStyle); - } - - // checkboxes only - BOOL GetCheckState(int nIndex) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetExtendedListViewStyle() & LVS_EX_CHECKBOXES) != 0); - UINT uRet = GetItemState(nIndex, LVIS_STATEIMAGEMASK); - return (uRet >> 12) - 1; - } - - BOOL SetCheckState(int nItem, BOOL bCheck) - { - int nCheck = bCheck ? 2 : 1; // one based index - return SetItemState(nItem, INDEXTOSTATEIMAGEMASK(nCheck), LVIS_STATEIMAGEMASK); - } - - // view type - DWORD GetViewType() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (GetStyle() & LVS_TYPEMASK); - } - - DWORD SetViewType(DWORD dwType) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(dwType == LVS_ICON || dwType == LVS_SMALLICON || dwType == LVS_LIST || dwType == LVS_REPORT); - DWORD dwOldType = GetViewType(); - if(dwType != dwOldType) - ModifyStyle(LVS_TYPEMASK, (dwType & LVS_TYPEMASK)); - return dwOldType; - } - -#if (_WIN32_IE >= 0x0400) -#ifndef _WIN32_WCE - BOOL GetBkImage(LPLVBKIMAGE plvbki) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_GETBKIMAGE, 0, (LPARAM)plvbki); - } - - BOOL SetBkImage(LPLVBKIMAGE plvbki) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_SETBKIMAGE, 0, (LPARAM)plvbki); - } -#endif // !_WIN32_WCE - - int GetSelectionMark() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_GETSELECTIONMARK, 0, 0L); - } - - int SetSelectionMark(int nIndex) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_SETSELECTIONMARK, 0, nIndex); - } - -#ifndef _WIN32_WCE - BOOL GetWorkAreas(int nWorkAreas, LPRECT lpRect) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_GETWORKAREAS, nWorkAreas, (LPARAM)lpRect); - } - - BOOL SetWorkAreas(int nWorkAreas, LPRECT lpRect) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_SETWORKAREAS, nWorkAreas, (LPARAM)lpRect); - } - - DWORD GetHoverTime() const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetExtendedListViewStyle() & (LVS_EX_TRACKSELECT | LVS_EX_ONECLICKACTIVATE | LVS_EX_TWOCLICKACTIVATE)) != 0); - return (DWORD)::SendMessage(m_hWnd, LVM_GETHOVERTIME, 0, 0L); - } - - DWORD SetHoverTime(DWORD dwHoverTime) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetExtendedListViewStyle() & (LVS_EX_TRACKSELECT | LVS_EX_ONECLICKACTIVATE | LVS_EX_TWOCLICKACTIVATE)) != 0); - return (DWORD)::SendMessage(m_hWnd, LVM_SETHOVERTIME, 0, dwHoverTime); - } - - BOOL GetNumberOfWorkAreas(int* pnWorkAreas) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_GETNUMBEROFWORKAREAS, 0, (LPARAM)pnWorkAreas); - } -#endif // !_WIN32_WCE - - BOOL SetItemCountEx(int nItems, DWORD dwFlags) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(((GetStyle() & LVS_OWNERDATA) != 0) && (((GetStyle() & LVS_TYPEMASK) == LVS_REPORT) || ((GetStyle() & LVS_TYPEMASK) == LVS_LIST))); - return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMCOUNT, nItems, dwFlags); - } - -#ifndef _WIN32_WCE - CToolTipCtrl GetToolTips() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return CToolTipCtrl((HWND)::SendMessage(m_hWnd, LVM_GETTOOLTIPS, 0, 0L)); - } - - CToolTipCtrl SetToolTips(HWND hWndTT) - { - ATLASSERT(::IsWindow(m_hWnd)); - return CToolTipCtrl((HWND)::SendMessage(m_hWnd, LVM_SETTOOLTIPS, (WPARAM)hWndTT, 0L)); - } - - BOOL GetUnicodeFormat() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_GETUNICODEFORMAT, 0, 0L); - } - - BOOL SetUnicodeFormat(BOOL bUnicode = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_SETUNICODEFORMAT, bUnicode, 0L); - } -#endif // !_WIN32_WCE -#endif // (_WIN32_IE >= 0x0400) - -#if (_WIN32_WINNT >= 0x0501) - int GetSelectedColumn() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_GETSELECTEDCOLUMN, 0, 0L); - } - - void SetSelectedColumn(int nColumn) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, LVM_SETSELECTEDCOLUMN, nColumn, 0L); - } - - DWORD GetView() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, LVM_GETVIEW, 0, 0L); - } - - int SetView(DWORD dwView) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_SETVIEW, dwView, 0L); - } - - BOOL IsGroupViewEnabled() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_ISGROUPVIEWENABLED, 0, 0L); - } - - int GetGroupInfo(int nGroupID, PLVGROUP pGroup) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_GETGROUPINFO, nGroupID, (LPARAM)pGroup); - } - - int SetGroupInfo(int nGroupID, PLVGROUP pGroup) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_SETGROUPINFO, nGroupID, (LPARAM)pGroup); - } - - void GetGroupMetrics(PLVGROUPMETRICS pGroupMetrics) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, LVM_GETGROUPMETRICS, 0, (LPARAM)pGroupMetrics); - } - - void SetGroupMetrics(PLVGROUPMETRICS pGroupMetrics) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, LVM_SETGROUPMETRICS, 0, (LPARAM)pGroupMetrics); - } - - void GetTileViewInfo(PLVTILEVIEWINFO pTileViewInfo) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, LVM_GETTILEVIEWINFO, 0, (LPARAM)pTileViewInfo); - } - - BOOL SetTileViewInfo(PLVTILEVIEWINFO pTileViewInfo) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_SETTILEVIEWINFO, 0, (LPARAM)pTileViewInfo); - } - - void GetTileInfo(PLVTILEINFO pTileInfo) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, LVM_GETTILEINFO, 0, (LPARAM)pTileInfo); - } - - BOOL SetTileInfo(PLVTILEINFO pTileInfo) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_SETTILEINFO, 0, (LPARAM)pTileInfo); - } - - BOOL GetInsertMark(LPLVINSERTMARK pInsertMark) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_GETINSERTMARK, 0, (LPARAM)pInsertMark); - } - - BOOL SetInsertMark(LPLVINSERTMARK pInsertMark) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_SETINSERTMARK, 0, (LPARAM)pInsertMark); - } - - int GetInsertMarkRect(LPRECT lpRect) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_GETINSERTMARKRECT, 0, (LPARAM)lpRect); - } - - COLORREF GetInsertMarkColor() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, LVM_GETINSERTMARKCOLOR, 0, 0L); - } - - COLORREF SetInsertMarkColor(COLORREF clr) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, LVM_SETINSERTMARKCOLOR, 0, clr); - } - - COLORREF GetOutlineColor() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, LVM_GETOUTLINECOLOR, 0, 0L); - } - - COLORREF SetOutlineColor(COLORREF clr) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, LVM_SETOUTLINECOLOR, 0, clr); - } -#endif // (_WIN32_WINNT >= 0x0501) - -#if (_WIN32_WINNT >= 0x0600) - int GetGroupCount() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_GETGROUPCOUNT, 0, 0L); - } - - BOOL GetGroupInfoByIndex(int nIndex, PLVGROUP pGroup) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_GETGROUPINFOBYINDEX, nIndex, (LPARAM)pGroup); - } - - BOOL GetGroupRect(int nGroupID, int nType, LPRECT lpRect) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(lpRect != NULL); - if(lpRect != NULL) - lpRect->top = nType; - return (BOOL)::SendMessage(m_hWnd, LVM_GETGROUPRECT, nGroupID, (LPARAM)lpRect); - } - - UINT GetGroupState(int nGroupID, UINT uMask) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::SendMessage(m_hWnd, LVM_GETGROUPSTATE, nGroupID, (LPARAM)uMask); - } - - int GetFocusedGroup() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_GETFOCUSEDGROUP, 0, 0L); - } - - BOOL GetEmptyText(LPWSTR lpstrText, int cchText) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_GETEMPTYTEXT, cchText, (LPARAM)lpstrText); - } - - BOOL GetFooterRect(LPRECT lpRect) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_GETFOOTERRECT, 0, (LPARAM)lpRect); - } - - BOOL GetFooterInfo(LPLVFOOTERINFO lpFooterInfo) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_GETFOOTERINFO, 0, (LPARAM)lpFooterInfo); - } - - BOOL GetFooterItemRect(int nItem, LPRECT lpRect) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_GETFOOTERITEMRECT, nItem, (LPARAM)lpRect); - } - - BOOL GetFooterItem(int nItem, LPLVFOOTERITEM lpFooterItem) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_GETFOOTERITEM, nItem, (LPARAM)lpFooterItem); - } - - BOOL GetItemIndexRect(PLVITEMINDEX pItemIndex, int nSubItem, int nType, LPRECT lpRect) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(pItemIndex != NULL); - ATLASSERT(lpRect != NULL); - if(lpRect != NULL) - { - lpRect->top = nSubItem; - lpRect->left = nType; - } - return (BOOL)::SendMessage(m_hWnd, LVM_GETITEMINDEXRECT, (WPARAM)pItemIndex, (LPARAM)lpRect); - } - - BOOL SetItemIndexState(PLVITEMINDEX pItemIndex, UINT uState, UINT dwMask) - { - ATLASSERT(::IsWindow(m_hWnd)); - LVITEM lvi = { 0 }; - lvi.state = uState; - lvi.stateMask = dwMask; - return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMINDEXSTATE, (WPARAM)pItemIndex, (LPARAM)&lvi); - } - - BOOL GetNextItemIndex(PLVITEMINDEX pItemIndex, WORD wFlags) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_GETNEXTITEMINDEX, (WPARAM)pItemIndex, MAKELPARAM(wFlags, 0)); - } -#endif // (_WIN32_WINNT >= 0x0600) - -// Operations - int InsertColumn(int nCol, const LVCOLUMN* pColumn) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_INSERTCOLUMN, nCol, (LPARAM)pColumn); - } - - int InsertColumn(int nCol, LPCTSTR lpszColumnHeading, int nFormat = LVCFMT_LEFT, - int nWidth = -1, int nSubItem = -1, int iImage = -1, int iOrder = -1) - { - LVCOLUMN column = { 0 }; - column.mask = LVCF_TEXT|LVCF_FMT; - column.pszText = (LPTSTR)lpszColumnHeading; - column.fmt = nFormat; - if (nWidth != -1) - { - column.mask |= LVCF_WIDTH; - column.cx = nWidth; - } - if (nSubItem != -1) - { - column.mask |= LVCF_SUBITEM; - column.iSubItem = nSubItem; - } - if (iImage != -1) - { - column.mask |= LVCF_IMAGE; - column.iImage = iImage; - } - if (iOrder != -1) - { - column.mask |= LVCF_ORDER; - column.iOrder = iOrder; - } - return InsertColumn(nCol, &column); - } - - BOOL DeleteColumn(int nCol) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_DELETECOLUMN, nCol, 0L); - } - - int InsertItem(UINT nMask, int nItem, LPCTSTR lpszItem, UINT nState, UINT nStateMask, int nImage, LPARAM lParam) - { - ATLASSERT(::IsWindow(m_hWnd)); - LVITEM item = { 0 }; - item.mask = nMask; - item.iItem = nItem; - item.iSubItem = 0; - item.pszText = (LPTSTR)lpszItem; - item.state = nState; - item.stateMask = nStateMask; - item.iImage = nImage; - item.lParam = lParam; - return InsertItem(&item); - } - - int InsertItem(const LVITEM* pItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_INSERTITEM, 0, (LPARAM)pItem); - } - - int InsertItem(int nItem, LPCTSTR lpszItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return InsertItem(LVIF_TEXT, nItem, lpszItem, 0, 0, 0, 0); - } - - int InsertItem(int nItem, LPCTSTR lpszItem, int nImage) - { - ATLASSERT(::IsWindow(m_hWnd)); - return InsertItem(LVIF_TEXT|LVIF_IMAGE, nItem, lpszItem, 0, 0, nImage, 0); - } - - int GetNextItem(int nItem, int nFlags) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_GETNEXTITEM, nItem, MAKELPARAM(nFlags, 0)); - } - - BOOL DeleteItem(int nItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_DELETEITEM, nItem, 0L); - } - - BOOL DeleteAllItems() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_DELETEALLITEMS, 0, 0L); - } - - int FindItem(LVFINDINFO* pFindInfo, int nStart) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_FINDITEM, nStart, (LPARAM)pFindInfo); - } - - int HitTest(LVHITTESTINFO* pHitTestInfo) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_HITTEST, 0, (LPARAM)pHitTestInfo); - } - - int HitTest(POINT pt, UINT* pFlags) const - { - ATLASSERT(::IsWindow(m_hWnd)); - LVHITTESTINFO hti = { 0 }; - hti.pt = pt; - int nRes = (int)::SendMessage(m_hWnd, LVM_HITTEST, 0, (LPARAM)&hti); - if (pFlags != NULL) - *pFlags = hti.flags; - return nRes; - } - - BOOL EnsureVisible(int nItem, BOOL bPartialOK) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_ENSUREVISIBLE, nItem, MAKELPARAM(bPartialOK, 0)); - } - - BOOL Scroll(SIZE size) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_SCROLL, size.cx, size.cy); - } - - BOOL RedrawItems(int nFirst, int nLast) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_REDRAWITEMS, nFirst, nLast); - } - - BOOL Arrange(UINT nCode) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_ARRANGE, nCode, 0L); - } - - CEdit EditLabel(int nItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return CEdit((HWND)::SendMessage(m_hWnd, LVM_EDITLABEL, nItem, 0L)); - } - - BOOL Update(int nItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_UPDATE, nItem, 0L); - } - - BOOL SortItems(PFNLVCOMPARE pfnCompare, LPARAM lParamSort) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_SORTITEMS, (WPARAM)lParamSort, (LPARAM)pfnCompare); - } - - CImageList RemoveImageList(int nImageList) - { - ATLASSERT(::IsWindow(m_hWnd)); - return CImageList((HIMAGELIST)::SendMessage(m_hWnd, LVM_SETIMAGELIST, (WPARAM)nImageList, NULL)); - } - - CImageList CreateDragImage(int nItem, LPPOINT lpPoint) - { - ATLASSERT(::IsWindow(m_hWnd)); - return CImageList((HIMAGELIST)::SendMessage(m_hWnd, LVM_CREATEDRAGIMAGE, nItem, (LPARAM)lpPoint)); - } - - DWORD ApproximateViewRect(int cx = -1, int cy = -1, int nCount = -1) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, LVM_APPROXIMATEVIEWRECT, nCount, MAKELPARAM(cx, cy)); - } - - int SubItemHitTest(LPLVHITTESTINFO lpInfo) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_SUBITEMHITTEST, 0, (LPARAM)lpInfo); - } - - int AddColumn(LPCTSTR strItem, int nItem, int nSubItem = -1, - int nMask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM, - int nFmt = LVCFMT_LEFT) - { - const int cxOffset = 15; - ATLASSERT(::IsWindow(m_hWnd)); - LVCOLUMN lvc = { 0 }; - lvc.mask = nMask; - lvc.fmt = nFmt; - lvc.pszText = (LPTSTR)strItem; - lvc.cx = GetStringWidth(lvc.pszText) + cxOffset; - if(nMask & LVCF_SUBITEM) - lvc.iSubItem = (nSubItem != -1) ? nSubItem : nItem; - return InsertColumn(nItem, &lvc); - } - - int AddItem(int nItem, int nSubItem, LPCTSTR strItem, int nImageIndex = -1) - { - ATLASSERT(::IsWindow(m_hWnd)); - LVITEM lvItem = { 0 }; - lvItem.mask = LVIF_TEXT; - lvItem.iItem = nItem; - lvItem.iSubItem = nSubItem; - lvItem.pszText = (LPTSTR)strItem; - if(nImageIndex != -1) - { - lvItem.mask |= LVIF_IMAGE; - lvItem.iImage = nImageIndex; - } - if(nSubItem == 0) - return InsertItem(&lvItem); - return SetItem(&lvItem) ? nItem : -1; - } - -#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) - BOOL SortItemsEx(PFNLVCOMPARE pfnCompare, LPARAM lParamSort) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_SORTITEMSEX, (WPARAM)lParamSort, (LPARAM)pfnCompare); - } -#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) - -#if (_WIN32_WINNT >= 0x0501) - int InsertGroup(int nItem, PLVGROUP pGroup) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_INSERTGROUP, nItem, (LPARAM)pGroup); - } - - int AddGroup(PLVGROUP pGroup) - { - return InsertGroup(-1, pGroup); - } - - int RemoveGroup(int nGroupID) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_REMOVEGROUP, nGroupID, 0L); - } - - void MoveGroup(int nGroupID, int nItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, LVM_MOVEGROUP, nGroupID, nItem); - } - - void MoveItemToGroup(int nItem, int nGroupID) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, LVM_MOVEITEMTOGROUP, nItem, nGroupID); - } - - int EnableGroupView(BOOL bEnable) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_ENABLEGROUPVIEW, bEnable, 0L); - } - - int SortGroups(PFNLVGROUPCOMPARE pCompareFunc, LPVOID lpVoid = NULL) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_SORTGROUPS, (WPARAM)pCompareFunc, (LPARAM)lpVoid); - } - - void InsertGroupSorted(PLVINSERTGROUPSORTED pInsertGroupSorted) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, LVM_INSERTGROUPSORTED, (WPARAM)pInsertGroupSorted, 0L); - } - - void RemoveAllGroups() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, LVM_REMOVEALLGROUPS, 0, 0L); - } - - BOOL HasGroup(int nGroupID) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_HASGROUP, nGroupID, 0L); - } - - BOOL InsertMarkHitTest(LPPOINT lpPoint, LPLVINSERTMARK pInsertMark) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_INSERTMARKHITTEST, (WPARAM)lpPoint, (LPARAM)pInsertMark); - } - - BOOL SetInfoTip(PLVSETINFOTIP pSetInfoTip) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LVM_SETINFOTIP, 0, (LPARAM)pSetInfoTip); - } - - void CancelEditLabel() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, LVM_CANCELEDITLABEL, 0, 0L); - } - - UINT MapIndexToID(int nIndex) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::SendMessage(m_hWnd, LVM_MAPINDEXTOID, nIndex, 0L); - } - - int MapIDToIndex(UINT uID) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_MAPIDTOINDEX, uID, 0L); - } -#endif // (_WIN32_WINNT >= 0x0501) - -#if (_WIN32_WINNT >= 0x0600) - int HitTestEx(LPLVHITTESTINFO lpHitTestInfo) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_HITTEST, (WPARAM)-1, (LPARAM)lpHitTestInfo); - } - - int HitTestEx(POINT pt, UINT* pFlags) const - { - ATLASSERT(::IsWindow(m_hWnd)); - LVHITTESTINFO hti = { 0 }; - hti.pt = pt; - int nRes = (int)::SendMessage(m_hWnd, LVM_HITTEST, (WPARAM)-1, (LPARAM)&hti); - if (pFlags != NULL) - *pFlags = hti.flags; - return nRes; - } - - int SubItemHitTestEx(LPLVHITTESTINFO lpHitTestInfo) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LVM_SUBITEMHITTEST, (WPARAM)-1, (LPARAM)lpHitTestInfo); - } -#endif // (_WIN32_WINNT >= 0x0600) - - // single-selection only - BOOL SelectItem(int nIndex) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetStyle() & LVS_SINGLESEL) != 0); - - BOOL bRet = SetItemState(nIndex, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED); - if(bRet) - bRet = EnsureVisible(nIndex, FALSE); - return bRet; - } -}; - -typedef CListViewCtrlT CListViewCtrl; - - -/////////////////////////////////////////////////////////////////////////////// -// CTreeViewCtrl - -template -class CTreeViewCtrlT : public TBase -{ -public: -// Constructors - CTreeViewCtrlT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CTreeViewCtrlT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return WC_TREEVIEW; - } - - UINT GetCount() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::SendMessage(m_hWnd, TVM_GETCOUNT, 0, 0L); - } - - UINT GetIndent() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::SendMessage(m_hWnd, TVM_GETINDENT, 0, 0L); - } - - void SetIndent(UINT nIndent) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TVM_SETINDENT, nIndent, 0L); - } - - CImageList GetImageList(int nImageListType = TVSIL_NORMAL) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TVM_GETIMAGELIST, (WPARAM)nImageListType, 0L)); - } - - CImageList SetImageList(HIMAGELIST hImageList, int nImageListType = TVSIL_NORMAL) - { - ATLASSERT(::IsWindow(m_hWnd)); - return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TVM_SETIMAGELIST, (WPARAM)nImageListType, (LPARAM)hImageList)); - } - - BOOL GetItem(LPTVITEM pItem) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)pItem); - } - - BOOL SetItem(LPTVITEM pItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TVM_SETITEM, 0, (LPARAM)pItem); - } - - BOOL SetItem(HTREEITEM hItem, UINT nMask, LPCTSTR lpszItem, int nImage, - int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam) - { - ATLASSERT(::IsWindow(m_hWnd)); - TVITEM item = { 0 }; - item.hItem = hItem; - item.mask = nMask; - item.pszText = (LPTSTR) lpszItem; - item.iImage = nImage; - item.iSelectedImage = nSelectedImage; - item.state = nState; - item.stateMask = nStateMask; - item.lParam = lParam; - return (BOOL)::SendMessage(m_hWnd, TVM_SETITEM, 0, (LPARAM)&item); - } - - BOOL GetItemText(HTREEITEM hItem, LPTSTR lpstrText, int nLen) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(lpstrText != NULL); - - TVITEM item = { 0 }; - item.hItem = hItem; - item.mask = TVIF_TEXT; - item.pszText = lpstrText; - item.cchTextMax = nLen; - - return (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item); - } - -#ifndef _ATL_NO_COM - BOOL GetItemText(HTREEITEM hItem, BSTR& bstrText) const - { - USES_CONVERSION; - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(bstrText == NULL); - TVITEM item = { 0 }; - item.hItem = hItem; - item.mask = TVIF_TEXT; - - LPTSTR lpstrText = NULL; - BOOL bRet = FALSE; - for(int nLen = 256; ; nLen *= 2) - { - ATLTRY(lpstrText = new TCHAR[nLen]); - if(lpstrText == NULL) - break; - lpstrText[0] = NULL; - item.pszText = lpstrText; - item.cchTextMax = nLen; - bRet = (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item); - if(!bRet || (lstrlen(item.pszText) < nLen - 1)) - break; - delete [] lpstrText; - lpstrText = NULL; - } - - if(lpstrText != NULL) - { - if(bRet) - bstrText = ::SysAllocString(T2OLE(lpstrText)); - delete [] lpstrText; - } - - return (bstrText != NULL) ? TRUE : FALSE; - } -#endif // !_ATL_NO_COM - -#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - BOOL GetItemText(HTREEITEM hItem, _CSTRING_NS::CString& strText) const - { - ATLASSERT(::IsWindow(m_hWnd)); - TVITEM item = { 0 }; - item.hItem = hItem; - item.mask = TVIF_TEXT; - - strText.Empty(); - BOOL bRet = FALSE; - for(int nLen = 256; ; nLen *= 2) - { - item.pszText = strText.GetBufferSetLength(nLen); - if(item.pszText == NULL) - { - bRet = FALSE; - break; - } - item.cchTextMax = nLen; - bRet = (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item); - if(!bRet || (lstrlen(item.pszText) < nLen - 1)) - break; - } - strText.ReleaseBuffer(); - return bRet; - } -#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - - BOOL SetItemText(HTREEITEM hItem, LPCTSTR lpszItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return SetItem(hItem, TVIF_TEXT, lpszItem, 0, 0, 0, 0, NULL); - } - - BOOL GetItemImage(HTREEITEM hItem, int& nImage, int& nSelectedImage) const - { - ATLASSERT(::IsWindow(m_hWnd)); - TVITEM item = { 0 }; - item.hItem = hItem; - item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE; - BOOL bRes = (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item); - if (bRes) - { - nImage = item.iImage; - nSelectedImage = item.iSelectedImage; - } - return bRes; - } - - BOOL SetItemImage(HTREEITEM hItem, int nImage, int nSelectedImage) - { - ATLASSERT(::IsWindow(m_hWnd)); - return SetItem(hItem, TVIF_IMAGE|TVIF_SELECTEDIMAGE, NULL, nImage, nSelectedImage, 0, 0, NULL); - } - - UINT GetItemState(HTREEITEM hItem, UINT nStateMask) const - { - ATLASSERT(::IsWindow(m_hWnd)); -#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) - return (((UINT)::SendMessage(m_hWnd, TVM_GETITEMSTATE, (WPARAM)hItem, (LPARAM)nStateMask)) & nStateMask); -#else // !((_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)) - TVITEM item = { 0 }; - item.hItem = hItem; - item.mask = TVIF_STATE; - item.state = 0; - item.stateMask = nStateMask; - ::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item); - return (item.state & nStateMask); -#endif // !((_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)) - } - - BOOL SetItemState(HTREEITEM hItem, UINT nState, UINT nStateMask) - { - ATLASSERT(::IsWindow(m_hWnd)); - return SetItem(hItem, TVIF_STATE, NULL, 0, 0, nState, nStateMask, NULL); - } - - DWORD_PTR GetItemData(HTREEITEM hItem) const - { - ATLASSERT(::IsWindow(m_hWnd)); - TVITEM item = { 0 }; - item.hItem = hItem; - item.mask = TVIF_PARAM; - BOOL bRet = (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item); - return (DWORD_PTR)(bRet ? item.lParam : NULL); - } - - BOOL SetItemData(HTREEITEM hItem, DWORD_PTR dwData) - { - ATLASSERT(::IsWindow(m_hWnd)); - return SetItem(hItem, TVIF_PARAM, NULL, 0, 0, 0, 0, (LPARAM)dwData); - } - - CEdit GetEditControl() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return CEdit((HWND)::SendMessage(m_hWnd, TVM_GETEDITCONTROL, 0, 0L)); - } - - UINT GetVisibleCount() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::SendMessage(m_hWnd, TVM_GETVISIBLECOUNT, 0, 0L); - } - - BOOL GetItemRect(HTREEITEM hItem, LPRECT lpRect, BOOL bTextOnly) const - { - ATLASSERT(::IsWindow(m_hWnd)); - *(HTREEITEM*)lpRect = hItem; - return (BOOL)::SendMessage(m_hWnd, TVM_GETITEMRECT, (WPARAM)bTextOnly, (LPARAM)lpRect); - } - - BOOL ItemHasChildren(HTREEITEM hItem) const - { - ATLASSERT(::IsWindow(m_hWnd)); - TVITEM item = { 0 }; - item.hItem = hItem; - item.mask = TVIF_CHILDREN; - ::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item); - return item.cChildren; - } - -#ifndef _WIN32_WCE - CToolTipCtrl GetToolTips() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return CToolTipCtrl((HWND)::SendMessage(m_hWnd, TVM_GETTOOLTIPS, 0, 0L)); - } - - CToolTipCtrl SetToolTips(HWND hWndTT) - { - ATLASSERT(::IsWindow(m_hWnd)); - return CToolTipCtrl((HWND)::SendMessage(m_hWnd, TVM_SETTOOLTIPS, (WPARAM)hWndTT, 0L)); - } -#endif // !_WIN32_WCE - - int GetISearchString(LPTSTR lpstr) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TVM_GETISEARCHSTRING, 0, (LPARAM)lpstr); - } - - // checkboxes only - BOOL GetCheckState(HTREEITEM hItem) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetStyle() & TVS_CHECKBOXES) != 0); - UINT uRet = GetItemState(hItem, TVIS_STATEIMAGEMASK); - return (uRet >> 12) - 1; - } - - BOOL SetCheckState(HTREEITEM hItem, BOOL bCheck) - { - int nCheck = bCheck ? 2 : 1; // one based index - return SetItemState(hItem, INDEXTOSTATEIMAGEMASK(nCheck), TVIS_STATEIMAGEMASK); - } - -#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) - COLORREF GetBkColor() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, TVM_GETBKCOLOR, 0, 0L); - } - - COLORREF SetBkColor(COLORREF clr) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, TVM_SETBKCOLOR, 0, (LPARAM)clr); - } - - COLORREF GetInsertMarkColor() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, TVM_GETINSERTMARKCOLOR, 0, 0L); - } - - COLORREF SetInsertMarkColor(COLORREF clr) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, TVM_SETINSERTMARKCOLOR, 0, (LPARAM)clr); - } - - int GetItemHeight() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TVM_GETITEMHEIGHT, 0, 0L); - } - - int SetItemHeight(int cyHeight) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TVM_SETITEMHEIGHT, cyHeight, 0L); - } - - int GetScrollTime() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TVM_GETSCROLLTIME, 0, 0L); - } - - int SetScrollTime(int nScrollTime) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TVM_SETSCROLLTIME, nScrollTime, 0L); - } - - COLORREF GetTextColor() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, TVM_GETTEXTCOLOR, 0, 0L); - } - - COLORREF SetTextColor(COLORREF clr) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, TVM_SETTEXTCOLOR, 0, (LPARAM)clr); - } - - BOOL GetUnicodeFormat() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TVM_GETUNICODEFORMAT, 0, 0L); - } - - BOOL SetUnicodeFormat(BOOL bUnicode = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TVM_SETUNICODEFORMAT, bUnicode, 0L); - } -#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) - -#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) - COLORREF GetLineColor() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, TVM_GETLINECOLOR, 0, 0L); - } - - COLORREF SetLineColor(COLORREF clrNew /*= CLR_DEFAULT*/) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, TVM_SETLINECOLOR, 0, (LPARAM)clrNew); - } -#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) - -#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) - BOOL GetItem(LPTVITEMEX pItem) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)pItem); - } - - BOOL SetItem(LPTVITEMEX pItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TVM_SETITEM, 0, (LPARAM)pItem); - } -#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) - - DWORD GetExtendedStyle() const - { -#ifndef TVM_GETEXTENDEDSTYLE - const UINT TVM_GETEXTENDEDSTYLE = (TV_FIRST + 45); -#endif - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, TVM_GETEXTENDEDSTYLE, 0, 0L); - } - - DWORD SetExtendedStyle(DWORD dwStyle, DWORD dwMask) - { -#ifndef TVM_SETEXTENDEDSTYLE - const UINT TVM_SETEXTENDEDSTYLE = (TV_FIRST + 44); -#endif - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, TVM_SETEXTENDEDSTYLE, dwMask, dwStyle); - } - -#if (_WIN32_WINNT >= 0x0600) - BOOL SetAutoScrollInfo(UINT uPixPerSec, UINT uUpdateTime) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TVM_SETAUTOSCROLLINFO, (WPARAM)uPixPerSec, (LPARAM)uUpdateTime); - } - - DWORD GetSelectedCount() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, TVM_GETSELECTEDCOUNT, 0, 0L); - } - - BOOL GetItemPartRect(HTREEITEM hItem, TVITEMPART partID, LPRECT lpRect) const - { - ATLASSERT(::IsWindow(m_hWnd)); - TVGETITEMPARTRECTINFO gipri = { hItem, lpRect, partID }; - return (BOOL)::SendMessage(m_hWnd, TVM_GETITEMPARTRECT, 0, (LPARAM)&gipri); - } -#endif // (_WIN32_WINNT >= 0x0600) - -// Operations - HTREEITEM InsertItem(LPTVINSERTSTRUCT lpInsertStruct) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HTREEITEM)::SendMessage(m_hWnd, TVM_INSERTITEM, 0, (LPARAM)lpInsertStruct); - } - - HTREEITEM InsertItem(LPCTSTR lpszItem, int nImage, - int nSelectedImage, HTREEITEM hParent, HTREEITEM hInsertAfter) - { - ATLASSERT(::IsWindow(m_hWnd)); - return InsertItem(TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE, lpszItem, nImage, nSelectedImage, 0, 0, 0, hParent, hInsertAfter); - } - - HTREEITEM InsertItem(LPCTSTR lpszItem, HTREEITEM hParent, HTREEITEM hInsertAfter) - { - ATLASSERT(::IsWindow(m_hWnd)); - return InsertItem(TVIF_TEXT, lpszItem, 0, 0, 0, 0, 0, hParent, hInsertAfter); - } - - HTREEITEM InsertItem(UINT nMask, LPCTSTR lpszItem, int nImage, - int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam, - HTREEITEM hParent, HTREEITEM hInsertAfter) - { - ATLASSERT(::IsWindow(m_hWnd)); - TVINSERTSTRUCT tvis = { 0 }; - tvis.hParent = hParent; - tvis.hInsertAfter = hInsertAfter; - tvis.item.mask = nMask; - tvis.item.pszText = (LPTSTR) lpszItem; - tvis.item.iImage = nImage; - tvis.item.iSelectedImage = nSelectedImage; - tvis.item.state = nState; - tvis.item.stateMask = nStateMask; - tvis.item.lParam = lParam; - return (HTREEITEM)::SendMessage(m_hWnd, TVM_INSERTITEM, 0, (LPARAM)&tvis); - } - - BOOL DeleteItem(HTREEITEM hItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TVM_DELETEITEM, 0, (LPARAM)hItem); - } - - BOOL DeleteAllItems() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT); - } - - BOOL Expand(HTREEITEM hItem, UINT nCode = TVE_EXPAND) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TVM_EXPAND, nCode, (LPARAM)hItem); - } - - HTREEITEM GetNextItem(HTREEITEM hItem, UINT nCode) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, nCode, (LPARAM)hItem); - } - - HTREEITEM GetChildItem(HTREEITEM hItem) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem); - } - - HTREEITEM GetNextSiblingItem(HTREEITEM hItem) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem); - } - - HTREEITEM GetPrevSiblingItem(HTREEITEM hItem) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PREVIOUS, (LPARAM)hItem); - } - - HTREEITEM GetParentItem(HTREEITEM hItem) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)hItem); - } - - HTREEITEM GetFirstVisibleItem() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_FIRSTVISIBLE, 0L); - } - - HTREEITEM GetNextVisibleItem(HTREEITEM hItem) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXTVISIBLE, (LPARAM)hItem); - } - - HTREEITEM GetPrevVisibleItem(HTREEITEM hItem) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PREVIOUSVISIBLE, (LPARAM)hItem); - } - - HTREEITEM GetSelectedItem() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_CARET, 0L); - } - - HTREEITEM GetDropHilightItem() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_DROPHILITE, 0L); - } - - HTREEITEM GetRootItem() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_ROOT, 0L); - } - -#if !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400) - HTREEITEM GetLastVisibleItem() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_LASTVISIBLE, 0L); - } -#endif // !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400) - -#if (_WIN32_IE >= 0x0600) - HTREEITEM GetNextSelectedItem() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXTSELECTED, 0L); - } -#endif // (_WIN32_IE >= 0x0600) - - BOOL Select(HTREEITEM hItem, UINT nCode) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TVM_SELECTITEM, nCode, (LPARAM)hItem); - } - - BOOL SelectItem(HTREEITEM hItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hItem); - } - - BOOL SelectDropTarget(HTREEITEM hItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TVM_SELECTITEM, TVGN_DROPHILITE, (LPARAM)hItem); - } - - BOOL SelectSetFirstVisible(HTREEITEM hItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TVM_SELECTITEM, TVGN_FIRSTVISIBLE, (LPARAM)hItem); - } - - CEdit EditLabel(HTREEITEM hItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return CEdit((HWND)::SendMessage(m_hWnd, TVM_EDITLABEL, 0, (LPARAM)hItem)); - } - - BOOL EndEditLabelNow(BOOL bCancel) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TVM_ENDEDITLABELNOW, bCancel, 0L); - } - - HTREEITEM HitTest(TVHITTESTINFO* pHitTestInfo) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HTREEITEM)::SendMessage(m_hWnd, TVM_HITTEST, 0, (LPARAM)pHitTestInfo); - } - - HTREEITEM HitTest(POINT pt, UINT* pFlags) const - { - ATLASSERT(::IsWindow(m_hWnd)); - TVHITTESTINFO hti = { 0 }; - hti.pt = pt; - HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_HITTEST, 0, (LPARAM)&hti); - if (pFlags != NULL) - *pFlags = hti.flags; - return hTreeItem; - } - - BOOL SortChildren(HTREEITEM hItem, BOOL bRecurse = FALSE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TVM_SORTCHILDREN, (WPARAM)bRecurse, (LPARAM)hItem); - } - - BOOL EnsureVisible(HTREEITEM hItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TVM_ENSUREVISIBLE, 0, (LPARAM)hItem); - } - - BOOL SortChildrenCB(LPTVSORTCB pSort, BOOL bRecurse = FALSE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TVM_SORTCHILDRENCB, (WPARAM)bRecurse, (LPARAM)pSort); - } - - CImageList RemoveImageList(int nImageList) - { - ATLASSERT(::IsWindow(m_hWnd)); - return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TVM_SETIMAGELIST, (WPARAM)nImageList, NULL)); - } - - CImageList CreateDragImage(HTREEITEM hItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TVM_CREATEDRAGIMAGE, 0, (LPARAM)hItem)); - } - -#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) - BOOL SetInsertMark(HTREEITEM hTreeItem, BOOL bAfter) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TVM_SETINSERTMARK, bAfter, (LPARAM)hTreeItem); - } - - BOOL RemoveInsertMark() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TVM_SETINSERTMARK, 0, 0L); - } -#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) - -#if (_WIN32_WINNT >= 0x0501) - HTREEITEM MapAccIDToHTREEITEM(UINT uID) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HTREEITEM)::SendMessage(m_hWnd, TVM_MAPACCIDTOHTREEITEM, uID, 0L); - } - - UINT MapHTREEITEMToAccID(HTREEITEM hTreeItem) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::SendMessage(m_hWnd, TVM_MAPHTREEITEMTOACCID, (WPARAM)hTreeItem, 0L); - } -#endif // (_WIN32_WINNT >= 0x0501) - -#if (_WIN32_WINNT >= 0x0600) - void ShowInfoTip(HTREEITEM hItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TVM_SHOWINFOTIP, 0, (LPARAM)hItem); - } -#endif // (_WIN32_WINNT >= 0x0600) -}; - -typedef CTreeViewCtrlT CTreeViewCtrl; - - -/////////////////////////////////////////////////////////////////////////////// -// CTreeViewCtrlEx - -// forward declaration -template class CTreeViewCtrlExT; - -// Note: TBase here is for CTreeViewCtrlExT, and not for CTreeItemT itself -template -class CTreeItemT -{ -public: - HTREEITEM m_hTreeItem; - CTreeViewCtrlExT* m_pTreeView; - -// Construction - CTreeItemT(HTREEITEM hTreeItem = NULL, CTreeViewCtrlExT* pTreeView = NULL) : m_hTreeItem(hTreeItem), m_pTreeView(pTreeView) - { } - - CTreeItemT(const CTreeItemT& posSrc) - { - *this = posSrc; - } - - operator HTREEITEM() { return m_hTreeItem; } - - CTreeItemT& operator =(const CTreeItemT& itemSrc) - { - m_hTreeItem = itemSrc.m_hTreeItem; - m_pTreeView = itemSrc.m_pTreeView; - return *this; - } - -// Attributes - CTreeViewCtrlExT* GetTreeView() const { return m_pTreeView; } - - BOOL operator !() const { return m_hTreeItem == NULL; } - - BOOL IsNull() const { return m_hTreeItem == NULL; } - - BOOL GetRect(LPRECT lpRect, BOOL bTextOnly) const; - BOOL GetText(LPTSTR lpstrText, int nLen) const; -#ifndef _ATL_NO_COM - BOOL GetText(BSTR& bstrText) const; -#endif // !_ATL_NO_COM -#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - BOOL GetText(_CSTRING_NS::CString& strText) const; -#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - BOOL SetText(LPCTSTR lpszItem); - BOOL GetImage(int& nImage, int& nSelectedImage) const; - BOOL SetImage(int nImage, int nSelectedImage); - UINT GetState(UINT nStateMask) const; - BOOL SetState(UINT nState, UINT nStateMask); - DWORD_PTR GetData() const; - BOOL SetData(DWORD_PTR dwData); - BOOL SetItem(UINT nMask, LPCTSTR lpszItem, int nImage, int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam); - -// Operations - CTreeItemT InsertAfter(LPCTSTR lpstrItem, HTREEITEM hItemAfter, int nImageIndex) - { - return _Insert(lpstrItem, nImageIndex, hItemAfter); - } - - CTreeItemT AddHead(LPCTSTR lpstrItem, int nImageIndex) - { - return _Insert(lpstrItem, nImageIndex, TVI_FIRST); - } - - CTreeItemT AddTail(LPCTSTR lpstrItem, int nImageIndex) - { - return _Insert(lpstrItem, nImageIndex, TVI_LAST); - } - - CTreeItemT GetChild() const; - CTreeItemT GetNext(UINT nCode) const; - CTreeItemT GetNextSibling() const; - CTreeItemT GetPrevSibling() const; - CTreeItemT GetParent() const; - CTreeItemT GetFirstVisible() const; - CTreeItemT GetNextVisible() const; - CTreeItemT GetPrevVisible() const; - CTreeItemT GetSelected() const; - CTreeItemT GetDropHilight() const; - CTreeItemT GetRoot() const; -#if !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400) - CTreeItemT GetLastVisible() const; -#endif // !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400) -#if (_WIN32_IE >= 0x0600) - CTreeItemT GetNextSelected() const; -#endif // (_WIN32_IE >= 0x0600) - BOOL HasChildren() const; - BOOL Delete(); - BOOL Expand(UINT nCode = TVE_EXPAND); - BOOL Select(UINT nCode); - BOOL Select(); - BOOL SelectDropTarget(); - BOOL SelectSetFirstVisible(); - HWND EditLabel(); - HIMAGELIST CreateDragImage(); - BOOL SortChildren(BOOL bRecurse = FALSE); - BOOL EnsureVisible(); - CTreeItemT _Insert(LPCTSTR lpstrItem, int nImageIndex, HTREEITEM hItemAfter); - int GetImageIndex() const; -#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) - BOOL SetInsertMark(BOOL bAfter); -#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) -#if (_WIN32_WINNT >= 0x0501) - UINT MapHTREEITEMToAccID() const; -#endif // (_WIN32_WINNT >= 0x0501) -#if (_WIN32_WINNT >= 0x0600) - void ShowInfoTip(); - BOOL GetPartRect(TVITEMPART partID, LPRECT lpRect) const; -#endif // (_WIN32_WINNT >= 0x0600) -}; - -typedef CTreeItemT CTreeItem; - - -template -class CTreeViewCtrlExT : public CTreeViewCtrlT< TBase > -{ -public: -// Constructors - CTreeViewCtrlExT(HWND hWnd = NULL) : CTreeViewCtrlT< TBase >(hWnd) - { } - - CTreeViewCtrlExT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - -// Operations (overides that return CTreeItem) - CTreeItemT InsertItem(LPTVINSERTSTRUCT lpInsertStruct) - { - ATLASSERT(::IsWindow(m_hWnd)); - HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_INSERTITEM, 0, (LPARAM)lpInsertStruct); - return CTreeItemT(hTreeItem, this); - } - - CTreeItemT InsertItem(LPCTSTR lpszItem, int nImage, - int nSelectedImage, HTREEITEM hParent, HTREEITEM hInsertAfter) - { - ATLASSERT(::IsWindow(m_hWnd)); - return InsertItem(TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE, lpszItem, nImage, nSelectedImage, 0, 0, 0, hParent, hInsertAfter); - } - - CTreeItemT InsertItem(LPCTSTR lpszItem, HTREEITEM hParent, HTREEITEM hInsertAfter) - { - ATLASSERT(::IsWindow(m_hWnd)); - return InsertItem(TVIF_TEXT, lpszItem, 0, 0, 0, 0, 0, hParent, hInsertAfter); - } - - CTreeItemT GetNextItem(HTREEITEM hItem, UINT nCode) const - { - ATLASSERT(::IsWindow(m_hWnd)); - HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, nCode, (LPARAM)hItem); - return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); - } - - CTreeItemT GetChildItem(HTREEITEM hItem) const - { - ATLASSERT(::IsWindow(m_hWnd)); - HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem); - return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); - } - - CTreeItemT GetNextSiblingItem(HTREEITEM hItem) const - { - ATLASSERT(::IsWindow(m_hWnd)); - HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem); - return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); - } - - CTreeItemT GetPrevSiblingItem(HTREEITEM hItem) const - { - ATLASSERT(::IsWindow(m_hWnd)); - HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PREVIOUS, (LPARAM)hItem); - return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); - } - - CTreeItemT GetParentItem(HTREEITEM hItem) const - { - ATLASSERT(::IsWindow(m_hWnd)); - HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)hItem); - return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); - } - - CTreeItemT GetFirstVisibleItem() const - { - ATLASSERT(::IsWindow(m_hWnd)); - HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_FIRSTVISIBLE, 0L); - return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); - } - - CTreeItemT GetNextVisibleItem(HTREEITEM hItem) const - { - ATLASSERT(::IsWindow(m_hWnd)); - HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXTVISIBLE, (LPARAM)hItem); - return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); - } - - CTreeItemT GetPrevVisibleItem(HTREEITEM hItem) const - { - ATLASSERT(::IsWindow(m_hWnd)); - HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PREVIOUSVISIBLE, (LPARAM)hItem); - return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); - } - - CTreeItemT GetSelectedItem() const - { - ATLASSERT(::IsWindow(m_hWnd)); - HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_CARET, 0L); - return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); - } - - CTreeItemT GetDropHilightItem() const - { - ATLASSERT(::IsWindow(m_hWnd)); - HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_DROPHILITE, 0L); - return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); - } - - CTreeItemT GetRootItem() const - { - ATLASSERT(::IsWindow(m_hWnd)); - HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_ROOT, 0L); - return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); - } - -#if !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400) - CTreeItemT GetLastVisibleItem() const - { - ATLASSERT(::IsWindow(m_hWnd)); - HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_LASTVISIBLE, 0L); - return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); - } -#endif // !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400) - -#if (_WIN32_IE >= 0x0600) - CTreeItemT GetNextSelectedItem() const - { - ATLASSERT(::IsWindow(m_hWnd)); - HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXTSELECTED, 0L); - return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); - } -#endif // (_WIN32_IE >= 0x0600) - - CTreeItemT HitTest(TVHITTESTINFO* pHitTestInfo) const - { - ATLASSERT(::IsWindow(m_hWnd)); - HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_HITTEST, 0, (LPARAM)pHitTestInfo); - return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); - } - - CTreeItemT InsertItem(UINT nMask, LPCTSTR lpszItem, int nImage, - int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam, - HTREEITEM hParent, HTREEITEM hInsertAfter) - { - ATLASSERT(::IsWindow(m_hWnd)); - TVINSERTSTRUCT tvis = { 0 }; - tvis.hParent = hParent; - tvis.hInsertAfter = hInsertAfter; - tvis.item.mask = nMask; - tvis.item.pszText = (LPTSTR) lpszItem; - tvis.item.iImage = nImage; - tvis.item.iSelectedImage = nSelectedImage; - tvis.item.state = nState; - tvis.item.stateMask = nStateMask; - tvis.item.lParam = lParam; - HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_INSERTITEM, 0, (LPARAM)&tvis); - return CTreeItemT(hTreeItem, this); - } - - CTreeItemT HitTest(POINT pt, UINT* pFlags) const - { - ATLASSERT(::IsWindow(m_hWnd)); - TVHITTESTINFO hti = { 0 }; - hti.pt = pt; - HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_HITTEST, 0, (LPARAM)&hti); - if (pFlags != NULL) - *pFlags = hti.flags; - return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); - } - -#if (_WIN32_WINNT >= 0x0501) - CTreeItemT MapAccIDToHTREEITEM(UINT uID) const - { - ATLASSERT(::IsWindow(m_hWnd)); - HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_MAPACCIDTOHTREEITEM, uID, 0L); - return CTreeItemT(hTreeItem, (CTreeViewCtrlExT*)this); - } -#endif // (_WIN32_WINNT >= 0x0501) -}; - -typedef CTreeViewCtrlExT CTreeViewCtrlEx; - - -// CTreeItem inline methods -template -inline BOOL CTreeItemT::GetRect(LPRECT lpRect, BOOL bTextOnly) const -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->GetItemRect(m_hTreeItem,lpRect,bTextOnly); -} - -template -inline CTreeItemT CTreeItemT::GetNext(UINT nCode) const -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->GetNextItem(m_hTreeItem,nCode); -} - -template -inline CTreeItemT CTreeItemT::GetChild() const -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->GetChildItem(m_hTreeItem); -} - -template -inline CTreeItemT CTreeItemT::GetNextSibling() const -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->GetNextSiblingItem(m_hTreeItem); -} - -template -inline CTreeItemT CTreeItemT::GetPrevSibling() const -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->GetPrevSiblingItem(m_hTreeItem); -} - -template -inline CTreeItemT CTreeItemT::GetParent() const -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->GetParentItem(m_hTreeItem); -} - -template -inline CTreeItemT CTreeItemT::GetFirstVisible() const -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->GetFirstVisibleItem(); -} - -template -inline CTreeItemT CTreeItemT::GetNextVisible() const -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->GetNextVisibleItem(m_hTreeItem); -} - -template -inline CTreeItemT CTreeItemT::GetPrevVisible() const -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->GetPrevVisibleItem(m_hTreeItem); -} - -template -inline CTreeItemT CTreeItemT::GetSelected() const -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->GetSelectedItem(); -} - -template -inline CTreeItemT CTreeItemT::GetDropHilight() const -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->GetDropHilightItem(); -} - -template -inline CTreeItemT CTreeItemT::GetRoot() const -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->GetRootItem(); -} - -#if !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400) -template -inline CTreeItemT CTreeItemT::GetLastVisible() const -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->GetLastVisibleItem(); -} -#endif // !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400) - -#if (_WIN32_IE >= 0x0600) -template -inline CTreeItemT CTreeItemT::GetNextSelected() const -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->GetNextSelectedItem(); -} -#endif // (_WIN32_IE >= 0x0600) - -template -inline BOOL CTreeItemT::GetText(LPTSTR lpstrText, int nLen) const -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->GetItemText(m_hTreeItem, lpstrText, nLen); -} - -#ifndef _ATL_NO_COM -#ifdef _OLEAUTO_H_ -template -inline BOOL CTreeItemT::GetText(BSTR& bstrText) const -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->GetItemText(m_hTreeItem, bstrText); -} -#endif // _OLEAUTO_H_ -#endif // !_ATL_NO_COM - -#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) -template -inline BOOL CTreeItemT::GetText(_CSTRING_NS::CString& strText) const -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->GetItemText(m_hTreeItem, strText); -} -#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - -template -inline BOOL CTreeItemT::GetImage(int& nImage, int& nSelectedImage) const -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->GetItemImage(m_hTreeItem,nImage,nSelectedImage); -} - -template -inline UINT CTreeItemT::GetState(UINT nStateMask) const -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->GetItemState(m_hTreeItem,nStateMask); -} - -template -inline DWORD_PTR CTreeItemT::GetData() const -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->GetItemData(m_hTreeItem); -} - -template -inline BOOL CTreeItemT::SetItem(UINT nMask, LPCTSTR lpszItem, int nImage, - int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam) -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->SetItem(m_hTreeItem, nMask, lpszItem, nImage, nSelectedImage, nState, nStateMask, lParam); -} - -template -inline BOOL CTreeItemT::SetText(LPCTSTR lpszItem) -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->SetItemText(m_hTreeItem,lpszItem); -} - -template -inline BOOL CTreeItemT::SetImage(int nImage, int nSelectedImage) -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->SetItemImage(m_hTreeItem,nImage,nSelectedImage); -} - -template -inline BOOL CTreeItemT::SetState(UINT nState, UINT nStateMask) -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->SetItemState(m_hTreeItem,nState,nStateMask); -} - -template -inline BOOL CTreeItemT::SetData(DWORD_PTR dwData) -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->SetItemData(m_hTreeItem,dwData); -} - -template -inline BOOL CTreeItemT::HasChildren() const -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->ItemHasChildren(m_hTreeItem); -} - -template -inline BOOL CTreeItemT::Delete() -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->DeleteItem(m_hTreeItem); -} - -template -inline BOOL CTreeItemT::Expand(UINT nCode /*= TVE_EXPAND*/) -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->Expand(m_hTreeItem,nCode); -} - -template -inline BOOL CTreeItemT::Select(UINT nCode) -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->Select(m_hTreeItem,nCode); -} - -template -inline BOOL CTreeItemT::Select() -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->SelectItem(m_hTreeItem); -} - -template -inline BOOL CTreeItemT::SelectDropTarget() -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->SelectDropTarget(m_hTreeItem); -} - -template -inline BOOL CTreeItemT::SelectSetFirstVisible() -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->SelectSetFirstVisible(m_hTreeItem); -} - -template -inline HWND CTreeItemT::EditLabel() -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->EditLabel(m_hTreeItem); -} - -template -inline HIMAGELIST CTreeItemT::CreateDragImage() -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->CreateDragImage(m_hTreeItem); -} - -template -inline BOOL CTreeItemT::SortChildren(BOOL bRecurse /*= FALSE*/) -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->SortChildren(m_hTreeItem, bRecurse); -} - -template -inline BOOL CTreeItemT::EnsureVisible() -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->EnsureVisible(m_hTreeItem); -} - -template -inline CTreeItemT CTreeItemT::_Insert(LPCTSTR lpstrItem, int nImageIndex, HTREEITEM hItemAfter) -{ - ATLASSERT(m_pTreeView != NULL); - TVINSERTSTRUCT ins = { 0 }; - ins.hParent = m_hTreeItem; - ins.hInsertAfter = hItemAfter; - ins.item.mask = TVIF_TEXT; - ins.item.pszText = (LPTSTR)lpstrItem; - if(nImageIndex != -1) - { - ins.item.mask |= TVIF_IMAGE | TVIF_SELECTEDIMAGE; - ins.item.iImage = nImageIndex; - ins.item.iSelectedImage = nImageIndex; - } - return CTreeItemT(m_pTreeView->InsertItem(&ins), m_pTreeView); -} - -template -inline int CTreeItemT::GetImageIndex() const -{ - ATLASSERT(m_pTreeView != NULL); - TVITEM item = { 0 }; - item.mask = TVIF_HANDLE | TVIF_IMAGE; - item.hItem = m_hTreeItem; - m_pTreeView->GetItem(&item); - return item.iImage; -} - -#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) -template -inline BOOL CTreeItemT::SetInsertMark(BOOL bAfter) -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->SetInsertMark(m_hTreeItem, bAfter); -} -#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) - -#if (_WIN32_WINNT >= 0x0501) -template -inline UINT CTreeItemT::MapHTREEITEMToAccID() const -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->MapHTREEITEMToAccID(m_hTreeItem); -} -#endif // (_WIN32_WINNT >= 0x0501) - -#if (_WIN32_WINNT >= 0x0600) -template -inline void CTreeItemT::ShowInfoTip() -{ - ATLASSERT(m_pTreeView != NULL); - m_pTreeView->ShowInfoTip(m_hTreeItem); -} - -template -inline BOOL CTreeItemT::GetPartRect(TVITEMPART partID, LPRECT lpRect) const -{ - ATLASSERT(m_pTreeView != NULL); - return m_pTreeView->GetItemPartRect(m_hTreeItem, partID, lpRect); -} -#endif // (_WIN32_WINNT >= 0x0600) - - -/////////////////////////////////////////////////////////////////////////////// -// CToolBarCtrl - -template -class CToolBarCtrlT : public TBase -{ -public: -// Construction - CToolBarCtrlT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CToolBarCtrlT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return TOOLBARCLASSNAME; - } - - BOOL IsButtonEnabled(int nID) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_ISBUTTONENABLED, nID, 0L); - } - - BOOL IsButtonChecked(int nID) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_ISBUTTONCHECKED, nID, 0L); - } - - BOOL IsButtonPressed(int nID) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_ISBUTTONPRESSED, nID, 0L); - } - - BOOL IsButtonHidden(int nID) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return(BOOL) ::SendMessage(m_hWnd, TB_ISBUTTONHIDDEN, nID, 0L); - } - - BOOL IsButtonIndeterminate(int nID) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_ISBUTTONINDETERMINATE, nID, 0L); - } - - int GetState(int nID) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TB_GETSTATE, nID, 0L); - } - - BOOL SetState(int nID, UINT nState) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_SETSTATE, nID, MAKELPARAM(nState, 0)); - } - - BOOL GetButton(int nIndex, LPTBBUTTON lpButton) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_GETBUTTON, nIndex, (LPARAM)lpButton); - } - - int GetButtonCount() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TB_BUTTONCOUNT, 0, 0L); - } - - BOOL GetItemRect(int nIndex, LPRECT lpRect) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_GETITEMRECT, nIndex, (LPARAM)lpRect); - } - - void SetButtonStructSize(int nSize = sizeof(TBBUTTON)) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TB_BUTTONSTRUCTSIZE, nSize, 0L); - } - - BOOL SetButtonSize(SIZE size) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_SETBUTTONSIZE, 0, MAKELPARAM(size.cx, size.cy)); - } - - BOOL SetButtonSize(int cx, int cy) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_SETBUTTONSIZE, 0, MAKELPARAM(cx, cy)); - } - - BOOL SetBitmapSize(SIZE size) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_SETBITMAPSIZE, 0, MAKELPARAM(size.cx, size.cy)); - } - - BOOL SetBitmapSize(int cx, int cy) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_SETBITMAPSIZE, 0, MAKELPARAM(cx, cy)); - } - -#ifndef _WIN32_WCE - CToolTipCtrl GetToolTips() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return CToolTipCtrl((HWND)::SendMessage(m_hWnd, TB_GETTOOLTIPS, 0, 0L)); - } - - void SetToolTips(HWND hWndToolTip) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TB_SETTOOLTIPS, (WPARAM)hWndToolTip, 0L); - } -#endif // !_WIN32_WCE - - void SetNotifyWnd(HWND hWnd) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TB_SETPARENT, (WPARAM)hWnd, 0L); - } - - int GetRows() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TB_GETROWS, 0, 0L); - } - - void SetRows(int nRows, BOOL bLarger, LPRECT lpRect) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TB_SETROWS, MAKELPARAM(nRows, bLarger), (LPARAM)lpRect); - } - - BOOL SetCmdID(int nIndex, UINT nID) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_SETCMDID, nIndex, nID); - } - - DWORD GetBitmapFlags() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, TB_GETBITMAPFLAGS, 0, 0L); - } - - int GetBitmap(int nID) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TB_GETBITMAP, nID, 0L); - } - - int GetButtonText(int nID, LPTSTR lpstrText) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TB_GETBUTTONTEXT, nID, (LPARAM)lpstrText); - } - - // nIndex - IE5 or higher only - CImageList GetImageList(int nIndex = 0) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_GETIMAGELIST, nIndex, 0L)); - } - - // nIndex - IE5 or higher only - CImageList SetImageList(HIMAGELIST hImageList, int nIndex = 0) - { - ATLASSERT(::IsWindow(m_hWnd)); - return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_SETIMAGELIST, nIndex, (LPARAM)hImageList)); - } - - // nIndex - IE5 or higher only - CImageList GetDisabledImageList(int nIndex = 0) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_GETDISABLEDIMAGELIST, nIndex, 0L)); - } - - // nIndex - IE5 or higher only - CImageList SetDisabledImageList(HIMAGELIST hImageList, int nIndex = 0) - { - ATLASSERT(::IsWindow(m_hWnd)); - return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_SETDISABLEDIMAGELIST, nIndex, (LPARAM)hImageList)); - } - -#ifndef _WIN32_WCE - // nIndex - IE5 or higher only - CImageList GetHotImageList(int nIndex = 0) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_GETHOTIMAGELIST, nIndex, 0L)); - } - - // nIndex - IE5 or higher only - CImageList SetHotImageList(HIMAGELIST hImageList, int nIndex = 0) - { - ATLASSERT(::IsWindow(m_hWnd)); - return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_SETHOTIMAGELIST, nIndex, (LPARAM)hImageList)); - } -#endif // !_WIN32_WCE - - DWORD GetStyle() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, TB_GETSTYLE, 0, 0L); - } - - void SetStyle(DWORD dwStyle) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TB_SETSTYLE, 0, dwStyle); - } - - DWORD GetButtonSize() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, TB_GETBUTTONSIZE, 0, 0L); - } - - void GetButtonSize(SIZE& size) const - { - ATLASSERT(::IsWindow(m_hWnd)); - DWORD dwRet = (DWORD)::SendMessage(m_hWnd, TB_GETBUTTONSIZE, 0, 0L); - size.cx = LOWORD(dwRet); - size.cy = HIWORD(dwRet); - } - - BOOL GetRect(int nID, LPRECT lpRect) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_GETRECT, nID, (LPARAM)lpRect); - } - - int GetTextRows() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TB_GETTEXTROWS, 0, 0L); - } - - BOOL SetButtonWidth(int cxMin, int cxMax) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_SETBUTTONWIDTH, 0, MAKELPARAM(cxMin, cxMax)); - } - - BOOL SetIndent(int nIndent) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_SETINDENT, nIndent, 0L); - } - - BOOL SetMaxTextRows(int nMaxTextRows) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_SETMAXTEXTROWS, nMaxTextRows, 0L); - } - -#if (_WIN32_IE >= 0x0400) -#ifndef _WIN32_WCE - BOOL GetAnchorHighlight() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_GETANCHORHIGHLIGHT, 0, 0L); - } - - BOOL SetAnchorHighlight(BOOL bEnable = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_SETANCHORHIGHLIGHT, bEnable, 0L); - } -#endif // !_WIN32_WCE - - int GetButtonInfo(int nID, LPTBBUTTONINFO lptbbi) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TB_GETBUTTONINFO, nID, (LPARAM)lptbbi); - } - - BOOL SetButtonInfo(int nID, LPTBBUTTONINFO lptbbi) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_SETBUTTONINFO, nID, (LPARAM)lptbbi); - } - - BOOL SetButtonInfo(int nID, DWORD dwMask, BYTE Style, BYTE State, LPCTSTR lpszItem, - int iImage, WORD cx, int iCommand, DWORD_PTR lParam) - { - ATLASSERT(::IsWindow(m_hWnd)); - TBBUTTONINFO tbbi = { 0 }; - tbbi.cbSize = sizeof(TBBUTTONINFO); - tbbi.dwMask = dwMask; - tbbi.idCommand = iCommand; - tbbi.iImage = iImage; - tbbi.fsState = State; - tbbi.fsStyle = Style; - tbbi.cx = cx; - tbbi.pszText = (LPTSTR) lpszItem; - tbbi.lParam = lParam; - return (BOOL)::SendMessage(m_hWnd, TB_SETBUTTONINFO, nID, (LPARAM)&tbbi); - } - -#ifndef _WIN32_WCE - int GetHotItem() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TB_GETHOTITEM, 0, 0L); - } - - int SetHotItem(int nItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TB_SETHOTITEM, nItem, 0L); - } -#endif // !_WIN32_WCE - - BOOL IsButtonHighlighted(int nButtonID) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_ISBUTTONHIGHLIGHTED, nButtonID, 0L); - } - - DWORD SetDrawTextFlags(DWORD dwMask, DWORD dwFlags) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, TB_SETDRAWTEXTFLAGS, dwMask, dwFlags); - } - -#ifndef _WIN32_WCE - BOOL GetColorScheme(LPCOLORSCHEME lpcs) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_GETCOLORSCHEME, 0, (LPARAM)lpcs); - } - - void SetColorScheme(LPCOLORSCHEME lpcs) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TB_SETCOLORSCHEME, 0, (LPARAM)lpcs); - } - - DWORD GetExtendedStyle() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, TB_GETEXTENDEDSTYLE, 0, 0L); - } - - DWORD SetExtendedStyle(DWORD dwStyle) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, TB_SETEXTENDEDSTYLE, 0, dwStyle); - } - - void GetInsertMark(LPTBINSERTMARK lptbim) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TB_GETINSERTMARK, 0, (LPARAM)lptbim); - } - - void SetInsertMark(LPTBINSERTMARK lptbim) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TB_SETINSERTMARK, 0, (LPARAM)lptbim); - } - - COLORREF GetInsertMarkColor() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, TB_GETINSERTMARKCOLOR, 0, 0L); - } - - COLORREF SetInsertMarkColor(COLORREF clr) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, TB_SETINSERTMARKCOLOR, 0, (LPARAM)clr); - } - - BOOL GetMaxSize(LPSIZE lpSize) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_GETMAXSIZE, 0, (LPARAM)lpSize); - } - - void GetPadding(LPSIZE lpSizePadding) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(lpSizePadding != NULL); - DWORD dwRet = (DWORD)::SendMessage(m_hWnd, TB_GETPADDING, 0, 0L); - lpSizePadding->cx = GET_X_LPARAM(dwRet); - lpSizePadding->cy = GET_Y_LPARAM(dwRet); - } - - void SetPadding(int cx, int cy, LPSIZE lpSizePadding = NULL) - { - ATLASSERT(::IsWindow(m_hWnd)); - DWORD dwRet = (DWORD)::SendMessage(m_hWnd, TB_SETPADDING, 0, MAKELPARAM(cx, cy)); - if(lpSizePadding != NULL) - { - lpSizePadding->cx = GET_X_LPARAM(dwRet); - lpSizePadding->cy = GET_Y_LPARAM(dwRet); - } - } - - BOOL GetUnicodeFormat() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_GETUNICODEFORMAT, 0, 0L); - } - - BOOL SetUnicodeFormat(BOOL bUnicode = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_SETUNICODEFORMAT, bUnicode, 0L); - } -#endif // !_WIN32_WCE -#endif // (_WIN32_IE >= 0x0400) - -#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) - int GetString(int nString, LPTSTR lpstrString, int cchMaxLen) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TB_GETSTRING, MAKEWPARAM(cchMaxLen, nString), (LPARAM)lpstrString); - } - - int GetStringBSTR(int nString, BSTR& bstrString) const - { - USES_CONVERSION; - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(bstrString == NULL); - int nLength = (int)(short)LOWORD(::SendMessage(m_hWnd, TB_GETSTRING, MAKEWPARAM(0, nString), NULL)); - if(nLength != -1) - { - CTempBuffer buff; - LPTSTR lpstrText = buff.Allocate(nLength + 1); - if(lpstrText != NULL) - { - nLength = (int)::SendMessage(m_hWnd, TB_GETSTRING, MAKEWPARAM(nLength + 1, nString), (LPARAM)lpstrText); - if(nLength != -1) - bstrString = ::SysAllocString(T2OLE(lpstrText)); - } - else - { - nLength = -1; - } - } - - return nLength; - } - -#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - int GetString(int nString, _CSTRING_NS::CString& str) const - { - ATLASSERT(::IsWindow(m_hWnd)); - int nLength = (int)(short)LOWORD(::SendMessage(m_hWnd, TB_GETSTRING, MAKEWPARAM(0, nString), NULL)); - if(nLength != -1) - { - LPTSTR lpstr = str.GetBufferSetLength(nLength + 1); - if(lpstr != NULL) - nLength = (int)::SendMessage(m_hWnd, TB_GETSTRING, MAKEWPARAM(nLength + 1, nString), (LPARAM)lpstr); - else - nLength = -1; - str.ReleaseBuffer(); - } - return nLength; - } -#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) -#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) - -#if (_WIN32_WINNT >= 0x0501) - void GetMetrics(LPTBMETRICS lptbm) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TB_GETMETRICS, 0, (LPARAM)lptbm); - } - - void SetMetrics(LPTBMETRICS lptbm) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TB_SETMETRICS, 0, (LPARAM)lptbm); - } - - void SetWindowTheme(LPCWSTR lpstrTheme) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TB_SETWINDOWTHEME, 0, (LPARAM)lpstrTheme); - } -#endif // (_WIN32_WINNT >= 0x0501) - -#if (_WIN32_WINNT >= 0x0600) - CImageList GetPressedImageList(int nIndex = 0) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_GETPRESSEDIMAGELIST, nIndex, 0L)); - } - - CImageList SetPressedImageList(HIMAGELIST hImageList, int nIndex = 0) - { - ATLASSERT(::IsWindow(m_hWnd)); - return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_SETPRESSEDIMAGELIST, nIndex, (LPARAM)hImageList)); - } -#endif // (_WIN32_WINNT >= 0x0600) - -// Operations - BOOL EnableButton(int nID, BOOL bEnable = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_ENABLEBUTTON, nID, MAKELPARAM(bEnable, 0)); - } - - BOOL CheckButton(int nID, BOOL bCheck = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_CHECKBUTTON, nID, MAKELPARAM(bCheck, 0)); - } - - BOOL PressButton(int nID, BOOL bPress = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_PRESSBUTTON, nID, MAKELPARAM(bPress, 0)); - } - - BOOL HideButton(int nID, BOOL bHide = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_HIDEBUTTON, nID, MAKELPARAM(bHide, 0)); - } - - BOOL Indeterminate(int nID, BOOL bIndeterminate = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_INDETERMINATE, nID, MAKELPARAM(bIndeterminate, 0)); - } - - int AddBitmap(int nNumButtons, UINT nBitmapID) - { - ATLASSERT(::IsWindow(m_hWnd)); - TBADDBITMAP tbab = { 0 }; - tbab.hInst = ModuleHelper::GetResourceInstance(); - ATLASSERT(tbab.hInst != NULL); - tbab.nID = nBitmapID; - return (int)::SendMessage(m_hWnd, TB_ADDBITMAP, (WPARAM)nNumButtons, (LPARAM)&tbab); - } - - int AddBitmap(int nNumButtons, HBITMAP hBitmap) - { - ATLASSERT(::IsWindow(m_hWnd)); - TBADDBITMAP tbab = { 0 }; - tbab.hInst = NULL; - tbab.nID = (UINT_PTR)hBitmap; - return (int)::SendMessage(m_hWnd, TB_ADDBITMAP, (WPARAM)nNumButtons, (LPARAM)&tbab); - } - - BOOL AddButtons(int nNumButtons, LPTBBUTTON lpButtons) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_ADDBUTTONS, nNumButtons, (LPARAM)lpButtons); - } - - BOOL InsertButton(int nIndex, LPTBBUTTON lpButton) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_INSERTBUTTON, nIndex, (LPARAM)lpButton); - } - - BOOL InsertButton(int nIndex, int iCommand, BYTE Style, BYTE State, int iBitmap, - INT_PTR iString, DWORD_PTR lParam) - { - ATLASSERT(::IsWindow(m_hWnd)); - TBBUTTON tbb = { 0 }; - tbb.fsStyle = Style; - tbb.fsState = State; - tbb.idCommand = iCommand; - tbb.iBitmap = iBitmap; - tbb.iString = iString; - tbb.dwData = lParam; - return (BOOL)::SendMessage(m_hWnd, TB_INSERTBUTTON, nIndex, (LPARAM)&tbb); - } - - BOOL InsertButton(int nIndex, int iCommand, BYTE Style, BYTE State, int iBitmap, - LPCTSTR lpszItem, DWORD_PTR lParam) - { - return InsertButton(nIndex, iCommand, Style, State, iBitmap, (INT_PTR)lpszItem, lParam); - } - - BOOL AddButton(LPTBBUTTON lpButton) - { - return InsertButton(-1, lpButton); - } - - BOOL AddButton(int iCommand, BYTE Style, BYTE State, int iBitmap, INT_PTR iString, DWORD_PTR lParam) - { - return InsertButton(-1, iCommand, Style, State, iBitmap, iString, lParam); - } - - BOOL AddButton(int iCommand, BYTE Style, BYTE State, int iBitmap, LPCTSTR lpszItem, DWORD_PTR lParam) - { - return InsertButton(-1, iCommand, Style, State, iBitmap, lpszItem, lParam); - } - - BOOL DeleteButton(int nIndex) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_DELETEBUTTON, nIndex, 0L); - } - - UINT CommandToIndex(UINT nID) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::SendMessage(m_hWnd, TB_COMMANDTOINDEX, nID, 0L); - } - -#ifndef _WIN32_WCE - void SaveState(HKEY hKeyRoot, LPCTSTR lpszSubKey, LPCTSTR lpszValueName) - { - ATLASSERT(::IsWindow(m_hWnd)); - TBSAVEPARAMS tbs = { 0 }; - tbs.hkr = hKeyRoot; - tbs.pszSubKey = lpszSubKey; - tbs.pszValueName = lpszValueName; - ::SendMessage(m_hWnd, TB_SAVERESTORE, (WPARAM)TRUE, (LPARAM)&tbs); - } - - void RestoreState(HKEY hKeyRoot, LPCTSTR lpszSubKey, LPCTSTR lpszValueName) - { - ATLASSERT(::IsWindow(m_hWnd)); - TBSAVEPARAMS tbs = { 0 }; - tbs.hkr = hKeyRoot; - tbs.pszSubKey = lpszSubKey; - tbs.pszValueName = lpszValueName; - ::SendMessage(m_hWnd, TB_SAVERESTORE, (WPARAM)FALSE, (LPARAM)&tbs); - } - - void Customize() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TB_CUSTOMIZE, 0, 0L); - } -#endif // !_WIN32_WCE - - int AddString(UINT nStringID) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TB_ADDSTRING, (WPARAM)ModuleHelper::GetResourceInstance(), (LPARAM)nStringID); - } - - int AddStrings(LPCTSTR lpszStrings) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TB_ADDSTRING, 0, (LPARAM)lpszStrings); - } - - void AutoSize() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TB_AUTOSIZE, 0, 0L); - } - - BOOL ChangeBitmap(int nID, int nBitmap) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_CHANGEBITMAP, nID, MAKELPARAM(nBitmap, 0)); - } - - int LoadImages(int nBitmapID) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TB_LOADIMAGES, nBitmapID, (LPARAM)ModuleHelper::GetResourceInstance()); - } - - int LoadStdImages(int nBitmapID) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TB_LOADIMAGES, nBitmapID, (LPARAM)HINST_COMMCTRL); - } - - BOOL ReplaceBitmap(LPTBREPLACEBITMAP ptbrb) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_REPLACEBITMAP, 0, (LPARAM)ptbrb); - } - -#if (_WIN32_IE >= 0x0400) - int HitTest(LPPOINT lpPoint) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TB_HITTEST, 0, (LPARAM)lpPoint); - } - -#ifndef _WIN32_WCE - BOOL InsertMarkHitTest(LPPOINT lpPoint, LPTBINSERTMARK lptbim) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_INSERTMARKHITTEST, (WPARAM)lpPoint, (LPARAM)lptbim); - } - - BOOL InsertMarkHitTest(int x, int y, LPTBINSERTMARK lptbim) const - { - ATLASSERT(::IsWindow(m_hWnd)); - POINT pt = { x, y }; - return (BOOL)::SendMessage(m_hWnd, TB_INSERTMARKHITTEST, (WPARAM)&pt, (LPARAM)lptbim); - } - - BOOL MapAccelerator(TCHAR chAccel, int& nID) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_MAPACCELERATOR, (WPARAM)chAccel, (LPARAM)&nID); - } - - BOOL MarkButton(int nID, BOOL bHighlight = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_MARKBUTTON, nID, MAKELPARAM(bHighlight, 0)); - } - - BOOL MoveButton(int nOldPos, int nNewPos) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TB_MOVEBUTTON, nOldPos, nNewPos); - } - - HRESULT GetObject(REFIID iid, LPVOID* ppvObject) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HRESULT)::SendMessage(m_hWnd, TB_GETOBJECT, (WPARAM)&iid, (LPARAM)ppvObject); - } -#endif // !_WIN32_WCE -#endif // (_WIN32_IE >= 0x0400) -}; - -typedef CToolBarCtrlT CToolBarCtrl; - - -/////////////////////////////////////////////////////////////////////////////// -// CStatusBarCtrl - -template -class CStatusBarCtrlT : public TBase -{ -public: -// Constructors - CStatusBarCtrlT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CStatusBarCtrlT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - } - -// Methods - static LPCTSTR GetWndClassName() - { - return STATUSCLASSNAME; - } - - int GetParts(int nParts, int* pParts) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, SB_GETPARTS, nParts, (LPARAM)pParts); - } - - BOOL SetParts(int nParts, int* pWidths) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, SB_SETPARTS, nParts, (LPARAM)pWidths); - } - - int GetTextLength(int nPane, int* pType = NULL) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(nPane < 256); - DWORD dwRet = (DWORD)::SendMessage(m_hWnd, SB_GETTEXTLENGTH, (WPARAM)nPane, 0L); - if (pType != NULL) - *pType = (int)(short)HIWORD(dwRet); - return (int)(short)LOWORD(dwRet); - } - - int GetText(int nPane, LPTSTR lpszText, int* pType = NULL) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(nPane < 256); - DWORD dwRet = (DWORD)::SendMessage(m_hWnd, SB_GETTEXT, (WPARAM)nPane, (LPARAM)lpszText); - if(pType != NULL) - *pType = (int)(short)HIWORD(dwRet); - return (int)(short)LOWORD(dwRet); - } - -#ifndef _ATL_NO_COM - BOOL GetTextBSTR(int nPane, BSTR& bstrText, int* pType = NULL) const - { - USES_CONVERSION; - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(nPane < 256); - ATLASSERT(bstrText == NULL); - int nLength = (int)(short)LOWORD(::SendMessage(m_hWnd, SB_GETTEXTLENGTH, (WPARAM)nPane, 0L)); - if(nLength == 0) - return FALSE; - - CTempBuffer buff; - LPTSTR lpstrText = buff.Allocate(nLength + 1); - if(lpstrText == NULL) - return FALSE; - - if(!GetText(nPane, lpstrText, pType)) - return FALSE; - - bstrText = ::SysAllocString(T2OLE(lpstrText)); - return (bstrText != NULL) ? TRUE : FALSE; - } -#endif // !_ATL_NO_COM - -#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - int GetText(int nPane, _CSTRING_NS::CString& strText, int* pType = NULL) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(nPane < 256); - int nLength = (int)(short)LOWORD(::SendMessage(m_hWnd, SB_GETTEXTLENGTH, (WPARAM)nPane, 0L)); - if(nLength == 0) - return 0; - - LPTSTR lpstr = strText.GetBufferSetLength(nLength); - if(lpstr == NULL) - return 0; - return GetText(nPane, lpstr, pType); - } -#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - - BOOL SetText(int nPane, LPCTSTR lpszText, int nType = 0) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(nPane < 256); - return (BOOL)::SendMessage(m_hWnd, SB_SETTEXT, (nPane | nType), (LPARAM)lpszText); - } - - BOOL GetRect(int nPane, LPRECT lpRect) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(nPane < 256); - return (BOOL)::SendMessage(m_hWnd, SB_GETRECT, nPane, (LPARAM)lpRect); - } - - BOOL GetBorders(int* pBorders) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, SB_GETBORDERS, 0, (LPARAM)pBorders); - } - - BOOL GetBorders(int& nHorz, int& nVert, int& nSpacing) const - { - ATLASSERT(::IsWindow(m_hWnd)); - int borders[3] = { 0, 0, 0 }; - BOOL bResult = (BOOL)::SendMessage(m_hWnd, SB_GETBORDERS, 0, (LPARAM)&borders); - if(bResult) - { - nHorz = borders[0]; - nVert = borders[1]; - nSpacing = borders[2]; - } - return bResult; - } - - void SetMinHeight(int nMin) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, SB_SETMINHEIGHT, nMin, 0L); - } - - BOOL SetSimple(BOOL bSimple = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, SB_SIMPLE, bSimple, 0L); - } - - BOOL IsSimple() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, SB_ISSIMPLE, 0, 0L); - } - -#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) - BOOL GetUnicodeFormat() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, SB_GETUNICODEFORMAT, 0, 0L); - } - - BOOL SetUnicodeFormat(BOOL bUnicode = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, SB_SETUNICODEFORMAT, bUnicode, 0L); - } - - void GetTipText(int nPane, LPTSTR lpstrText, int nSize) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(nPane < 256); - ::SendMessage(m_hWnd, SB_GETTIPTEXT, MAKEWPARAM(nPane, nSize), (LPARAM)lpstrText); - } - - void SetTipText(int nPane, LPCTSTR lpstrText) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(nPane < 256); - ::SendMessage(m_hWnd, SB_SETTIPTEXT, nPane, (LPARAM)lpstrText); - } -#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) - -#if ((_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 0x0500)) - COLORREF SetBkColor(COLORREF clrBk) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, SB_SETBKCOLOR, 0, (LPARAM)clrBk); - } - - HICON GetIcon(int nPane) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(nPane < 256); - return (HICON)::SendMessage(m_hWnd, SB_GETICON, nPane, 0L); - } - - BOOL SetIcon(int nPane, HICON hIcon) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(nPane < 256); - return (BOOL)::SendMessage(m_hWnd, SB_SETICON, nPane, (LPARAM)hIcon); - } -#endif // ((_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 0x0500)) -}; - -typedef CStatusBarCtrlT CStatusBarCtrl; - - -/////////////////////////////////////////////////////////////////////////////// -// CTabCtrl - -template -class CTabCtrlT : public TBase -{ -public: -// Constructors - CTabCtrlT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CTabCtrlT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return WC_TABCONTROL; - } - - CImageList GetImageList() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TCM_GETIMAGELIST, 0, 0L)); - } - - CImageList SetImageList(HIMAGELIST hImageList) - { - ATLASSERT(::IsWindow(m_hWnd)); - return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TCM_SETIMAGELIST, 0, (LPARAM)hImageList)); - } - - int GetItemCount() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TCM_GETITEMCOUNT, 0, 0L); - } - - BOOL GetItem(int nItem, LPTCITEM pTabCtrlItem) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TCM_GETITEM, nItem, (LPARAM)pTabCtrlItem); - } - - BOOL SetItem(int nItem, LPTCITEM pTabCtrlItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TCM_SETITEM, nItem, (LPARAM)pTabCtrlItem); - } - - int SetItem(int nItem, UINT mask, LPCTSTR lpszItem, DWORD dwState, DWORD dwStateMask, int iImage, LPARAM lParam) - { - ATLASSERT(::IsWindow(m_hWnd)); - TCITEM tci = { 0 }; - tci.mask = mask; - tci.pszText = (LPTSTR) lpszItem; - tci.dwState = dwState; - tci.dwStateMask = dwStateMask; - tci.iImage = iImage; - tci.lParam = lParam; - return (int)::SendMessage(m_hWnd, TCM_SETITEM, nItem, (LPARAM)&tci); - } - - BOOL GetItemRect(int nItem, LPRECT lpRect) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TCM_GETITEMRECT, nItem, (LPARAM)lpRect); - } - - int GetCurSel() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TCM_GETCURSEL, 0, 0L); - } - - int SetCurSel(int nItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TCM_SETCURSEL, nItem, 0L); - } - - SIZE SetItemSize(SIZE size) - { - ATLASSERT(::IsWindow(m_hWnd)); - DWORD dwSize = (DWORD)::SendMessage(m_hWnd, TCM_SETITEMSIZE, 0, MAKELPARAM(size.cx, size.cy)); - SIZE sizeRet = { GET_X_LPARAM(dwSize), GET_Y_LPARAM(dwSize) }; - return sizeRet; - } - - void SetItemSize(int cx, int cy) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TCM_SETITEMSIZE, 0, MAKELPARAM(cx, cy)); - } - - void SetPadding(SIZE size) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TCM_SETPADDING, 0, MAKELPARAM(size.cx, size.cy)); - } - - int GetRowCount() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TCM_GETROWCOUNT, 0, 0L); - } - -#ifndef _WIN32_WCE - CToolTipCtrl GetTooltips() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return CToolTipCtrl((HWND)::SendMessage(m_hWnd, TCM_GETTOOLTIPS, 0, 0L)); - } - - void SetTooltips(HWND hWndToolTip) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TCM_SETTOOLTIPS, (WPARAM)hWndToolTip, 0L); - } -#endif // !_WIN32_WCE - - int GetCurFocus() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TCM_GETCURFOCUS, 0, 0L); - } - - void SetCurFocus(int nItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TCM_SETCURFOCUS, nItem, 0L); - } - - BOOL SetItemExtra(int cbExtra) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(GetItemCount() == 0); // must be empty - return (BOOL)::SendMessage(m_hWnd, TCM_SETITEMEXTRA, cbExtra, 0L); - } - - int SetMinTabWidth(int nWidth = -1) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TCM_SETMINTABWIDTH, 0, nWidth); - } - -#if (_WIN32_IE >= 0x0400) - DWORD GetExtendedStyle() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, TCM_GETEXTENDEDSTYLE, 0, 0L); - } - - DWORD SetExtendedStyle(DWORD dwExMask, DWORD dwExStyle) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, TCM_SETEXTENDEDSTYLE, dwExMask, dwExStyle); - } - -#ifndef _WIN32_WCE - BOOL GetUnicodeFormat() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TCM_GETUNICODEFORMAT, 0, 0L); - } - - BOOL SetUnicodeFormat(BOOL bUnicode = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TCM_SETUNICODEFORMAT, bUnicode, 0L); - } -#endif // !_WIN32_WCE -#endif // (_WIN32_IE >= 0x0400) - -// Operations - int InsertItem(int nItem, LPTCITEM pTabCtrlItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TCM_INSERTITEM, nItem, (LPARAM)pTabCtrlItem); - } - - int InsertItem(int nItem, UINT mask, LPCTSTR lpszItem, int iImage, LPARAM lParam) - { - ATLASSERT(::IsWindow(m_hWnd)); - TCITEM tci = { 0 }; - tci.mask = mask; - tci.pszText = (LPTSTR) lpszItem; - tci.iImage = iImage; - tci.lParam = lParam; - return (int)::SendMessage(m_hWnd, TCM_INSERTITEM, nItem, (LPARAM)&tci); - } - - int InsertItem(int nItem, LPCTSTR lpszItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - TCITEM tci = { 0 }; - tci.mask = TCIF_TEXT; - tci.pszText = (LPTSTR) lpszItem; - return (int)::SendMessage(m_hWnd, TCM_INSERTITEM, nItem, (LPARAM)&tci); - } - - int AddItem(LPTCITEM pTabCtrlItem) - { - return InsertItem(GetItemCount(), pTabCtrlItem); - } - - int AddItem(UINT mask, LPCTSTR lpszItem, int iImage, LPARAM lParam) - { - return InsertItem(GetItemCount(), mask, lpszItem, iImage, lParam); - } - - int AddItem(LPCTSTR lpszItem) - { - return InsertItem(GetItemCount(), lpszItem); - } - - BOOL DeleteItem(int nItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TCM_DELETEITEM, nItem, 0L); - } - - BOOL DeleteAllItems() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TCM_DELETEALLITEMS, 0, 0L); - } - - void AdjustRect(BOOL bLarger, LPRECT lpRect) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TCM_ADJUSTRECT, bLarger, (LPARAM)lpRect); - } - - void RemoveImage(int nImage) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TCM_REMOVEIMAGE, nImage, 0L); - } - - int HitTest(TC_HITTESTINFO* pHitTestInfo) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TCM_HITTEST, 0, (LPARAM)pHitTestInfo); - } - - void DeselectAll(BOOL bExcludeFocus = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TCM_DESELECTALL, bExcludeFocus, 0L); - } - -#if (_WIN32_IE >= 0x0400) - BOOL HighlightItem(int nIndex, BOOL bHighlight = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TCM_HIGHLIGHTITEM, nIndex, MAKELPARAM(bHighlight, 0)); - } -#endif // (_WIN32_IE >= 0x0400) -}; - -typedef CTabCtrlT CTabCtrl; - - -/////////////////////////////////////////////////////////////////////////////// -// CTrackBarCtrl - -template -class CTrackBarCtrlT : public TBase -{ -public: -// Constructors - CTrackBarCtrlT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CTrackBarCtrlT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return TRACKBAR_CLASS; - } - - int GetLineSize() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TBM_GETLINESIZE, 0, 0L); - } - - int SetLineSize(int nSize) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TBM_SETLINESIZE, 0, nSize); - } - - int GetPageSize() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TBM_GETPAGESIZE, 0, 0L); - } - - int SetPageSize(int nSize) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TBM_SETPAGESIZE, 0, nSize); - } - - int GetRangeMin() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TBM_GETRANGEMIN, 0, 0L); - } - - void SetRangeMin(int nMin, BOOL bRedraw = FALSE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TBM_SETRANGEMIN, bRedraw, nMin); - } - - int GetRangeMax() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TBM_GETRANGEMAX, 0, 0L); - } - - void SetRangeMax(int nMax, BOOL bRedraw = FALSE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TBM_SETRANGEMAX, bRedraw, nMax); - } - - void GetRange(int& nMin, int& nMax) const - { - nMin = GetRangeMin(); - nMax = GetRangeMax(); - } - - void SetRange(int nMin, int nMax, BOOL bRedraw = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TBM_SETRANGE, bRedraw, MAKELPARAM(nMin, nMax)); - } - - int GetSelStart() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TBM_GETSELSTART, 0, 0L); - } - - void SetSelStart(int nMin) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TBM_SETSELSTART, 0, (LPARAM)nMin); - } - - int GetSelEnd() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TBM_GETSELEND, 0, 0L); - } - - void SetSelEnd(int nMax) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TBM_SETSELEND, 0, (LPARAM)nMax); - } - - void GetSelection(int& nMin, int& nMax) const - { - nMin = GetSelStart(); - nMax = GetSelEnd(); - } - - void SetSelection(int nMin, int nMax) - { - SetSelStart(nMin); - SetSelEnd(nMax); - } - - void GetChannelRect(LPRECT lprc) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TBM_GETCHANNELRECT, 0, (LPARAM)lprc); - } - - void GetThumbRect(LPRECT lprc) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TBM_GETTHUMBRECT, 0, (LPARAM)lprc); - } - - int GetPos() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TBM_GETPOS, 0, 0L); - } - - void SetPos(int nPos) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TBM_SETPOS, TRUE, nPos); - } - - UINT GetNumTics() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::SendMessage(m_hWnd, TBM_GETNUMTICS, 0, 0L); - } - - DWORD* GetTicArray() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD*)::SendMessage(m_hWnd, TBM_GETPTICS, 0, 0L); - } - - int GetTic(int nTic) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TBM_GETTIC, nTic, 0L); - } - - BOOL SetTic(int nTic) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TBM_SETTIC, 0, nTic); - } - - int GetTicPos(int nTic) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TBM_GETTICPOS, nTic, 0L); - } - - void SetTicFreq(int nFreq) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TBM_SETTICFREQ, nFreq, 0L); - } - - int GetThumbLength() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TBM_GETTHUMBLENGTH, 0, 0L); - } - - void SetThumbLength(int nLength) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TBM_SETTHUMBLENGTH, nLength, 0L); - } - - void SetSel(int nStart, int nEnd, BOOL bRedraw = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetStyle() & TBS_ENABLESELRANGE) != 0); - ::SendMessage(m_hWnd, TBM_SETSEL, bRedraw, MAKELPARAM(nStart, nEnd)); - } - - ATL::CWindow GetBuddy(BOOL bLeft = TRUE) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return ATL::CWindow((HWND)::SendMessage(m_hWnd, TBM_GETBUDDY, bLeft, 0L)); - } - - ATL::CWindow SetBuddy(HWND hWndBuddy, BOOL bLeft = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return ATL::CWindow((HWND)::SendMessage(m_hWnd, TBM_SETBUDDY, bLeft, (LPARAM)hWndBuddy)); - } - -#ifndef _WIN32_WCE - CToolTipCtrl GetToolTips() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return CToolTipCtrl((HWND)::SendMessage(m_hWnd, TBM_GETTOOLTIPS, 0, 0L)); - } - - void SetToolTips(HWND hWndTT) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TBM_SETTOOLTIPS, (WPARAM)hWndTT, 0L); - } - - int SetTipSide(int nSide) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, TBM_SETTIPSIDE, nSide, 0L); - } -#endif // !_WIN32_WCE - -#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) - BOOL GetUnicodeFormat() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TBM_GETUNICODEFORMAT, 0, 0L); - } - - BOOL SetUnicodeFormat(BOOL bUnicode = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, TBM_SETUNICODEFORMAT, bUnicode, 0L); - } -#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) - -// Operations - void ClearSel(BOOL bRedraw = FALSE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TBM_CLEARSEL, bRedraw, 0L); - } - - void VerifyPos() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TBM_SETPOS, FALSE, 0L); - } - - void ClearTics(BOOL bRedraw = FALSE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, TBM_CLEARTICS, bRedraw, 0L); - } -}; - -typedef CTrackBarCtrlT CTrackBarCtrl; - - -/////////////////////////////////////////////////////////////////////////////// -// CUpDownCtrl - -template -class CUpDownCtrlT : public TBase -{ -public: -// Constructors - CUpDownCtrlT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CUpDownCtrlT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return UPDOWN_CLASS; - } - - UINT GetAccel(int nAccel, UDACCEL* pAccel) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)LOWORD(::SendMessage(m_hWnd, UDM_GETACCEL, nAccel, (LPARAM)pAccel)); - } - - BOOL SetAccel(int nAccel, UDACCEL* pAccel) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)LOWORD(::SendMessage(m_hWnd, UDM_SETACCEL, nAccel, (LPARAM)pAccel)); - } - - UINT GetBase() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)LOWORD(::SendMessage(m_hWnd, UDM_GETBASE, 0, 0L)); - } - - int SetBase(int nBase) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, UDM_SETBASE, nBase, 0L); - } - - ATL::CWindow GetBuddy() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return ATL::CWindow((HWND)::SendMessage(m_hWnd, UDM_GETBUDDY, 0, 0L)); - } - - ATL::CWindow SetBuddy(HWND hWndBuddy) - { - ATLASSERT(::IsWindow(m_hWnd)); - return ATL::CWindow((HWND)::SendMessage(m_hWnd, UDM_SETBUDDY, (WPARAM)hWndBuddy, 0L)); - } - - int GetPos(LPBOOL lpbError = NULL) const - { - ATLASSERT(::IsWindow(m_hWnd)); - DWORD dwRet = (DWORD)::SendMessage(m_hWnd, UDM_GETPOS, 0, 0L); - // Note: Seems that Windows always sets error to TRUE if - // UDS_SETBUDDYINT style is not used - if(lpbError != NULL) - *lpbError = (HIWORD(dwRet) != 0) ? TRUE : FALSE; - return (int)(short)LOWORD(dwRet); - } - - int SetPos(int nPos) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)(short)LOWORD(::SendMessage(m_hWnd, UDM_SETPOS, 0, MAKELPARAM(nPos, 0))); - } - - DWORD GetRange() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, UDM_GETRANGE, 0, 0L); - } - - void GetRange(int& nLower, int& nUpper) const - { - ATLASSERT(::IsWindow(m_hWnd)); - DWORD dwRet = (DWORD)::SendMessage(m_hWnd, UDM_GETRANGE, 0, 0L); - nLower = (int)(short)HIWORD(dwRet); - nUpper = (int)(short)LOWORD(dwRet); - } - - void SetRange(int nLower, int nUpper) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, UDM_SETRANGE, 0, MAKELPARAM(nUpper, nLower)); - } - -#if (_WIN32_IE >= 0x0400) - void SetRange32(int nLower, int nUpper) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, UDM_SETRANGE32, nLower, nUpper); - } - - void GetRange32(int& nLower, int& nUpper) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, UDM_GETRANGE32, (WPARAM)&nLower, (LPARAM)&nUpper); - } - -#ifndef _WIN32_WCE - BOOL GetUnicodeFormat() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, UDM_GETUNICODEFORMAT, 0, 0L); - } - - BOOL SetUnicodeFormat(BOOL bUnicode = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, UDM_SETUNICODEFORMAT, bUnicode, 0L); - } -#endif // !_WIN32_WCE -#endif // (_WIN32_IE >= 0x0400) - -#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) - int GetPos32(LPBOOL lpbError = NULL) const - { - ATLASSERT(::IsWindow(m_hWnd)); - // Note: Seems that Windows always sets error to TRUE if - // UDS_SETBUDDYINT style is not used - return (int)::SendMessage(m_hWnd, UDM_GETPOS32, 0, (LPARAM)lpbError); - } - - int SetPos32(int nPos) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, UDM_SETPOS32, 0, (LPARAM)nPos); - } -#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) -}; - -typedef CUpDownCtrlT CUpDownCtrl; - - -/////////////////////////////////////////////////////////////////////////////// -// CProgressBarCtrl - -template -class CProgressBarCtrlT : public TBase -{ -public: -// Constructors - CProgressBarCtrlT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CProgressBarCtrlT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return PROGRESS_CLASS; - } - - DWORD SetRange(int nLower, int nUpper) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, PBM_SETRANGE, 0, MAKELPARAM(nLower, nUpper)); - } - - int SetPos(int nPos) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)(short)LOWORD(::SendMessage(m_hWnd, PBM_SETPOS, nPos, 0L)); - } - - int OffsetPos(int nPos) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)(short)LOWORD(::SendMessage(m_hWnd, PBM_DELTAPOS, nPos, 0L)); - } - - int SetStep(int nStep) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)(short)LOWORD(::SendMessage(m_hWnd, PBM_SETSTEP, nStep, 0L)); - } - - UINT GetPos() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::SendMessage(m_hWnd, PBM_GETPOS, 0, 0L); - } - - void GetRange(PPBRANGE pPBRange) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(pPBRange != NULL); - ::SendMessage(m_hWnd, PBM_GETRANGE, TRUE, (LPARAM)pPBRange); - } - - void GetRange(int& nLower, int& nUpper) const - { - ATLASSERT(::IsWindow(m_hWnd)); - PBRANGE range = { 0 }; - ::SendMessage(m_hWnd, PBM_GETRANGE, TRUE, (LPARAM)&range); - nLower = range.iLow; - nUpper = range.iHigh; - } - - int GetRangeLimit(BOOL bLowLimit) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, PBM_GETRANGE, bLowLimit, (LPARAM)NULL); - } - - DWORD SetRange32(int nMin, int nMax) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, PBM_SETRANGE32, nMin, nMax); - } - -#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) - COLORREF SetBarColor(COLORREF clr) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, PBM_SETBARCOLOR, 0, (LPARAM)clr); - } - - COLORREF SetBkColor(COLORREF clr) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, PBM_SETBKCOLOR, 0, (LPARAM)clr); - } -#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) - -#if (_WIN32_WINNT >= 0x0501) && defined(PBM_SETMARQUEE) - BOOL SetMarquee(BOOL bMarquee, UINT uUpdateTime = 0U) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, PBM_SETMARQUEE, (WPARAM)bMarquee, (LPARAM)uUpdateTime); - } -#endif // (_WIN32_WINNT >= 0x0501) && defined(PBM_SETMARQUEE) - -#if (_WIN32_WINNT >= 0x0600) - int GetStep() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, PBM_GETSTEP, 0, 0L); - } - - COLORREF GetBkColor() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, PBM_GETBKCOLOR, 0, 0L); - } - - COLORREF GetBarColor() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, PBM_GETBARCOLOR, 0, 0L); - } - - int GetState() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, PBM_GETSTATE, 0, 0L); - } - - int SetState(int nState) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, PBM_SETSTATE, nState, 0L); - } -#endif // (_WIN32_WINNT >= 0x0600) - -// Operations - int StepIt() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)(short)LOWORD(::SendMessage(m_hWnd, PBM_STEPIT, 0, 0L)); - } -}; - -typedef CProgressBarCtrlT CProgressBarCtrl; - - -/////////////////////////////////////////////////////////////////////////////// -// CHotKeyCtrl - -#ifndef _WIN32_WCE - -template -class CHotKeyCtrlT : public TBase -{ -public: -// Constructors - CHotKeyCtrlT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CHotKeyCtrlT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return HOTKEY_CLASS; - } - - DWORD GetHotKey() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, HKM_GETHOTKEY, 0, 0L); - } - - void GetHotKey(WORD &wVirtualKeyCode, WORD &wModifiers) const - { - ATLASSERT(::IsWindow(m_hWnd)); - DWORD dw = (DWORD)::SendMessage(m_hWnd, HKM_GETHOTKEY, 0, 0L); - wVirtualKeyCode = LOBYTE(LOWORD(dw)); - wModifiers = HIBYTE(LOWORD(dw)); - } - - void SetHotKey(WORD wVirtualKeyCode, WORD wModifiers) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, HKM_SETHOTKEY, MAKEWORD(wVirtualKeyCode, wModifiers), 0L); - } - - void SetRules(WORD wInvalidComb, WORD wModifiers) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, HKM_SETRULES, wInvalidComb, MAKELPARAM(wModifiers, 0)); - } -}; - -typedef CHotKeyCtrlT CHotKeyCtrl; - -#endif // !_WIN32_WCE - - -/////////////////////////////////////////////////////////////////////////////// -// CAnimateCtrl - -#ifndef _WIN32_WCE - -template -class CAnimateCtrlT : public TBase -{ -public: -// Constructors - CAnimateCtrlT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CAnimateCtrlT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return ANIMATE_CLASS; - } - -// Operations - BOOL Open(ATL::_U_STRINGorID FileName) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, ACM_OPEN, 0, (LPARAM)FileName.m_lpstr); - } - - BOOL Play(UINT nFrom, UINT nTo, UINT nRep) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, ACM_PLAY, nRep, MAKELPARAM(nFrom, nTo)); - } - - BOOL Stop() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, ACM_STOP, 0, 0L); - } - - BOOL Close() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, ACM_OPEN, 0, 0L); - } - - BOOL Seek(UINT nTo) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, ACM_PLAY, 0, MAKELPARAM(nTo, nTo)); - } - - // Vista only - BOOL IsPlaying() const - { -#ifndef ACM_ISPLAYING - const UINT ACM_ISPLAYING = (WM_USER+104); -#endif - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, ACM_ISPLAYING, 0, 0L); - } -}; - -typedef CAnimateCtrlT CAnimateCtrl; - -#endif // !_WIN32_WCE - - -/////////////////////////////////////////////////////////////////////////////// -// CRichEditCtrl - -#ifndef _WIN32_WCE - -#ifdef _UNICODE -#if (_RICHEDIT_VER == 0x0100) -#undef RICHEDIT_CLASS -#define RICHEDIT_CLASS L"RICHEDIT" -#endif // (_RICHEDIT_VER == 0x0100) -#endif // _UNICODE - -template -class CRichEditCtrlT : public TBase -{ -public: -// Constructors - CRichEditCtrlT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CRichEditCtrlT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return RICHEDIT_CLASS; - } - - static LPCTSTR GetLibraryName() - { -#if (_RICHEDIT_VER >= 0x0200) - return _T("RICHED20.DLL"); -#else - return _T("RICHED32.DLL"); -#endif - } - - int GetLineCount() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, EM_GETLINECOUNT, 0, 0L); - } - - BOOL GetModify() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_GETMODIFY, 0, 0L); - } - - void SetModify(BOOL bModified = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_SETMODIFY, bModified, 0L); - } - - void GetRect(LPRECT lpRect) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_GETRECT, 0, (LPARAM)lpRect); - } - - DWORD GetOptions() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, EM_GETOPTIONS, 0, 0L); - } - - DWORD SetOptions(WORD wOperation, DWORD dwOptions) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, EM_SETOPTIONS, wOperation, dwOptions); - } - - // NOTE: first word in lpszBuffer must contain the size of the buffer! - int GetLine(int nIndex, LPTSTR lpszBuffer) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, EM_GETLINE, nIndex, (LPARAM)lpszBuffer); - } - - int GetLine(int nIndex, LPTSTR lpszBuffer, int nMaxLength) const - { - ATLASSERT(::IsWindow(m_hWnd)); - *(LPWORD)lpszBuffer = (WORD)nMaxLength; - return (int)::SendMessage(m_hWnd, EM_GETLINE, nIndex, (LPARAM)lpszBuffer); - } - - BOOL CanUndo() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_CANUNDO, 0, 0L); - } - - BOOL CanPaste(UINT nFormat = 0) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_CANPASTE, nFormat, 0L); - } - - void GetSel(LONG& nStartChar, LONG& nEndChar) const - { - ATLASSERT(::IsWindow(m_hWnd)); - CHARRANGE cr = { 0, 0 }; - ::SendMessage(m_hWnd, EM_EXGETSEL, 0, (LPARAM)&cr); - nStartChar = cr.cpMin; - nEndChar = cr.cpMax; - } - - void GetSel(CHARRANGE &cr) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_EXGETSEL, 0, (LPARAM)&cr); - } - - int SetSel(LONG nStartChar, LONG nEndChar) - { - ATLASSERT(::IsWindow(m_hWnd)); - CHARRANGE cr = { nStartChar, nEndChar }; - return (int)::SendMessage(m_hWnd, EM_EXSETSEL, 0, (LPARAM)&cr); - } - - int SetSel(CHARRANGE &cr) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, EM_EXSETSEL, 0, (LPARAM)&cr); - } - - int SetSelAll() - { - return SetSel(0, -1); - } - - int SetSelNone() - { - return SetSel(-1, 0); - } - - DWORD GetDefaultCharFormat(CHARFORMAT& cf) const - { - ATLASSERT(::IsWindow(m_hWnd)); - cf.cbSize = sizeof(CHARFORMAT); - return (DWORD)::SendMessage(m_hWnd, EM_GETCHARFORMAT, 0, (LPARAM)&cf); - } - - DWORD GetSelectionCharFormat(CHARFORMAT& cf) const - { - ATLASSERT(::IsWindow(m_hWnd)); - cf.cbSize = sizeof(CHARFORMAT); - return (DWORD)::SendMessage(m_hWnd, EM_GETCHARFORMAT, 1, (LPARAM)&cf); - } - - DWORD GetEventMask() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, EM_GETEVENTMASK, 0, 0L); - } - - LONG GetLimitText() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (LONG)::SendMessage(m_hWnd, EM_GETLIMITTEXT, 0, 0L); - } - - DWORD GetParaFormat(PARAFORMAT& pf) const - { - ATLASSERT(::IsWindow(m_hWnd)); - pf.cbSize = sizeof(PARAFORMAT); - return (DWORD)::SendMessage(m_hWnd, EM_GETPARAFORMAT, 0, (LPARAM)&pf); - } - -#if (_RICHEDIT_VER >= 0x0200) - LONG GetSelText(LPTSTR lpstrBuff) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (LONG)::SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpstrBuff); - } -#else // !(_RICHEDIT_VER >= 0x0200) - // RichEdit 1.0 EM_GETSELTEXT is ANSI only - LONG GetSelText(LPSTR lpstrBuff) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (LONG)::SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpstrBuff); - } -#endif // !(_RICHEDIT_VER >= 0x0200) - -#ifndef _ATL_NO_COM - BOOL GetSelTextBSTR(BSTR& bstrText) const - { - USES_CONVERSION; - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(bstrText == NULL); - - CHARRANGE cr = { 0, 0 }; - ::SendMessage(m_hWnd, EM_EXGETSEL, 0, (LPARAM)&cr); - -#if (_RICHEDIT_VER >= 0x0200) - CTempBuffer buff; - LPTSTR lpstrText = buff.Allocate(cr.cpMax - cr.cpMin + 1); - if(lpstrText == NULL) - return FALSE; - if(::SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpstrText) == 0) - return FALSE; - - bstrText = ::SysAllocString(T2W(lpstrText)); -#else // !(_RICHEDIT_VER >= 0x0200) - CTempBuffer buff; - LPSTR lpstrText = buff.Allocate(cr.cpMax - cr.cpMin + 1); - if(lpstrText == NULL) - return FALSE; - if(::SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpstrText) == 0) - return FALSE; - - bstrText = ::SysAllocString(A2W(lpstrText)); -#endif // !(_RICHEDIT_VER >= 0x0200) - - return (bstrText != NULL) ? TRUE : FALSE; - } -#endif // !_ATL_NO_COM - -#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - LONG GetSelText(_CSTRING_NS::CString& strText) const - { - ATLASSERT(::IsWindow(m_hWnd)); - - CHARRANGE cr = { 0, 0 }; - ::SendMessage(m_hWnd, EM_EXGETSEL, 0, (LPARAM)&cr); - -#if (_RICHEDIT_VER >= 0x0200) - LONG lLen = 0; - LPTSTR lpstrText = strText.GetBufferSetLength(cr.cpMax - cr.cpMin); - if(lpstrText != NULL) - { - lLen = (LONG)::SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpstrText); - strText.ReleaseBuffer(); - } -#else // !(_RICHEDIT_VER >= 0x0200) - CTempBuffer buff; - LPSTR lpstrText = buff.Allocate(cr.cpMax - cr.cpMin + 1); - if(lpstrText == NULL) - return 0; - LONG lLen = (LONG)::SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpstrText); - if(lLen == 0) - return 0; - - USES_CONVERSION; - strText = A2T(lpstrText); -#endif // !(_RICHEDIT_VER >= 0x0200) - - return lLen; - } -#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - - WORD GetSelectionType() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (WORD)::SendMessage(m_hWnd, EM_SELECTIONTYPE, 0, 0L); - } - - COLORREF SetBackgroundColor(COLORREF cr) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, EM_SETBKGNDCOLOR, 0, cr); - } - - COLORREF SetBackgroundColor() // sets to system background - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, EM_SETBKGNDCOLOR, 1, 0); - } - - BOOL SetCharFormat(CHARFORMAT& cf, WORD wFlags) - { - ATLASSERT(::IsWindow(m_hWnd)); - cf.cbSize = sizeof(CHARFORMAT); - return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, (WPARAM)wFlags, (LPARAM)&cf); - } - - BOOL SetDefaultCharFormat(CHARFORMAT& cf) - { - ATLASSERT(::IsWindow(m_hWnd)); - cf.cbSize = sizeof(CHARFORMAT); - return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, 0, (LPARAM)&cf); - } - - BOOL SetSelectionCharFormat(CHARFORMAT& cf) - { - ATLASSERT(::IsWindow(m_hWnd)); - cf.cbSize = sizeof(CHARFORMAT); - return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); - } - - BOOL SetWordCharFormat(CHARFORMAT& cf) - { - ATLASSERT(::IsWindow(m_hWnd)); - cf.cbSize = sizeof(CHARFORMAT); - return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, SCF_SELECTION | SCF_WORD, (LPARAM)&cf); - } - - DWORD SetEventMask(DWORD dwEventMask) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, EM_SETEVENTMASK, 0, dwEventMask); - } - - BOOL SetParaFormat(PARAFORMAT& pf) - { - ATLASSERT(::IsWindow(m_hWnd)); - pf.cbSize = sizeof(PARAFORMAT); - return (BOOL)::SendMessage(m_hWnd, EM_SETPARAFORMAT, 0, (LPARAM)&pf); - } - - BOOL SetTargetDevice(HDC hDC, int cxLineWidth) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_SETTARGETDEVICE, (WPARAM)hDC, cxLineWidth); - } - - int GetTextLength() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, WM_GETTEXTLENGTH, 0, 0L); - } - - BOOL SetReadOnly(BOOL bReadOnly = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_SETREADONLY, bReadOnly, 0L); - } - - int GetFirstVisibleLine() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, EM_GETFIRSTVISIBLELINE, 0, 0L); - } - - EDITWORDBREAKPROCEX GetWordBreakProcEx() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (EDITWORDBREAKPROCEX)::SendMessage(m_hWnd, EM_GETWORDBREAKPROCEX, 0, 0L); - } - - EDITWORDBREAKPROCEX SetWordBreakProcEx(EDITWORDBREAKPROCEX pfnEditWordBreakProcEx) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (EDITWORDBREAKPROCEX)::SendMessage(m_hWnd, EM_SETWORDBREAKPROCEX, 0, (LPARAM)pfnEditWordBreakProcEx); - } - - int GetTextRange(TEXTRANGE* pTextRange) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, EM_GETTEXTRANGE, 0, (LPARAM)pTextRange); - } - -#if (_RICHEDIT_VER >= 0x0200) - int GetTextRange(LONG nStartChar, LONG nEndChar, LPTSTR lpstrText) const - { - ATLASSERT(::IsWindow(m_hWnd)); - TEXTRANGE tr = { 0 }; - tr.chrg.cpMin = nStartChar; - tr.chrg.cpMax = nEndChar; - tr.lpstrText = lpstrText; - return (int)::SendMessage(m_hWnd, EM_GETTEXTRANGE, 0, (LPARAM)&tr); - } -#else // !(_RICHEDIT_VER >= 0x0200) - - int GetTextRange(LONG nStartChar, LONG nEndChar, LPSTR lpstrText) const - { - ATLASSERT(::IsWindow(m_hWnd)); - TEXTRANGE tr = { 0 }; - tr.chrg.cpMin = nStartChar; - tr.chrg.cpMax = nEndChar; - tr.lpstrText = lpstrText; - return (int)::SendMessage(m_hWnd, EM_GETTEXTRANGE, 0, (LPARAM)&tr); - } -#endif // !(_RICHEDIT_VER >= 0x0200) - -#if (_RICHEDIT_VER >= 0x0200) - DWORD GetDefaultCharFormat(CHARFORMAT2& cf) const - { - ATLASSERT(::IsWindow(m_hWnd)); - cf.cbSize = sizeof(CHARFORMAT2); - return (DWORD)::SendMessage(m_hWnd, EM_GETCHARFORMAT, 0, (LPARAM)&cf); - } - - BOOL SetCharFormat(CHARFORMAT2& cf, WORD wFlags) - { - ATLASSERT(::IsWindow(m_hWnd)); - cf.cbSize = sizeof(CHARFORMAT2); - return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, (WPARAM)wFlags, (LPARAM)&cf); - } - - BOOL SetDefaultCharFormat(CHARFORMAT2& cf) - { - ATLASSERT(::IsWindow(m_hWnd)); - cf.cbSize = sizeof(CHARFORMAT2); - return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, 0, (LPARAM)&cf); - } - - DWORD GetSelectionCharFormat(CHARFORMAT2& cf) const - { - ATLASSERT(::IsWindow(m_hWnd)); - cf.cbSize = sizeof(CHARFORMAT2); - return (DWORD)::SendMessage(m_hWnd, EM_GETCHARFORMAT, 1, (LPARAM)&cf); - } - - BOOL SetSelectionCharFormat(CHARFORMAT2& cf) - { - ATLASSERT(::IsWindow(m_hWnd)); - cf.cbSize = sizeof(CHARFORMAT2); - return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); - } - - BOOL SetWordCharFormat(CHARFORMAT2& cf) - { - ATLASSERT(::IsWindow(m_hWnd)); - cf.cbSize = sizeof(CHARFORMAT2); - return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, SCF_SELECTION | SCF_WORD, (LPARAM)&cf); - } - - DWORD GetParaFormat(PARAFORMAT2& pf) const - { - ATLASSERT(::IsWindow(m_hWnd)); - pf.cbSize = sizeof(PARAFORMAT2); - return (DWORD)::SendMessage(m_hWnd, EM_GETPARAFORMAT, 0, (LPARAM)&pf); - } - - BOOL SetParaFormat(PARAFORMAT2& pf) - { - ATLASSERT(::IsWindow(m_hWnd)); - pf.cbSize = sizeof(PARAFORMAT2); - return (BOOL)::SendMessage(m_hWnd, EM_SETPARAFORMAT, 0, (LPARAM)&pf); - } - - TEXTMODE GetTextMode() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (TEXTMODE)::SendMessage(m_hWnd, EM_GETTEXTMODE, 0, 0L); - } - - BOOL SetTextMode(TEXTMODE enumTextMode) - { - ATLASSERT(::IsWindow(m_hWnd)); - return !(BOOL)::SendMessage(m_hWnd, EM_SETTEXTMODE, enumTextMode, 0L); - } - - UNDONAMEID GetUndoName() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UNDONAMEID)::SendMessage(m_hWnd, EM_GETUNDONAME, 0, 0L); - } - - UNDONAMEID GetRedoName() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UNDONAMEID)::SendMessage(m_hWnd, EM_GETREDONAME, 0, 0L); - } - - BOOL CanRedo() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_CANREDO, 0, 0L); - } - - BOOL GetAutoURLDetect() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_GETAUTOURLDETECT, 0, 0L); - } - - BOOL SetAutoURLDetect(BOOL bAutoDetect = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return !(BOOL)::SendMessage(m_hWnd, EM_AUTOURLDETECT, bAutoDetect, 0L); - } - - // this method is deprecated, please use SetAutoURLDetect - BOOL EnableAutoURLDetect(BOOL bEnable = TRUE) { return SetAutoURLDetect(bEnable); } - - UINT SetUndoLimit(UINT uUndoLimit) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::SendMessage(m_hWnd, EM_SETUNDOLIMIT, uUndoLimit, 0L); - } - - void SetPalette(HPALETTE hPalette) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_SETPALETTE, (WPARAM)hPalette, 0L); - } - - int GetTextEx(GETTEXTEX* pGetTextEx, LPTSTR lpstrText) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, EM_GETTEXTEX, (WPARAM)pGetTextEx, (LPARAM)lpstrText); - } - - int GetTextEx(LPTSTR lpstrText, int nTextLen, DWORD dwFlags = GT_DEFAULT, UINT uCodePage = CP_ACP, LPCSTR lpDefaultChar = NULL, LPBOOL lpUsedDefChar = NULL) const - { - ATLASSERT(::IsWindow(m_hWnd)); - GETTEXTEX gte = { 0 }; - gte.cb = nTextLen * sizeof(TCHAR); - gte.codepage = uCodePage; - gte.flags = dwFlags; - gte.lpDefaultChar = lpDefaultChar; - gte.lpUsedDefChar = lpUsedDefChar; - return (int)::SendMessage(m_hWnd, EM_GETTEXTEX, (WPARAM)>e, (LPARAM)lpstrText); - } - - int GetTextLengthEx(GETTEXTLENGTHEX* pGetTextLengthEx) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, EM_GETTEXTLENGTHEX, (WPARAM)pGetTextLengthEx, 0L); - } - - int GetTextLengthEx(DWORD dwFlags = GTL_DEFAULT, UINT uCodePage = CP_ACP) const - { - ATLASSERT(::IsWindow(m_hWnd)); - GETTEXTLENGTHEX gtle = { 0 }; - gtle.codepage = uCodePage; - gtle.flags = dwFlags; - return (int)::SendMessage(m_hWnd, EM_GETTEXTLENGTHEX, (WPARAM)>le, 0L); - } -#endif // (_RICHEDIT_VER >= 0x0200) - -#if (_RICHEDIT_VER >= 0x0300) - int SetTextEx(SETTEXTEX* pSetTextEx, LPCTSTR lpstrText) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, EM_SETTEXTEX, (WPARAM)pSetTextEx, (LPARAM)lpstrText); - } - - int SetTextEx(LPCTSTR lpstrText, DWORD dwFlags = ST_DEFAULT, UINT uCodePage = CP_ACP) - { - ATLASSERT(::IsWindow(m_hWnd)); - SETTEXTEX ste = { 0 }; - ste.flags = dwFlags; - ste.codepage = uCodePage; - return (int)::SendMessage(m_hWnd, EM_SETTEXTEX, (WPARAM)&ste, (LPARAM)lpstrText); - } - - int GetEditStyle() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, EM_GETEDITSTYLE, 0, 0L); - } - - int SetEditStyle(int nStyle, int nMask = -1) - { - ATLASSERT(::IsWindow(m_hWnd)); - if(nMask == -1) - nMask = nStyle; // set everything specified - return (int)::SendMessage(m_hWnd, EM_SETEDITSTYLE, nStyle, nMask); - } - - BOOL SetFontSize(int nFontSizeDelta) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(nFontSizeDelta >= -1637 && nFontSizeDelta <= 1638); - return (BOOL)::SendMessage(m_hWnd, EM_SETFONTSIZE, nFontSizeDelta, 0L); - } - - void GetScrollPos(LPPOINT lpPoint) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(lpPoint != NULL); - ::SendMessage(m_hWnd, EM_GETSCROLLPOS, 0, (LPARAM)lpPoint); - } - - void SetScrollPos(LPPOINT lpPoint) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(lpPoint != NULL); - ::SendMessage(m_hWnd, EM_SETSCROLLPOS, 0, (LPARAM)lpPoint); - } - - BOOL GetZoom(int& nNum, int& nDen) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_GETZOOM, (WPARAM)&nNum, (LPARAM)&nDen); - } - - BOOL SetZoom(int nNum, int nDen) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(nNum >= 0 && nNum <= 64); - ATLASSERT(nDen >= 0 && nDen <= 64); - return (BOOL)::SendMessage(m_hWnd, EM_SETZOOM, nNum, nDen); - } - - BOOL SetZoomOff() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_SETZOOM, 0, 0L); - } -#endif // (_RICHEDIT_VER >= 0x0300) - -// Operations - void LimitText(LONG nChars = 0) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_EXLIMITTEXT, 0, nChars); - } - - int LineFromChar(LONG nIndex) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, EM_EXLINEFROMCHAR, 0, nIndex); - } - - POINT PosFromChar(LONG nChar) const - { - ATLASSERT(::IsWindow(m_hWnd)); - POINT point = { 0, 0 }; - ::SendMessage(m_hWnd, EM_POSFROMCHAR, (WPARAM)&point, nChar); - return point; - } - - int CharFromPos(POINT pt) const - { - ATLASSERT(::IsWindow(m_hWnd)); - POINTL ptl = { pt.x, pt.y }; - return (int)::SendMessage(m_hWnd, EM_CHARFROMPOS, 0, (LPARAM)&ptl); - } - - void EmptyUndoBuffer() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_EMPTYUNDOBUFFER, 0, 0L); - } - - int LineIndex(int nLine = -1) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, EM_LINEINDEX, nLine, 0L); - } - - int LineLength(int nLine = -1) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, EM_LINELENGTH, nLine, 0L); - } - - BOOL LineScroll(int nLines, int nChars = 0) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_LINESCROLL, nChars, nLines); - } - - void ReplaceSel(LPCTSTR lpszNewText, BOOL bCanUndo = FALSE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_REPLACESEL, (WPARAM) bCanUndo, (LPARAM)lpszNewText); - } - - void SetRect(LPCRECT lpRect) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_SETRECT, 0, (LPARAM)lpRect); - } - - BOOL DisplayBand(LPRECT pDisplayRect) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_DISPLAYBAND, 0, (LPARAM)pDisplayRect); - } - - LONG FindText(DWORD dwFlags, FINDTEXT& ft) const - { - ATLASSERT(::IsWindow(m_hWnd)); -#if (_RICHEDIT_VER >= 0x0200) && defined(_UNICODE) - return (LONG)::SendMessage(m_hWnd, EM_FINDTEXTW, dwFlags, (LPARAM)&ft); -#else - return (LONG)::SendMessage(m_hWnd, EM_FINDTEXT, dwFlags, (LPARAM)&ft); -#endif - } - - LONG FindText(DWORD dwFlags, FINDTEXTEX& ft) const - { - ATLASSERT(::IsWindow(m_hWnd)); -#if (_RICHEDIT_VER >= 0x0200) && defined(_UNICODE) - return (LONG)::SendMessage(m_hWnd, EM_FINDTEXTEXW, dwFlags, (LPARAM)&ft); -#else - return (LONG)::SendMessage(m_hWnd, EM_FINDTEXTEX, dwFlags, (LPARAM)&ft); -#endif - } - - LONG FormatRange(FORMATRANGE& fr, BOOL bDisplay = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (LONG)::SendMessage(m_hWnd, EM_FORMATRANGE, bDisplay, (LPARAM)&fr); - } - - LONG FormatRange(FORMATRANGE* pFormatRange, BOOL bDisplay = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (LONG)::SendMessage(m_hWnd, EM_FORMATRANGE, bDisplay, (LPARAM)pFormatRange); - } - - void HideSelection(BOOL bHide = TRUE, BOOL bChangeStyle = FALSE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_HIDESELECTION, bHide, bChangeStyle); - } - - void PasteSpecial(UINT uClipFormat, DWORD dwAspect = 0, HMETAFILE hMF = 0) - { - ATLASSERT(::IsWindow(m_hWnd)); - REPASTESPECIAL reps = { dwAspect, (DWORD_PTR)hMF }; - ::SendMessage(m_hWnd, EM_PASTESPECIAL, uClipFormat, (LPARAM)&reps); - } - - void RequestResize() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_REQUESTRESIZE, 0, 0L); - } - - LONG StreamIn(UINT uFormat, EDITSTREAM& es) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (LONG)::SendMessage(m_hWnd, EM_STREAMIN, uFormat, (LPARAM)&es); - } - - LONG StreamOut(UINT uFormat, EDITSTREAM& es) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (LONG)::SendMessage(m_hWnd, EM_STREAMOUT, uFormat, (LPARAM)&es); - } - - DWORD FindWordBreak(int nCode, LONG nStartChar) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, EM_FINDWORDBREAK, nCode, nStartChar); - } - - // Additional operations - void ScrollCaret() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_SCROLLCARET, 0, 0L); - } - - int InsertText(long nInsertAfterChar, LPCTSTR lpstrText, BOOL bCanUndo = FALSE) - { - int nRet = SetSel(nInsertAfterChar, nInsertAfterChar); - ReplaceSel(lpstrText, bCanUndo); - return nRet; - } - - int AppendText(LPCTSTR lpstrText, BOOL bCanUndo = FALSE) - { - return InsertText(GetWindowTextLength(), lpstrText, bCanUndo); - } - - // Clipboard operations - BOOL Undo() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_UNDO, 0, 0L); - } - - void Clear() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_CLEAR, 0, 0L); - } - - void Copy() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_COPY, 0, 0L); - } - - void Cut() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_CUT, 0, 0L); - } - - void Paste() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_PASTE, 0, 0L); - } - - // OLE support - IRichEditOle* GetOleInterface() const - { - ATLASSERT(::IsWindow(m_hWnd)); - IRichEditOle *pRichEditOle = NULL; - ::SendMessage(m_hWnd, EM_GETOLEINTERFACE, 0, (LPARAM)&pRichEditOle); - return pRichEditOle; - } - - BOOL SetOleCallback(IRichEditOleCallback* pCallback) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_SETOLECALLBACK, 0, (LPARAM)pCallback); - } - -#if (_RICHEDIT_VER >= 0x0200) - BOOL Redo() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_REDO, 0, 0L); - } - - void StopGroupTyping() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_STOPGROUPTYPING, 0, 0L); - } - - void ShowScrollBar(int nBarType, BOOL bVisible = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_SHOWSCROLLBAR, nBarType, bVisible); - } -#endif // (_RICHEDIT_VER >= 0x0200) - -#if (_RICHEDIT_VER >= 0x0300) - BOOL SetTabStops(int nTabStops, LPINT rgTabStops) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, nTabStops, (LPARAM)rgTabStops); - } - - BOOL SetTabStops() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, 0, 0L); - } - - BOOL SetTabStops(const int& cxEachStop) // takes an 'int' - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, 1, (LPARAM)(LPINT)&cxEachStop); - } -#endif // (_RICHEDIT_VER >= 0x0300) -}; - -typedef CRichEditCtrlT CRichEditCtrl; - -#endif // !_WIN32_WCE - - -/////////////////////////////////////////////////////////////////////////////// -// CRichEditCommands - message handlers for standard EDIT commands - -#ifndef _WIN32_WCE - -// Chain to CRichEditCommands message map. Your class must also derive from CRichEditCtrl. -// Example: -// class CMyRichEdit : public CWindowImpl, -// public CRichEditCommands -// { -// public: -// BEGIN_MSG_MAP(CMyRichEdit) -// // your handlers... -// CHAIN_MSG_MAP_ALT(CRichEditCommands, 1) -// END_MSG_MAP() -// // other stuff... -// }; - -template -class CRichEditCommands : public CEditCommands< T > -{ -public: - BEGIN_MSG_MAP(CRichEditCommands< T >) - ALT_MSG_MAP(1) - COMMAND_ID_HANDLER(ID_EDIT_CLEAR, CEditCommands< T >::OnEditClear) - COMMAND_ID_HANDLER(ID_EDIT_CLEAR_ALL, CEditCommands< T >::OnEditClearAll) - COMMAND_ID_HANDLER(ID_EDIT_COPY, CEditCommands< T >::OnEditCopy) - COMMAND_ID_HANDLER(ID_EDIT_CUT, CEditCommands< T >::OnEditCut) - COMMAND_ID_HANDLER(ID_EDIT_PASTE, CEditCommands< T >::OnEditPaste) - COMMAND_ID_HANDLER(ID_EDIT_SELECT_ALL, CEditCommands< T >::OnEditSelectAll) - COMMAND_ID_HANDLER(ID_EDIT_UNDO, CEditCommands< T >::OnEditUndo) -#if (_RICHEDIT_VER >= 0x0200) - COMMAND_ID_HANDLER(ID_EDIT_REDO, OnEditRedo) -#endif // (_RICHEDIT_VER >= 0x0200) - END_MSG_MAP() - -#if (_RICHEDIT_VER >= 0x0200) - LRESULT OnEditRedo(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - pT->Redo(); - return 0; - } -#endif // (_RICHEDIT_VER >= 0x0200) - -// State (update UI) helpers - BOOL CanCut() const - { return HasSelection(); } - - BOOL CanCopy() const - { return HasSelection(); } - - BOOL CanClear() const - { return HasSelection(); } - -// Implementation - BOOL HasSelection() const - { - const T* pT = static_cast(this); - return (pT->GetSelectionType() != SEL_EMPTY); - } -}; - -#endif // _WIN32_WCE - - -/////////////////////////////////////////////////////////////////////////////// -// CDragListBox - -#ifndef _WIN32_WCE - -template -class CDragListBoxT : public CListBoxT< TBase > -{ -public: -// Constructors - CDragListBoxT(HWND hWnd = NULL) : CListBoxT< TBase >(hWnd) - { } - - CDragListBoxT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - HWND hWnd = TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - if(hWnd != NULL) - MakeDragList(); - return hWnd; - } - -// Operations - BOOL MakeDragList() - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) == 0); - return ::MakeDragList(m_hWnd); - } - - int LBItemFromPt(POINT pt, BOOL bAutoScroll = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::LBItemFromPt(m_hWnd, pt, bAutoScroll); - } - - void DrawInsert(int nItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::DrawInsert(GetParent(), m_hWnd, nItem); - } - - static UINT GetDragListMessage() - { - static UINT uDragListMessage = 0; - if(uDragListMessage == 0) - { - CStaticDataInitCriticalSectionLock lock; - if(FAILED(lock.Lock())) - { - ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CDragListBox::GetDragListMessage.\n")); - ATLASSERT(FALSE); - return 0; - } - - if(uDragListMessage == 0) - uDragListMessage = ::RegisterWindowMessage(DRAGLISTMSGSTRING); - - lock.Unlock(); - } - ATLASSERT(uDragListMessage != 0); - return uDragListMessage; - } -}; - -typedef CDragListBoxT CDragListBox; - -template -class CDragListNotifyImpl -{ -public: - BEGIN_MSG_MAP(CDragListNotifyImpl< T >) - MESSAGE_HANDLER(CDragListBox::GetDragListMessage(), OnDragListNotify) - END_MSG_MAP() - - LRESULT OnDragListNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - uMsg; // avoid level 4 warning - ATLASSERT(uMsg == CDragListBox::GetDragListMessage()); - T* pT = static_cast(this); - LPDRAGLISTINFO lpDragListInfo = (LPDRAGLISTINFO)lParam; - LRESULT lRet = 0; - switch(lpDragListInfo->uNotification) - { - case DL_BEGINDRAG: - lRet = (LPARAM)pT->OnBeginDrag((int)wParam, lpDragListInfo->hWnd, lpDragListInfo->ptCursor); - break; - case DL_CANCELDRAG: - pT->OnCancelDrag((int)wParam, lpDragListInfo->hWnd, lpDragListInfo->ptCursor); - break; - case DL_DRAGGING: - lRet = (LPARAM)pT->OnDragging((int)wParam, lpDragListInfo->hWnd, lpDragListInfo->ptCursor); - break; - case DL_DROPPED: - pT->OnDropped((int)wParam, lpDragListInfo->hWnd, lpDragListInfo->ptCursor); - break; - default: - ATLTRACE2(atlTraceUI, 0, _T("Unknown DragListBox notification\n")); - bHandled = FALSE; // don't handle it - break; - } - return lRet; - } - -// Overrideables - BOOL OnBeginDrag(int /*nCtlID*/, HWND /*hWndDragList*/, POINT /*ptCursor*/) - { - return TRUE; // allow dragging - } - - void OnCancelDrag(int /*nCtlID*/, HWND /*hWndDragList*/, POINT /*ptCursor*/) - { - // nothing to do - } - - int OnDragging(int /*nCtlID*/, HWND /*hWndDragList*/, POINT /*ptCursor*/) - { - return 0; // don't change cursor - } - - void OnDropped(int /*nCtlID*/, HWND /*hWndDragList*/, POINT /*ptCursor*/) - { - // nothing to do - } -}; - -#endif // _WIN32_WCE - - -/////////////////////////////////////////////////////////////////////////////// -// CReBarCtrl - -template -class CReBarCtrlT : public TBase -{ -public: -// Constructors - CReBarCtrlT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CReBarCtrlT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return REBARCLASSNAME; - } - - UINT GetBandCount() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::SendMessage(m_hWnd, RB_GETBANDCOUNT, 0, 0L); - } - - BOOL GetBandInfo(int nBand, LPREBARBANDINFO lprbbi) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, RB_GETBANDINFO, nBand, (LPARAM)lprbbi); - } - - BOOL SetBandInfo(int nBand, LPREBARBANDINFO lprbbi) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, RB_SETBANDINFO, nBand, (LPARAM)lprbbi); - } - - BOOL GetBarInfo(LPREBARINFO lprbi) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, RB_GETBARINFO, 0, (LPARAM)lprbi); - } - - BOOL SetBarInfo(LPREBARINFO lprbi) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, RB_SETBARINFO, 0, (LPARAM)lprbi); - } - - CImageList GetImageList() const - { - ATLASSERT(::IsWindow(m_hWnd)); - REBARINFO rbi = { 0 }; - rbi.cbSize = sizeof(REBARINFO); - rbi.fMask = RBIM_IMAGELIST; - if( (BOOL)::SendMessage(m_hWnd, RB_GETBARINFO, 0, (LPARAM)&rbi) == FALSE ) return CImageList(); - return CImageList(rbi.himl); - } - - BOOL SetImageList(HIMAGELIST hImageList) - { - ATLASSERT(::IsWindow(m_hWnd)); - REBARINFO rbi = { 0 }; - rbi.cbSize = sizeof(REBARINFO); - rbi.fMask = RBIM_IMAGELIST; - rbi.himl = hImageList; - return (BOOL)::SendMessage(m_hWnd, RB_SETBARINFO, 0, (LPARAM)&rbi); - } - - UINT GetRowCount() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::SendMessage(m_hWnd, RB_GETROWCOUNT, 0, 0L); - } - - UINT GetRowHeight(int nBand) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::SendMessage(m_hWnd, RB_GETROWHEIGHT, nBand, 0L); - } - -#if (_WIN32_IE >= 0x0400) - COLORREF GetTextColor() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, RB_GETTEXTCOLOR, 0, 0L); - } - - COLORREF SetTextColor(COLORREF clr) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, RB_SETTEXTCOLOR, 0, (LPARAM)clr); - } - - COLORREF GetBkColor() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, RB_GETBKCOLOR, 0, 0L); - } - - COLORREF SetBkColor(COLORREF clr) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, RB_SETBKCOLOR, 0, (LPARAM)clr); - } - - UINT GetBarHeight() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::SendMessage(m_hWnd, RB_GETBARHEIGHT, 0, 0L); - } - - BOOL GetRect(int nBand, LPRECT lpRect) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, RB_GETRECT, nBand, (LPARAM)lpRect); - } - -#ifndef _WIN32_WCE - CToolTipCtrl GetToolTips() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return CToolTipCtrl((HWND)::SendMessage(m_hWnd, RB_GETTOOLTIPS, 0, 0L)); - } - - void SetToolTips(HWND hwndToolTip) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, RB_SETTOOLTIPS, (WPARAM)hwndToolTip, 0L); - } -#endif // !_WIN32_WCE - - void GetBandBorders(int nBand, LPRECT lpRect) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(lpRect != NULL); - ::SendMessage(m_hWnd, RB_GETBANDBORDERS, nBand, (LPARAM)lpRect); - } - -#ifndef _WIN32_WCE - BOOL GetColorScheme(LPCOLORSCHEME lpColorScheme) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(lpColorScheme != NULL); - return (BOOL)::SendMessage(m_hWnd, RB_GETCOLORSCHEME, 0, (LPARAM)lpColorScheme); - } - - void SetColorScheme(LPCOLORSCHEME lpColorScheme) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(lpColorScheme != NULL); - ::SendMessage(m_hWnd, RB_SETCOLORSCHEME, 0, (LPARAM)lpColorScheme); - } - - HPALETTE GetPalette() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HPALETTE)::SendMessage(m_hWnd, RB_GETPALETTE, 0, 0L); - } - - HPALETTE SetPalette(HPALETTE hPalette) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HPALETTE)::SendMessage(m_hWnd, RB_SETPALETTE, 0, (LPARAM)hPalette); - } - - BOOL GetUnicodeFormat() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, RB_GETUNICODEFORMAT, 0, 0L); - } - - BOOL SetUnicodeFormat(BOOL bUnicode = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, RB_SETUNICODEFORMAT, bUnicode, 0L); - } -#endif // !_WIN32_WCE -#endif // (_WIN32_IE >= 0x0400) - -#if (_WIN32_WINNT >= 0x0501) - // requires uxtheme.h to be included to use MARGINS struct -#ifndef _UXTHEME_H_ - typedef struct _MARGINS* PMARGINS; -#endif // !_UXTHEME_H_ - void GetBandMargins(PMARGINS pMargins) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, RB_GETBANDMARGINS, 0, (LPARAM)pMargins); - } - - void SetWindowTheme(LPCWSTR lpstrTheme) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, RB_SETWINDOWTHEME, 0, (LPARAM)lpstrTheme); - } -#endif // (_WIN32_WINNT >= 0x0501) - -#if (_WIN32_IE >= 0x0600) - DWORD GetExtendedStyle() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, RB_GETEXTENDEDSTYLE, 0, 0L); - } - - DWORD SetExtendedStyle(DWORD dwStyle, DWORD dwMask) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, RB_SETEXTENDEDSTYLE, dwMask, dwStyle); - } -#endif // (_WIN32_IE >= 0x0600) - -// Operations - BOOL InsertBand(int nBand, LPREBARBANDINFO lprbbi) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, RB_INSERTBAND, nBand, (LPARAM)lprbbi); - } - - BOOL AddBand(LPREBARBANDINFO lprbbi) - { - return InsertBand(-1, lprbbi); - } - - BOOL DeleteBand(int nBand) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, RB_DELETEBAND, nBand, 0L); - } - - ATL::CWindow SetNotifyWnd(HWND hWnd) - { - ATLASSERT(::IsWindow(m_hWnd)); - return ATL::CWindow((HWND)::SendMessage(m_hWnd, RB_SETPARENT, (WPARAM)hWnd, 0L)); - } - -#if (_WIN32_IE >= 0x0400) - void BeginDrag(int nBand, DWORD dwPos) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, RB_BEGINDRAG, nBand, dwPos); - } - - void BeginDrag(int nBand, int xPos, int yPos) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, RB_BEGINDRAG, nBand, MAKELPARAM(xPos, yPos)); - } - - void EndDrag() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, RB_ENDDRAG, 0, 0L); - } - - void DragMove(DWORD dwPos) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, RB_DRAGMOVE, 0, dwPos); - } - - void DragMove(int xPos, int yPos) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, RB_DRAGMOVE, 0, MAKELPARAM(xPos, yPos)); - } - -#ifndef _WIN32_WCE - void GetDropTarget(IDropTarget** ppDropTarget) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, RB_GETDROPTARGET, 0, (LPARAM)ppDropTarget); - } -#endif // !_WIN32_WCE - - void MaximizeBand(int nBand, BOOL bIdeal = FALSE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, RB_MAXIMIZEBAND, nBand, bIdeal); - } - - void MinimizeBand(int nBand) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, RB_MINIMIZEBAND, nBand, 0L); - } - - BOOL SizeToRect(LPRECT lpRect) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, RB_SIZETORECT, 0, (LPARAM)lpRect); - } - - int IdToIndex(UINT uBandID) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, RB_IDTOINDEX, uBandID, 0L); - } - - int HitTest(LPRBHITTESTINFO lprbht) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, RB_HITTEST, 0, (LPARAM)lprbht); - } - - BOOL ShowBand(int nBand, BOOL bShow) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, RB_SHOWBAND, nBand, bShow); - } - -#ifndef _WIN32_WCE - BOOL MoveBand(int nBand, int nNewPos) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(nNewPos >= 0 && nNewPos <= ((int)GetBandCount() - 1)); - return (BOOL)::SendMessage(m_hWnd, RB_MOVEBAND, nBand, nNewPos); - } -#endif // !_WIN32_WCE -#endif // (_WIN32_IE >= 0x0400) - -#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) - void PushChevron(int nBand, LPARAM lAppValue) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, RB_PUSHCHEVRON, nBand, lAppValue); - } -#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) - -// Extra operations -#if (_WIN32_IE >= 0x0400) - void LockBands(bool bLock) - { - int nBandCount = GetBandCount(); - for(int i =0; i < nBandCount; i++) - { - REBARBANDINFO rbbi = { RunTimeHelper::SizeOf_REBARBANDINFO() }; - rbbi.fMask = RBBIM_STYLE; - BOOL bRet = GetBandInfo(i, &rbbi); - ATLASSERT(bRet); - - if((rbbi.fStyle & RBBS_GRIPPERALWAYS) == 0) - { - rbbi.fStyle |= RBBS_GRIPPERALWAYS; - bRet = SetBandInfo(i, &rbbi); - ATLASSERT(bRet); - rbbi.fStyle &= ~RBBS_GRIPPERALWAYS; - } - - if(bLock) - rbbi.fStyle |= RBBS_NOGRIPPER; - else - rbbi.fStyle &= ~RBBS_NOGRIPPER; - - bRet = SetBandInfo(i, &rbbi); - ATLASSERT(bRet); - } - } -#endif // (_WIN32_IE >= 0x0400) - -#if (_WIN32_WINNT >= 0x0600) - BOOL SetBandWidth(int nBand, int cxWidth) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, RB_SETBANDWIDTH, nBand, cxWidth); - } -#endif // (_WIN32_WINNT >= 0x0600) -}; - -typedef CReBarCtrlT CReBarCtrl; - - -/////////////////////////////////////////////////////////////////////////////// -// CComboBoxEx - -#ifndef _WIN32_WCE - -template -class CComboBoxExT : public CComboBoxT< TBase > -{ -public: -// Constructors - CComboBoxExT(HWND hWnd = NULL) : CComboBoxT< TBase >(hWnd) - { } - - CComboBoxExT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return WC_COMBOBOXEX; - } - - CImageList GetImageList() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return CImageList((HIMAGELIST)::SendMessage(m_hWnd, CBEM_GETIMAGELIST, 0, 0L)); - } - - CImageList SetImageList(HIMAGELIST hImageList) - { - ATLASSERT(::IsWindow(m_hWnd)); - return CImageList((HIMAGELIST)::SendMessage(m_hWnd, CBEM_SETIMAGELIST, 0, (LPARAM)hImageList)); - } - -#if (_WIN32_IE >= 0x0400) - DWORD GetExtendedStyle() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, CBEM_GETEXTENDEDSTYLE, 0, 0L); - } - - DWORD SetExtendedStyle(DWORD dwExMask, DWORD dwExStyle) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, CBEM_SETEXTENDEDSTYLE, dwExMask, dwExStyle); - } - - BOOL GetUnicodeFormat() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, CBEM_GETUNICODEFORMAT, 0, 0L); - } - - BOOL SetUnicodeFormat(BOOL bUnicode = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, CBEM_SETUNICODEFORMAT, bUnicode, 0L); - } -#endif // (_WIN32_IE >= 0x0400) - -#if (_WIN32_WINNT >= 0x0501) - void SetWindowTheme(LPCWSTR lpstrTheme) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, CBEM_SETWINDOWTHEME, 0, (LPARAM)lpstrTheme); - } -#endif // (_WIN32_WINNT >= 0x0501) - -// Operations - int InsertItem(const COMBOBOXEXITEM* lpcCBItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, CBEM_INSERTITEM, 0, (LPARAM)lpcCBItem); - } - - int InsertItem(UINT nMask, int nIndex, LPCTSTR lpszItem, int nImage, int nSelImage, - int iIndent, int iOverlay, LPARAM lParam) - { - ATLASSERT(::IsWindow(m_hWnd)); - COMBOBOXEXITEM cbex = { 0 }; - cbex.mask = nMask; - cbex.iItem = nIndex; - cbex.pszText = (LPTSTR) lpszItem; - cbex.iImage = nImage; - cbex.iSelectedImage = nSelImage; - cbex.iIndent = iIndent; - cbex.iOverlay = iOverlay; - cbex.lParam = lParam; - return (int)::SendMessage(m_hWnd, CBEM_INSERTITEM, 0, (LPARAM)&cbex); - } - - int InsertItem(int nIndex, LPCTSTR lpszItem, int nImage, int nSelImage, int iIndent, LPARAM lParam = 0) - { - ATLASSERT(::IsWindow(m_hWnd)); - COMBOBOXEXITEM cbex = { 0 }; - cbex.mask = CBEIF_TEXT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE | CBEIF_INDENT | CBEIF_LPARAM; - cbex.iItem = nIndex; - cbex.pszText = (LPTSTR) lpszItem; - cbex.iImage = nImage; - cbex.iSelectedImage = nSelImage; - cbex.iIndent = iIndent; - cbex.lParam = lParam; - return (int)::SendMessage(m_hWnd, CBEM_INSERTITEM, 0, (LPARAM)&cbex); - } - - int AddItem(UINT nMask, LPCTSTR lpszItem, int nImage, int nSelImage, int iIndent, int iOverlay, LPARAM lParam) - { - return InsertItem(nMask, -1, lpszItem, nImage, nSelImage, iIndent, iOverlay, lParam); - } - - int AddItem(LPCTSTR lpszItem, int nImage, int nSelImage, int iIndent, LPARAM lParam = 0) - { - return InsertItem(-1, lpszItem, nImage, nSelImage, iIndent, lParam); - } - - int DeleteItem(int nIndex) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, CBEM_DELETEITEM, nIndex, 0L); - } - - BOOL GetItem(PCOMBOBOXEXITEM pCBItem) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, CBEM_GETITEM, 0, (LPARAM)pCBItem); - } - - BOOL SetItem(const COMBOBOXEXITEM* lpcCBItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, CBEM_SETITEM, 0, (LPARAM)lpcCBItem); - } - - int SetItem(int nIndex, UINT nMask, LPCTSTR lpszItem, int nImage, int nSelImage, - int iIndent, int iOverlay, LPARAM lParam) - { - ATLASSERT(::IsWindow(m_hWnd)); - COMBOBOXEXITEM cbex = { 0 }; - cbex.mask = nMask; - cbex.iItem = nIndex; - cbex.pszText = (LPTSTR) lpszItem; - cbex.iImage = nImage; - cbex.iSelectedImage = nSelImage; - cbex.iIndent = iIndent; - cbex.iOverlay = iOverlay; - cbex.lParam = lParam; - return (int)::SendMessage(m_hWnd, CBEM_SETITEM, 0, (LPARAM)&cbex); - } - - BOOL GetItemText(int nIndex, LPTSTR lpszItem, int nLen) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(lpszItem != NULL); - - COMBOBOXEXITEM cbex = { 0 }; - cbex.mask = CBEIF_TEXT; - cbex.iItem = nIndex; - cbex.pszText = lpszItem; - cbex.cchTextMax = nLen; - - return (BOOL)::SendMessage(m_hWnd, CBEM_GETITEM, 0, (LPARAM)&cbex); - } - -#ifndef _ATL_NO_COM - BOOL GetItemText(int nIndex, BSTR& bstrText) const - { - USES_CONVERSION; - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(bstrText == NULL); - - COMBOBOXEXITEM cbex = { 0 }; - cbex.mask = CBEIF_TEXT; - cbex.iItem = nIndex; - - LPTSTR lpstrText = NULL; - BOOL bRet = FALSE; - for(int nLen = 256; ; nLen *= 2) - { - ATLTRY(lpstrText = new TCHAR[nLen]); - if(lpstrText == NULL) - break; - lpstrText[0] = NULL; - cbex.pszText = lpstrText; - cbex.cchTextMax = nLen; - bRet = (BOOL)::SendMessage(m_hWnd, CBEM_GETITEM, 0, (LPARAM)&cbex); - if(!bRet || (lstrlen(cbex.pszText) < nLen - 1)) - break; - delete [] lpstrText; - lpstrText = NULL; - } - - if(lpstrText != NULL) - { - if(bRet) - bstrText = ::SysAllocString(T2OLE(lpstrText)); - delete [] lpstrText; - } - - return (bstrText != NULL) ? TRUE : FALSE; - } -#endif // !_ATL_NO_COM - -#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - BOOL GetItemText(int nIndex, _CSTRING_NS::CString& strText) const - { - ATLASSERT(::IsWindow(m_hWnd)); - - COMBOBOXEXITEM cbex = { 0 }; - cbex.mask = CBEIF_TEXT; - cbex.iItem = nIndex; - - strText.Empty(); - BOOL bRet = FALSE; - for(int nLen = 256; ; nLen *= 2) - { - cbex.pszText = strText.GetBufferSetLength(nLen); - if(cbex.pszText == NULL) - { - bRet = FALSE; - break; - } - cbex.cchTextMax = nLen; - bRet = (BOOL)::SendMessage(m_hWnd, CBEM_GETITEM, 0, (LPARAM)&cbex); - if(!bRet || (lstrlen(cbex.pszText) < nLen - 1)) - break; - } - strText.ReleaseBuffer(); - return bRet; - } -#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - - BOOL SetItemText(int nIndex, LPCTSTR lpszItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return SetItem(nIndex, CBEIF_TEXT, lpszItem, 0, 0, 0, 0, 0); - } - - CComboBox GetComboCtrl() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return CComboBox((HWND)::SendMessage(m_hWnd, CBEM_GETCOMBOCONTROL, 0, 0L)); - } - - CEdit GetEditCtrl() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return CEdit((HWND)::SendMessage(m_hWnd, CBEM_GETEDITCONTROL, 0, 0L)); - } - - BOOL HasEditChanged() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, CBEM_HASEDITCHANGED, 0, 0L); - } - -// Non-functional - int AddString(LPCTSTR /*lpszItem*/) - { - ATLASSERT(FALSE); // Not available in CComboBoxEx; use InsertItem - return 0; - } - - int InsertString(int /*nIndex*/, LPCTSTR /*lpszString*/) - { - ATLASSERT(FALSE); // Not available in CComboBoxEx; use InsertItem - return 0; - } - - int Dir(UINT /*attr*/, LPCTSTR /*lpszWildCard*/) - { - ATLASSERT(FALSE); // Not available in CComboBoxEx - return 0; - } - - int FindString(int /*nStartAfter*/, LPCTSTR /*lpszString*/) const - { - ATLASSERT(FALSE); // Not available in CComboBoxEx; try FindStringExact - return 0; - } -}; - -typedef CComboBoxExT CComboBoxEx; - -#endif // !_WIN32_WCE - - -/////////////////////////////////////////////////////////////////////////////// -// CMonthCalendarCtrl - -template -class CMonthCalendarCtrlT : public TBase -{ -public: -// Constructors - CMonthCalendarCtrlT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CMonthCalendarCtrlT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return MONTHCAL_CLASS; - } - - COLORREF GetColor(int nColorType) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, MCM_GETCOLOR, nColorType, 0L); - } - - COLORREF SetColor(int nColorType, COLORREF clr) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, MCM_SETCOLOR, nColorType, clr); - } - - BOOL GetCurSel(LPSYSTEMTIME lpSysTime) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, MCM_GETCURSEL, 0, (LPARAM)lpSysTime); - } - - BOOL SetCurSel(LPSYSTEMTIME lpSysTime) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, MCM_SETCURSEL, 0, (LPARAM)lpSysTime); - } - - int GetFirstDayOfWeek(BOOL* pbLocaleVal = NULL) const - { - ATLASSERT(::IsWindow(m_hWnd)); - DWORD dwRet = (DWORD)::SendMessage(m_hWnd, MCM_GETFIRSTDAYOFWEEK, 0, 0L); - if(pbLocaleVal != NULL) - *pbLocaleVal = (BOOL)HIWORD(dwRet); - return (int)(short)LOWORD(dwRet); - } - - int SetFirstDayOfWeek(int nDay, BOOL* pbLocaleVal = NULL) - { - ATLASSERT(::IsWindow(m_hWnd)); - DWORD dwRet = (DWORD)::SendMessage(m_hWnd, MCM_SETFIRSTDAYOFWEEK, 0, nDay); - if(pbLocaleVal != NULL) - *pbLocaleVal = (BOOL)HIWORD(dwRet); - return (int)(short)LOWORD(dwRet); - } - - int GetMaxSelCount() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, MCM_GETMAXSELCOUNT, 0, 0L); - } - - BOOL SetMaxSelCount(int nMax) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, MCM_SETMAXSELCOUNT, nMax, 0L); - } - - int GetMonthDelta() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, MCM_GETMONTHDELTA, 0, 0L); - } - - int SetMonthDelta(int nDelta) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, MCM_SETMONTHDELTA, nDelta, 0L); - } - - DWORD GetRange(LPSYSTEMTIME lprgSysTimeArray) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, MCM_GETRANGE, 0, (LPARAM)lprgSysTimeArray); - } - - BOOL SetRange(DWORD dwFlags, LPSYSTEMTIME lprgSysTimeArray) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, MCM_SETRANGE, dwFlags, (LPARAM)lprgSysTimeArray); - } - - BOOL GetSelRange(LPSYSTEMTIME lprgSysTimeArray) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, MCM_GETSELRANGE, 0, (LPARAM)lprgSysTimeArray); - } - - BOOL SetSelRange(LPSYSTEMTIME lprgSysTimeArray) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, MCM_SETSELRANGE, 0, (LPARAM)lprgSysTimeArray); - } - - BOOL GetToday(LPSYSTEMTIME lpSysTime) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, MCM_GETTODAY, 0, (LPARAM)lpSysTime); - } - - void SetToday(LPSYSTEMTIME lpSysTime) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, MCM_SETTODAY, 0, (LPARAM)lpSysTime); - } - - BOOL GetMinReqRect(LPRECT lpRectInfo) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, MCM_GETMINREQRECT, 0, (LPARAM)lpRectInfo); - } - - int GetMaxTodayWidth() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, MCM_GETMAXTODAYWIDTH, 0, 0L); - } - -#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) - BOOL GetUnicodeFormat() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, MCM_GETUNICODEFORMAT, 0, 0L); - } - - BOOL SetUnicodeFormat(BOOL bUnicode = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, MCM_SETUNICODEFORMAT, bUnicode, 0L); - } -#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) - -#if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) - DWORD GetCurrentView() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, MCM_GETCURRENTVIEW, 0, 0L); - } - - BOOL SetCurrentView(DWORD dwView) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, MCM_SETCURRENTVIEW, 0, dwView); - } - - DWORD GetCalendarCount() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, MCM_GETCALENDARCOUNT, 0, 0L); - } - - BOOL GetCalendarGridInfo(PMCGRIDINFO pGridInfo) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, MCM_GETCALENDARGRIDINFO, 0, (LPARAM)pGridInfo); - } - - CALID GetCALID() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (CALID)::SendMessage(m_hWnd, MCM_GETCALID, 0, 0L); - } - - void SetCALID(CALID calid) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, MCM_SETCALID, (LPARAM)calid, 0L); - } - - int GetCalendarBorder() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, MCM_GETCALENDARBORDER, 0, 0L); - } - - void SetCalendarBorder(int cxyBorder, BOOL bSet = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, MCM_SETCALENDARBORDER, (WPARAM)bSet, (LPARAM)cxyBorder); - } -#endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) - -// Operations - int GetMonthRange(DWORD dwFlags, LPSYSTEMTIME lprgSysTimeArray) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, MCM_GETMONTHRANGE, dwFlags, (LPARAM)lprgSysTimeArray); - } - - BOOL SetDayState(int nMonths, LPMONTHDAYSTATE lpDayStateArray) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, MCM_SETDAYSTATE, nMonths, (LPARAM)lpDayStateArray); - } - - DWORD HitTest(PMCHITTESTINFO pMCHitTest) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, MCM_HITTEST, 0, (LPARAM)pMCHitTest); - } - -#if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) - void SizeRectToMin(LPRECT lpRect) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, MCM_SIZERECTTOMIN, 0, (LPARAM)lpRect); - } -#endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) -}; - -typedef CMonthCalendarCtrlT CMonthCalendarCtrl; - - -/////////////////////////////////////////////////////////////////////////////// -// CDateTimePickerCtrl - -template -class CDateTimePickerCtrlT : public TBase -{ -public: -// Constructors - CDateTimePickerCtrlT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CDateTimePickerCtrlT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - } - -// Operations - static LPCTSTR GetWndClassName() - { - return DATETIMEPICK_CLASS; - } - - BOOL SetFormat(LPCTSTR lpszFormat) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, DTM_SETFORMAT, 0, (LPARAM)lpszFormat); - } - - COLORREF GetMonthCalColor(int nColorType) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, DTM_GETMCCOLOR, nColorType, 0L); - } - - COLORREF SetMonthCalColor(int nColorType, COLORREF clr) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, DTM_SETMCCOLOR, nColorType, clr); - } - - DWORD GetRange(LPSYSTEMTIME lpSysTimeArray) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, DTM_GETRANGE, 0, (LPARAM)lpSysTimeArray); - } - - BOOL SetRange(DWORD dwFlags, LPSYSTEMTIME lpSysTimeArray) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, DTM_SETRANGE, dwFlags, (LPARAM)lpSysTimeArray); - } - - DWORD GetSystemTime(LPSYSTEMTIME lpSysTime) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)lpSysTime); - } - - BOOL SetSystemTime(DWORD dwFlags, LPSYSTEMTIME lpSysTime) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, DTM_SETSYSTEMTIME, dwFlags, (LPARAM)lpSysTime); - } - - CMonthCalendarCtrl GetMonthCal() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return CMonthCalendarCtrl((HWND)::SendMessage(m_hWnd, DTM_GETMONTHCAL, 0, 0L)); - } - -#if (_WIN32_IE >= 0x0400) - CFontHandle GetMonthCalFont() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return CFontHandle((HFONT)::SendMessage(m_hWnd, DTM_GETMCFONT, 0, 0L)); - } - - void SetMonthCalFont(HFONT hFont, BOOL bRedraw = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, DTM_SETMCFONT, (WPARAM)hFont, MAKELPARAM(bRedraw, 0)); - } -#endif // (_WIN32_IE >= 0x0400) - -#if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) - DWORD GetMonthCalStyle() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, DTM_GETMCSTYLE, 0, 0L); - } - - DWORD SetMonthCalStyle(DWORD dwStyle) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, DTM_SETMCSTYLE, 0, (LPARAM)dwStyle); - } - - void GetDateTimePickerInfo(LPDATETIMEPICKERINFO lpPickerInfo) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, DTM_GETDATETIMEPICKERINFO, 0, (LPARAM)lpPickerInfo); - } - - BOOL GetIdealSize(LPSIZE lpSize) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, DTM_GETIDEALSIZE, 0, (LPARAM)lpSize); - } - - void CloseMonthCal() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, DTM_CLOSEMONTHCAL, 0, 0L); - } -#endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) -}; - -typedef CDateTimePickerCtrlT CDateTimePickerCtrl; - - -/////////////////////////////////////////////////////////////////////////////// -// CFlatScrollBarImpl - support for flat scroll bars - -#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) - -template -class CFlatScrollBarImpl -{ -public: -// Initialization - BOOL FlatSB_Initialize() - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - return ::InitializeFlatSB(pT->m_hWnd); - } - - HRESULT FlatSB_Uninitialize() - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - return ::UninitializeFlatSB(pT->m_hWnd); - } - -// Flat scroll bar properties - BOOL FlatSB_GetScrollProp(UINT uIndex, LPINT lpnValue) const - { - const T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - return ::FlatSB_GetScrollProp(pT->m_hWnd, uIndex, lpnValue); - } - - BOOL FlatSB_SetScrollProp(UINT uIndex, int nValue, BOOL bRedraw = TRUE) - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - return ::FlatSB_SetScrollProp(pT->m_hWnd, uIndex, nValue, bRedraw); - } - -// Attributes - int FlatSB_GetScrollPos(int nBar) const - { - const T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - return ::FlatSB_GetScrollPos(pT->m_hWnd, nBar); - } - - int FlatSB_SetScrollPos(int nBar, int nPos, BOOL bRedraw = TRUE) - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - return ::FlatSB_SetScrollPos(pT->m_hWnd, nBar, nPos, bRedraw); - } - - BOOL FlatSB_GetScrollRange(int nBar, LPINT lpMinPos, LPINT lpMaxPos) const - { - const T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - return ::FlatSB_GetScrollRange(pT->m_hWnd, nBar, lpMinPos, lpMaxPos); - } - - BOOL FlatSB_SetScrollRange(int nBar, int nMinPos, int nMaxPos, BOOL bRedraw = TRUE) - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - return ::FlatSB_SetScrollRange(pT->m_hWnd, nBar, nMinPos, nMaxPos, bRedraw); - } - - BOOL FlatSB_GetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo) const - { - const T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - return ::FlatSB_GetScrollInfo(pT->m_hWnd, nBar, lpScrollInfo); - } - - int FlatSB_SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE) - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - return ::FlatSB_SetScrollInfo(pT->m_hWnd, nBar, lpScrollInfo, bRedraw); - } - -// Operations - BOOL FlatSB_ShowScrollBar(UINT nBar, BOOL bShow = TRUE) - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - return ::FlatSB_ShowScrollBar(pT->m_hWnd, nBar, bShow); - } - - BOOL FlatSB_EnableScrollBar(UINT uSBFlags, UINT uArrowFlags = ESB_ENABLE_BOTH) - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - return ::FlatSB_EnableScrollBar(pT->m_hWnd, uSBFlags, uArrowFlags); - } -}; - -template -class CFlatScrollBarT : public TBase, public CFlatScrollBarImpl > -{ -public: - CFlatScrollBarT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CFlatScrollBarT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } -}; - -typedef CFlatScrollBarT CFlatScrollBar; - -#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) - - -/////////////////////////////////////////////////////////////////////////////// -// CIPAddressCtrl - -#if (_WIN32_IE >= 0x0400) - -template -class CIPAddressCtrlT : public TBase -{ -public: -// Constructors - CIPAddressCtrlT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CIPAddressCtrlT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - } - -// Atteributes - static LPCTSTR GetWndClassName() - { - return WC_IPADDRESS; - } - - BOOL IsBlank() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, IPM_ISBLANK, 0, 0L); - } - - int GetAddress(LPDWORD lpdwAddress) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, IPM_GETADDRESS, 0, (LPARAM)lpdwAddress); - } - - void SetAddress(DWORD dwAddress) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, IPM_SETADDRESS, 0, dwAddress); - } - - void ClearAddress() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, IPM_CLEARADDRESS, 0, 0L); - } - - void SetRange(int nField, WORD wRange) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, IPM_SETRANGE, nField, wRange); - } - - void SetRange(int nField, BYTE nMin, BYTE nMax) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, IPM_SETRANGE, nField, MAKEIPRANGE(nMin, nMax)); - } - - void SetFocus(int nField) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, IPM_SETFOCUS, nField, 0L); - } -}; - -typedef CIPAddressCtrlT CIPAddressCtrl; - -#endif // (_WIN32_IE >= 0x0400) - - -/////////////////////////////////////////////////////////////////////////////// -// CPagerCtrl - -#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) - -template -class CPagerCtrlT : public TBase -{ -public: -// Constructors - CPagerCtrlT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CPagerCtrlT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return WC_PAGESCROLLER; - } - - int GetButtonSize() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, PGM_GETBUTTONSIZE, 0, 0L); - } - - int SetButtonSize(int nButtonSize) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, PGM_SETBUTTONSIZE, 0, nButtonSize); - } - - DWORD GetButtonState(int nButton) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(nButton == PGB_TOPORLEFT || nButton == PGB_BOTTOMORRIGHT); - return (DWORD)::SendMessage(m_hWnd, PGM_GETBUTTONSTATE, 0, nButton); - } - - COLORREF GetBkColor() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, PGM_GETBKCOLOR, 0, 0L); - } - - COLORREF SetBkColor(COLORREF clrBk) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (COLORREF)::SendMessage(m_hWnd, PGM_SETBKCOLOR, 0, (LPARAM)clrBk); - } - - int GetBorder() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, PGM_GETBORDER, 0, 0L); - } - - int SetBorder(int nBorderSize) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, PGM_SETBORDER, 0, nBorderSize); - } - - int GetPos() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, PGM_GETPOS, 0, 0L); - } - - int SetPos(int nPos) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, PGM_SETPOS, 0, nPos); - } - -// Operations - void SetChild(HWND hWndChild) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, PGM_SETCHILD, 0, (LPARAM)hWndChild); - } - - void ForwardMouse(BOOL bForward = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, PGM_FORWARDMOUSE, bForward, 0L); - } - - void RecalcSize() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, PGM_RECALCSIZE, 0, 0L); - } - - void GetDropTarget(IDropTarget** ppDropTarget) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(ppDropTarget != NULL); - ::SendMessage(m_hWnd, PGM_GETDROPTARGET, 0, (LPARAM)ppDropTarget); - } -}; - -typedef CPagerCtrlT CPagerCtrl; - -#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) - - -/////////////////////////////////////////////////////////////////////////////// -// CLinkCtrl - Windows SYSLINK control - -#if (_WIN32_WINNT >= 0x0501) && !defined(_WIN32_WCE) - -template -class CLinkCtrlT : public TBase -{ -public: -// Constructors - CLinkCtrlT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CLinkCtrlT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - } - -// Attributes - static LPCTSTR GetWndClassName() - { -#ifdef _UNICODE - return WC_LINK; -#else // !_UNICODE - return "SysLink"; -#endif // !_UNICODE - } - - int GetIdealHeight(int cxMaxWidth = 0) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LM_GETIDEALHEIGHT, cxMaxWidth, 0L); - } - - BOOL GetItem(PLITEM pLItem) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LM_GETITEM, 0, (LPARAM)pLItem); - } - - BOOL SetItem(PLITEM pLItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LM_SETITEM, 0, (LPARAM)pLItem); - } - - // Vista only - int GetIdealSize(SIZE& size, int cxMaxWidth = 0) const - { -#ifndef LM_GETIDEALSIZE - const UINT LM_GETIDEALSIZE = LM_GETIDEALHEIGHT; -#endif - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, LM_GETIDEALSIZE, cxMaxWidth, (LPARAM)&size); - } - -// Operations - BOOL HitTest(PLHITTESTINFO pLHitTestInfo) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, LM_HITTEST, 0, (LPARAM)pLHitTestInfo); - } -}; - -typedef CLinkCtrlT CLinkCtrl; - -#endif // (_WIN32_WINNT >= 0x0501) && !defined(_WIN32_WCE) - - -/////////////////////////////////////////////////////////////////////////////// -// CCustomDraw - MI class for custom-draw support - -template -class CCustomDraw -{ -public: -#if (_ATL_VER < 0x0700) - BOOL m_bHandledCD; - - BOOL IsMsgHandled() const - { - return m_bHandledCD; - } - - void SetMsgHandled(BOOL bHandled) - { - m_bHandledCD = bHandled; - } -#endif // !(_ATL_VER < 0x0700) - -// Message map and handlers - BEGIN_MSG_MAP(CCustomDraw< T >) - NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnCustomDraw) - ALT_MSG_MAP(1) - REFLECTED_NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnCustomDraw) - END_MSG_MAP() - -// message handler - LRESULT OnCustomDraw(int idCtrl, LPNMHDR pnmh, BOOL& bHandled) - { - T* pT = static_cast(this); - pT->SetMsgHandled(TRUE); - LPNMCUSTOMDRAW lpNMCustomDraw = (LPNMCUSTOMDRAW)pnmh; - DWORD dwRet = 0; - switch(lpNMCustomDraw->dwDrawStage) - { - case CDDS_PREPAINT: - dwRet = pT->OnPrePaint(idCtrl, lpNMCustomDraw); - break; - case CDDS_POSTPAINT: - dwRet = pT->OnPostPaint(idCtrl, lpNMCustomDraw); - break; - case CDDS_PREERASE: - dwRet = pT->OnPreErase(idCtrl, lpNMCustomDraw); - break; - case CDDS_POSTERASE: - dwRet = pT->OnPostErase(idCtrl, lpNMCustomDraw); - break; - case CDDS_ITEMPREPAINT: - dwRet = pT->OnItemPrePaint(idCtrl, lpNMCustomDraw); - break; - case CDDS_ITEMPOSTPAINT: - dwRet = pT->OnItemPostPaint(idCtrl, lpNMCustomDraw); - break; - case CDDS_ITEMPREERASE: - dwRet = pT->OnItemPreErase(idCtrl, lpNMCustomDraw); - break; - case CDDS_ITEMPOSTERASE: - dwRet = pT->OnItemPostErase(idCtrl, lpNMCustomDraw); - break; -#if (_WIN32_IE >= 0x0400) - case (CDDS_ITEMPREPAINT | CDDS_SUBITEM): - dwRet = pT->OnSubItemPrePaint(idCtrl, lpNMCustomDraw); - break; -#endif // (_WIN32_IE >= 0x0400) - default: - pT->SetMsgHandled(FALSE); - break; - } - bHandled = pT->IsMsgHandled(); - return dwRet; - } - -// Overrideables - DWORD OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/) - { - return CDRF_DODEFAULT; - } - - DWORD OnPostPaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/) - { - return CDRF_DODEFAULT; - } - - DWORD OnPreErase(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/) - { - return CDRF_DODEFAULT; - } - - DWORD OnPostErase(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/) - { - return CDRF_DODEFAULT; - } - - DWORD OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/) - { - return CDRF_DODEFAULT; - } - - DWORD OnItemPostPaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/) - { - return CDRF_DODEFAULT; - } - - DWORD OnItemPreErase(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/) - { - return CDRF_DODEFAULT; - } - - DWORD OnItemPostErase(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/) - { - return CDRF_DODEFAULT; - } - -#if (_WIN32_IE >= 0x0400) - DWORD OnSubItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/) - { - return CDRF_DODEFAULT; - } -#endif // (_WIN32_IE >= 0x0400) -}; - - -// --- Windows CE common controls --- - -#ifdef _WIN32_WCE - -/////////////////////////////////////////////////////////////////////////////// -// CCECommandBarCtrl - -template -class CCECommandBarCtrlT : public TBase -{ -public: -// Constructors - CCECommandBarCtrlT(HWND hWnd = NULL) : TBase(hWnd) { } - - CCECommandBarCtrlT< TBase >& operator=(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - -// Attributes - BOOL IsVisible() const - { - return IsWindowVisible(); - } - - int GetHeight() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::CommandBar_Height(m_hWnd); - } - - HMENU GetMenu(WORD wButton) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::CommandBar_GetMenu(m_hWnd, wButton); - } - -// Operations - HWND Create(HWND hWndParent, int nCmdBarID) - { - m_hWnd = ::CommandBar_Create(ModuleHelper::GetModuleInstance(), hWndParent, nCmdBarID); - ATLASSERT(::IsWindow(m_hWnd)); - return m_hWnd; - } - - void Destroy() - { - DestroyWindow(); - } - - BOOL Show(BOOL bShow = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::CommandBar_Show(m_hWnd, bShow); - } - - BOOL DrawMenuBar(WORD wButton) - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::CommandBar_DrawMenuBar(m_hWnd, wButton); - } - - BOOL AddAdornments(DWORD dwFlags = 0) - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::CommandBar_AddAdornments(m_hWnd, dwFlags, 0); - } - - int AddBitmap(int nBitmapID, int nNumImages) - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::CommandBar_AddBitmap(m_hWnd, ModuleHelper::GetResourceInstance(), nBitmapID, nNumImages, 16, 16); - } - - BOOL AddButtons(UINT uNumButtons, LPTBBUTTON lpButtons) - { - ATLASSERT(::IsWindow(m_hWnd)); - return CommandBar_AddButtons(m_hWnd, uNumButtons, lpButtons); - } - - BOOL AddToolTips(UINT uNumToolTips, LPTSTR lpToolTips) - { - ATLASSERT(::IsWindow(m_hWnd)); - return CommandBar_AddToolTips(m_hWnd, uNumToolTips, lpToolTips); - } - - BOOL InsertButton(int nButton, LPTBBUTTON lpButton) - { - ATLASSERT(::IsWindow(m_hWnd)); - return CommandBar_InsertButton(m_hWnd, nButton, lpButton); - } - - HWND InsertComboBox(int nWidth, UINT dwStyle, WORD wComboBoxID, WORD wButton) - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::CommandBar_InsertComboBox(m_hWnd, ModuleHelper::GetModuleInstance(), nWidth, dwStyle, wComboBoxID, wButton); - } - - BOOL InsertMenubar(WORD wMenuID, WORD wButton) - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::CommandBar_InsertMenubar(m_hWnd, ModuleHelper::GetResourceInstance(), wMenuID, wButton); - } - - BOOL InsertMenubarEx(ATL::_U_STRINGorID menu, WORD wButton) - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::CommandBar_InsertMenubarEx(m_hWnd, ModuleHelper::GetResourceInstance(), (LPTSTR)menu.m_lpstr, wButton); - } - - BOOL IsCommandBarMessage(LPMSG lpMsg) - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::IsCommandBarMessage(m_hWnd, lpMsg); - } -}; - -#if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC MenuBar - typedef CCECommandBarCtrlT CMenuBarCtrl; -#else - typedef CCECommandBarCtrlT CCECommandBarCtrl; -#endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) - -/////////////////////////////////////////////////////////////////////////////// -// CCECommandBandsCtrl - -template -class CCECommandBandsCtrlT : public TBase -{ -public: -// Constructors - CCECommandBandsCtrlT(HWND hWnd = NULL) : TBase(hWnd) { } - - CCECommandBandsCtrlT< TBase >& operator=(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - -// Attributes - BOOL IsVisible() const - { - return IsWindowVisible(); - } - -#if (_WIN32_IE >= 0x0400) - UINT GetHeight() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return CommandBands_Height(m_hWnd); - } -#endif // (_WIN32_IE >= 0x0400) - - HWND GetCommandBar(UINT uBand) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::CommandBands_GetCommandBar(m_hWnd, uBand); - } - - BOOL GetRestoreInformation(UINT uBand, LPCOMMANDBANDSRESTOREINFO pcbr) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::CommandBands_GetRestoreInformation(m_hWnd, uBand, pcbr); - } - -// Operations - HWND Create(HWND hWndParent, UINT wID, DWORD dwStyles, HIMAGELIST hImageList = NULL) - { - m_hWnd = ::CommandBands_Create(ModuleHelper::GetModuleInstance(), hWndParent, wID, dwStyles, hImageList); - ATLASSERT(::IsWindow(m_hWnd)); - return m_hWnd; - } - - BOOL AddAdornments(DWORD dwFlags = 0, LPREBARBANDINFO prbbi = NULL) - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::CommandBands_AddAdornments(m_hWnd, ModuleHelper::GetModuleInstance(), dwFlags, prbbi); - } - - BOOL AddBands(UINT uBandCount, LPREBARBANDINFO prbbi) - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::CommandBands_AddBands(m_hWnd, ModuleHelper::GetModuleInstance(), uBandCount, prbbi); - } - - BOOL Show(BOOL bShow = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::CommandBands_Show(m_hWnd, bShow); - } -}; - -typedef CCECommandBandsCtrlT CCECommandBandsCtrl; - -#endif // _WIN32_WCE - -}; // namespace WTL - -#endif // __ATLCTRLS_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/atlctrlw.h b/prog/3rdPartyLibs/wtl-8.1/include/atlctrlw.h deleted file mode 100644 index ef75f1244..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/atlctrlw.h +++ /dev/null @@ -1,4161 +0,0 @@ -// Windows Template Library - WTL version 8.1 -// Copyright (C) Microsoft Corporation. All rights reserved. -// -// This file is a part of the Windows Template Library. -// The use and distribution terms for this software are covered by the -// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php) -// which can be found in the file CPL.TXT at the root of this distribution. -// By using this software in any fashion, you are agreeing to be bound by -// the terms of this license. You must not remove this notice, or -// any other, from this software. - -#ifndef __ATLCTRLW_H__ -#define __ATLCTRLW_H__ - -#pragma once - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#ifdef _WIN32_WCE - #error atlctrlw.h is not supported on Windows CE -#endif - -#ifndef __ATLAPP_H__ - #error atlctrlw.h requires atlapp.h to be included first -#endif - -#ifndef __ATLCTRLS_H__ - #error atlctrlw.h requires atlctrls.h to be included first -#endif - -#if (_WIN32_IE < 0x0400) - #error atlctrlw.h requires _WIN32_IE >= 0x0400 -#endif - -// Define _WTL_CMDBAR_VISTA_MENUS as 0 to exclude Vista menus support -#if !defined(_WTL_CMDBAR_VISTA_MENUS) && (WINVER >= 0x0500) && (_WIN32_WINNT >= 0x0501) && (_WIN32_IE >= 0x0501) - #define _WTL_CMDBAR_VISTA_MENUS 1 -#endif - -#if _WTL_CMDBAR_VISTA_MENUS - #if !((_WIN32_WINNT >= 0x0501) && (_WIN32_IE >= 0x0501)) - #error _WTL_CMDBAR_VISTA_MENUS requires (_WIN32_WINNT >= 0x0501) && (_WIN32_IE >= 0x0501) - #endif -#endif - - -/////////////////////////////////////////////////////////////////////////////// -// Classes in this file: -// -// CCommandBarCtrlImpl -// CCommandBarCtrl -// CMDICommandBarCtrlImpl -// CMDICommandBarCtrl - - -namespace WTL -{ - -/////////////////////////////////////////////////////////////////////////////// -// Command Bars - -// Window Styles: -#define CBRWS_TOP CCS_TOP -#define CBRWS_BOTTOM CCS_BOTTOM -#define CBRWS_NORESIZE CCS_NORESIZE -#define CBRWS_NOPARENTALIGN CCS_NOPARENTALIGN -#define CBRWS_NODIVIDER CCS_NODIVIDER - -// Extended styles -#define CBR_EX_TRANSPARENT 0x00000001L -#define CBR_EX_SHAREMENU 0x00000002L -#define CBR_EX_ALTFOCUSMODE 0x00000004L -#define CBR_EX_TRACKALWAYS 0x00000008L -#define CBR_EX_NOVISTAMENUS 0x00000010L - -// standard command bar styles -#define ATL_SIMPLE_CMDBAR_PANE_STYLE \ - (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CBRWS_NODIVIDER | CBRWS_NORESIZE | CBRWS_NOPARENTALIGN) - -// Messages - support chevrons for frame windows -#define CBRM_GETCMDBAR (WM_USER + 301) // returns command bar HWND -#define CBRM_GETMENU (WM_USER + 302) // returns loaded or attached menu -#define CBRM_TRACKPOPUPMENU (WM_USER + 303) // displays a popup menu - -typedef struct tagCBRPOPUPMENU -{ - int cbSize; - HMENU hMenu; // popup menu do display - UINT uFlags; // TPM_* flags for ::TrackPopupMenuEx - int x; - int y; - LPTPMPARAMS lptpm; // ptr to TPMPARAMS for ::TrackPopupMenuEx -} CBRPOPUPMENU, *LPCBRPOPUPMENU; - -// helper class -template -class CSimpleStack : public ATL::CSimpleArray< T > -{ -public: - BOOL Push(T t) - { -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("CmdBar - STACK-PUSH (%8.8X) size = %i\n"), t, GetSize()); -#endif - return Add(t); - } - - T Pop() - { - int nLast = GetSize() - 1; - if(nLast < 0) - return NULL; // must be able to convert to NULL - T t = m_aT[nLast]; -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("CmdBar - STACK-POP (%8.8X) size = %i\n"), t, GetSize()); -#endif - if(!RemoveAt(nLast)) - return NULL; - return t; - } - - T GetCurrent() - { - int nLast = GetSize() - 1; - if(nLast < 0) - return NULL; // must be able to convert to NULL - return m_aT[nLast]; - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CCommandBarCtrlBase - base class for the Command Bar implementation - -class CCommandBarCtrlBase : public CToolBarCtrl -{ -public: - struct _MsgHookData - { - HHOOK hMsgHook; - DWORD dwUsage; - - _MsgHookData() : hMsgHook(NULL), dwUsage(0) - { } - }; - - typedef ATL::CSimpleMap CMsgHookMap; - static CMsgHookMap* s_pmapMsgHook; - - static HHOOK s_hCreateHook; - static bool s_bW2K; // For animation flag - static CCommandBarCtrlBase* s_pCurrentBar; - static bool s_bStaticInit; - - CSimpleStack m_stackMenuWnd; - CSimpleStack m_stackMenuHandle; - - HWND m_hWndHook; - DWORD m_dwMagic; - - - CCommandBarCtrlBase() : m_hWndHook(NULL), m_dwMagic(1314) - { - // init static variables - if(!s_bStaticInit) - { - CStaticDataInitCriticalSectionLock lock; - if(FAILED(lock.Lock())) - { - ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CCommandBarCtrlBase::CCommandBarCtrlBase.\n")); - ATLASSERT(FALSE); - return; - } - - if(!s_bStaticInit) - { - // Just in case... - AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES); - // Animation on Win2000 only - s_bW2K = !AtlIsOldWindows(); - // done - s_bStaticInit = true; - } - - lock.Unlock(); - } - } - - bool IsCommandBarBase() const { return m_dwMagic == 1314; } -}; - -__declspec(selectany) CCommandBarCtrlBase::CMsgHookMap* CCommandBarCtrlBase::s_pmapMsgHook = NULL; -__declspec(selectany) HHOOK CCommandBarCtrlBase::s_hCreateHook = NULL; -__declspec(selectany) CCommandBarCtrlBase* CCommandBarCtrlBase::s_pCurrentBar = NULL; -__declspec(selectany) bool CCommandBarCtrlBase::s_bW2K = false; -__declspec(selectany) bool CCommandBarCtrlBase::s_bStaticInit = false; - - -/////////////////////////////////////////////////////////////////////////////// -// CCommandBarCtrl - ATL implementation of Command Bars - -template -class ATL_NO_VTABLE CCommandBarCtrlImpl : public ATL::CWindowImpl< T, TBase, TWinTraits > -{ -public: - DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName()) - -// Declarations - struct _MenuItemData // menu item data - { - DWORD dwMagic; - LPTSTR lpstrText; - UINT fType; - UINT fState; - int iButton; - - _MenuItemData() { dwMagic = 0x1313; } - bool IsCmdBarMenuItem() { return (dwMagic == 0x1313); } - }; - - struct _ToolBarData // toolbar resource data - { - WORD wVersion; - WORD wWidth; - WORD wHeight; - WORD wItemCount; - //WORD aItems[wItemCount] - - WORD* items() - { return (WORD*)(this+1); } - }; - -// Constants - enum _CmdBarDrawConstants - { - s_kcxGap = 1, - s_kcxTextMargin = 2, - s_kcxButtonMargin = 3, - s_kcyButtonMargin = 3 - }; - - enum - { - _nMaxMenuItemTextLength = 100, - _chChevronShortcut = _T('/') - }; - -#ifndef DT_HIDEPREFIX - enum { DT_HIDEPREFIX = 0x00100000 }; -#endif // !DT_HIDEPREFIX - -// Data members - HMENU m_hMenu; - HIMAGELIST m_hImageList; - ATL::CSimpleValArray m_arrCommand; - - DWORD m_dwExtendedStyle; // Command Bar specific extended styles - - ATL::CContainedWindow m_wndParent; - - bool m_bMenuActive:1; - bool m_bAttachedMenu:1; - bool m_bImagesVisible:1; - bool m_bPopupItem:1; - bool m_bContextMenu:1; - bool m_bEscapePressed:1; - bool m_bSkipMsg:1; - bool m_bParentActive:1; - bool m_bFlatMenus:1; - bool m_bUseKeyboardCues:1; - bool m_bShowKeyboardCues:1; - bool m_bAllowKeyboardCues:1; - bool m_bKeyboardInput:1; - bool m_bAlphaImages:1; - bool m_bLayoutRTL:1; - bool m_bSkipPostDown:1; - bool m_bVistaMenus:1; - - int m_nPopBtn; - int m_nNextPopBtn; - - SIZE m_szBitmap; - SIZE m_szButton; - - COLORREF m_clrMask; - CFont m_fontMenu; // used internally, only to measure text - - UINT m_uSysKey; - - HWND m_hWndFocus; // Alternate focus mode - - int m_cxExtraSpacing; - -#if _WTL_CMDBAR_VISTA_MENUS - ATL::CSimpleValArray m_arrVistaBitmap; // Bitmaps for Vista menus -#endif // _WTL_CMDBAR_VISTA_MENUS - -// Constructor/destructor - CCommandBarCtrlImpl() : - m_hMenu(NULL), - m_hImageList(NULL), - m_wndParent(this, 1), - m_bMenuActive(false), - m_bAttachedMenu(false), - m_nPopBtn(-1), - m_nNextPopBtn(-1), - m_bPopupItem(false), - m_bImagesVisible(true), - m_bSkipMsg(false), - m_uSysKey(0), - m_hWndFocus(NULL), - m_bContextMenu(false), - m_bEscapePressed(false), - m_clrMask(RGB(192, 192, 192)), - m_dwExtendedStyle(CBR_EX_TRANSPARENT | CBR_EX_SHAREMENU | CBR_EX_TRACKALWAYS), - m_bParentActive(true), - m_bFlatMenus(false), - m_bUseKeyboardCues(false), - m_bShowKeyboardCues(false), - m_bAllowKeyboardCues(true), - m_bKeyboardInput(false), - m_cxExtraSpacing(0), - m_bAlphaImages(false), - m_bLayoutRTL(false), - m_bSkipPostDown(false), - m_bVistaMenus(false) - { - SetImageSize(16, 15); // default - } - - ~CCommandBarCtrlImpl() - { - if(m_wndParent.IsWindow()) -/*scary!*/ m_wndParent.UnsubclassWindow(); - - if(m_hMenu != NULL && (m_dwExtendedStyle & CBR_EX_SHAREMENU) == 0) - ::DestroyMenu(m_hMenu); - - if(m_hImageList != NULL) - ::ImageList_Destroy(m_hImageList); - } - -// Attributes - DWORD GetCommandBarExtendedStyle() const - { - return m_dwExtendedStyle; - } - - DWORD SetCommandBarExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0) - { - DWORD dwPrevStyle = m_dwExtendedStyle; - if(dwMask == 0) - m_dwExtendedStyle = dwExtendedStyle; - else - m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask); - return dwPrevStyle; - } - - CMenuHandle GetMenu() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return m_hMenu; - } - - COLORREF GetImageMaskColor() const - { - return m_clrMask; - } - - COLORREF SetImageMaskColor(COLORREF clrMask) - { - COLORREF clrOld = m_clrMask; - m_clrMask = clrMask; - return clrOld; - } - - bool GetImagesVisible() const - { - return m_bImagesVisible; - } - - bool SetImagesVisible(bool bVisible) - { - bool bOld = m_bImagesVisible; - m_bImagesVisible = bVisible; - return bOld; - } - - void GetImageSize(SIZE& size) const - { - size = m_szBitmap; - } - - bool SetImageSize(SIZE& size) - { - return SetImageSize(size.cx, size.cy); - } - - bool SetImageSize(int cx, int cy) - { - if(m_hImageList != NULL) - { - if(::ImageList_GetImageCount(m_hImageList) == 0) // empty - { - ::ImageList_Destroy(m_hImageList); - m_hImageList = NULL; - } - else - { - return false; // can't set, image list exists - } - } - - if(cx == 0 || cy == 0) - return false; - - m_szBitmap.cx = cx; - m_szBitmap.cy = cy; - m_szButton.cx = m_szBitmap.cx + 2 * s_kcxButtonMargin; - m_szButton.cy = m_szBitmap.cy + 2 * s_kcyButtonMargin; - - return true; - } - - bool GetAlphaImages() const - { - return m_bAlphaImages; - } - - bool SetAlphaImages(bool bAlphaImages) - { - if(m_hImageList != NULL) - { - if(::ImageList_GetImageCount(m_hImageList) == 0) // empty - { - ::ImageList_Destroy(m_hImageList); - m_hImageList = NULL; - } - else - { - return false; // can't set, image list exists - } - } - - m_bAlphaImages = bAlphaImages; - return true; - } - - HWND GetCmdBar() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HWND)::SendMessage(m_hWnd, CBRM_GETCMDBAR, 0, 0L); - } - -// Methods - HWND Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - UINT nID = 0, LPVOID lpCreateParam = NULL) - { - // These styles are required for command bars - dwStyle |= TBSTYLE_LIST | TBSTYLE_FLAT; -#if (_MSC_VER >= 1300) - return ATL::CWindowImpl< T, TBase, TWinTraits >::Create(hWndParent, rcPos, szWindowName, dwStyle, dwExStyle, nID, lpCreateParam); -#else // !(_MSC_VER >= 1300) - typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass; - return _baseClass::Create(hWndParent, rcPos, szWindowName, dwStyle, dwExStyle, nID, lpCreateParam); -#endif // !(_MSC_VER >= 1300) - } - - BOOL AttachToWindow(HWND hWnd) - { - ATLASSERT(m_hWnd == NULL); - ATLASSERT(::IsWindow(hWnd)); - BOOL bRet = SubclassWindow(hWnd); - if(bRet) - { - m_bAttachedMenu = true; - T* pT = static_cast(this); - pT->GetSystemSettings(); - } - return bRet; - } - - BOOL LoadMenu(ATL::_U_STRINGorID menu) - { - ATLASSERT(::IsWindow(m_hWnd)); - - if(m_bAttachedMenu) // doesn't work in this mode - return FALSE; - if(menu.m_lpstr == NULL) - return FALSE; - - HMENU hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), menu.m_lpstr); - if(hMenu == NULL) - return FALSE; - - return AttachMenu(hMenu); - } - - BOOL AttachMenu(HMENU hMenu) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(hMenu == NULL || ::IsMenu(hMenu)); - if(hMenu != NULL && !::IsMenu(hMenu)) - return FALSE; - -#if _WTL_CMDBAR_VISTA_MENUS - // remove Vista bitmaps if used - if(m_bVistaMenus && (m_hMenu != NULL)) - { - T* pT = static_cast(this); - pT->_RemoveVistaBitmapsFromMenu(); - } -#endif // _WTL_CMDBAR_VISTA_MENUS - - // destroy old menu, if needed, and set new one - if(m_hMenu != NULL && (m_dwExtendedStyle & CBR_EX_SHAREMENU) == 0) - ::DestroyMenu(m_hMenu); - - m_hMenu = hMenu; - - if(m_bAttachedMenu) // Nothing else in this mode - return TRUE; - - // Build buttons according to menu - SetRedraw(FALSE); - - // Clear all buttons - int nCount = GetButtonCount(); - for(int i = 0; i < nCount; i++) - ATLVERIFY(DeleteButton(0) != FALSE); - - // Add buttons for each menu item - if(m_hMenu != NULL) - { - int nItems = ::GetMenuItemCount(m_hMenu); - - T* pT = static_cast(this); - pT; // avoid level 4 warning - TCHAR szString[pT->_nMaxMenuItemTextLength]; - for(int i = 0; i < nItems; i++) - { - CMenuItemInfo mii; - mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_SUBMENU; - mii.fType = MFT_STRING; - mii.dwTypeData = szString; - mii.cch = pT->_nMaxMenuItemTextLength; - BOOL bRet = ::GetMenuItemInfo(m_hMenu, i, TRUE, &mii); - ATLASSERT(bRet); - // If we have more than the buffer, we assume we have bitmaps bits - if(lstrlen(szString) > pT->_nMaxMenuItemTextLength - 1) - { - mii.fType = MFT_BITMAP; - ::SetMenuItemInfo(m_hMenu, i, TRUE, &mii); - szString[0] = 0; - } - - // NOTE: Command Bar currently supports only drop-down menu items - ATLASSERT(mii.hSubMenu != NULL); - - TBBUTTON btn = { 0 }; - btn.iBitmap = 0; - btn.idCommand = i; - btn.fsState = (BYTE)(((mii.fState & MFS_DISABLED) == 0) ? TBSTATE_ENABLED : 0); - btn.fsStyle = TBSTYLE_BUTTON | TBSTYLE_AUTOSIZE | TBSTYLE_DROPDOWN; - btn.dwData = 0; - btn.iString = 0; - - bRet = InsertButton(-1, &btn); - ATLASSERT(bRet); - - TBBUTTONINFO bi = { 0 }; - bi.cbSize = sizeof(TBBUTTONINFO); - bi.dwMask = TBIF_TEXT; - bi.pszText = szString; - - bRet = SetButtonInfo(i, &bi); - ATLASSERT(bRet); - } - } - - SetRedraw(TRUE); - Invalidate(); - UpdateWindow(); - - return TRUE; - } - - BOOL LoadImages(ATL::_U_STRINGorID image) - { - return _LoadImagesHelper(image, false); - } - - BOOL LoadMappedImages(UINT nIDImage, UINT nFlags = 0, LPCOLORMAP lpColorMap = NULL, int nMapSize = 0) - { - return _LoadImagesHelper(nIDImage, true, nFlags , lpColorMap, nMapSize); - } - - BOOL _LoadImagesHelper(ATL::_U_STRINGorID image, bool bMapped, UINT nFlags = 0, LPCOLORMAP lpColorMap = NULL, int nMapSize = 0) - { - ATLASSERT(::IsWindow(m_hWnd)); - HINSTANCE hInstance = ModuleHelper::GetResourceInstance(); - - HRSRC hRsrc = ::FindResource(hInstance, image.m_lpstr, (LPTSTR)RT_TOOLBAR); - if(hRsrc == NULL) - return FALSE; - - HGLOBAL hGlobal = ::LoadResource(hInstance, hRsrc); - if(hGlobal == NULL) - return FALSE; - - _ToolBarData* pData = (_ToolBarData*)::LockResource(hGlobal); - if(pData == NULL) - return FALSE; - ATLASSERT(pData->wVersion == 1); - - WORD* pItems = pData->items(); - int nItems = pData->wItemCount; - - // Set internal data - SetImageSize(pData->wWidth, pData->wHeight); - - // Create image list if needed - if(m_hImageList == NULL) - { - // Check if the bitmap is 32-bit (alpha channel) bitmap (valid for Windows XP only) - T* pT = static_cast(this); - m_bAlphaImages = AtlIsAlphaBitmapResource(image); - - if(!pT->CreateInternalImageList(pData->wItemCount)) - return FALSE; - } - -#if _WTL_CMDBAR_VISTA_MENUS - int nOldImageCount = ::ImageList_GetImageCount(m_hImageList); -#endif // _WTL_CMDBAR_VISTA_MENUS - - // Add bitmap to our image list - CBitmap bmp; - if(bMapped) - { - ATLASSERT(HIWORD(PtrToUlong(image.m_lpstr)) == 0); // if mapped, must be a numeric ID - int nIDImage = (int)(short)LOWORD(PtrToUlong(image.m_lpstr)); - bmp.LoadMappedBitmap(nIDImage, (WORD)nFlags, lpColorMap, nMapSize); - } - else - { - if(m_bAlphaImages) - bmp = (HBITMAP)::LoadImage(ModuleHelper::GetResourceInstance(), image.m_lpstr, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_DEFAULTSIZE); - else - bmp.LoadBitmap(image.m_lpstr); - } - ATLASSERT(bmp.m_hBitmap != NULL); - if(bmp.m_hBitmap == NULL) - return FALSE; - if(::ImageList_AddMasked(m_hImageList, bmp, m_clrMask) == -1) - return FALSE; - - // Fill the array with command IDs - for(int i = 0; i < nItems; i++) - { - if(pItems[i] != 0) - m_arrCommand.Add(pItems[i]); - } - - int nImageCount = ::ImageList_GetImageCount(m_hImageList); - ATLASSERT(nImageCount == m_arrCommand.GetSize()); - if(nImageCount != m_arrCommand.GetSize()) - return FALSE; - -#if _WTL_CMDBAR_VISTA_MENUS - if(RunTimeHelper::IsVista()) - { - T* pT = static_cast(this); - pT->_AddVistaBitmapsFromImageList(nOldImageCount, nImageCount - nOldImageCount); - ATLASSERT(nImageCount == m_arrVistaBitmap.GetSize()); - } -#endif // _WTL_CMDBAR_VISTA_MENUS - - return TRUE; - } - - BOOL AddBitmap(ATL::_U_STRINGorID bitmap, int nCommandID) - { - ATLASSERT(::IsWindow(m_hWnd)); - CBitmap bmp; - bmp.LoadBitmap(bitmap.m_lpstr); - if(bmp.m_hBitmap == NULL) - return FALSE; - return AddBitmap(bmp, nCommandID); - } - - BOOL AddBitmap(HBITMAP hBitmap, UINT nCommandID) - { - ATLASSERT(::IsWindow(m_hWnd)); - T* pT = static_cast(this); - // Create image list if it doesn't exist - if(m_hImageList == NULL) - { - if(!pT->CreateInternalImageList(1)) - return FALSE; - } - // check bitmap size - CBitmapHandle bmp = hBitmap; - SIZE size = { 0, 0 }; - bmp.GetSize(size); - if(size.cx != m_szBitmap.cx || size.cy != m_szBitmap.cy) - { - ATLASSERT(FALSE); // must match size! - return FALSE; - } - // add bitmap - int nRet = ::ImageList_AddMasked(m_hImageList, hBitmap, m_clrMask); - if(nRet == -1) - return FALSE; - BOOL bRet = m_arrCommand.Add((WORD)nCommandID); - ATLASSERT(::ImageList_GetImageCount(m_hImageList) == m_arrCommand.GetSize()); -#if _WTL_CMDBAR_VISTA_MENUS - if(RunTimeHelper::IsVista()) - { - pT->_AddVistaBitmapFromImageList(m_arrCommand.GetSize() - 1); - ATLASSERT(m_arrVistaBitmap.GetSize() == m_arrCommand.GetSize()); - } -#endif // _WTL_CMDBAR_VISTA_MENUS - return bRet; - } - - BOOL AddIcon(ATL::_U_STRINGorID icon, UINT nCommandID) - { - ATLASSERT(::IsWindow(m_hWnd)); - HICON hIcon = ::LoadIcon(ModuleHelper::GetResourceInstance(), icon.m_lpstr); - if(hIcon == NULL) - return FALSE; - return AddIcon(hIcon, nCommandID); - } - - BOOL AddIcon(HICON hIcon, UINT nCommandID) - { - ATLASSERT(::IsWindow(m_hWnd)); - T* pT = static_cast(this); - // create image list if it doesn't exist - if(m_hImageList == NULL) - { - if(!pT->CreateInternalImageList(1)) - return FALSE; - } - - int nRet = ::ImageList_AddIcon(m_hImageList, hIcon); - if(nRet == -1) - return FALSE; - BOOL bRet = m_arrCommand.Add((WORD)nCommandID); - ATLASSERT(::ImageList_GetImageCount(m_hImageList) == m_arrCommand.GetSize()); -#if _WTL_CMDBAR_VISTA_MENUS - if(RunTimeHelper::IsVista()) - { - pT->_AddVistaBitmapFromImageList(m_arrCommand.GetSize() - 1); - ATLASSERT(m_arrVistaBitmap.GetSize() == m_arrCommand.GetSize()); - } -#endif // _WTL_CMDBAR_VISTA_MENUS - return bRet; - } - - BOOL ReplaceBitmap(ATL::_U_STRINGorID bitmap, int nCommandID) - { - ATLASSERT(::IsWindow(m_hWnd)); - CBitmap bmp; - bmp.LoadBitmap(bitmap.m_lpstr); - if(bmp.m_hBitmap == NULL) - return FALSE; - return ReplaceBitmap(bmp, nCommandID); - } - - BOOL ReplaceBitmap(HBITMAP hBitmap, UINT nCommandID) - { - ATLASSERT(::IsWindow(m_hWnd)); - BOOL bRet = FALSE; - for(int i = 0; i < m_arrCommand.GetSize(); i++) - { - if(m_arrCommand[i] == nCommandID) - { - bRet = ::ImageList_Remove(m_hImageList, i); - if(bRet) - { - m_arrCommand.RemoveAt(i); -#if _WTL_CMDBAR_VISTA_MENUS - if(RunTimeHelper::IsVista()) - { - if(m_arrVistaBitmap[i] != NULL) - ::DeleteObject(m_arrVistaBitmap[i]); - m_arrVistaBitmap.RemoveAt(i); - } -#endif // _WTL_CMDBAR_VISTA_MENUS - } - break; - } - } - if(bRet) - bRet = AddBitmap(hBitmap, nCommandID); - return bRet; - } - - BOOL ReplaceIcon(ATL::_U_STRINGorID icon, UINT nCommandID) - { - ATLASSERT(::IsWindow(m_hWnd)); - HICON hIcon = ::LoadIcon(ModuleHelper::GetResourceInstance(), icon.m_lpstr); - if(hIcon == NULL) - return FALSE; - return ReplaceIcon(hIcon, nCommandID); - } - - BOOL ReplaceIcon(HICON hIcon, UINT nCommandID) - { - ATLASSERT(::IsWindow(m_hWnd)); - BOOL bRet = FALSE; - for(int i = 0; i < m_arrCommand.GetSize(); i++) - { - if(m_arrCommand[i] == nCommandID) - { - bRet = (::ImageList_ReplaceIcon(m_hImageList, i, hIcon) != -1); -#if _WTL_CMDBAR_VISTA_MENUS - if(RunTimeHelper::IsVista() && bRet != FALSE) - { - T* pT = static_cast(this); - pT->_ReplaceVistaBitmapFromImageList(i); - } -#endif // _WTL_CMDBAR_VISTA_MENUS - break; - } - } - return bRet; - } - - BOOL RemoveImage(int nCommandID) - { - ATLASSERT(::IsWindow(m_hWnd)); - - BOOL bRet = FALSE; - for(int i = 0; i < m_arrCommand.GetSize(); i++) - { - if(m_arrCommand[i] == nCommandID) - { - bRet = ::ImageList_Remove(m_hImageList, i); - if(bRet) - { - m_arrCommand.RemoveAt(i); -#if _WTL_CMDBAR_VISTA_MENUS - if(RunTimeHelper::IsVista()) - { - if(m_arrVistaBitmap[i] != NULL) - ::DeleteObject(m_arrVistaBitmap[i]); - m_arrVistaBitmap.RemoveAt(i); - } -#endif // _WTL_CMDBAR_VISTA_MENUS - } - break; - } - } - return bRet; - } - - BOOL RemoveAllImages() - { - ATLASSERT(::IsWindow(m_hWnd)); - - ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Removing all images\n")); - BOOL bRet = ::ImageList_RemoveAll(m_hImageList); - if(bRet) - { - m_arrCommand.RemoveAll(); -#if _WTL_CMDBAR_VISTA_MENUS - for(int i = 0; i < m_arrVistaBitmap.GetSize(); i++) - { - if(m_arrVistaBitmap[i] != NULL) - ::DeleteObject(m_arrVistaBitmap[i]); - } - m_arrVistaBitmap.RemoveAll(); -#endif // _WTL_CMDBAR_VISTA_MENUS - } - return bRet; - } - - BOOL TrackPopupMenu(HMENU hMenu, UINT uFlags, int x, int y, LPTPMPARAMS lpParams = NULL) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(::IsMenu(hMenu)); - if(!::IsMenu(hMenu)) - return FALSE; - m_bContextMenu = true; - if(m_bUseKeyboardCues) - m_bShowKeyboardCues = m_bKeyboardInput; - T* pT = static_cast(this); - return pT->DoTrackPopupMenu(hMenu, uFlags, x, y, lpParams); - } - - BOOL SetMDIClient(HWND /*hWndMDIClient*/) - { - // Use CMDICommandBarCtrl for MDI support - ATLASSERT(FALSE); - return FALSE; - } - -// Message map and handlers - BEGIN_MSG_MAP(CCommandBarCtrlImpl) - MESSAGE_HANDLER(WM_CREATE, OnCreate) - MESSAGE_HANDLER(WM_DESTROY, OnDestroy) - MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) - MESSAGE_HANDLER(WM_INITMENU, OnInitMenu) - MESSAGE_HANDLER(WM_INITMENUPOPUP, OnInitMenuPopup) - MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect) - MESSAGE_HANDLER(GetAutoPopupMessage(), OnInternalAutoPopup) - MESSAGE_HANDLER(GetGetBarMessage(), OnInternalGetBar) - MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange) - MESSAGE_HANDLER(WM_MENUCHAR, OnMenuChar) - - MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown) - MESSAGE_HANDLER(WM_KEYUP, OnKeyUp) - MESSAGE_HANDLER(WM_CHAR, OnChar) - MESSAGE_HANDLER(WM_SYSKEYDOWN, OnSysKeyDown) - MESSAGE_HANDLER(WM_SYSKEYUP, OnSysKeyUp) - MESSAGE_HANDLER(WM_SYSCHAR, OnSysChar) -// public API handlers - these stay to support chevrons in atlframe.h - MESSAGE_HANDLER(CBRM_GETMENU, OnAPIGetMenu) - MESSAGE_HANDLER(CBRM_TRACKPOPUPMENU, OnAPITrackPopupMenu) - MESSAGE_HANDLER(CBRM_GETCMDBAR, OnAPIGetCmdBar) - - MESSAGE_HANDLER(WM_DRAWITEM, OnDrawItem) - MESSAGE_HANDLER(WM_MEASUREITEM, OnMeasureItem) - - MESSAGE_HANDLER(WM_FORWARDMSG, OnForwardMsg) - ALT_MSG_MAP(1) // Parent window messages - NOTIFY_CODE_HANDLER(TBN_HOTITEMCHANGE, OnParentHotItemChange) - NOTIFY_CODE_HANDLER(TBN_DROPDOWN, OnParentDropDown) - MESSAGE_HANDLER(WM_INITMENUPOPUP, OnParentInitMenuPopup) - MESSAGE_HANDLER(GetGetBarMessage(), OnParentInternalGetBar) - MESSAGE_HANDLER(WM_SYSCOMMAND, OnParentSysCommand) - MESSAGE_HANDLER(CBRM_GETMENU, OnParentAPIGetMenu) - MESSAGE_HANDLER(WM_MENUCHAR, OnParentMenuChar) - MESSAGE_HANDLER(CBRM_TRACKPOPUPMENU, OnParentAPITrackPopupMenu) - MESSAGE_HANDLER(CBRM_GETCMDBAR, OnParentAPIGetCmdBar) - MESSAGE_HANDLER(WM_SETTINGCHANGE, OnParentSettingChange) - - MESSAGE_HANDLER(WM_DRAWITEM, OnParentDrawItem) - MESSAGE_HANDLER(WM_MEASUREITEM, OnParentMeasureItem) - - MESSAGE_HANDLER(WM_ACTIVATE, OnParentActivate) - NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnParentCustomDraw) - ALT_MSG_MAP(2) // MDI client window messages - // Use CMDICommandBarCtrl for MDI support - ALT_MSG_MAP(3) // Message hook messages - MESSAGE_HANDLER(WM_MOUSEMOVE, OnHookMouseMove) - MESSAGE_HANDLER(WM_SYSKEYDOWN, OnHookSysKeyDown) - MESSAGE_HANDLER(WM_SYSKEYUP, OnHookSysKeyUp) - MESSAGE_HANDLER(WM_SYSCHAR, OnHookSysChar) - MESSAGE_HANDLER(WM_KEYDOWN, OnHookKeyDown) - MESSAGE_HANDLER(WM_NEXTMENU, OnHookNextMenu) - MESSAGE_HANDLER(WM_CHAR, OnHookChar) - END_MSG_MAP() - - LRESULT OnForwardMsg(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) - { - LPMSG pMsg = (LPMSG)lParam; - if(pMsg->message >= WM_MOUSEFIRST && pMsg->message <= WM_MOUSELAST) - m_bKeyboardInput = false; - else if(pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST) - m_bKeyboardInput = true; - LRESULT lRet = 0; - ProcessWindowMessage(pMsg->hwnd, pMsg->message, pMsg->wParam, pMsg->lParam, lRet, 3); - return lRet; - } - - LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) - { - // Let the toolbar initialize itself - LRESULT lRet = DefWindowProc(uMsg, wParam, lParam); - // get and use system settings - T* pT = static_cast(this); - pT->GetSystemSettings(); - // Parent init - ATL::CWindow wndParent = GetParent(); - ATL::CWindow wndTopLevelParent = wndParent.GetTopLevelParent(); - m_wndParent.SubclassWindow(wndTopLevelParent); - // Toolbar Init - SetButtonStructSize(); - SetImageList(NULL); - - // Create message hook if needed - CWindowCreateCriticalSectionLock lock; - if(FAILED(lock.Lock())) - { - ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CCommandBarCtrlImpl::OnCreate.\n")); - ATLASSERT(FALSE); - return -1; - } - - if(s_pmapMsgHook == NULL) - { - ATLTRY(s_pmapMsgHook = new CMsgHookMap); - ATLASSERT(s_pmapMsgHook != NULL); - } - - if(s_pmapMsgHook != NULL) - { - DWORD dwThreadID = ::GetCurrentThreadId(); - _MsgHookData* pData = s_pmapMsgHook->Lookup(dwThreadID); - if(pData == NULL) - { - ATLTRY(pData = new _MsgHookData); - ATLASSERT(pData != NULL); - HHOOK hMsgHook = ::SetWindowsHookEx(WH_GETMESSAGE, MessageHookProc, ModuleHelper::GetModuleInstance(), dwThreadID); - ATLASSERT(hMsgHook != NULL); - if(pData != NULL && hMsgHook != NULL) - { - pData->hMsgHook = hMsgHook; - pData->dwUsage = 1; - BOOL bRet = s_pmapMsgHook->Add(dwThreadID, pData); - bRet; - ATLASSERT(bRet); - } - } - else - { - (pData->dwUsage)++; - } - } - lock.Unlock(); - - // Get layout -#if (WINVER >= 0x0500) - m_bLayoutRTL = ((GetExStyle() & WS_EX_LAYOUTRTL) != 0); -#endif // (WINVER >= 0x0500) - - return lRet; - } - - LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) - { - LRESULT lRet = DefWindowProc(uMsg, wParam, lParam); - -#if _WTL_CMDBAR_VISTA_MENUS - if(m_bVistaMenus && (m_hMenu != NULL)) - { - T* pT = static_cast(this); - pT->_RemoveVistaBitmapsFromMenu(); - } - - for(int i = 0; i < m_arrVistaBitmap.GetSize(); i++) - { - if(m_arrVistaBitmap[i] != NULL) - ::DeleteObject(m_arrVistaBitmap[i]); - } -#endif // _WTL_CMDBAR_VISTA_MENUS - - if(m_bAttachedMenu) // nothing to do in this mode - return lRet; - - CWindowCreateCriticalSectionLock lock; - if(FAILED(lock.Lock())) - { - ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CCommandBarCtrlImpl::OnDestroy.\n")); - ATLASSERT(FALSE); - return lRet; - } - - if(s_pmapMsgHook != NULL) - { - DWORD dwThreadID = ::GetCurrentThreadId(); - _MsgHookData* pData = s_pmapMsgHook->Lookup(dwThreadID); - if(pData != NULL) - { - (pData->dwUsage)--; - if(pData->dwUsage == 0) - { - BOOL bRet = ::UnhookWindowsHookEx(pData->hMsgHook); - ATLASSERT(bRet); - bRet = s_pmapMsgHook->Remove(dwThreadID); - ATLASSERT(bRet); - if(bRet) - delete pData; - } - - if(s_pmapMsgHook->GetSize() == 0) - { - delete s_pmapMsgHook; - s_pmapMsgHook = NULL; - } - } - } - - lock.Unlock(); - - return lRet; - } - - LRESULT OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnKeyDown\n")); -#endif - bHandled = FALSE; - // Simulate Alt+Space for the parent - if(wParam == VK_SPACE) - { - m_wndParent.PostMessage(WM_SYSKEYDOWN, wParam, lParam | (1 << 29)); - bHandled = TRUE; - } -#if (_WIN32_IE >= 0x0500) - else if(wParam == VK_LEFT || wParam == VK_RIGHT) - { - WPARAM wpNext = m_bLayoutRTL ? VK_LEFT : VK_RIGHT; - - if(!m_bMenuActive) - { - T* pT = static_cast(this); - int nBtn = GetHotItem(); - int nNextBtn = (wParam == wpNext) ? pT->GetNextMenuItem(nBtn) : pT->GetPreviousMenuItem(nBtn); - if(nNextBtn == -2) - { - SetHotItem(-1); - if(pT->DisplayChevronMenu()) - bHandled = TRUE; - } - } - } -#endif // (_WIN32_IE >= 0x0500) - return 0; - } - - LRESULT OnKeyUp(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) - { -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnKeyUp\n")); -#endif - if(wParam != VK_SPACE) - bHandled = FALSE; - return 0; - } - - LRESULT OnChar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) - { -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnChar\n")); -#endif - if(wParam != VK_SPACE) - bHandled = FALSE; - else - return 0; - // Security - if(!m_wndParent.IsWindowEnabled() || ::GetFocus() != m_hWnd) - return 0; - - // Handle mnemonic press when we have focus - int nBtn = 0; - if(wParam != VK_RETURN && !MapAccelerator((TCHAR)LOWORD(wParam), nBtn)) - { -#if (_WIN32_IE >= 0x0500) - if((TCHAR)LOWORD(wParam) != _chChevronShortcut) -#endif // (_WIN32_IE >= 0x0500) - ::MessageBeep(0); - } - else - { -#if (_WIN32_IE >= 0x0500) - RECT rcClient = { 0 }; - GetClientRect(&rcClient); - RECT rcBtn = { 0 }; - GetItemRect(nBtn, &rcBtn); - TBBUTTON tbb = { 0 }; - GetButton(nBtn, &tbb); - if((tbb.fsState & TBSTATE_ENABLED) != 0 && (tbb.fsState & TBSTATE_HIDDEN) == 0 && rcBtn.right <= rcClient.right) - { -#endif // (_WIN32_IE >= 0x0500) - PostMessage(WM_KEYDOWN, VK_DOWN, 0L); - if(wParam != VK_RETURN) - SetHotItem(nBtn); -#if (_WIN32_IE >= 0x0500) - } - else - { - ::MessageBeep(0); - bHandled = TRUE; - } -#endif // (_WIN32_IE >= 0x0500) - } - return 0; - } - - LRESULT OnSysKeyDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnSysKeyDown\n")); -#endif - bHandled = FALSE; - return 0; - } - - LRESULT OnSysKeyUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnSysKeyUp\n")); -#endif - bHandled = FALSE; - return 0; - } - - LRESULT OnSysChar(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnSysChar\n")); -#endif - bHandled = FALSE; - return 0; - } - - LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) - { - if(m_bAttachedMenu || (m_dwExtendedStyle & CBR_EX_TRANSPARENT)) - { - bHandled = FALSE; - return 0; - } - - CDCHandle dc = (HDC)wParam; - RECT rect = { 0 }; - GetClientRect(&rect); - dc.FillRect(&rect, COLOR_MENU); - - return 1; // don't do the default erase - } - - LRESULT OnInitMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - int nIndex = GetHotItem(); - SendMessage(WM_MENUSELECT, MAKEWPARAM(nIndex, MF_POPUP|MF_HILITE), (LPARAM)m_hMenu); - bHandled = FALSE; - return 1; - } - - LRESULT OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - if((BOOL)HIWORD(lParam)) // System menu, do nothing - { - bHandled = FALSE; - return 1; - } - - if(!(m_bAttachedMenu || m_bMenuActive)) // Not attached or ours, do nothing - { - bHandled = FALSE; - return 1; - } - -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnInitMenuPopup\n")); -#endif - // forward to the parent or subclassed window, so it can handle update UI - LRESULT lRet = 0; - if(m_bAttachedMenu) - lRet = DefWindowProc(uMsg, wParam, (lParam || m_bContextMenu) ? lParam : GetHotItem()); - else - lRet = m_wndParent.DefWindowProc(uMsg, wParam, (lParam || m_bContextMenu) ? lParam : GetHotItem()); - -#if _WTL_CMDBAR_VISTA_MENUS - // If Vista menus are active, just set bitmaps and return - if(m_bVistaMenus) - { - CMenuHandle menu = (HMENU)wParam; - ATLASSERT(menu.m_hMenu != NULL); - - for(int i = 0; i < menu.GetMenuItemCount(); i++) - { - WORD nID = (WORD)menu.GetMenuItemID(i); - int nIndex = m_arrCommand.Find(nID); - - CMenuItemInfo mii; - mii.fMask = MIIM_BITMAP; - mii.hbmpItem = (m_bImagesVisible && (nIndex != -1)) ? m_arrVistaBitmap[nIndex] : NULL; - menu.SetMenuItemInfo(i, TRUE, &mii); - } - - return lRet; - } -#endif // _WTL_CMDBAR_VISTA_MENUS - - // Convert menu items to ownerdraw, add our data - if(m_bImagesVisible) - { - CMenuHandle menuPopup = (HMENU)wParam; - ATLASSERT(menuPopup.m_hMenu != NULL); - - T* pT = static_cast(this); - pT; // avoid level 4 warning - TCHAR szString[pT->_nMaxMenuItemTextLength]; - BOOL bRet = FALSE; - for(int i = 0; i < menuPopup.GetMenuItemCount(); i++) - { - CMenuItemInfo mii; - mii.cch = pT->_nMaxMenuItemTextLength; - mii.fMask = MIIM_CHECKMARKS | MIIM_DATA | MIIM_ID | MIIM_STATE | MIIM_SUBMENU | MIIM_TYPE; - mii.dwTypeData = szString; - bRet = menuPopup.GetMenuItemInfo(i, TRUE, &mii); - ATLASSERT(bRet); - - if(!(mii.fType & MFT_OWNERDRAW)) // Not already an ownerdraw item - { - mii.fMask = MIIM_DATA | MIIM_TYPE | MIIM_STATE; - _MenuItemData* pMI = NULL; - ATLTRY(pMI = new _MenuItemData); - ATLASSERT(pMI != NULL); - if(pMI != NULL) - { - pMI->fType = mii.fType; - pMI->fState = mii.fState; - mii.fType |= MFT_OWNERDRAW; - pMI->iButton = -1; - for(int j = 0; j < m_arrCommand.GetSize(); j++) - { - if(m_arrCommand[j] == mii.wID) - { - pMI->iButton = j; - break; - } - } - int cchLen = lstrlen(szString) + 1; - pMI->lpstrText = NULL; - ATLTRY(pMI->lpstrText = new TCHAR[cchLen]); - ATLASSERT(pMI->lpstrText != NULL); - if(pMI->lpstrText != NULL) - SecureHelper::strcpy_x(pMI->lpstrText, cchLen, szString); - mii.dwItemData = (ULONG_PTR)pMI; - bRet = menuPopup.SetMenuItemInfo(i, TRUE, &mii); - ATLASSERT(bRet); - } - } - } - - // Add it to the list - m_stackMenuHandle.Push(menuPopup.m_hMenu); - } - - return lRet; - } - - LRESULT OnMenuSelect(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - if(!m_bAttachedMenu) // Not attached, do nothing, forward to parent - { - m_bPopupItem = (lParam != NULL) && ((HMENU)lParam != m_hMenu) && (HIWORD(wParam) & MF_POPUP); - if(m_wndParent.IsWindow()) - m_wndParent.SendMessage(uMsg, wParam, lParam); - bHandled = FALSE; - return 1; - } - - // Check if a menu is closing, do a cleanup - if(HIWORD(wParam) == 0xFFFF && lParam == NULL) // Menu closing - { -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnMenuSelect - CLOSING!!!!\n")); -#endif - ATLASSERT(m_stackMenuWnd.GetSize() == 0); - // Restore the menu items to the previous state for all menus that were converted - if(m_bImagesVisible) - { - HMENU hMenu = NULL; - while((hMenu = m_stackMenuHandle.Pop()) != NULL) - { - CMenuHandle menuPopup = hMenu; - ATLASSERT(menuPopup.m_hMenu != NULL); - // Restore state and delete menu item data - BOOL bRet = FALSE; - for(int i = 0; i < menuPopup.GetMenuItemCount(); i++) - { - CMenuItemInfo mii; - mii.fMask = MIIM_DATA | MIIM_TYPE; - bRet = menuPopup.GetMenuItemInfo(i, TRUE, &mii); - ATLASSERT(bRet); - - _MenuItemData* pMI = (_MenuItemData*)mii.dwItemData; - if(pMI != NULL && pMI->IsCmdBarMenuItem()) - { - mii.fMask = MIIM_DATA | MIIM_TYPE | MIIM_STATE; - mii.fType = pMI->fType; - mii.dwTypeData = pMI->lpstrText; - mii.cch = lstrlen(pMI->lpstrText); - mii.dwItemData = NULL; - - bRet = menuPopup.SetMenuItemInfo(i, TRUE, &mii); - ATLASSERT(bRet); - - delete [] pMI->lpstrText; - pMI->dwMagic = 0x6666; - delete pMI; - } - } - } - } - } - - bHandled = FALSE; - return 1; - } - - LRESULT OnInternalAutoPopup(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - int nIndex = (int)wParam; - T* pT = static_cast(this); - pT->DoPopupMenu(nIndex, false); - return 0; - } - - LRESULT OnInternalGetBar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - // Let's make sure we're not embedded in another process - if((LPVOID)wParam != NULL) - *((DWORD*)wParam) = GetCurrentProcessId(); - if(IsWindowVisible()) - return (LRESULT)static_cast(this); - else - return NULL; - } - - LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { -#ifndef SPI_GETKEYBOARDCUES - const UINT SPI_SETKEYBOARDCUES = 0x100B; -#endif // !SPI_GETKEYBOARDCUES -#ifndef SPI_GETFLATMENU - const UINT SPI_SETFLATMENU = 0x1023; -#endif // !SPI_GETFLATMENU - - if(wParam == SPI_SETNONCLIENTMETRICS || wParam == SPI_SETKEYBOARDCUES || wParam == SPI_SETFLATMENU) - { - T* pT = static_cast(this); - pT->GetSystemSettings(); - } - - return 0; - } - - LRESULT OnWindowPosChanging(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) - { - LRESULT lRet = DefWindowProc(uMsg, wParam, lParam); - - LPWINDOWPOS lpWP = (LPWINDOWPOS)lParam; - int cyMin = ::GetSystemMetrics(SM_CYMENU); - if(lpWP->cy < cyMin) - lpWP->cy = cyMin; - - return lRet; - } - - LRESULT OnMenuChar(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnMenuChar\n")); -#endif - bHandled = TRUE; - T* pT = static_cast(this); - - LRESULT lRet; - if(m_bMenuActive && LOWORD(wParam) != 0x0D) - lRet = 0; - else - lRet = MAKELRESULT(1, 1); - - if(m_bMenuActive && HIWORD(wParam) == MF_POPUP) - { - // Convert character to lower/uppercase and possibly Unicode, using current keyboard layout - TCHAR ch = (TCHAR)LOWORD(wParam); - CMenuHandle menu = (HMENU)lParam; - int nCount = ::GetMenuItemCount(menu); - int nRetCode = MNC_EXECUTE; - BOOL bRet = FALSE; - TCHAR szString[pT->_nMaxMenuItemTextLength]; - WORD wMnem = 0; - bool bFound = false; - for(int i = 0; i < nCount; i++) - { - CMenuItemInfo mii; - mii.cch = pT->_nMaxMenuItemTextLength; - mii.fMask = MIIM_CHECKMARKS | MIIM_DATA | MIIM_ID | MIIM_STATE | MIIM_SUBMENU | MIIM_TYPE; - mii.dwTypeData = szString; - bRet = menu.GetMenuItemInfo(i, TRUE, &mii); - if(!bRet || (mii.fType & MFT_SEPARATOR)) - continue; - _MenuItemData* pmd = (_MenuItemData*)mii.dwItemData; - if(pmd != NULL && pmd->IsCmdBarMenuItem()) - { - LPTSTR p = pmd->lpstrText; - - if(p != NULL) - { - while(*p && *p != _T('&')) - p = ::CharNext(p); - if(p != NULL && *p) - { - DWORD dwP = MAKELONG(*(++p), 0); - DWORD dwC = MAKELONG(ch, 0); - if(::CharLower((LPTSTR)ULongToPtr(dwP)) == ::CharLower((LPTSTR)ULongToPtr(dwC))) - { - if(!bFound) - { - wMnem = (WORD)i; - bFound = true; - } - else - { - nRetCode = MNC_SELECT; - break; - } - } - } - } - } - } - if(bFound) - { - if(nRetCode == MNC_EXECUTE) - { - PostMessage(TB_SETHOTITEM, (WPARAM)-1, 0L); - pT->GiveFocusBack(); - } - bHandled = TRUE; - lRet = MAKELRESULT(wMnem, nRetCode); - } - } - else if(!m_bMenuActive) - { - int nBtn = 0; - if(!MapAccelerator((TCHAR)LOWORD(wParam), nBtn)) - { - bHandled = FALSE; - PostMessage(TB_SETHOTITEM, (WPARAM)-1, 0L); - pT->GiveFocusBack(); - -#if (_WIN32_IE >= 0x0500) - // check if we should display chevron menu - if((TCHAR)LOWORD(wParam) == pT->_chChevronShortcut) - { - if(pT->DisplayChevronMenu()) - bHandled = TRUE; - } -#endif // (_WIN32_IE >= 0x0500) - } - else if(m_wndParent.IsWindowEnabled()) - { -#if (_WIN32_IE >= 0x0500) - RECT rcClient = { 0 }; - GetClientRect(&rcClient); - RECT rcBtn = { 0 }; - GetItemRect(nBtn, &rcBtn); - TBBUTTON tbb = { 0 }; - GetButton(nBtn, &tbb); - if((tbb.fsState & TBSTATE_ENABLED) != 0 && (tbb.fsState & TBSTATE_HIDDEN) == 0 && rcBtn.right <= rcClient.right) - { -#endif // (_WIN32_IE >= 0x0500) - if(m_bUseKeyboardCues && !m_bShowKeyboardCues) - { - m_bAllowKeyboardCues = true; - ShowKeyboardCues(true); - } - pT->TakeFocus(); - PostMessage(WM_KEYDOWN, VK_DOWN, 0L); - SetHotItem(nBtn); -#if (_WIN32_IE >= 0x0500) - } - else - { - ::MessageBeep(0); - } -#endif // (_WIN32_IE >= 0x0500) - } - } - - return lRet; - } - - LRESULT OnDrawItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) - { - LPDRAWITEMSTRUCT lpDrawItemStruct = (LPDRAWITEMSTRUCT)lParam; - _MenuItemData* pmd = (_MenuItemData*)lpDrawItemStruct->itemData; - if(lpDrawItemStruct->CtlType == ODT_MENU && pmd != NULL && pmd->IsCmdBarMenuItem()) - { - T* pT = static_cast(this); - pT->DrawItem(lpDrawItemStruct); - } - else - { - bHandled = FALSE; - } - return (LRESULT)TRUE; - } - - LRESULT OnMeasureItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) - { - LPMEASUREITEMSTRUCT lpMeasureItemStruct = (LPMEASUREITEMSTRUCT)lParam; - _MenuItemData* pmd = (_MenuItemData*)lpMeasureItemStruct->itemData; - if(lpMeasureItemStruct->CtlType == ODT_MENU && pmd != NULL && pmd->IsCmdBarMenuItem()) - { - T* pT = static_cast(this); - pT->MeasureItem(lpMeasureItemStruct); - } - else - { - bHandled = FALSE; - } - return (LRESULT)TRUE; - } - -// API message handlers - LRESULT OnAPIGetMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - return (LRESULT)m_hMenu; - } - - LRESULT OnAPITrackPopupMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) - { - if(lParam == NULL) - return FALSE; - LPCBRPOPUPMENU lpCBRPopupMenu = (LPCBRPOPUPMENU)lParam; - if(lpCBRPopupMenu->cbSize != sizeof(CBRPOPUPMENU)) - return FALSE; - - T* pT = static_cast(this); - return pT->TrackPopupMenu(lpCBRPopupMenu->hMenu, lpCBRPopupMenu->uFlags, lpCBRPopupMenu->x, lpCBRPopupMenu->y, lpCBRPopupMenu->lptpm); - } - - LRESULT OnAPIGetCmdBar(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - return (LRESULT)m_hWnd; - } - -// Parent window message handlers - LRESULT OnParentHotItemChange(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled) - { - LPNMTBHOTITEM lpNMHT = (LPNMTBHOTITEM)pnmh; - - // Check if this comes from us - if(pnmh->hwndFrom != m_hWnd) - { - bHandled = FALSE; - return 0; - } - - bool bBlockTracking = false; - if((m_dwExtendedStyle & CBR_EX_TRACKALWAYS) == 0) - { - DWORD dwProcessID; - ::GetWindowThreadProcessId(::GetActiveWindow(), &dwProcessID); - bBlockTracking = (::GetCurrentProcessId() != dwProcessID); - } - - if((!m_wndParent.IsWindowEnabled() || bBlockTracking) && (lpNMHT->dwFlags & HICF_MOUSE)) - { - return 1; - } - else - { -#ifndef HICF_LMOUSE - const DWORD HICF_LMOUSE = 0x00000080; // left mouse button selected -#endif - bHandled = FALSE; - - // Send WM_MENUSELECT to the app if it needs to display a status text - if(!(lpNMHT->dwFlags & HICF_MOUSE) - && !(lpNMHT->dwFlags & HICF_ACCELERATOR) - && !(lpNMHT->dwFlags & HICF_LMOUSE)) - { - if(lpNMHT->dwFlags & HICF_ENTERING) - m_wndParent.SendMessage(WM_MENUSELECT, 0, (LPARAM)m_hMenu); - if(lpNMHT->dwFlags & HICF_LEAVING) - m_wndParent.SendMessage(WM_MENUSELECT, MAKEWPARAM(0, 0xFFFF), NULL); - } - - return 0; - } - } - - LRESULT OnParentDropDown(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled) - { - // Check if this comes from us - if(pnmh->hwndFrom != m_hWnd) - { - bHandled = FALSE; - return 1; - } - - T* pT = static_cast(this); - if(::GetFocus() != m_hWnd) - pT->TakeFocus(); - LPNMTOOLBAR pNMToolBar = (LPNMTOOLBAR)pnmh; - int nIndex = CommandToIndex(pNMToolBar->iItem); - m_bContextMenu = false; - m_bEscapePressed = false; - pT->DoPopupMenu(nIndex, true); - - return TBDDRET_DEFAULT; - } - - LRESULT OnParentInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - return OnInitMenuPopup(uMsg, wParam, lParam, bHandled); - } - - LRESULT OnParentInternalGetBar(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - return OnInternalGetBar(uMsg, wParam, lParam, bHandled); - } - - LRESULT OnParentSysCommand(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) - { - bHandled = FALSE; - if((m_uSysKey == VK_MENU - || (m_uSysKey == VK_F10 && !(::GetKeyState(VK_SHIFT) & 0x80)) - || m_uSysKey == VK_SPACE) - && wParam == SC_KEYMENU) - { - T* pT = static_cast(this); - if(::GetFocus() == m_hWnd) - { - pT->GiveFocusBack(); // exit menu "loop" - PostMessage(TB_SETHOTITEM, (WPARAM)-1, 0L); - } - else if(m_uSysKey != VK_SPACE && !m_bSkipMsg) - { - if(m_bUseKeyboardCues && !m_bShowKeyboardCues && m_bAllowKeyboardCues) - ShowKeyboardCues(true); - - pT->TakeFocus(); // enter menu "loop" - bHandled = TRUE; - } - else if(m_uSysKey != VK_SPACE) - { - bHandled = TRUE; - } - } - m_bSkipMsg = false; - return 0; - } - - LRESULT OnParentAPIGetMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - return OnAPIGetMenu(uMsg, wParam, lParam, bHandled); - } - - LRESULT OnParentMenuChar(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - return OnMenuChar(uMsg, wParam, lParam, bHandled); - } - - LRESULT OnParentAPITrackPopupMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - return OnAPITrackPopupMenu(uMsg, wParam, lParam, bHandled); - } - - LRESULT OnParentAPIGetCmdBar(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - return OnAPIGetCmdBar(uMsg, wParam, lParam, bHandled); - } - - LRESULT OnParentSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - OnSettingChange(uMsg, wParam, lParam, bHandled); - bHandled = FALSE; - return 1; - } - - LRESULT OnParentDrawItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - return OnDrawItem(uMsg, wParam, lParam, bHandled); - } - - LRESULT OnParentMeasureItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - return OnMeasureItem(uMsg, wParam, lParam, bHandled); - } - - LRESULT OnParentActivate(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) - { - m_bParentActive = (LOWORD(wParam) != WA_INACTIVE); - if(!m_bParentActive && m_bUseKeyboardCues && m_bShowKeyboardCues) - { - ShowKeyboardCues(false); // this will repaint our window - } - else - { - Invalidate(); - UpdateWindow(); - } - bHandled = FALSE; - return 1; - } - - LRESULT OnParentCustomDraw(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled) - { - LRESULT lRet = CDRF_DODEFAULT; - bHandled = FALSE; - if(pnmh->hwndFrom == m_hWnd) - { - LPNMTBCUSTOMDRAW lpTBCustomDraw = (LPNMTBCUSTOMDRAW)pnmh; - if(lpTBCustomDraw->nmcd.dwDrawStage == CDDS_PREPAINT) - { - lRet = CDRF_NOTIFYITEMDRAW; - bHandled = TRUE; - } - else if(lpTBCustomDraw->nmcd.dwDrawStage == CDDS_ITEMPREPAINT) - { - if(m_bFlatMenus) - { -#ifndef COLOR_MENUHILIGHT - const int COLOR_MENUHILIGHT = 29; -#endif // !COLOR_MENUHILIGHT - bool bDisabled = ((lpTBCustomDraw->nmcd.uItemState & CDIS_DISABLED) == CDIS_DISABLED); - if(!bDisabled && ((lpTBCustomDraw->nmcd.uItemState & CDIS_HOT) == CDIS_HOT || - (lpTBCustomDraw->nmcd.uItemState & CDIS_SELECTED) == CDIS_SELECTED)) - { - ::FillRect(lpTBCustomDraw->nmcd.hdc, &lpTBCustomDraw->nmcd.rc, ::GetSysColorBrush(COLOR_MENUHILIGHT)); - ::FrameRect(lpTBCustomDraw->nmcd.hdc, &lpTBCustomDraw->nmcd.rc, ::GetSysColorBrush(COLOR_HIGHLIGHT)); - lpTBCustomDraw->clrText = ::GetSysColor(m_bParentActive ? COLOR_HIGHLIGHTTEXT : COLOR_GRAYTEXT); - } - else if(bDisabled || !m_bParentActive) - { - lpTBCustomDraw->clrText = ::GetSysColor(COLOR_GRAYTEXT); - } - CDCHandle dc = lpTBCustomDraw->nmcd.hdc; - dc.SetTextColor(lpTBCustomDraw->clrText); - dc.SetBkMode(lpTBCustomDraw->nStringBkMode); - HFONT hFont = GetFont(); - HFONT hFontOld = NULL; - if(hFont != NULL) - hFontOld = dc.SelectFont(hFont); - const int cchText = 200; - TCHAR szText[cchText] = { 0 }; - TBBUTTONINFO tbbi = { 0 }; - tbbi.cbSize = sizeof(TBBUTTONINFO); - tbbi.dwMask = TBIF_TEXT; - tbbi.pszText = szText; - tbbi.cchText = cchText; - GetButtonInfo((int)lpTBCustomDraw->nmcd.dwItemSpec, &tbbi); - dc.DrawText(szText, -1, &lpTBCustomDraw->nmcd.rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER | (m_bShowKeyboardCues ? 0 : DT_HIDEPREFIX)); - if(hFont != NULL) - dc.SelectFont(hFontOld); - lRet = CDRF_SKIPDEFAULT; - bHandled = TRUE; - } - else if(!m_bParentActive) - { - lpTBCustomDraw->clrText = ::GetSysColor(COLOR_GRAYTEXT); - bHandled = TRUE; - } - } - } - return lRet; - } - -// Message hook handlers - LRESULT OnHookMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - static POINT s_point = { -1, -1 }; - DWORD dwPoint = ::GetMessagePos(); - POINT point = { GET_X_LPARAM(dwPoint), GET_Y_LPARAM(dwPoint) }; - - bHandled = FALSE; - if(m_bMenuActive) - { - if(::WindowFromPoint(point) == m_hWnd) - { - ScreenToClient(&point); - int nHit = HitTest(&point); - - if((point.x != s_point.x || point.y != s_point.y) && nHit >= 0 && nHit < ::GetMenuItemCount(m_hMenu) && nHit != m_nPopBtn && m_nPopBtn != -1) - { - TBBUTTON tbb = { 0 }; - GetButton(nHit, &tbb); - if((tbb.fsState & TBSTATE_ENABLED) != 0) - { - m_nNextPopBtn = nHit | 0xFFFF0000; - HWND hWndMenu = m_stackMenuWnd.GetCurrent(); - ATLASSERT(hWndMenu != NULL); - - // this one is needed to close a menu if mouse button was down - ::PostMessage(hWndMenu, WM_LBUTTONUP, 0, MAKELPARAM(point.x, point.y)); - // this one closes a popup menu - ::PostMessage(hWndMenu, WM_KEYDOWN, VK_ESCAPE, 0L); - - bHandled = TRUE; - } - } - } - } - else - { - ScreenToClient(&point); - } - - s_point = point; - return 0; - } - - LRESULT OnHookSysKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) - { - bHandled = FALSE; -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_SYSKEYDOWN (0x%2.2X)\n"), wParam); -#endif - - if(wParam == VK_MENU && m_bParentActive && m_bUseKeyboardCues && !m_bShowKeyboardCues && m_bAllowKeyboardCues) - ShowKeyboardCues(true); - - if(wParam != VK_SPACE && !m_bMenuActive && ::GetFocus() == m_hWnd) - { - m_bAllowKeyboardCues = false; - PostMessage(TB_SETHOTITEM, (WPARAM)-1, 0L); - T* pT = static_cast(this); - pT->GiveFocusBack(); - m_bSkipMsg = true; - } - else - { - if(wParam == VK_SPACE && m_bUseKeyboardCues && m_bShowKeyboardCues) - { - m_bAllowKeyboardCues = true; - ShowKeyboardCues(false); - } - m_uSysKey = (UINT)wParam; - } - return 0; - } - - LRESULT OnHookSysKeyUp(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) - { - if(!m_bAllowKeyboardCues) - m_bAllowKeyboardCues = true; - bHandled = FALSE; - wParam; -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_SYSKEYUP (0x%2.2X)\n"), wParam); -#endif - return 0; - } - - LRESULT OnHookSysChar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) - { - bHandled = FALSE; -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_SYSCHAR (0x%2.2X)\n"), wParam); -#endif - - if(!m_bMenuActive && m_hWndHook != m_hWnd && wParam != VK_SPACE) - bHandled = TRUE; - return 0; - } - - LRESULT OnHookKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) - { -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_KEYDOWN (0x%2.2X)\n"), wParam); -#endif - bHandled = FALSE; - T* pT = static_cast(this); - - if(wParam == VK_ESCAPE && m_stackMenuWnd.GetSize() <= 1) - { - if(m_bMenuActive && !m_bContextMenu) - { - int nHot = GetHotItem(); - if(nHot == -1) - nHot = m_nPopBtn; - if(nHot == -1) - nHot = 0; - SetHotItem(nHot); - bHandled = TRUE; - pT->TakeFocus(); - m_bEscapePressed = true; // To keep focus - m_bSkipPostDown = false; - } - else if(::GetFocus() == m_hWnd && m_wndParent.IsWindow()) - { - SetHotItem(-1); - pT->GiveFocusBack(); - bHandled = TRUE; - } - } - else if(wParam == VK_RETURN || wParam == VK_UP || wParam == VK_DOWN) - { - if(!m_bMenuActive && ::GetFocus() == m_hWnd && m_wndParent.IsWindow()) - { - int nHot = GetHotItem(); - if(nHot != -1) - { - if(wParam != VK_RETURN) - { - if(!m_bSkipPostDown) - { -// IE4 only: WM_KEYDOWN doesn't generate TBN_DROPDOWN, we need to simulate a mouse click -#if (_WIN32_IE < 0x0500) - DWORD dwMajor = 0, dwMinor = 0; - ATL::AtlGetCommCtrlVersion(&dwMajor, &dwMinor); - if(dwMajor <= 4 || (dwMajor == 5 && dwMinor < 80)) - { - RECT rect; - GetItemRect(nHot, &rect); - PostMessage(WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(rect.left, rect.top)); - } -#endif // (_WIN32_IE < 0x0500) - PostMessage(WM_KEYDOWN, VK_DOWN, 0L); - m_bSkipPostDown = true; - } - else - { - ATLTRACE2(atlTraceUI, 0, _T("CmdBar - skipping posting another VK_DOWN\n")); - m_bSkipPostDown = false; - } - } - } - else - { - ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Can't find hot button\n")); - } - } - if(wParam == VK_RETURN && m_bMenuActive) - { - PostMessage(TB_SETHOTITEM, (WPARAM)-1, 0L); - m_nNextPopBtn = -1; - pT->GiveFocusBack(); - } - } - else if(wParam == VK_LEFT || wParam == VK_RIGHT) - { - WPARAM wpNext = m_bLayoutRTL ? VK_LEFT : VK_RIGHT; - WPARAM wpPrev = m_bLayoutRTL ? VK_RIGHT : VK_LEFT; - - if(m_bMenuActive && !m_bContextMenu && !(wParam == wpNext && m_bPopupItem)) - { - bool bAction = false; - if(wParam == wpPrev && s_pCurrentBar->m_stackMenuWnd.GetSize() == 1) - { - m_nNextPopBtn = pT->GetPreviousMenuItem(m_nPopBtn); - if(m_nNextPopBtn != -1) - bAction = true; - } - else if(wParam == wpNext) - { - m_nNextPopBtn = pT->GetNextMenuItem(m_nPopBtn); - if(m_nNextPopBtn != -1) - bAction = true; - } - HWND hWndMenu = m_stackMenuWnd.GetCurrent(); - ATLASSERT(hWndMenu != NULL); - - // Close the popup menu - if(bAction) - { - ::PostMessage(hWndMenu, WM_KEYDOWN, VK_ESCAPE, 0L); - if(wParam == wpNext) - { - int cItem = m_stackMenuWnd.GetSize() - 1; - while(cItem >= 0) - { - hWndMenu = m_stackMenuWnd[cItem]; - if(hWndMenu != NULL) - ::PostMessage(hWndMenu, WM_KEYDOWN, VK_ESCAPE, 0L); - cItem--; - } - } -#if (_WIN32_IE >= 0x0500) - if(m_nNextPopBtn == -2) - { - m_nNextPopBtn = -1; - pT->DisplayChevronMenu(); - } -#endif // (_WIN32_IE >= 0x0500) - bHandled = TRUE; - } - } - } - return 0; - } - - LRESULT OnHookNextMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_NEXTMENU\n")); -#endif - bHandled = FALSE; - return 1; - } - - LRESULT OnHookChar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) - { -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_CHAR (0x%2.2X)\n"), wParam); -#endif - bHandled = (wParam == VK_ESCAPE); - return 0; - } - -// Implementation - ownerdraw overrideables and helpers - void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) - { - T* pT = static_cast(this); - if(m_bFlatMenus) - pT->DrawItemFlat(lpDrawItemStruct); - else - pT->DrawItem3D(lpDrawItemStruct); - - } - - void DrawItem3D(LPDRAWITEMSTRUCT lpDrawItemStruct) - { - _MenuItemData* pmd = (_MenuItemData*)lpDrawItemStruct->itemData; - CDCHandle dc = lpDrawItemStruct->hDC; - const RECT& rcItem = lpDrawItemStruct->rcItem; - T* pT = static_cast(this); - - if(pmd->fType & MFT_SEPARATOR) - { - // draw separator - RECT rc = rcItem; - rc.top += (rc.bottom - rc.top) / 2; // vertical center - dc.DrawEdge(&rc, EDGE_ETCHED, BF_TOP); // draw separator line - } - else // not a separator - { - BOOL bDisabled = lpDrawItemStruct->itemState & ODS_GRAYED; - BOOL bSelected = lpDrawItemStruct->itemState & ODS_SELECTED; - BOOL bChecked = lpDrawItemStruct->itemState & ODS_CHECKED; - BOOL bHasImage = FALSE; - - if(LOWORD(lpDrawItemStruct->itemID) == (WORD)-1) - bSelected = FALSE; - RECT rcButn = { rcItem.left, rcItem.top, rcItem.left + m_szButton.cx, rcItem.top + m_szButton.cy }; // button rect - ::OffsetRect(&rcButn, 0, ((rcItem.bottom - rcItem.top) - (rcButn.bottom - rcButn.top)) / 2); // center vertically - - int iButton = pmd->iButton; - if(iButton >= 0) - { - bHasImage = TRUE; - - // calc drawing point - SIZE sz = { rcButn.right - rcButn.left - m_szBitmap.cx, rcButn.bottom - rcButn.top - m_szBitmap.cy }; - sz.cx /= 2; - sz.cy /= 2; - POINT point = { rcButn.left + sz.cx, rcButn.top + sz.cy }; - - // fill background depending on state - if(!bChecked || (bSelected && !bDisabled)) - { - if(!bDisabled) - dc.FillRect(&rcButn, (bChecked && !bSelected) ? COLOR_3DLIGHT : COLOR_MENU); - else - dc.FillRect(&rcButn, COLOR_MENU); - } - else - { - COLORREF crTxt = dc.SetTextColor(::GetSysColor(COLOR_BTNFACE)); - COLORREF crBk = dc.SetBkColor(::GetSysColor(COLOR_BTNHILIGHT)); - CBrush hbr(CDCHandle::GetHalftoneBrush()); - dc.SetBrushOrg(rcButn.left, rcButn.top); - dc.FillRect(&rcButn, hbr); - dc.SetTextColor(crTxt); - dc.SetBkColor(crBk); - } - - // draw disabled or normal - if(!bDisabled) - { - // draw pushed-in or popped-out edge - if(bSelected || bChecked) - { - RECT rc2 = rcButn; - dc.DrawEdge(&rc2, bChecked ? BDR_SUNKENOUTER : BDR_RAISEDINNER, BF_RECT); - } - // draw the image - ::ImageList_Draw(m_hImageList, iButton, dc, point.x, point.y, ILD_TRANSPARENT); - } - else - { - HBRUSH hBrushBackground = bChecked ? NULL : ::GetSysColorBrush(COLOR_MENU); - pT->DrawBitmapDisabled(dc, iButton, point, hBrushBackground); - } - } - else - { - // no image - look for custom checked/unchecked bitmaps - CMenuItemInfo info; - info.fMask = MIIM_CHECKMARKS | MIIM_TYPE; - ::GetMenuItemInfo((HMENU)lpDrawItemStruct->hwndItem, lpDrawItemStruct->itemID, MF_BYCOMMAND, &info); - if(bChecked || info.hbmpUnchecked != NULL) - { - BOOL bRadio = ((info.fType & MFT_RADIOCHECK) != 0); - bHasImage = pT->DrawCheckmark(dc, rcButn, bSelected, bDisabled, bRadio, bChecked ? info.hbmpChecked : info.hbmpUnchecked); - } - } - - // draw item text - int cxButn = m_szButton.cx; - COLORREF colorBG = ::GetSysColor(bSelected ? COLOR_HIGHLIGHT : COLOR_MENU); - if(bSelected || lpDrawItemStruct->itemAction == ODA_SELECT) - { - RECT rcBG = rcItem; - if(bHasImage) - rcBG.left += cxButn + s_kcxGap; - dc.FillRect(&rcBG, bSelected ? COLOR_HIGHLIGHT : COLOR_MENU); - } - - // calc text rectangle and colors - RECT rcText = rcItem; - rcText.left += cxButn + s_kcxGap + s_kcxTextMargin; - rcText.right -= cxButn; - dc.SetBkMode(TRANSPARENT); - COLORREF colorText = ::GetSysColor(bDisabled ? (bSelected ? COLOR_GRAYTEXT : COLOR_3DSHADOW) : (bSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT)); - - // font already selected by Windows - if(bDisabled && (!bSelected || colorText == colorBG)) - { - // disabled - draw shadow text shifted down and right 1 pixel (unles selected) - RECT rcDisabled = rcText; - ::OffsetRect(&rcDisabled, 1, 1); - pT->DrawMenuText(dc, rcDisabled, pmd->lpstrText, ::GetSysColor(COLOR_3DHILIGHT)); - } - pT->DrawMenuText(dc, rcText, pmd->lpstrText, colorText); // finally! - } - } - - void DrawItemFlat(LPDRAWITEMSTRUCT lpDrawItemStruct) - { - _MenuItemData* pmd = (_MenuItemData*)lpDrawItemStruct->itemData; - CDCHandle dc = lpDrawItemStruct->hDC; - const RECT& rcItem = lpDrawItemStruct->rcItem; - T* pT = static_cast(this); - -#ifndef COLOR_MENUHILIGHT - const int COLOR_MENUHILIGHT = 29; -#endif // !COLOR_MENUHILIGHT - - BOOL bDisabled = lpDrawItemStruct->itemState & ODS_GRAYED; - BOOL bSelected = lpDrawItemStruct->itemState & ODS_SELECTED; - BOOL bChecked = lpDrawItemStruct->itemState & ODS_CHECKED; - - // paint background - if(bSelected || lpDrawItemStruct->itemAction == ODA_SELECT) - { - if(bSelected) - { - dc.FillRect(&rcItem, ::GetSysColorBrush(COLOR_MENUHILIGHT)); - dc.FrameRect(&rcItem, ::GetSysColorBrush(COLOR_HIGHLIGHT)); - } - else - { - dc.FillRect(&rcItem, ::GetSysColorBrush(COLOR_MENU)); - } - } - - if(pmd->fType & MFT_SEPARATOR) - { - // draw separator - RECT rc = rcItem; - rc.top += (rc.bottom - rc.top) / 2; // vertical center - dc.DrawEdge(&rc, EDGE_ETCHED, BF_TOP); // draw separator line - } - else // not a separator - { - if(LOWORD(lpDrawItemStruct->itemID) == (WORD)-1) - bSelected = FALSE; - RECT rcButn = { rcItem.left, rcItem.top, rcItem.left + m_szButton.cx, rcItem.top + m_szButton.cy }; // button rect - ::OffsetRect(&rcButn, 0, ((rcItem.bottom - rcItem.top) - (rcButn.bottom - rcButn.top)) / 2); // center vertically - - // draw background and border for checked items - if(bChecked) - { - RECT rcCheck = rcButn; - ::InflateRect(&rcCheck, -1, -1); - if(bSelected) - dc.FillRect(&rcCheck, ::GetSysColorBrush(COLOR_MENU)); - dc.FrameRect(&rcCheck, ::GetSysColorBrush(COLOR_HIGHLIGHT)); - } - - int iButton = pmd->iButton; - if(iButton >= 0) - { - // calc drawing point - SIZE sz = { rcButn.right - rcButn.left - m_szBitmap.cx, rcButn.bottom - rcButn.top - m_szBitmap.cy }; - sz.cx /= 2; - sz.cy /= 2; - POINT point = { rcButn.left + sz.cx, rcButn.top + sz.cy }; - - // draw disabled or normal - if(!bDisabled) - { - ::ImageList_Draw(m_hImageList, iButton, dc, point.x, point.y, ILD_TRANSPARENT); - } - else - { - HBRUSH hBrushBackground = ::GetSysColorBrush((bSelected && !(bDisabled && bChecked)) ? COLOR_MENUHILIGHT : COLOR_MENU); - HBRUSH hBrushDisabledImage = ::GetSysColorBrush(COLOR_3DSHADOW); - pT->DrawBitmapDisabled(dc, iButton, point, hBrushBackground, hBrushBackground, hBrushDisabledImage); - } - } - else - { - // no image - look for custom checked/unchecked bitmaps - CMenuItemInfo info; - info.fMask = MIIM_CHECKMARKS | MIIM_TYPE; - ::GetMenuItemInfo((HMENU)lpDrawItemStruct->hwndItem, lpDrawItemStruct->itemID, MF_BYCOMMAND, &info); - if(bChecked || info.hbmpUnchecked != NULL) - { - BOOL bRadio = ((info.fType & MFT_RADIOCHECK) != 0); - pT->DrawCheckmark(dc, rcButn, bSelected, bDisabled, bRadio, bChecked ? info.hbmpChecked : info.hbmpUnchecked); - } - } - - // draw item text - int cxButn = m_szButton.cx; - // calc text rectangle and colors - RECT rcText = rcItem; - rcText.left += cxButn + s_kcxGap + s_kcxTextMargin; - rcText.right -= cxButn; - dc.SetBkMode(TRANSPARENT); - COLORREF colorText = ::GetSysColor(bDisabled ? (bSelected ? COLOR_GRAYTEXT : COLOR_3DSHADOW) : (bSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT)); - - pT->DrawMenuText(dc, rcText, pmd->lpstrText, colorText); // finally! - } - } - - void DrawMenuText(CDCHandle& dc, RECT& rc, LPCTSTR lpstrText, COLORREF color) - { - int nTab = -1; - for(int i = 0; i < lstrlen(lpstrText); i++) - { - if(lpstrText[i] == _T('\t')) - { - nTab = i; - break; - } - } - dc.SetTextColor(color); - dc.DrawText(lpstrText, nTab, &rc, DT_SINGLELINE | DT_LEFT | DT_VCENTER | (m_bShowKeyboardCues ? 0 : DT_HIDEPREFIX)); - if(nTab != -1) - dc.DrawText(&lpstrText[nTab + 1], -1, &rc, DT_SINGLELINE | DT_RIGHT | DT_VCENTER | (m_bShowKeyboardCues ? 0 : DT_HIDEPREFIX)); - } - - void DrawBitmapDisabled(CDCHandle& dc, int nImage, POINT point, - HBRUSH hBrushBackground = ::GetSysColorBrush(COLOR_3DFACE), - HBRUSH hBrush3DEffect = ::GetSysColorBrush(COLOR_3DHILIGHT), - HBRUSH hBrushDisabledImage = ::GetSysColorBrush(COLOR_3DSHADOW)) - { -#if (_WIN32_WINNT >= 0x0501) && (_WIN32_IE >= 0x0501) - if(m_bAlphaImages) - { - IMAGELISTDRAWPARAMS ildp = { 0 }; - ildp.cbSize = sizeof(IMAGELISTDRAWPARAMS); - ildp.himl = m_hImageList; - ildp.i = nImage; - ildp.hdcDst = dc; - ildp.x = point.x; - ildp.y = point.y; - ildp.cx = 0; - ildp.cy = 0; - ildp.xBitmap = 0; - ildp.yBitmap = 0; - ildp.fStyle = ILD_TRANSPARENT; - ildp.fState = ILS_SATURATE; - ildp.Frame = 0; - ::ImageList_DrawIndirect(&ildp); - } - else -#endif // (_WIN32_WINNT >= 0x0501) && (_WIN32_IE >= 0x0501) - { - // create memory DC - CDC dcMem; - dcMem.CreateCompatibleDC(dc); - // create mono or color bitmap - CBitmap bmp; - bmp.CreateCompatibleBitmap(dc, m_szBitmap.cx, m_szBitmap.cy); - ATLASSERT(bmp.m_hBitmap != NULL); - // draw image into memory DC--fill BG white first - HBITMAP hBmpOld = dcMem.SelectBitmap(bmp); - dcMem.PatBlt(0, 0, m_szBitmap.cx, m_szBitmap.cy, WHITENESS); - // If white is the text color, we can't use the normal painting since - // it would blend with the WHITENESS, but the mask is OK - UINT uDrawStyle = (::GetSysColor(COLOR_BTNTEXT) == RGB(255, 255, 255)) ? ILD_MASK : ILD_NORMAL; - ::ImageList_Draw(m_hImageList, nImage, dcMem, 0, 0, uDrawStyle); - dc.DitherBlt(point.x, point.y, m_szBitmap.cx, m_szBitmap.cy, dcMem, NULL, 0, 0, hBrushBackground, hBrush3DEffect, hBrushDisabledImage); - dcMem.SelectBitmap(hBmpOld); // restore - } - } - - // old name - BOOL Draw3DCheckmark(CDCHandle& dc, const RECT& rc, BOOL bSelected, BOOL bDisabled, BOOL bRadio, HBITMAP hBmpCheck) - { - return DrawCheckmark(dc, rc, bSelected, bDisabled, bRadio, hBmpCheck); - } - - BOOL DrawCheckmark(CDCHandle& dc, const RECT& rc, BOOL bSelected, BOOL bDisabled, BOOL bRadio, HBITMAP hBmpCheck) - { - // get checkmark bitmap, if none, use Windows standard - SIZE size = { 0, 0 }; - CBitmapHandle bmp = hBmpCheck; - if(hBmpCheck != NULL) - { - bmp.GetSize(size); - } - else - { - size.cx = ::GetSystemMetrics(SM_CXMENUCHECK); - size.cy = ::GetSystemMetrics(SM_CYMENUCHECK); - bmp.CreateCompatibleBitmap(dc, size.cx, size.cy); - ATLASSERT(bmp.m_hBitmap != NULL); - } - // center bitmap in caller's rectangle - RECT rcDest = rc; - if((rc.right - rc.left) > size.cx) - { - rcDest.left = rc.left + (rc.right - rc.left - size.cx) / 2; - rcDest.right = rcDest.left + size.cx; - } - if((rc.bottom - rc.top) > size.cy) - { - rcDest.top = rc.top + (rc.bottom - rc.top - size.cy) / 2; - rcDest.bottom = rcDest.top + size.cy; - } - // paint background - if(!m_bFlatMenus) - { - if(bSelected && !bDisabled) - { - dc.FillRect(&rcDest, COLOR_MENU); - } - else - { - COLORREF clrTextOld = dc.SetTextColor(::GetSysColor(COLOR_BTNFACE)); - COLORREF clrBkOld = dc.SetBkColor(::GetSysColor(COLOR_BTNHILIGHT)); - CBrush hbr(CDCHandle::GetHalftoneBrush()); - dc.SetBrushOrg(rcDest.left, rcDest.top); - dc.FillRect(&rcDest, hbr); - dc.SetTextColor(clrTextOld); - dc.SetBkColor(clrBkOld); - } - } - - // create source image - CDC dcSource; - dcSource.CreateCompatibleDC(dc); - HBITMAP hBmpOld = dcSource.SelectBitmap(bmp); - // set colors - const COLORREF clrBlack = RGB(0, 0, 0); - const COLORREF clrWhite = RGB(255, 255, 255); - COLORREF clrTextOld = dc.SetTextColor(clrBlack); - COLORREF clrBkOld = dc.SetBkColor(clrWhite); - // create mask - CDC dcMask; - dcMask.CreateCompatibleDC(dc); - CBitmap bmpMask; - bmpMask.CreateBitmap(size.cx, size.cy, 1, 1, NULL); - HBITMAP hBmpOld1 = dcMask.SelectBitmap(bmpMask); - - // draw the checkmark transparently - int cx = rcDest.right - rcDest.left; - int cy = rcDest.bottom - rcDest.top; - if(hBmpCheck != NULL) - { - // build mask based on transparent color - dcSource.SetBkColor(m_clrMask); - dcMask.SetBkColor(clrBlack); - dcMask.SetTextColor(clrWhite); - dcMask.BitBlt(0, 0, size.cx, size.cy, dcSource, 0, 0, SRCCOPY); - // draw bitmap using the mask - dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcSource, 0, 0, SRCINVERT); - dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcMask, 0, 0, SRCAND); - dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcSource, 0, 0, SRCINVERT); - } - else - { - const DWORD ROP_DSno = 0x00BB0226L; - const DWORD ROP_DSa = 0x008800C6L; - const DWORD ROP_DSo = 0x00EE0086L; - const DWORD ROP_DSna = 0x00220326L; - - // draw mask - RECT rcSource = { 0, 0, min(size.cx, rc.right - rc.left), min(size.cy, rc.bottom - rc.top) }; - dcMask.DrawFrameControl(&rcSource, DFC_MENU, bRadio ? DFCS_MENUBULLET : DFCS_MENUCHECK); - - // draw shadow if disabled - if(!m_bFlatMenus && bDisabled) - { - // offset by one pixel - int x = rcDest.left + 1; - int y = rcDest.top + 1; - // paint source bitmap - const int nColor = COLOR_3DHILIGHT; - dcSource.FillRect(&rcSource, nColor); - // draw checkmark - special case black and white colors - COLORREF clrCheck = ::GetSysColor(nColor); - if(clrCheck == clrWhite) - { - dc.BitBlt(x, y, cx, cy, dcMask, 0, 0, ROP_DSno); - dc.BitBlt(x, y, cx, cy, dcSource, 0, 0, ROP_DSa); - } - else - { - if(clrCheck != clrBlack) - { - ATLASSERT(dcSource.GetTextColor() == clrBlack); - ATLASSERT(dcSource.GetBkColor() == clrWhite); - dcSource.BitBlt(0, 0, size.cx, size.cy, dcMask, 0, 0, ROP_DSna); - } - dc.BitBlt(x, y, cx, cy, dcMask, 0, 0, ROP_DSa); - dc.BitBlt(x, y, cx, cy, dcSource, 0, 0, ROP_DSo); - } - } - - // paint source bitmap - const int nColor = bDisabled ? COLOR_BTNSHADOW : COLOR_MENUTEXT; - dcSource.FillRect(&rcSource, nColor); - // draw checkmark - special case black and white colors - COLORREF clrCheck = ::GetSysColor(nColor); - if(clrCheck == clrWhite) - { - dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcMask, 0, 0, ROP_DSno); - dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcSource, 0, 0, ROP_DSa); - } - else - { - if(clrCheck != clrBlack) - { - ATLASSERT(dcSource.GetTextColor() == clrBlack); - ATLASSERT(dcSource.GetBkColor() == clrWhite); - dcSource.BitBlt(0, 0, size.cx, size.cy, dcMask, 0, 0, ROP_DSna); - } - dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcMask, 0, 0, ROP_DSa); - dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcSource, 0, 0, ROP_DSo); - } - } - // restore all - dc.SetTextColor(clrTextOld); - dc.SetBkColor(clrBkOld); - dcSource.SelectBitmap(hBmpOld); - dcMask.SelectBitmap(hBmpOld1); - if(hBmpCheck == NULL) - bmp.DeleteObject(); - // draw pushed-in hilight - if(!m_bFlatMenus && !bDisabled) - { - if(rc.right - rc.left > size.cx) - ::InflateRect(&rcDest, 1,1); // inflate checkmark by one pixel all around - dc.DrawEdge(&rcDest, BDR_SUNKENOUTER, BF_RECT); - } - - return TRUE; - } - - void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) - { - _MenuItemData* pmd = (_MenuItemData*)lpMeasureItemStruct->itemData; - - if(pmd->fType & MFT_SEPARATOR) // separator - use half system height and zero width - { - lpMeasureItemStruct->itemHeight = ::GetSystemMetrics(SM_CYMENU) / 2; - lpMeasureItemStruct->itemWidth = 0; - } - else - { - // compute size of text - use DrawText with DT_CALCRECT - CWindowDC dc(NULL); - CFont fontBold; - HFONT hOldFont = NULL; - if(pmd->fState & MFS_DEFAULT) - { - // need bold version of font - LOGFONT lf = { 0 }; - m_fontMenu.GetLogFont(lf); - lf.lfWeight += 200; - fontBold.CreateFontIndirect(&lf); - ATLASSERT(fontBold.m_hFont != NULL); - hOldFont = dc.SelectFont(fontBold); - } - else - { - hOldFont = dc.SelectFont(m_fontMenu); - } - - RECT rcText = { 0, 0, 0, 0 }; - dc.DrawText(pmd->lpstrText, -1, &rcText, DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_CALCRECT); - int cx = rcText.right - rcText.left; - dc.SelectFont(hOldFont); - - LOGFONT lf = { 0 }; - m_fontMenu.GetLogFont(lf); - int cy = lf.lfHeight; - if(cy < 0) - cy = -cy; - const int cyMargin = 8; - cy += cyMargin; - - // height of item is the bigger of these two - lpMeasureItemStruct->itemHeight = max(cy, (int)m_szButton.cy); - - // width is width of text plus a bunch of stuff - cx += 2 * s_kcxTextMargin; // L/R margin for readability - cx += s_kcxGap; // space between button and menu text - cx += 2 * m_szButton.cx; // button width (L=button; R=empty margin) - cx += m_cxExtraSpacing; // extra between item text and accelerator keys - - // Windows adds 1 to returned value - cx -= ::GetSystemMetrics(SM_CXMENUCHECK) - 1; - lpMeasureItemStruct->itemWidth = cx; // done deal - } - } - -// Implementation - Hook procs - static LRESULT CALLBACK CreateHookProc(int nCode, WPARAM wParam, LPARAM lParam) - { - const int cchClassName = 7; - TCHAR szClassName[cchClassName] = { 0 }; - - if(nCode == HCBT_CREATEWND) - { - HWND hWndMenu = (HWND)wParam; -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("CmdBar - HCBT_CREATEWND (HWND = %8.8X)\n"), hWndMenu); -#endif - - ::GetClassName(hWndMenu, szClassName, cchClassName); - if(!lstrcmp(_T("#32768"), szClassName)) - s_pCurrentBar->m_stackMenuWnd.Push(hWndMenu); - } - else if(nCode == HCBT_DESTROYWND) - { - HWND hWndMenu = (HWND)wParam; -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("CmdBar - HCBT_DESTROYWND (HWND = %8.8X)\n"), hWndMenu); -#endif - - ::GetClassName(hWndMenu, szClassName, cchClassName); - if(!lstrcmp(_T("#32768"), szClassName)) - { - ATLASSERT(hWndMenu == s_pCurrentBar->m_stackMenuWnd.GetCurrent()); - s_pCurrentBar->m_stackMenuWnd.Pop(); - } - } - - return ::CallNextHookEx(s_hCreateHook, nCode, wParam, lParam); - } - - static LRESULT CALLBACK MessageHookProc(int nCode, WPARAM wParam, LPARAM lParam) - { - LPMSG pMsg = (LPMSG)lParam; - - if(nCode == HC_ACTION && wParam == PM_REMOVE && pMsg->message != GetGetBarMessage() && pMsg->message != WM_FORWARDMSG) - { - CCommandBarCtrlBase* pCmdBar = NULL; - HWND hWnd = pMsg->hwnd; - DWORD dwPID = 0; - while(pCmdBar == NULL && hWnd != NULL) - { - pCmdBar = (CCommandBarCtrlBase*)::SendMessage(hWnd, GetGetBarMessage(), (WPARAM)&dwPID, 0L); - hWnd = ::GetParent(hWnd); - } - - if(pCmdBar != NULL && dwPID == GetCurrentProcessId()) - { - pCmdBar->m_hWndHook = pMsg->hwnd; - ATLASSERT(pCmdBar->IsCommandBarBase()); - - if(::IsWindow(pCmdBar->m_hWnd)) - pCmdBar->SendMessage(WM_FORWARDMSG, 0, (LPARAM)pMsg); - else - ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook skipping message, can't find command bar!\n")); - } - } - - LRESULT lRet = 0; - ATLASSERT(s_pmapMsgHook != NULL); - if(s_pmapMsgHook != NULL) - { - DWORD dwThreadID = ::GetCurrentThreadId(); - _MsgHookData* pData = s_pmapMsgHook->Lookup(dwThreadID); - if(pData != NULL) - { - lRet = ::CallNextHookEx(pData->hMsgHook, nCode, wParam, lParam); - } - } - return lRet; - } - -// Implementation - void DoPopupMenu(int nIndex, bool bAnimate) - { -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("CmdBar - DoPopupMenu, bAnimate = %s\n"), bAnimate ? "true" : "false"); -#endif - - // Menu animation flags -#ifndef TPM_VERPOSANIMATION - const UINT TPM_VERPOSANIMATION = 0x1000L; -#endif -#ifndef TPM_NOANIMATION - const UINT TPM_NOANIMATION = 0x4000L; -#endif - T* pT = static_cast(this); - - // get popup menu and it's position - RECT rect = { 0 }; - GetItemRect(nIndex, &rect); - POINT pt = { rect.left, rect.bottom }; - MapWindowPoints(NULL, &pt, 1); - MapWindowPoints(NULL, &rect); - TPMPARAMS TPMParams = { 0 }; - TPMParams.cbSize = sizeof(TPMPARAMS); - TPMParams.rcExclude = rect; - HMENU hMenuPopup = ::GetSubMenu(m_hMenu, nIndex); - ATLASSERT(hMenuPopup != NULL); - - // get button ID - TBBUTTON tbb = { 0 }; - GetButton(nIndex, &tbb); - int nCmdID = tbb.idCommand; - - m_nPopBtn = nIndex; // remember current button's index - - // press button and display popup menu - PressButton(nCmdID, TRUE); - SetHotItem(nCmdID); - pT->DoTrackPopupMenu(hMenuPopup, TPM_LEFTBUTTON | TPM_VERTICAL | TPM_LEFTALIGN | TPM_TOPALIGN | - (s_bW2K ? (bAnimate ? TPM_VERPOSANIMATION : TPM_NOANIMATION) : 0), pt.x, pt.y, &TPMParams); - PressButton(nCmdID, FALSE); - if(::GetFocus() != m_hWnd) - SetHotItem(-1); - - m_nPopBtn = -1; // restore - - // eat next message if click is on the same button - MSG msg = { 0 }; - if(::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_NOREMOVE) && ::PtInRect(&rect, msg.pt)) - ::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_REMOVE); - - // check if another popup menu should be displayed - if(m_nNextPopBtn != -1) - { - PostMessage(GetAutoPopupMessage(), m_nNextPopBtn & 0xFFFF); - if(!(m_nNextPopBtn & 0xFFFF0000) && !m_bPopupItem) - PostMessage(WM_KEYDOWN, VK_DOWN, 0); - m_nNextPopBtn = -1; - } - else - { - m_bContextMenu = false; - // If user didn't hit escape, give focus back - if(!m_bEscapePressed) - { - if(m_bUseKeyboardCues && m_bShowKeyboardCues) - m_bAllowKeyboardCues = false; - pT->GiveFocusBack(); - } - else - { - SetHotItem(nCmdID); - SetAnchorHighlight(TRUE); - } - } - } - - BOOL DoTrackPopupMenu(HMENU hMenu, UINT uFlags, int x, int y, LPTPMPARAMS lpParams = NULL) - { - CMenuHandle menuPopup = hMenu; - - CWindowCreateCriticalSectionLock lock; - if(FAILED(lock.Lock())) - { - ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CCommandBarCtrlImpl::DoTrackPopupMenu.\n")); - ATLASSERT(FALSE); - return FALSE; - } - - ATLASSERT(s_hCreateHook == NULL); - - s_pCurrentBar = static_cast(this); - - s_hCreateHook = ::SetWindowsHookEx(WH_CBT, CreateHookProc, ModuleHelper::GetModuleInstance(), GetCurrentThreadId()); - ATLASSERT(s_hCreateHook != NULL); - - m_bPopupItem = false; - m_bMenuActive = true; - - BOOL bTrackRet = menuPopup.TrackPopupMenuEx(uFlags, x, y, m_hWnd, lpParams); - m_bMenuActive = false; - - ::UnhookWindowsHookEx(s_hCreateHook); - - s_hCreateHook = NULL; - s_pCurrentBar = NULL; - - lock.Unlock(); - - // cleanup - convert menus back to original state -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("CmdBar - TrackPopupMenu - cleanup\n")); -#endif - - ATLASSERT(m_stackMenuWnd.GetSize() == 0); - - UpdateWindow(); - ATL::CWindow wndTL = GetTopLevelParent(); - wndTL.UpdateWindow(); - - // restore the menu items to the previous state for all menus that were converted - if(m_bImagesVisible) - { - HMENU hMenuSav = NULL; - while((hMenuSav = m_stackMenuHandle.Pop()) != NULL) - { - menuPopup = hMenuSav; - BOOL bRet = FALSE; - // restore state and delete menu item data - for(int i = 0; i < menuPopup.GetMenuItemCount(); i++) - { - CMenuItemInfo mii; - mii.fMask = MIIM_DATA | MIIM_TYPE | MIIM_ID; - bRet = menuPopup.GetMenuItemInfo(i, TRUE, &mii); - ATLASSERT(bRet); - - _MenuItemData* pMI = (_MenuItemData*)mii.dwItemData; - if(pMI != NULL && pMI->IsCmdBarMenuItem()) - { - mii.fMask = MIIM_DATA | MIIM_TYPE | MIIM_STATE; - mii.fType = pMI->fType; - mii.fState = pMI->fState; - mii.dwTypeData = pMI->lpstrText; - mii.cch = lstrlen(pMI->lpstrText); - mii.dwItemData = NULL; - - bRet = menuPopup.SetMenuItemInfo(i, TRUE, &mii); - // this one triggers WM_MEASUREITEM - menuPopup.ModifyMenu(i, MF_BYPOSITION | mii.fType | mii.fState, mii.wID, pMI->lpstrText); - ATLASSERT(bRet); - - delete [] pMI->lpstrText; - delete pMI; - } - } - } - } - return bTrackRet; - } - - int GetPreviousMenuItem(int nBtn) const - { - if(nBtn == -1) - return -1; -#if (_WIN32_IE >= 0x0500) - RECT rcClient; - GetClientRect(&rcClient); -#endif // (_WIN32_IE >= 0x0500) - int nNextBtn; - for(nNextBtn = nBtn - 1; nNextBtn != nBtn; nNextBtn--) - { - if(nNextBtn < 0) - nNextBtn = ::GetMenuItemCount(m_hMenu) - 1; - TBBUTTON tbb = { 0 }; - GetButton(nNextBtn, &tbb); -#if (_WIN32_IE >= 0x0500) - RECT rcBtn; - GetItemRect(nNextBtn, &rcBtn); - if(rcBtn.right > rcClient.right) - { - nNextBtn = -2; // chevron - break; - } -#endif // (_WIN32_IE >= 0x0500) - if((tbb.fsState & TBSTATE_ENABLED) != 0 && (tbb.fsState & TBSTATE_HIDDEN) == 0) - break; - } - return (nNextBtn != nBtn) ? nNextBtn : -1; - } - - int GetNextMenuItem(int nBtn) const - { - if(nBtn == -1) - return -1; -#if (_WIN32_IE >= 0x0500) - RECT rcClient = { 0 }; - GetClientRect(&rcClient); -#endif // (_WIN32_IE >= 0x0500) - int nNextBtn = 0; - int nCount = ::GetMenuItemCount(m_hMenu); - for(nNextBtn = nBtn + 1; nNextBtn != nBtn; nNextBtn++) - { - if(nNextBtn >= nCount) - nNextBtn = 0; - TBBUTTON tbb = { 0 }; - GetButton(nNextBtn, &tbb); -#if (_WIN32_IE >= 0x0500) - RECT rcBtn = { 0 }; - GetItemRect(nNextBtn, &rcBtn); - if(rcBtn.right > rcClient.right) - { - nNextBtn = -2; // chevron - break; - } -#endif // (_WIN32_IE >= 0x0500) - if((tbb.fsState & TBSTATE_ENABLED) != 0 && (tbb.fsState & TBSTATE_HIDDEN) == 0) - break; - } - return (nNextBtn != nBtn) ? nNextBtn : -1; - } - -#if (_WIN32_IE >= 0x0500) - bool DisplayChevronMenu() - { - // assume we are in a rebar - HWND hWndReBar = GetParent(); - int nCount = (int)::SendMessage(hWndReBar, RB_GETBANDCOUNT, 0, 0L); - bool bRet = false; - for(int i = 0; i < nCount; i++) - { - REBARBANDINFO rbbi = { RunTimeHelper::SizeOf_REBARBANDINFO(), RBBIM_CHILD | RBBIM_STYLE }; - BOOL bRetBandInfo = (BOOL)::SendMessage(hWndReBar, RB_GETBANDINFO, i, (LPARAM)&rbbi); - if(bRetBandInfo && rbbi.hwndChild == m_hWnd) - { - if((rbbi.fStyle & RBBS_USECHEVRON) != 0) - { - ::PostMessage(hWndReBar, RB_PUSHCHEVRON, i, 0L); - PostMessage(WM_KEYDOWN, VK_DOWN, 0L); - bRet = true; - } - break; - } - } - return bRet; - } -#endif // (_WIN32_IE >= 0x0500) - - void GetSystemSettings() - { - // refresh our font - NONCLIENTMETRICS info = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() }; - BOOL bRet = ::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0); - ATLASSERT(bRet); - if(bRet) - { - LOGFONT logfont = { 0 }; - if(m_fontMenu.m_hFont != NULL) - m_fontMenu.GetLogFont(logfont); - if(logfont.lfHeight != info.lfMenuFont.lfHeight || - logfont.lfWidth != info.lfMenuFont.lfWidth || - logfont.lfEscapement != info.lfMenuFont.lfEscapement || - logfont.lfOrientation != info.lfMenuFont.lfOrientation || - logfont.lfWeight != info.lfMenuFont.lfWeight || - logfont.lfItalic != info.lfMenuFont.lfItalic || - logfont.lfUnderline != info.lfMenuFont.lfUnderline || - logfont.lfStrikeOut != info.lfMenuFont.lfStrikeOut || - logfont.lfCharSet != info.lfMenuFont.lfCharSet || - logfont.lfOutPrecision != info.lfMenuFont.lfOutPrecision || - logfont.lfClipPrecision != info.lfMenuFont.lfClipPrecision || - logfont.lfQuality != info.lfMenuFont.lfQuality || - logfont.lfPitchAndFamily != info.lfMenuFont.lfPitchAndFamily || - lstrcmp(logfont.lfFaceName, info.lfMenuFont.lfFaceName) != 0) - { - HFONT hFontMenu = ::CreateFontIndirect(&info.lfMenuFont); - ATLASSERT(hFontMenu != NULL); - if(hFontMenu != NULL) - { - if(m_fontMenu.m_hFont != NULL) - m_fontMenu.DeleteObject(); - m_fontMenu.Attach(hFontMenu); - SetFont(m_fontMenu); - AddStrings(_T("NS\0")); // for proper item height - AutoSize(); - } - } - } - - // check if we need extra spacing for menu item text - CWindowDC dc(m_hWnd); - HFONT hFontOld = dc.SelectFont(m_fontMenu); - RECT rcText = { 0, 0, 0, 0 }; - dc.DrawText(_T("\t"), -1, &rcText, DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_CALCRECT); - if((rcText.right - rcText.left) < 4) - { - ::SetRectEmpty(&rcText); - dc.DrawText(_T("x"), -1, &rcText, DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_CALCRECT); - m_cxExtraSpacing = rcText.right - rcText.left; - } - else - { - m_cxExtraSpacing = 0; - } - dc.SelectFont(hFontOld); - - // get Windows version - OSVERSIONINFO ovi = { sizeof(OSVERSIONINFO) }; - ::GetVersionEx(&ovi); - - // query keyboard cues mode (Windows 2000 or later) - if(ovi.dwMajorVersion >= 5) - { -#ifndef SPI_GETKEYBOARDCUES - const UINT SPI_GETKEYBOARDCUES = 0x100A; -#endif // !SPI_GETKEYBOARDCUES - BOOL bRetVal = TRUE; - bRet = ::SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &bRetVal, 0); - m_bUseKeyboardCues = (bRet && !bRetVal); - m_bAllowKeyboardCues = true; - ShowKeyboardCues(!m_bUseKeyboardCues); - } - - // query flat menu mode (Windows XP or later) - if((ovi.dwMajorVersion == 5 && ovi.dwMinorVersion >= 1) || (ovi.dwMajorVersion > 5)) - { -#ifndef SPI_GETFLATMENU - const UINT SPI_GETFLATMENU = 0x1022; -#endif // !SPI_GETFLATMENU - BOOL bRetVal = FALSE; - bRet = ::SystemParametersInfo(SPI_GETFLATMENU, 0, &bRetVal, 0); - m_bFlatMenus = (bRet && bRetVal); - } - -#if _WTL_CMDBAR_VISTA_MENUS - // check if we should use Vista menus - bool bVistaMenus = (RunTimeHelper::IsVista() && RunTimeHelper::IsCommCtrl6() && ((m_dwExtendedStyle & CBR_EX_NOVISTAMENUS) == 0)); - - if(bVistaMenus) - { - HMODULE hThemeDLL = ::LoadLibrary(_T("uxtheme.dll")); - if(hThemeDLL != NULL) - { - typedef BOOL (STDAPICALLTYPE *PFN_IsThemeActive)(); - PFN_IsThemeActive pfnIsThemeActive = (PFN_IsThemeActive)::GetProcAddress(hThemeDLL, "IsThemeActive"); - ATLASSERT(pfnIsThemeActive != NULL); - bVistaMenus = bVistaMenus && (pfnIsThemeActive != NULL) && (pfnIsThemeActive() != FALSE); - - typedef BOOL (STDAPICALLTYPE *PFN_IsAppThemed)(); - PFN_IsAppThemed pfnIsAppThemed = (PFN_IsAppThemed)::GetProcAddress(hThemeDLL, "IsAppThemed"); - ATLASSERT(pfnIsAppThemed != NULL); - bVistaMenus = bVistaMenus && (pfnIsAppThemed != NULL) && (pfnIsAppThemed() != FALSE); - - ::FreeLibrary(hThemeDLL); - } - } - - if(!bVistaMenus && m_bVistaMenus && (m_hMenu != NULL) && (m_arrCommand.GetSize() > 0)) - { - T* pT = static_cast(this); - pT->_RemoveVistaBitmapsFromMenu(); - } - - m_bVistaMenus = bVistaMenus; -#endif // _WTL_CMDBAR_VISTA_MENUS - -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("CmdBar - GetSystemSettings:\n m_bFlatMenus = %s\n m_bUseKeyboardCues = %s m_bVistaMenus = %s\n"), - m_bFlatMenus ? "true" : "false", m_bUseKeyboardCues ? "true" : "false", m_bVistaMenus ? "true" : "false"); -#endif - } - -// Implementation - alternate focus mode support - void TakeFocus() - { - if((m_dwExtendedStyle & CBR_EX_ALTFOCUSMODE) && m_hWndFocus == NULL) - m_hWndFocus = ::GetFocus(); - SetFocus(); - } - - void GiveFocusBack() - { - if(m_bParentActive) - { - if((m_dwExtendedStyle & CBR_EX_ALTFOCUSMODE) && ::IsWindow(m_hWndFocus)) - ::SetFocus(m_hWndFocus); - else if(!(m_dwExtendedStyle & CBR_EX_ALTFOCUSMODE) && m_wndParent.IsWindow()) - m_wndParent.SetFocus(); - } - m_hWndFocus = NULL; - SetAnchorHighlight(FALSE); - if(m_bUseKeyboardCues && m_bShowKeyboardCues) - ShowKeyboardCues(false); - m_bSkipPostDown = false; - } - - void ShowKeyboardCues(bool bShow) - { - m_bShowKeyboardCues = bShow; - SetDrawTextFlags(DT_HIDEPREFIX, m_bShowKeyboardCues ? 0 : DT_HIDEPREFIX); - Invalidate(); - UpdateWindow(); - } - -// Implementation - internal message helpers - static UINT GetAutoPopupMessage() - { - static UINT uAutoPopupMessage = 0; - if(uAutoPopupMessage == 0) - { - CStaticDataInitCriticalSectionLock lock; - if(FAILED(lock.Lock())) - { - ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CCommandBarCtrlImpl::GetAutoPopupMessage.\n")); - ATLASSERT(FALSE); - return 0; - } - - if(uAutoPopupMessage == 0) - uAutoPopupMessage = ::RegisterWindowMessage(_T("WTL_CmdBar_InternalAutoPopupMsg")); - - lock.Unlock(); - } - ATLASSERT(uAutoPopupMessage != 0); - return uAutoPopupMessage; - } - - static UINT GetGetBarMessage() - { - static UINT uGetBarMessage = 0; - if(uGetBarMessage == 0) - { - CStaticDataInitCriticalSectionLock lock; - if(FAILED(lock.Lock())) - { - ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CCommandBarCtrlImpl::GetGetBarMessage.\n")); - ATLASSERT(FALSE); - return 0; - } - - if(uGetBarMessage == 0) - uGetBarMessage = ::RegisterWindowMessage(_T("WTL_CmdBar_InternalGetBarMsg")); - - lock.Unlock(); - } - ATLASSERT(uGetBarMessage != 0); - return uGetBarMessage; - } - -// Implementation - bool CreateInternalImageList(int cImages) - { - UINT uFlags = (m_bAlphaImages ? ILC_COLOR32 : ILC_COLOR24) | ILC_MASK; - m_hImageList = ::ImageList_Create(m_szBitmap.cx, m_szBitmap.cy, uFlags, cImages, 1); - ATLASSERT(m_hImageList != NULL); - return (m_hImageList != NULL); - } - -// Implementation - support for Vista menus -#if _WTL_CMDBAR_VISTA_MENUS - void _AddVistaBitmapsFromImageList(int nStartIndex, int nCount) - { - // Create display compatible memory DC - HDC hDC = ::GetDC(NULL); - CDC dcMem; - dcMem.CreateCompatibleDC(hDC); - HBITMAP hBitmapSave = dcMem.GetCurrentBitmap(); - - T* pT = static_cast(this); - // Create bitmaps for all menu items - for(int i = 0; i < nCount; i++) - { - HBITMAP hBitmap = pT->_CreateVistaBitmapHelper(nStartIndex + i, hDC, dcMem); - dcMem.SelectBitmap(hBitmapSave); - m_arrVistaBitmap.Add(hBitmap); - } - } - - void _AddVistaBitmapFromImageList(int nIndex) - { - // Create display compatible memory DC - HDC hDC = ::GetDC(NULL); - CDC dcMem; - dcMem.CreateCompatibleDC(hDC); - HBITMAP hBitmapSave = dcMem.GetCurrentBitmap(); - - // Create bitmap for menu item - T* pT = static_cast(this); - HBITMAP hBitmap = pT->_CreateVistaBitmapHelper(nIndex, hDC, dcMem); - - // Select saved bitmap back and add bitmap to the array - dcMem.SelectBitmap(hBitmapSave); - m_arrVistaBitmap.Add(hBitmap); - } - - void _ReplaceVistaBitmapFromImageList(int nIndex) - { - // Delete existing bitmap - if(m_arrVistaBitmap[nIndex] != NULL) - ::DeleteObject(m_arrVistaBitmap[nIndex]); - - // Create display compatible memory DC - HDC hDC = ::GetDC(NULL); - CDC dcMem; - dcMem.CreateCompatibleDC(hDC); - HBITMAP hBitmapSave = dcMem.GetCurrentBitmap(); - - // Create bitmap for menu item - T* pT = static_cast(this); - HBITMAP hBitmap = pT->_CreateVistaBitmapHelper(nIndex, hDC, dcMem); - - // Select saved bitmap back and replace bitmap in the array - dcMem.SelectBitmap(hBitmapSave); - m_arrVistaBitmap.SetAtIndex(nIndex, hBitmap); - } - - HBITMAP _CreateVistaBitmapHelper(int nIndex, HDC hDCSource, HDC hDCTarget) - { - // Create 32-bit bitmap - BITMAPINFO bi = { 0 }; - bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bi.bmiHeader.biWidth = m_szBitmap.cx; - bi.bmiHeader.biHeight = m_szBitmap.cy; - bi.bmiHeader.biPlanes = 1; - bi.bmiHeader.biBitCount = 32; - bi.bmiHeader.biCompression = BI_RGB; - bi.bmiHeader.biSizeImage = 0; - bi.bmiHeader.biXPelsPerMeter = 0; - bi.bmiHeader.biYPelsPerMeter = 0; - bi.bmiHeader.biClrUsed = 0; - bi.bmiHeader.biClrImportant = 0; - HBITMAP hBitmap = ::CreateDIBSection(hDCSource, &bi, DIB_RGB_COLORS, NULL, NULL, 0); - ATLASSERT(hBitmap != NULL); - - // Select bitmap into target DC and draw from image list to it - if(hBitmap != NULL) - { - ::SelectObject(hDCTarget, hBitmap); - - IMAGELISTDRAWPARAMS ildp = { 0 }; - ildp.cbSize = sizeof(IMAGELISTDRAWPARAMS); - ildp.himl = m_hImageList; - ildp.i = nIndex; - ildp.hdcDst = hDCTarget; - ildp.x = 0; - ildp.y = 0; - ildp.cx = 0; - ildp.cy = 0; - ildp.xBitmap = 0; - ildp.yBitmap = 0; - ildp.fStyle = ILD_TRANSPARENT; - ildp.fState = ILS_ALPHA; - ildp.Frame = 255; - ::ImageList_DrawIndirect(&ildp); - } - - return hBitmap; - } - - void _RemoveVistaBitmapsFromMenu() - { - CMenuHandle menu = m_hMenu; - for(int i = 0; i < m_arrCommand.GetSize(); i++) - { - CMenuItemInfo mii; - mii.fMask = MIIM_BITMAP; - mii.hbmpItem = NULL; - menu.SetMenuItemInfo(m_arrCommand[i], FALSE, &mii); - } - } -#endif // _WTL_CMDBAR_VISTA_MENUS -}; - - -class CCommandBarCtrl : public CCommandBarCtrlImpl -{ -public: - DECLARE_WND_SUPERCLASS(_T("WTL_CommandBar"), GetWndClassName()) -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CMDICommandBarCtrl - ATL implementation of Command Bars for MDI apps - -template -class ATL_NO_VTABLE CMDICommandBarCtrlImpl : public CCommandBarCtrlImpl< T, TBase, TWinTraits> -{ -public: -// Data members - ATL::CContainedWindow m_wndMDIClient; - bool m_bChildMaximized; - HWND m_hWndChildMaximized; - HICON m_hIconChildMaximized; - int m_nBtnPressed; - int m_nBtnWasPressed; - - int m_cxyOffset; // offset between nonclient elements - int m_cxIconWidth; // small icon width - int m_cyIconHeight; // small icon height - int m_cxBtnWidth; // nonclient button width - int m_cyBtnHeight; // nonclient button height - int m_cxLeft; // left nonclient area width - int m_cxRight; // right nonclient area width - -// Theme declarations and data members -#ifndef _WTL_NO_AUTO_THEME -#ifndef _UXTHEME_H_ - typedef HANDLE HTHEME; -#endif // !_UXTHEME_H_ - typedef HTHEME (STDAPICALLTYPE *PFN_OpenThemeData)(HWND hwnd, LPCWSTR pszClassList); - typedef HRESULT (STDAPICALLTYPE *PFN_CloseThemeData)(HTHEME hTheme); - typedef HRESULT (STDAPICALLTYPE *PFN_DrawThemeBackground)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const RECT *pClipRect); - typedef HRESULT (STDAPICALLTYPE *PFN_DrawThemeParentBackground)(HWND hwnd, HDC hdc, OPTIONAL RECT* prc); - - HMODULE m_hThemeDLL; - HTHEME m_hTheme; - PFN_DrawThemeBackground m_pfnDrawThemeBackground; - PFN_DrawThemeParentBackground m_pfnDrawThemeParentBackground; -#endif // !_WTL_NO_AUTO_THEME - -// Constructor/destructor - CMDICommandBarCtrlImpl() : - m_wndMDIClient(this, 2), m_bChildMaximized(false), - m_hWndChildMaximized(NULL), m_hIconChildMaximized(NULL), - m_nBtnPressed(-1), m_nBtnWasPressed(-1), -#ifndef _WTL_NO_AUTO_THEME - m_hThemeDLL(NULL), m_hTheme(NULL), m_pfnDrawThemeBackground(NULL), m_pfnDrawThemeParentBackground(NULL), -#endif // !_WTL_NO_AUTO_THEME - m_cxyOffset(2), - m_cxIconWidth(16), m_cyIconHeight(16), - m_cxBtnWidth(16), m_cyBtnHeight(14), - m_cxLeft(20), m_cxRight(55) - { } - - ~CMDICommandBarCtrlImpl() - { - if(m_wndMDIClient.IsWindow()) -/*scary!*/ m_wndMDIClient.UnsubclassWindow(); - } - -// Operations - BOOL SetMDIClient(HWND hWndMDIClient) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(::IsWindow(hWndMDIClient)); - if(!::IsWindow(hWndMDIClient)) - return FALSE; - -#ifdef _DEBUG - // BLOCK: Test if the passed window is MDICLIENT - { - LPCTSTR lpszMDIClientClass = _T("MDICLIENT"); - const int nNameLen = 9 + 1; // "MDICLIENT" + NULL - TCHAR szClassName[nNameLen] = { 0 }; - ::GetClassName(hWndMDIClient, szClassName, nNameLen); - ATLASSERT(lstrcmpi(szClassName, lpszMDIClientClass) == 0); - } -#endif // _DEBUG - - if(m_wndMDIClient.IsWindow()) -/*scary!*/ m_wndMDIClient.UnsubclassWindow(); - - return m_wndMDIClient.SubclassWindow(hWndMDIClient); - } - -// Message maps - typedef CCommandBarCtrlImpl< T, TBase, TWinTraits > _baseClass; - BEGIN_MSG_MAP(CMDICommandBarCtrlImpl) - MESSAGE_HANDLER(WM_CREATE, OnCreate) - MESSAGE_HANDLER(WM_DESTROY, OnDestroy) -#ifndef _WTL_NO_AUTO_THEME - MESSAGE_HANDLER(_GetThemeChangedMsg(), OnThemeChanged) -#endif // !_WTL_NO_AUTO_THEME - MESSAGE_HANDLER(WM_SIZE, OnSize) - MESSAGE_HANDLER(WM_NCCALCSIZE, OnNcCalcSize) - MESSAGE_HANDLER(WM_NCPAINT, OnNcPaint) - MESSAGE_HANDLER(WM_NCHITTEST, OnNcHitTest) - MESSAGE_HANDLER(WM_NCLBUTTONDOWN, OnNcLButtonDown) - MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove) - MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp) - MESSAGE_HANDLER(WM_NCLBUTTONDBLCLK, OnNcLButtonDblClk) - MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged) - CHAIN_MSG_MAP(_baseClass) - ALT_MSG_MAP(1) // Parent window messages - MESSAGE_HANDLER(WM_ACTIVATE, OnParentActivate) - CHAIN_MSG_MAP_ALT(_baseClass, 1) - ALT_MSG_MAP(2) // MDI client window messages - MESSAGE_HANDLER(WM_MDISETMENU, OnMDISetMenu) - // no chaining needed since this was moved from the base class here - ALT_MSG_MAP(3) // Message hook messages - MESSAGE_RANGE_HANDLER(0, 0xFFFF, OnAllHookMessages) - CHAIN_MSG_MAP_ALT(_baseClass, 3) - END_MSG_MAP() - -// Additional MDI message handlers - LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - LRESULT lRet = _baseClass::OnCreate(uMsg, wParam, lParam, bHandled); - if(lRet == (LRESULT)-1) - return lRet; - -#ifndef _WTL_NO_AUTO_THEME - // this will fail if theming is not supported - m_hThemeDLL = ::LoadLibrary(_T("uxtheme.dll")); - if(m_hThemeDLL != NULL) - { - m_pfnDrawThemeBackground = (PFN_DrawThemeBackground)::GetProcAddress(m_hThemeDLL, "DrawThemeBackground"); - ATLASSERT(m_pfnDrawThemeBackground != NULL); - if(m_pfnDrawThemeBackground != NULL) - { - T* pT = static_cast(this); - pT->_OpenThemeData(); - } - else - { - ::FreeLibrary(m_hThemeDLL); - m_hThemeDLL = NULL; - } - m_pfnDrawThemeParentBackground = (PFN_DrawThemeParentBackground)::GetProcAddress(m_hThemeDLL, "DrawThemeParentBackground"); - ATLASSERT(m_pfnDrawThemeParentBackground != NULL); - } -#endif // !_WTL_NO_AUTO_THEME - - return lRet; - } - - LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - LRESULT lRet = _baseClass::OnDestroy(uMsg, wParam, lParam, bHandled); - -#ifndef _WTL_NO_AUTO_THEME - if(m_hThemeDLL != NULL) - { - T* pT = static_cast(this); - pT->_CloseThemeData(); - ::FreeLibrary(m_hThemeDLL); - m_hThemeDLL = NULL; - } -#endif // !_WTL_NO_AUTO_THEME - - return lRet; - } - -#ifndef _WTL_NO_AUTO_THEME - LRESULT OnThemeChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - if(m_hThemeDLL != NULL) - { - T* pT = static_cast(this); - pT->_CloseThemeData(); - pT->_OpenThemeData(); - } - return 0; - } -#endif // !_WTL_NO_AUTO_THEME - - LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) - { - LRESULT lRet = DefWindowProc(uMsg, wParam, lParam); - T* pT = static_cast(this); - pT->_AdjustBtnSize(GET_Y_LPARAM(lParam)); - return lRet; - } - - LRESULT OnNcCalcSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) - { - LRESULT lRet = DefWindowProc(uMsg, wParam, lParam); - - if(m_bChildMaximized && (BOOL)wParam) - { - LPNCCALCSIZE_PARAMS lpParams = (LPNCCALCSIZE_PARAMS)lParam; - if(m_bLayoutRTL) - { - lpParams->rgrc[0].left += m_cxRight; - lpParams->rgrc[0].right -= m_cxLeft; - } - else - { - lpParams->rgrc[0].left += m_cxLeft; - lpParams->rgrc[0].right -= m_cxRight; - } - } - - return lRet; - } - - LRESULT OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) - { - LRESULT lRet = DefWindowProc(uMsg, wParam, lParam); - - if(!m_bChildMaximized) - return lRet; - - ATLASSERT(m_hWndChildMaximized != NULL && m_hIconChildMaximized != NULL); - - // get DC and window rectangle - CWindowDC dc(m_hWnd); - RECT rect; - GetWindowRect(&rect); - int cxWidth = rect.right - rect.left; - int cyHeight = rect.bottom - rect.top; - - // paint left side nonclient background and draw icon - ::SetRect(&rect, 0, 0, m_cxLeft, cyHeight); -#ifndef _WTL_NO_AUTO_THEME - if(m_hTheme != NULL) - { - if(m_pfnDrawThemeParentBackground != NULL) - m_pfnDrawThemeParentBackground(m_hWnd, dc, &rect); - else - dc.FillRect(&rect, COLOR_WINDOW); - } - else -#endif // !_WTL_NO_AUTO_THEME - { - if((m_dwExtendedStyle & CBR_EX_TRANSPARENT) != 0) - dc.FillRect(&rect, COLOR_3DFACE); - else - dc.FillRect(&rect, COLOR_MENU); - } - - RECT rcIcon = { 0 }; - T* pT = static_cast(this); - pT->_CalcIconRect(cxWidth, cyHeight, rcIcon); - dc.DrawIconEx(rcIcon.left, rcIcon.top, m_hIconChildMaximized, m_cxIconWidth, m_cyIconHeight); - - // paint right side nonclient background - ::SetRect(&rect, cxWidth - m_cxRight, 0, cxWidth, cyHeight); -#ifndef _WTL_NO_AUTO_THEME - if(m_hTheme != NULL) - { - if(m_pfnDrawThemeParentBackground != NULL) - { - // this is to account for the left non-client area - POINT ptOrg = { 0, 0 }; - dc.GetViewportOrg(&ptOrg); - dc.SetViewportOrg(ptOrg.x + m_cxLeft, ptOrg.y); - ::OffsetRect(&rect, -m_cxLeft, 0); - - m_pfnDrawThemeParentBackground(m_hWnd, dc, &rect); - - // restore - dc.SetViewportOrg(ptOrg); - ::OffsetRect(&rect, m_cxLeft, 0); - } - else - { - dc.FillRect(&rect, COLOR_3DFACE); - } - } - else -#endif // !_WTL_NO_AUTO_THEME - { - if((m_dwExtendedStyle & CBR_EX_TRANSPARENT) != 0) - dc.FillRect(&rect, COLOR_3DFACE); - else - dc.FillRect(&rect, COLOR_MENU); - } - - // draw buttons - RECT arrRect[3] = { 0 }; - pT->_CalcBtnRects(cxWidth, cyHeight, arrRect); - pT->_DrawMDIButton(dc, arrRect, -1); // draw all buttons - - return lRet; - } - - LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) - { - LRESULT lRet = DefWindowProc(uMsg, wParam, lParam); - if(m_bChildMaximized) - { - RECT rect = { 0 }; - GetWindowRect(&rect); - POINT pt = { GET_X_LPARAM(lParam) - rect.left, GET_Y_LPARAM(lParam) - rect.top }; - if(m_bLayoutRTL) - { - if((pt.x < m_cxRight) || (pt.x > ((rect.right - rect.left) - m_cxLeft))) - lRet = HTBORDER; - } - else - { - if((pt.x < m_cxLeft) || (pt.x > ((rect.right - rect.left) - m_cxRight))) - lRet = HTBORDER; - } - } - return lRet; - } - - LRESULT OnNcLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) - { - if(!m_bChildMaximized) - { - bHandled = FALSE; - return 1; - } - - ATLASSERT(_DebugCheckChild()); - - POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; - RECT rect = { 0 }; - GetWindowRect(&rect); - pt.x -= rect.left; - pt.y -= rect.top; - - RECT rcIcon = { 0 }; - T* pT = static_cast(this); - pT->_CalcIconRect(rect.right - rect.left, rect.bottom - rect.top, rcIcon, m_bLayoutRTL); - RECT arrRect[3] = { 0 }; - pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top, arrRect, m_bLayoutRTL); - - if(::PtInRect(&rcIcon, pt)) - { -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonDown: icon\n")); -#endif -#ifndef TPM_VERPOSANIMATION - const UINT TPM_VERPOSANIMATION = 0x1000L; // Menu animation flag -#endif - CMenuHandle menu = ::GetSystemMenu(m_hWndChildMaximized, FALSE); - UINT uRet = (UINT)menu.TrackPopupMenu(TPM_LEFTBUTTON | TPM_VERTICAL | TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD | - (s_bW2K ? TPM_VERPOSANIMATION : 0), m_bLayoutRTL ? rect.right : rect.left, rect.bottom, m_hWndChildMaximized); - - // eat next message if click is on the same button - ::OffsetRect(&rcIcon, rect.left, rect.top); - MSG msg = { 0 }; - if(::PeekMessage(&msg, m_hWnd, WM_NCLBUTTONDOWN, WM_NCLBUTTONDOWN, PM_NOREMOVE) && ::PtInRect(&rcIcon, msg.pt)) - ::PeekMessage(&msg, m_hWnd, WM_NCLBUTTONDOWN, WM_NCLBUTTONDOWN, PM_REMOVE); - - if(uRet != 0) - ::SendMessage(m_hWndChildMaximized, WM_SYSCOMMAND, uRet, 0L); - } - else if(::PtInRect(&arrRect[0], pt)) - { -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonDown: close button\n")); -#endif - m_nBtnWasPressed = m_nBtnPressed = 0; - } - else if(::PtInRect(&arrRect[1], pt)) - { -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonDown: restore button\n")); -#endif - m_nBtnWasPressed = m_nBtnPressed = 1; - } - else if(::PtInRect(&arrRect[2], pt)) - { -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonDown: minimize button\n")); -#endif - m_nBtnWasPressed = m_nBtnPressed = 2; - } - else - { - bHandled = FALSE; - } - - // draw the button state if it was pressed - if(m_nBtnPressed != -1) - { - SetCapture(); - CWindowDC dc(m_hWnd); - pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top, arrRect); - pT->_DrawMDIButton(dc, arrRect, m_nBtnPressed); - } - - return 0; - } - - LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) - { - if(!m_bChildMaximized || ::GetCapture() != m_hWnd || m_nBtnWasPressed == -1) - { - bHandled = FALSE; - return 1; - } - - POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; - ClientToScreen(&pt); - RECT rect = { 0 }; - GetWindowRect(&rect); - pt.x -= rect.left; - pt.y -= rect.top; - RECT arrRect[3] = { 0 }; - T* pT = static_cast(this); - pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top, arrRect, m_bLayoutRTL); - int nOldBtnPressed = m_nBtnPressed; - m_nBtnPressed = ::PtInRect(&arrRect[m_nBtnWasPressed], pt) ? m_nBtnWasPressed : -1; - if(nOldBtnPressed != m_nBtnPressed) - { - CWindowDC dc(m_hWnd); - pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top, arrRect); - pT->_DrawMDIButton(dc, arrRect, (m_nBtnPressed != -1) ? m_nBtnPressed : nOldBtnPressed); - } - - return 0; - } - - LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) - { - if(!m_bChildMaximized || ::GetCapture() != m_hWnd || m_nBtnWasPressed == -1) - { - bHandled = FALSE; - return 1; - } - - ATLASSERT(_DebugCheckChild()); - - POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; - ClientToScreen(&pt); - RECT rect = { 0 }; - GetWindowRect(&rect); - pt.x -= rect.left; - pt.y -= rect.top; - - int nBtn = m_nBtnWasPressed; - ReleaseCapture(); - - RECT arrRect[3] = { 0 }; - T* pT = static_cast(this); - pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top, arrRect, m_bLayoutRTL); - if(::PtInRect(&arrRect[nBtn], pt)) - { - switch(nBtn) - { - case 0: // close -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonUp: close button\n")); -#endif - ::SendMessage(m_hWndChildMaximized, WM_SYSCOMMAND, SC_CLOSE, 0L); - break; - case 1: // restore -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonUp: restore button\n")); -#endif - ::SendMessage(m_hWndChildMaximized, WM_SYSCOMMAND, SC_RESTORE, 0L); - break; - case 2: // minimize -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonUp: minimize button\n")); -#endif - ::SendMessage(m_hWndChildMaximized, WM_SYSCOMMAND, SC_MINIMIZE, 0L); - break; - default: - break; - } - } - - return 0; - } - - LRESULT OnNcLButtonDblClk(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) - { - if(!m_bChildMaximized || m_nBtnWasPressed != -1) - { - bHandled = FALSE; - return 1; - } - - ATLASSERT(_DebugCheckChild()); - - POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; - RECT rect = { 0 }; - GetWindowRect(&rect); - pt.x -= rect.left; - pt.y -= rect.top; - - RECT rcIcon = { 0 }; - T* pT = static_cast(this); - pT->_CalcIconRect(rect.right - rect.left, rect.bottom - rect.top, rcIcon, m_bLayoutRTL); - RECT arrRect[3] = { 0 }; - pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top, arrRect, m_bLayoutRTL); - - if(::PtInRect(&rcIcon, pt)) - { - CMenuHandle menu = ::GetSystemMenu(m_hWndChildMaximized, FALSE); - UINT uDefID = menu.GetMenuDefaultItem(); - if(uDefID == (UINT)-1) - uDefID = SC_CLOSE; - ::SendMessage(m_hWndChildMaximized, WM_SYSCOMMAND, uDefID, 0L); - } - - return 0; - } - - LRESULT OnCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - if(m_bChildMaximized) - { - if(m_nBtnPressed != -1) - { - ATLASSERT(m_nBtnPressed == m_nBtnWasPressed); // must be - m_nBtnPressed = -1; - RECT rect = { 0 }; - GetWindowRect(&rect); - RECT arrRect[3] = { 0 }; - T* pT = static_cast(this); - pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top, arrRect); - CWindowDC dc(m_hWnd); - pT->_DrawMDIButton(dc, arrRect, m_nBtnWasPressed); - } - m_nBtnWasPressed = -1; - } - else - { - bHandled = FALSE; - } - return 0; - } - -// Parent window message handlers - LRESULT OnParentActivate(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) - { - m_bParentActive = (LOWORD(wParam) != WA_INACTIVE); - RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_UPDATENOW); - bHandled = FALSE; - return 1; - } - -// MDI client window message handlers - LRESULT OnMDISetMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) - { - m_wndMDIClient.DefWindowProc(uMsg, NULL, lParam); - HMENU hOldMenu = GetMenu(); - BOOL bRet = AttachMenu((HMENU)wParam); - bRet; // avoid level 4 warning - ATLASSERT(bRet); - -#if (_WIN32_IE >= 0x0400) - T* pT = static_cast(this); - pT->UpdateRebarBandIdealSize(); -#endif // (_WIN32_IE >= 0x0400) - - return (LRESULT)hOldMenu; - } - -// All messages from the message hook - LRESULT OnAllHookMessages(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - T* pT = static_cast(this); - pT->_ProcessAllHookMessages(uMsg, wParam, lParam); - - bHandled = FALSE; - return 1; - } - -// Overrideables - // override this to provide different ideal size - void UpdateRebarBandIdealSize() - { - // assuming we are in a rebar, change ideal size to our size - // we hope that if we are not in a rebar, nCount will be 0 - int nCount = (int)::SendMessage(GetParent(), RB_GETBANDCOUNT, 0, 0L); - for(int i = 0; i < nCount; i++) - { - REBARBANDINFO rbi = { RunTimeHelper::SizeOf_REBARBANDINFO(), RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE }; - ::SendMessage(GetParent(), RB_GETBANDINFO, i, (LPARAM)&rbi); - if(rbi.hwndChild == m_hWnd) - { - rbi.fMask = RBBIM_IDEALSIZE; - rbi.cxIdeal = m_bChildMaximized ? m_cxLeft + m_cxRight : 0; - int nBtnCount = GetButtonCount(); - if(nBtnCount > 0) - { - RECT rect = { 0 }; - GetItemRect(nBtnCount - 1, &rect); - rbi.cxIdeal += rect.right; - } - ::SendMessage(GetParent(), RB_SETBANDINFO, i, (LPARAM)&rbi); - break; - } - } - } - - // all hook messages - check for the maximized MDI child window change - void _ProcessAllHookMessages(UINT uMsg, WPARAM /*wParam*/, LPARAM /*lParam*/) - { - if(uMsg == WM_MDIGETACTIVE || uMsg == WM_MDISETMENU) - return; - - BOOL bMaximized = FALSE; - HWND hWndChild = (HWND)::SendMessage(m_wndMDIClient, WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized); - bool bMaxOld = m_bChildMaximized; - m_bChildMaximized = (hWndChild != NULL && bMaximized); - HICON hIconOld = m_hIconChildMaximized; - - if(m_bChildMaximized) - { - if(m_hWndChildMaximized != hWndChild) - { - ATL::CWindow wnd = m_hWndChildMaximized = hWndChild; - m_hIconChildMaximized = wnd.GetIcon(FALSE); - if(m_hIconChildMaximized == NULL) - { - m_hIconChildMaximized = wnd.GetIcon(TRUE); - if(m_hIconChildMaximized == NULL) - { - // no icon set with WM_SETICON, get the class one -// need conditional code because types don't match in winuser.h -#ifdef _WIN64 - m_hIconChildMaximized = (HICON)::GetClassLongPtr(wnd, GCLP_HICONSM); -#else - m_hIconChildMaximized = (HICON)LongToHandle(::GetClassLongPtr(wnd, GCLP_HICONSM)); -#endif - } - } - } - } - else - { - m_hWndChildMaximized = NULL; - m_hIconChildMaximized = NULL; - } - - if(bMaxOld != m_bChildMaximized) - { -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - All messages hook change: m_bChildMaximized = %s\n"), m_bChildMaximized ? "true" : "false"); -#endif - // assuming we are in a rebar, change our size to accomodate new state - // we hope that if we are not in a rebar, nCount will be 0 - int nCount = (int)::SendMessage(GetParent(), RB_GETBANDCOUNT, 0, 0L); - int cxDiff = (m_bChildMaximized ? 1 : -1) * (m_cxLeft + m_cxRight); - for(int i = 0; i < nCount; i++) - { -#if (_WIN32_IE >= 0x0500) - REBARBANDINFO rbi = { RunTimeHelper::SizeOf_REBARBANDINFO(), RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE | RBBIM_STYLE }; - ::SendMessage(GetParent(), RB_GETBANDINFO, i, (LPARAM)&rbi); - if(rbi.hwndChild == m_hWnd) - { - if((rbi.fStyle & RBBS_USECHEVRON) != 0) - { - rbi.fMask = RBBIM_CHILDSIZE | RBBIM_IDEALSIZE; - rbi.cxMinChild += cxDiff; - rbi.cxIdeal += cxDiff; - ::SendMessage(GetParent(), RB_SETBANDINFO, i, (LPARAM)&rbi); - } - break; - } -#elif (_WIN32_IE >= 0x0400) - REBARBANDINFO rbi = { RunTimeHelper::SizeOf_REBARBANDINFO(), RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE }; - ::SendMessage(GetParent(), RB_GETBANDINFO, i, (LPARAM)&rbi); - if(rbi.hwndChild == m_hWnd) - { - rbi.fMask = RBBIM_CHILDSIZE | RBBIM_IDEALSIZE; - rbi.cxMinChild += cxDiff; - rbi.cxIdeal += cxDiff; - ::SendMessage(GetParent(), RB_SETBANDINFO, i, (LPARAM)&rbi); - break; - } -#else // (_WIN32_IE < 0x0400) - REBARBANDINFO rbi = { RunTimeHelper::SizeOf_REBARBANDINFO(), RBBIM_CHILD | RBBIM_CHILDSIZE }; - ::SendMessage(GetParent(), RB_GETBANDINFO, i, (LPARAM)&rbi); - if(rbi.hwndChild == m_hWnd) - { - rbi.fMask = RBBIM_CHILDSIZE; - rbi.cxMinChild += cxDiff; - ::SendMessage(GetParent(), RB_SETBANDINFO, i, (LPARAM)&rbi); - break; - } -#endif // (_WIN32_IE < 0x0400) - } - } - - if(bMaxOld != m_bChildMaximized || hIconOld != m_hIconChildMaximized) - { - // force size change and redraw everything - RECT rect = { 0 }; - GetWindowRect(&rect); - ::MapWindowPoints(NULL, GetParent(), (LPPOINT)&rect, 2); - SetRedraw(FALSE); - SetWindowPos(NULL, 0, 0, 1, 1, SWP_NOZORDER | SWP_NOMOVE); - SetWindowPos(NULL, &rect, SWP_NOZORDER | SWP_NOMOVE); - SetRedraw(TRUE); - RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW); - } - } - -// Implementation - void GetSystemSettings() - { -#ifdef _CMDBAR_EXTRA_TRACE - ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - GetSystemSettings\n")); -#endif - _baseClass::GetSystemSettings(); - - NONCLIENTMETRICS info = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() }; - BOOL bRet = ::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0); - ATLASSERT(bRet); - if(bRet) - { - m_cxIconWidth = ::GetSystemMetrics(SM_CXSMICON); - m_cyIconHeight = ::GetSystemMetrics(SM_CYSMICON); - m_cxLeft = m_cxIconWidth; - -#ifndef _WTL_NO_AUTO_THEME - if(m_hTheme != NULL) - { - m_cxBtnWidth = info.iCaptionWidth - 2 * m_cxyOffset; - m_cyBtnHeight = info.iCaptionHeight - 2 * m_cxyOffset; - m_cxRight = 3 * m_cxBtnWidth; - } - else -#endif // !_WTL_NO_AUTO_THEME - { - m_cxBtnWidth = info.iCaptionWidth - m_cxyOffset; - m_cyBtnHeight = info.iCaptionHeight - 2 * m_cxyOffset; - m_cxRight = 3 * m_cxBtnWidth + m_cxyOffset; - } - } - - RECT rect = { 0 }; - GetClientRect(&rect); - T* pT = static_cast(this); - pT->_AdjustBtnSize(rect.bottom); - } - - void _AdjustBtnSize(int cyHeight) - { - if(cyHeight > 1 && m_cyBtnHeight > cyHeight) - { -#ifndef _WTL_NO_AUTO_THEME - if(m_hTheme != NULL) - { - m_cyBtnHeight = cyHeight; - m_cxBtnWidth = cyHeight; - m_cxRight = 3 * m_cxBtnWidth; - } - else -#endif // !_WTL_NO_AUTO_THEME - { - m_cyBtnHeight = cyHeight; - m_cxBtnWidth = cyHeight + m_cxyOffset; - m_cxRight = 3 * m_cxBtnWidth + m_cxyOffset; - } - } - } - - void _CalcIconRect(int cxWidth, int cyHeight, RECT& rect, bool bInvertX = false) const - { - int xStart = (m_cxLeft - m_cxIconWidth) / 2; - if(xStart < 0) - xStart = 0; - int yStart = (cyHeight - m_cyIconHeight) / 2; - if(yStart < 0) - yStart = 0; - - if(bInvertX) - ::SetRect(&rect, cxWidth - (xStart + m_cxBtnWidth), yStart, cxWidth - xStart, yStart + m_cyBtnHeight); - else - ::SetRect(&rect, xStart, yStart, xStart + m_cxBtnWidth, yStart + m_cyBtnHeight); - } - - void _CalcBtnRects(int cxWidth, int cyHeight, RECT arrRect[3], bool bInvertX = false) const - { - int yStart = (cyHeight - m_cyBtnHeight) / 2; - if(yStart < 0) - yStart = 0; - - RECT rcBtn = { cxWidth - m_cxBtnWidth, yStart, cxWidth, yStart + m_cyBtnHeight }; - int nDirection = -1; - if(bInvertX) - { - ::SetRect(&rcBtn, 0, yStart, m_cxBtnWidth, yStart + m_cyBtnHeight); - nDirection = 1; - } - - arrRect[0] = rcBtn; -#ifndef _WTL_NO_AUTO_THEME - if(m_hTheme != NULL) - ::OffsetRect(&rcBtn, nDirection * m_cxBtnWidth, 0); - else -#endif // !_WTL_NO_AUTO_THEME - ::OffsetRect(&rcBtn, nDirection * (m_cxBtnWidth + m_cxyOffset), 0); - arrRect[1] = rcBtn; - ::OffsetRect(&rcBtn, nDirection * m_cxBtnWidth, 0); - arrRect[2] = rcBtn; - } - - void _DrawMDIButton(CWindowDC& dc, LPRECT pRects, int nBtn) - { -#ifndef _WTL_NO_AUTO_THEME - if(m_hTheme != NULL) - { -#ifndef TMSCHEMA_H - const int WP_MDICLOSEBUTTON = 20; - const int CBS_NORMAL = 1; - const int CBS_PUSHED = 3; - const int CBS_DISABLED = 4; - const int WP_MDIRESTOREBUTTON = 22; - const int RBS_NORMAL = 1; - const int RBS_PUSHED = 3; - const int RBS_DISABLED = 4; - const int WP_MDIMINBUTTON = 16; - const int MINBS_NORMAL = 1; - const int MINBS_PUSHED = 3; - const int MINBS_DISABLED = 4; -#endif // TMSCHEMA_H - if(nBtn == -1 || nBtn == 0) - m_pfnDrawThemeBackground(m_hTheme, dc, WP_MDICLOSEBUTTON, m_bParentActive ? ((m_nBtnPressed == 0) ? CBS_PUSHED : CBS_NORMAL) : CBS_DISABLED, &pRects[0], NULL); - if(nBtn == -1 || nBtn == 1) - m_pfnDrawThemeBackground(m_hTheme, dc, WP_MDIRESTOREBUTTON, m_bParentActive ? ((m_nBtnPressed == 1) ? RBS_PUSHED : RBS_NORMAL) : RBS_DISABLED, &pRects[1], NULL); - if(nBtn == -1 || nBtn == 2) - m_pfnDrawThemeBackground(m_hTheme, dc, WP_MDIMINBUTTON, m_bParentActive ? ((m_nBtnPressed == 2) ? MINBS_PUSHED : MINBS_NORMAL) : MINBS_DISABLED, &pRects[2], NULL); - } - else -#endif // !_WTL_NO_AUTO_THEME - { - if(nBtn == -1 || nBtn == 0) - dc.DrawFrameControl(&pRects[0], DFC_CAPTION, DFCS_CAPTIONCLOSE | ((m_nBtnPressed == 0) ? DFCS_PUSHED : 0)); - if(nBtn == -1 || nBtn == 1) - dc.DrawFrameControl(&pRects[1], DFC_CAPTION, DFCS_CAPTIONRESTORE | ((m_nBtnPressed == 1) ? DFCS_PUSHED : 0)); - if(nBtn == -1 || nBtn == 2) - dc.DrawFrameControl(&pRects[2], DFC_CAPTION, DFCS_CAPTIONMIN | ((m_nBtnPressed == 2) ? DFCS_PUSHED : 0)); - } - } - -#ifndef _WTL_NO_AUTO_THEME - static UINT _GetThemeChangedMsg() - { -#ifndef WM_THEMECHANGED - static const UINT WM_THEMECHANGED = 0x031A; -#endif // !WM_THEMECHANGED - return WM_THEMECHANGED; - } - - void _OpenThemeData() - { - ATLASSERT(m_hThemeDLL != NULL); - - PFN_OpenThemeData pfnOpenThemeData = (PFN_OpenThemeData)::GetProcAddress(m_hThemeDLL, "OpenThemeData"); - ATLASSERT(pfnOpenThemeData != NULL); - if(pfnOpenThemeData != NULL) - m_hTheme = pfnOpenThemeData(m_hWnd, L"Window"); - } - - void _CloseThemeData() - { - ATLASSERT(m_hThemeDLL != NULL); - - if(m_hTheme == NULL) - return; // nothing to do - - PFN_CloseThemeData pfnCloseThemeData = (PFN_CloseThemeData)::GetProcAddress(m_hThemeDLL, "CloseThemeData"); - ATLASSERT(pfnCloseThemeData != NULL); - if(pfnCloseThemeData != NULL) - { - pfnCloseThemeData(m_hTheme); - m_hTheme = NULL; - } - } -#endif // !_WTL_NO_AUTO_THEME - - bool _DebugCheckChild() - { -#ifdef _DEBUG - BOOL bMaximized = FALSE; - HWND hWndChild = (HWND)::SendMessage(m_wndMDIClient, WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized); - return (bMaximized && hWndChild == m_hWndChildMaximized); -#else // !_DEBUG - return true; -#endif // !_DEBUG - } -}; - -class CMDICommandBarCtrl : public CMDICommandBarCtrlImpl -{ -public: - DECLARE_WND_SUPERCLASS(_T("WTL_MDICommandBar"), GetWndClassName()) -}; - -}; // namespace WTL - -#endif // __ATLCTRLW_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/atlctrlx.h b/prog/3rdPartyLibs/wtl-8.1/include/atlctrlx.h deleted file mode 100644 index 4861b9f88..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/atlctrlx.h +++ /dev/null @@ -1,4827 +0,0 @@ -// Windows Template Library - WTL version 8.1 -// Copyright (C) Microsoft Corporation. All rights reserved. -// -// This file is a part of the Windows Template Library. -// The use and distribution terms for this software are covered by the -// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php) -// which can be found in the file CPL.TXT at the root of this distribution. -// By using this software in any fashion, you are agreeing to be bound by -// the terms of this license. You must not remove this notice, or -// any other, from this software. - -#ifndef __ATLCTRLX_H__ -#define __ATLCTRLX_H__ - -#pragma once - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#ifndef __ATLAPP_H__ - #error atlctrlx.h requires atlapp.h to be included first -#endif - -#ifndef __ATLCTRLS_H__ - #error atlctrlx.h requires atlctrls.h to be included first -#endif - -#ifndef WM_UPDATEUISTATE - #define WM_UPDATEUISTATE 0x0128 -#endif // !WM_UPDATEUISTATE - - -/////////////////////////////////////////////////////////////////////////////// -// Classes in this file: -// -// CBitmapButtonImpl -// CBitmapButton -// CCheckListViewCtrlImpl -// CCheckListViewCtrl -// CHyperLinkImpl -// CHyperLink -// CWaitCursor -// CCustomWaitCursor -// CMultiPaneStatusBarCtrlImpl -// CMultiPaneStatusBarCtrl -// CPaneContainerImpl -// CPaneContainer -// CSortListViewImpl -// CSortListViewCtrlImpl -// CSortListViewCtrl -// CTabViewImpl -// CTabView - -namespace WTL -{ - -/////////////////////////////////////////////////////////////////////////////// -// CBitmapButton - bitmap button implementation - -#ifndef _WIN32_WCE - -// bitmap button extended styles -#define BMPBTN_HOVER 0x00000001 -#define BMPBTN_AUTO3D_SINGLE 0x00000002 -#define BMPBTN_AUTO3D_DOUBLE 0x00000004 -#define BMPBTN_AUTOSIZE 0x00000008 -#define BMPBTN_SHAREIMAGELISTS 0x00000010 -#define BMPBTN_AUTOFIRE 0x00000020 - -template -class ATL_NO_VTABLE CBitmapButtonImpl : public ATL::CWindowImpl< T, TBase, TWinTraits> -{ -public: - DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName()) - - enum - { - _nImageNormal = 0, - _nImagePushed, - _nImageFocusOrHover, - _nImageDisabled, - - _nImageCount = 4, - }; - - enum - { - ID_TIMER_FIRST = 1000, - ID_TIMER_REPEAT = 1001 - }; - - // Bitmap button specific extended styles - DWORD m_dwExtendedStyle; - - CImageList m_ImageList; - int m_nImage[_nImageCount]; - - CToolTipCtrl m_tip; - LPTSTR m_lpstrToolTipText; - - // Internal states - unsigned m_fMouseOver:1; - unsigned m_fFocus:1; - unsigned m_fPressed:1; - - -// Constructor/Destructor - CBitmapButtonImpl(DWORD dwExtendedStyle = BMPBTN_AUTOSIZE, HIMAGELIST hImageList = NULL) : - m_ImageList(hImageList), m_dwExtendedStyle(dwExtendedStyle), - m_lpstrToolTipText(NULL), - m_fMouseOver(0), m_fFocus(0), m_fPressed(0) - { - m_nImage[_nImageNormal] = -1; - m_nImage[_nImagePushed] = -1; - m_nImage[_nImageFocusOrHover] = -1; - m_nImage[_nImageDisabled] = -1; - } - - ~CBitmapButtonImpl() - { - if((m_dwExtendedStyle & BMPBTN_SHAREIMAGELISTS) == 0) - m_ImageList.Destroy(); - delete [] m_lpstrToolTipText; - } - - // overridden to provide proper initialization - BOOL SubclassWindow(HWND hWnd) - { -#if (_MSC_VER >= 1300) - BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits>::SubclassWindow(hWnd); -#else // !(_MSC_VER >= 1300) - typedef ATL::CWindowImpl< T, TBase, TWinTraits> _baseClass; - BOOL bRet = _baseClass::SubclassWindow(hWnd); -#endif // !(_MSC_VER >= 1300) - if(bRet) - Init(); - return bRet; - } - -// Attributes - DWORD GetBitmapButtonExtendedStyle() const - { - return m_dwExtendedStyle; - } - - DWORD SetBitmapButtonExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0) - { - DWORD dwPrevStyle = m_dwExtendedStyle; - if(dwMask == 0) - m_dwExtendedStyle = dwExtendedStyle; - else - m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask); - return dwPrevStyle; - } - - HIMAGELIST GetImageList() const - { - return m_ImageList; - } - - HIMAGELIST SetImageList(HIMAGELIST hImageList) - { - HIMAGELIST hImageListPrev = m_ImageList; - m_ImageList = hImageList; - if((m_dwExtendedStyle & BMPBTN_AUTOSIZE) != 0 && ::IsWindow(m_hWnd)) - SizeToImage(); - return hImageListPrev; - } - - int GetToolTipTextLength() const - { - return (m_lpstrToolTipText == NULL) ? -1 : lstrlen(m_lpstrToolTipText); - } - - bool GetToolTipText(LPTSTR lpstrText, int nLength) const - { - ATLASSERT(lpstrText != NULL); - if(m_lpstrToolTipText == NULL) - return false; - - errno_t nRet = SecureHelper::strncpy_x(lpstrText, nLength, m_lpstrToolTipText, _TRUNCATE); - - return (nRet == 0 || nRet == STRUNCATE); - } - - bool SetToolTipText(LPCTSTR lpstrText) - { - if(m_lpstrToolTipText != NULL) - { - delete [] m_lpstrToolTipText; - m_lpstrToolTipText = NULL; - } - - if(lpstrText == NULL) - { - if(m_tip.IsWindow()) - m_tip.Activate(FALSE); - return true; - } - - int cchLen = lstrlen(lpstrText) + 1; - ATLTRY(m_lpstrToolTipText = new TCHAR[cchLen]); - if(m_lpstrToolTipText == NULL) - return false; - - SecureHelper::strcpy_x(m_lpstrToolTipText, cchLen, lpstrText); - if(m_tip.IsWindow()) - { - m_tip.Activate(TRUE); - m_tip.AddTool(m_hWnd, m_lpstrToolTipText); - } - - return true; - } - -// Operations - void SetImages(int nNormal, int nPushed = -1, int nFocusOrHover = -1, int nDisabled = -1) - { - if(nNormal != -1) - m_nImage[_nImageNormal] = nNormal; - if(nPushed != -1) - m_nImage[_nImagePushed] = nPushed; - if(nFocusOrHover != -1) - m_nImage[_nImageFocusOrHover] = nFocusOrHover; - if(nDisabled != -1) - m_nImage[_nImageDisabled] = nDisabled; - } - - BOOL SizeToImage() - { - ATLASSERT(::IsWindow(m_hWnd) && m_ImageList.m_hImageList != NULL); - int cx = 0; - int cy = 0; - if(!m_ImageList.GetIconSize(cx, cy)) - return FALSE; - return ResizeClient(cx, cy); - } - -// Overrideables - void DoPaint(CDCHandle dc) - { - ATLASSERT(m_ImageList.m_hImageList != NULL); // image list must be set - ATLASSERT(m_nImage[0] != -1); // main bitmap must be set - - // set bitmap according to the current button state - int nImage = -1; - bool bHover = IsHoverMode(); - if(!IsWindowEnabled()) - nImage = m_nImage[_nImageDisabled]; - else if(m_fPressed == 1) - nImage = m_nImage[_nImagePushed]; - else if((!bHover && m_fFocus == 1) || (bHover && m_fMouseOver == 1)) - nImage = m_nImage[_nImageFocusOrHover]; - if(nImage == -1) // not there, use default one - nImage = m_nImage[_nImageNormal]; - - // draw the button image - int xyPos = 0; - if((m_fPressed == 1) && ((m_dwExtendedStyle & (BMPBTN_AUTO3D_SINGLE | BMPBTN_AUTO3D_DOUBLE)) != 0) && (m_nImage[_nImagePushed] == -1)) - xyPos = 1; - m_ImageList.Draw(dc, nImage, xyPos, xyPos, ILD_NORMAL); - - // draw 3D border if required - if((m_dwExtendedStyle & (BMPBTN_AUTO3D_SINGLE | BMPBTN_AUTO3D_DOUBLE)) != 0) - { - RECT rect; - GetClientRect(&rect); - - if(m_fPressed == 1) - dc.DrawEdge(&rect, ((m_dwExtendedStyle & BMPBTN_AUTO3D_SINGLE) != 0) ? BDR_SUNKENOUTER : EDGE_SUNKEN, BF_RECT); - else if(!bHover || m_fMouseOver == 1) - dc.DrawEdge(&rect, ((m_dwExtendedStyle & BMPBTN_AUTO3D_SINGLE) != 0) ? BDR_RAISEDINNER : EDGE_RAISED, BF_RECT); - - if(!bHover && m_fFocus == 1) - { - ::InflateRect(&rect, -2 * ::GetSystemMetrics(SM_CXEDGE), -2 * ::GetSystemMetrics(SM_CYEDGE)); - dc.DrawFocusRect(&rect); - } - } - } - -// Message map and handlers - BEGIN_MSG_MAP(CBitmapButtonImpl) - MESSAGE_HANDLER(WM_CREATE, OnCreate) - MESSAGE_HANDLER(WM_DESTROY, OnDestroy) - MESSAGE_RANGE_HANDLER(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseMessage) - MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) - MESSAGE_HANDLER(WM_PAINT, OnPaint) - MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) - MESSAGE_HANDLER(WM_SETFOCUS, OnFocus) - MESSAGE_HANDLER(WM_KILLFOCUS, OnFocus) - MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown) - MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnLButtonDblClk) - MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp) - MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged) - MESSAGE_HANDLER(WM_ENABLE, OnEnable) - MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove) - MESSAGE_HANDLER(WM_MOUSELEAVE, OnMouseLeave) - MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown) - MESSAGE_HANDLER(WM_KEYUP, OnKeyUp) - MESSAGE_HANDLER(WM_TIMER, OnTimer) - MESSAGE_HANDLER(WM_UPDATEUISTATE, OnUpdateUiState) - END_MSG_MAP() - - LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - Init(); - bHandled = FALSE; - return 1; - } - - LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - if(m_tip.IsWindow()) - { - m_tip.DestroyWindow(); - m_tip.m_hWnd = NULL; - } - bHandled = FALSE; - return 1; - } - - LRESULT OnMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - MSG msg = { m_hWnd, uMsg, wParam, lParam }; - if(m_tip.IsWindow()) - m_tip.RelayEvent(&msg); - bHandled = FALSE; - return 1; - } - - LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - return 1; // no background needed - } - - LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - if(wParam != NULL) - { - pT->DoPaint((HDC)wParam); - } - else - { - CPaintDC dc(m_hWnd); - pT->DoPaint(dc.m_hDC); - } - return 0; - } - - LRESULT OnFocus(UINT uMsg, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - m_fFocus = (uMsg == WM_SETFOCUS) ? 1 : 0; - Invalidate(); - UpdateWindow(); - bHandled = FALSE; - return 1; - } - - LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) - { - LRESULT lRet = 0; - if(IsHoverMode()) - SetCapture(); - else - lRet = DefWindowProc(uMsg, wParam, lParam); - if(::GetCapture() == m_hWnd) - { - m_fPressed = 1; - Invalidate(); - UpdateWindow(); - } - if((m_dwExtendedStyle & BMPBTN_AUTOFIRE) != 0) - { - int nElapse = 250; - int nDelay = 0; - if(::SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &nDelay, 0)) - nElapse += nDelay * 250; // all milli-seconds - SetTimer(ID_TIMER_FIRST, nElapse); - } - return lRet; - } - - LRESULT OnLButtonDblClk(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) - { - LRESULT lRet = 0; - if(!IsHoverMode()) - lRet = DefWindowProc(uMsg, wParam, lParam); - if(::GetCapture() != m_hWnd) - SetCapture(); - if(m_fPressed == 0) - { - m_fPressed = 1; - Invalidate(); - UpdateWindow(); - } - return lRet; - } - - LRESULT OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) - { - LRESULT lRet = 0; - bool bHover = IsHoverMode(); - if(!bHover) - lRet = DefWindowProc(uMsg, wParam, lParam); - if(::GetCapture() == m_hWnd) - { - if(bHover && m_fPressed == 1) - ::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd); - ::ReleaseCapture(); - } - return lRet; - } - - LRESULT OnCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - if(m_fPressed == 1) - { - m_fPressed = 0; - Invalidate(); - UpdateWindow(); - } - bHandled = FALSE; - return 1; - } - - LRESULT OnEnable(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - Invalidate(); - UpdateWindow(); - bHandled = FALSE; - return 1; - } - - LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) - { - if(::GetCapture() == m_hWnd) - { - POINT ptCursor = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; - ClientToScreen(&ptCursor); - RECT rect = { 0 }; - GetWindowRect(&rect); - unsigned int uPressed = ::PtInRect(&rect, ptCursor) ? 1 : 0; - if(m_fPressed != uPressed) - { - m_fPressed = uPressed; - Invalidate(); - UpdateWindow(); - } - } - else if(IsHoverMode() && m_fMouseOver == 0) - { - m_fMouseOver = 1; - Invalidate(); - UpdateWindow(); - StartTrackMouseLeave(); - } - bHandled = FALSE; - return 1; - } - - LRESULT OnMouseLeave(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - if(m_fMouseOver == 1) - { - m_fMouseOver = 0; - Invalidate(); - UpdateWindow(); - } - return 0; - } - - LRESULT OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) - { - if(wParam == VK_SPACE && IsHoverMode()) - return 0; // ignore if in hover mode - if(wParam == VK_SPACE && m_fPressed == 0) - { - m_fPressed = 1; - Invalidate(); - UpdateWindow(); - } - bHandled = FALSE; - return 1; - } - - LRESULT OnKeyUp(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) - { - if(wParam == VK_SPACE && IsHoverMode()) - return 0; // ignore if in hover mode - if(wParam == VK_SPACE && m_fPressed == 1) - { - m_fPressed = 0; - Invalidate(); - UpdateWindow(); - } - bHandled = FALSE; - return 1; - } - - LRESULT OnTimer(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - ATLASSERT((m_dwExtendedStyle & BMPBTN_AUTOFIRE) != 0); - switch(wParam) // timer ID - { - case ID_TIMER_FIRST: - KillTimer(ID_TIMER_FIRST); - if(m_fPressed == 1) - { - ::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd); - int nElapse = 250; - int nRepeat = 40; - if(::SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &nRepeat, 0)) - nElapse = 10000 / (10 * nRepeat + 25); // milli-seconds, approximated - SetTimer(ID_TIMER_REPEAT, nElapse); - } - break; - case ID_TIMER_REPEAT: - if(m_fPressed == 1) - ::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd); - else if(::GetCapture() != m_hWnd) - KillTimer(ID_TIMER_REPEAT); - break; - default: // not our timer - break; - } - return 0; - } - - LRESULT OnUpdateUiState(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - // If the control is subclassed or superclassed, this message can cause - // repainting without WM_PAINT. We don't use this state, so just do nothing. - return 0; - } - -// Implementation - void Init() - { - // We need this style to prevent Windows from painting the button - ModifyStyle(0, BS_OWNERDRAW); - - // create a tool tip - m_tip.Create(m_hWnd); - ATLASSERT(m_tip.IsWindow()); - if(m_tip.IsWindow() && m_lpstrToolTipText != NULL) - { - m_tip.Activate(TRUE); - m_tip.AddTool(m_hWnd, m_lpstrToolTipText); - } - - if(m_ImageList.m_hImageList != NULL && (m_dwExtendedStyle & BMPBTN_AUTOSIZE) != 0) - SizeToImage(); - } - - BOOL StartTrackMouseLeave() - { - TRACKMOUSEEVENT tme = { 0 }; - tme.cbSize = sizeof(tme); - tme.dwFlags = TME_LEAVE; - tme.hwndTrack = m_hWnd; - return _TrackMouseEvent(&tme); - } - - bool IsHoverMode() const - { - return ((m_dwExtendedStyle & BMPBTN_HOVER) != 0); - } -}; - - -class CBitmapButton : public CBitmapButtonImpl -{ -public: - DECLARE_WND_SUPERCLASS(_T("WTL_BitmapButton"), GetWndClassName()) - - CBitmapButton(DWORD dwExtendedStyle = BMPBTN_AUTOSIZE, HIMAGELIST hImageList = NULL) : - CBitmapButtonImpl(dwExtendedStyle, hImageList) - { } -}; - -#endif // !_WIN32_WCE - - -/////////////////////////////////////////////////////////////////////////////// -// CCheckListCtrlView - list view control with check boxes - -template -class CCheckListViewCtrlImplTraits -{ -public: - static DWORD GetWndStyle(DWORD dwStyle) - { - return (dwStyle == 0) ? t_dwStyle : dwStyle; - } - - static DWORD GetWndExStyle(DWORD dwExStyle) - { - return (dwExStyle == 0) ? t_dwExStyle : dwExStyle; - } - - static DWORD GetExtendedLVStyle() - { - return t_dwExListViewStyle; - } -}; - -typedef CCheckListViewCtrlImplTraits CCheckListViewCtrlTraits; - -template -class ATL_NO_VTABLE CCheckListViewCtrlImpl : public ATL::CWindowImpl -{ -public: - DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName()) - -// Attributes - static DWORD GetExtendedLVStyle() - { - return TWinTraits::GetExtendedLVStyle(); - } - -// Operations - BOOL SubclassWindow(HWND hWnd) - { -#if (_MSC_VER >= 1300) - BOOL bRet = ATL::CWindowImplBaseT< TBase, TWinTraits>::SubclassWindow(hWnd); -#else // !(_MSC_VER >= 1300) - typedef ATL::CWindowImplBaseT< TBase, TWinTraits> _baseClass; - BOOL bRet = _baseClass::SubclassWindow(hWnd); -#endif // !(_MSC_VER >= 1300) - if(bRet) - { - T* pT = static_cast(this); - pT; - ATLASSERT((pT->GetExtendedLVStyle() & LVS_EX_CHECKBOXES) != 0); - SetExtendedListViewStyle(pT->GetExtendedLVStyle()); - } - return bRet; - } - - void CheckSelectedItems(int nCurrItem) - { - // first check if this item is selected - LVITEM lvi = { 0 }; - lvi.iItem = nCurrItem; - lvi.iSubItem = 0; - lvi.mask = LVIF_STATE; - lvi.stateMask = LVIS_SELECTED; - GetItem(&lvi); - // if item is not selected, don't do anything - if(!(lvi.state & LVIS_SELECTED)) - return; - // new check state will be reverse of the current state, - BOOL bCheck = !GetCheckState(nCurrItem); - int nItem = -1; - int nOldItem = -1; - while((nItem = GetNextItem(nOldItem, LVNI_SELECTED)) != -1) - { - if(nItem != nCurrItem) - SetCheckState(nItem, bCheck); - nOldItem = nItem; - } - } - -// Implementation - BEGIN_MSG_MAP(CCheckListViewCtrlImpl) - MESSAGE_HANDLER(WM_CREATE, OnCreate) - MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown) - MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnLButtonDown) - MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown) - END_MSG_MAP() - - LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) - { - // first let list view control initialize everything - LRESULT lRet = DefWindowProc(uMsg, wParam, lParam); - T* pT = static_cast(this); - pT; - ATLASSERT((pT->GetExtendedLVStyle() & LVS_EX_CHECKBOXES) != 0); - SetExtendedListViewStyle(pT->GetExtendedLVStyle()); - return lRet; - } - - LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) - { - POINT ptMsg = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; - LVHITTESTINFO lvh = { 0 }; - lvh.pt = ptMsg; - if(HitTest(&lvh) != -1 && lvh.flags == LVHT_ONITEMSTATEICON && ::GetKeyState(VK_CONTROL) >= 0) - { - T* pT = static_cast(this); - pT->CheckSelectedItems(lvh.iItem); - } - bHandled = FALSE; - return 1; - } - - LRESULT OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) - { - if(wParam == VK_SPACE) - { - int nCurrItem = GetNextItem(-1, LVNI_FOCUSED); - if(nCurrItem != -1 && ::GetKeyState(VK_CONTROL) >= 0) - { - T* pT = static_cast(this); - pT->CheckSelectedItems(nCurrItem); - } - } - bHandled = FALSE; - return 1; - } -}; - -class CCheckListViewCtrl : public CCheckListViewCtrlImpl -{ -public: - DECLARE_WND_SUPERCLASS(_T("WTL_CheckListView"), GetWndClassName()) -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CHyperLink - hyper link control implementation - -#if (WINVER < 0x0500) && !defined(_WIN32_WCE) -__declspec(selectany) struct -{ - enum { cxWidth = 32, cyHeight = 32 }; - int xHotSpot; - int yHotSpot; - unsigned char arrANDPlane[cxWidth * cyHeight / 8]; - unsigned char arrXORPlane[cxWidth * cyHeight / 8]; -} _AtlHyperLink_CursorData = -{ - 5, 0, - { - 0xF9, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, - 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0x10, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x7F, 0xFF, - 0x80, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x7F, 0xFF, - 0xE0, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, - 0xF8, 0x01, 0xFF, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF - }, - { - 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0xC0, 0x00, 0x00, 0x06, 0xD8, 0x00, 0x00, - 0x06, 0xDA, 0x00, 0x00, 0x06, 0xDB, 0x00, 0x00, 0x67, 0xFB, 0x00, 0x00, 0x77, 0xFF, 0x00, 0x00, - 0x37, 0xFF, 0x00, 0x00, 0x17, 0xFF, 0x00, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x00, - 0x0F, 0xFE, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, - 0x03, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - } -}; -#endif // (WINVER < 0x0500) && !defined(_WIN32_WCE) - -#define HLINK_UNDERLINED 0x00000000 -#define HLINK_NOTUNDERLINED 0x00000001 -#define HLINK_UNDERLINEHOVER 0x00000002 -#define HLINK_COMMANDBUTTON 0x00000004 -#define HLINK_NOTIFYBUTTON 0x0000000C -#define HLINK_USETAGS 0x00000010 -#define HLINK_USETAGSBOLD 0x00000030 -#define HLINK_NOTOOLTIP 0x00000040 - -// Notes: -// - HLINK_USETAGS and HLINK_USETAGSBOLD are always left-aligned -// - When HLINK_USETAGSBOLD is used, the underlined styles will be ignored - -template -class ATL_NO_VTABLE CHyperLinkImpl : public ATL::CWindowImpl< T, TBase, TWinTraits > -{ -public: - LPTSTR m_lpstrLabel; - LPTSTR m_lpstrHyperLink; - - HCURSOR m_hCursor; - HFONT m_hFont; - HFONT m_hFontNormal; - - RECT m_rcLink; -#ifndef _WIN32_WCE - CToolTipCtrl m_tip; -#endif // !_WIN32_WCE - - COLORREF m_clrLink; - COLORREF m_clrVisited; - - DWORD m_dwExtendedStyle; // Hyper Link specific extended styles - - bool m_bPaintLabel:1; - bool m_bVisited:1; - bool m_bHover:1; - bool m_bInternalLinkFont:1; - - -// Constructor/Destructor - CHyperLinkImpl(DWORD dwExtendedStyle = HLINK_UNDERLINED) : - m_lpstrLabel(NULL), m_lpstrHyperLink(NULL), - m_hCursor(NULL), m_hFont(NULL), m_hFontNormal(NULL), - m_clrLink(RGB(0, 0, 255)), m_clrVisited(RGB(128, 0, 128)), - m_dwExtendedStyle(dwExtendedStyle), - m_bPaintLabel(true), m_bVisited(false), - m_bHover(false), m_bInternalLinkFont(false) - { - ::SetRectEmpty(&m_rcLink); - } - - ~CHyperLinkImpl() - { - delete [] m_lpstrLabel; - delete [] m_lpstrHyperLink; - if(m_bInternalLinkFont && m_hFont != NULL) - ::DeleteObject(m_hFont); -#if (WINVER < 0x0500) && !defined(_WIN32_WCE) - // It was created, not loaded, so we have to destroy it - if(m_hCursor != NULL) - ::DestroyCursor(m_hCursor); -#endif // (WINVER < 0x0500) && !defined(_WIN32_WCE) - } - -// Attributes - DWORD GetHyperLinkExtendedStyle() const - { - return m_dwExtendedStyle; - } - - DWORD SetHyperLinkExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0) - { - DWORD dwPrevStyle = m_dwExtendedStyle; - if(dwMask == 0) - m_dwExtendedStyle = dwExtendedStyle; - else - m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask); - return dwPrevStyle; - } - - bool GetLabel(LPTSTR lpstrBuffer, int nLength) const - { - if(m_lpstrLabel == NULL) - return false; - ATLASSERT(lpstrBuffer != NULL); - if(nLength <= lstrlen(m_lpstrLabel)) - return false; - - SecureHelper::strcpy_x(lpstrBuffer, nLength, m_lpstrLabel); - - return true; - } - - bool SetLabel(LPCTSTR lpstrLabel) - { - delete [] m_lpstrLabel; - m_lpstrLabel = NULL; - int cchLen = lstrlen(lpstrLabel) + 1; - ATLTRY(m_lpstrLabel = new TCHAR[cchLen]); - if(m_lpstrLabel == NULL) - return false; - - SecureHelper::strcpy_x(m_lpstrLabel, cchLen, lpstrLabel); - T* pT = static_cast(this); - pT->CalcLabelRect(); - - if(m_hWnd != NULL) - SetWindowText(lpstrLabel); // Set this for accessibility - - return true; - } - - bool GetHyperLink(LPTSTR lpstrBuffer, int nLength) const - { - if(m_lpstrHyperLink == NULL) - return false; - ATLASSERT(lpstrBuffer != NULL); - if(nLength <= lstrlen(m_lpstrHyperLink)) - return false; - - SecureHelper::strcpy_x(lpstrBuffer, nLength, m_lpstrHyperLink); - - return true; - } - - bool SetHyperLink(LPCTSTR lpstrLink) - { - delete [] m_lpstrHyperLink; - m_lpstrHyperLink = NULL; - int cchLen = lstrlen(lpstrLink) + 1; - ATLTRY(m_lpstrHyperLink = new TCHAR[cchLen]); - if(m_lpstrHyperLink == NULL) - return false; - - SecureHelper::strcpy_x(m_lpstrHyperLink, cchLen, lpstrLink); - if(m_lpstrLabel == NULL) - { - T* pT = static_cast(this); - pT->CalcLabelRect(); - } -#ifndef _WIN32_WCE - if(m_tip.IsWindow()) - { - m_tip.Activate(TRUE); - m_tip.AddTool(m_hWnd, m_lpstrHyperLink, &m_rcLink, 1); - } -#endif // !_WIN32_WCE - return true; - } - - HFONT GetLinkFont() const - { - return m_hFont; - } - - void SetLinkFont(HFONT hFont) - { - if(m_bInternalLinkFont && m_hFont != NULL) - { - ::DeleteObject(m_hFont); - m_bInternalLinkFont = false; - } - m_hFont = hFont; - } - - int GetIdealHeight() const - { - ATLASSERT(::IsWindow(m_hWnd)); - if(m_lpstrLabel == NULL && m_lpstrHyperLink == NULL) - return -1; - if(!m_bPaintLabel) - return -1; - - CClientDC dc(m_hWnd); - RECT rect = { 0 }; - GetClientRect(&rect); - HFONT hFontOld = dc.SelectFont(m_hFontNormal); - RECT rcText = rect; - dc.DrawText(_T("NS"), -1, &rcText, DT_LEFT | DT_WORDBREAK | DT_CALCRECT); - dc.SelectFont(m_hFont); - RECT rcLink = rect; - dc.DrawText(_T("NS"), -1, &rcLink, DT_LEFT | DT_WORDBREAK | DT_CALCRECT); - dc.SelectFont(hFontOld); - return max(rcText.bottom - rcText.top, rcLink.bottom - rcLink.top); - } - - bool GetIdealSize(SIZE& size) const - { - int cx = 0, cy = 0; - bool bRet = GetIdealSize(cx, cy); - if(bRet) - { - size.cx = cx; - size.cy = cy; - } - return bRet; - } - - bool GetIdealSize(int& cx, int& cy) const - { - ATLASSERT(::IsWindow(m_hWnd)); - if(m_lpstrLabel == NULL && m_lpstrHyperLink == NULL) - return false; - if(!m_bPaintLabel) - return false; - - CClientDC dc(m_hWnd); - RECT rcClient = { 0 }; - GetClientRect(&rcClient); - RECT rcAll = rcClient; - - if(IsUsingTags()) - { - // find tags and label parts - LPTSTR lpstrLeft = NULL; - int cchLeft = 0; - LPTSTR lpstrLink = NULL; - int cchLink = 0; - LPTSTR lpstrRight = NULL; - int cchRight = 0; - - const T* pT = static_cast(this); - pT->CalcLabelParts(lpstrLeft, cchLeft, lpstrLink, cchLink, lpstrRight, cchRight); - - // get label part rects - HFONT hFontOld = dc.SelectFont(m_hFontNormal); - RECT rcLeft = rcClient; - dc.DrawText(lpstrLeft, cchLeft, &rcLeft, DT_LEFT | DT_WORDBREAK | DT_CALCRECT); - - dc.SelectFont(m_hFont); - RECT rcLink = { rcLeft.right, rcLeft.top, rcClient.right, rcClient.bottom }; - dc.DrawText(lpstrLink, cchLink, &rcLink, DT_LEFT | DT_WORDBREAK | DT_CALCRECT); - - dc.SelectFont(m_hFontNormal); - RECT rcRight = { rcLink.right, rcLink.top, rcClient.right, rcClient.bottom }; - dc.DrawText(lpstrRight, cchRight, &rcRight, DT_LEFT | DT_WORDBREAK | DT_CALCRECT); - - dc.SelectFont(hFontOld); - - int cyMax = max(rcLeft.bottom, max(rcLink.bottom, rcRight.bottom)); - ::SetRect(&rcAll, rcLeft.left, rcLeft.top, rcRight.right, cyMax); - } - else - { - HFONT hOldFont = NULL; - if(m_hFont != NULL) - hOldFont = dc.SelectFont(m_hFont); - LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink; - DWORD dwStyle = GetStyle(); - int nDrawStyle = DT_LEFT; - if (dwStyle & SS_CENTER) - nDrawStyle = DT_CENTER; - else if (dwStyle & SS_RIGHT) - nDrawStyle = DT_RIGHT; - dc.DrawText(lpstrText, -1, &rcAll, nDrawStyle | DT_WORDBREAK | DT_CALCRECT); - if(m_hFont != NULL) - dc.SelectFont(hOldFont); - if (dwStyle & SS_CENTER) - { - int dx = (rcClient.right - rcAll.right) / 2; - ::OffsetRect(&rcAll, dx, 0); - } - else if (dwStyle & SS_RIGHT) - { - int dx = rcClient.right - rcAll.right; - ::OffsetRect(&rcAll, dx, 0); - } - } - - cx = rcAll.right - rcAll.left; - cy = rcAll.bottom - rcAll.top; - - return true; - } - - // for command buttons only - bool GetToolTipText(LPTSTR lpstrBuffer, int nLength) const - { - ATLASSERT(IsCommandButton()); - return GetHyperLink(lpstrBuffer, nLength); - } - - bool SetToolTipText(LPCTSTR lpstrToolTipText) - { - ATLASSERT(IsCommandButton()); - return SetHyperLink(lpstrToolTipText); - } - -// Operations - BOOL SubclassWindow(HWND hWnd) - { - ATLASSERT(m_hWnd == NULL); - ATLASSERT(::IsWindow(hWnd)); -#if (_MSC_VER >= 1300) - BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits>::SubclassWindow(hWnd); -#else // !(_MSC_VER >= 1300) - typedef ATL::CWindowImpl< T, TBase, TWinTraits> _baseClass; - BOOL bRet = _baseClass::SubclassWindow(hWnd); -#endif // !(_MSC_VER >= 1300) - if(bRet) - { - T* pT = static_cast(this); - pT->Init(); - } - return bRet; - } - - bool Navigate() - { - ATLASSERT(::IsWindow(m_hWnd)); - bool bRet = true; - if(IsNotifyButton()) - { - NMHDR nmhdr = { m_hWnd, GetDlgCtrlID(), NM_CLICK }; - ::SendMessage(GetParent(), WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmhdr); - } - else if(IsCommandButton()) - { - ::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd); - } - else - { - ATLASSERT(m_lpstrHyperLink != NULL); -#ifndef _WIN32_WCE - DWORD_PTR dwRet = (DWORD_PTR)::ShellExecute(0, _T("open"), m_lpstrHyperLink, 0, 0, SW_SHOWNORMAL); - bRet = (dwRet > 32); -#else // CE specific - SHELLEXECUTEINFO shExeInfo = { sizeof(SHELLEXECUTEINFO), 0, 0, L"open", m_lpstrHyperLink, 0, 0, SW_SHOWNORMAL, 0, 0, 0, 0, 0, 0, 0 }; - ::ShellExecuteEx(&shExeInfo); - DWORD_PTR dwRet = (DWORD_PTR)shExeInfo.hInstApp; - bRet = (dwRet == 0) || (dwRet > 32); -#endif // _WIN32_WCE - ATLASSERT(bRet); - if(bRet) - { - m_bVisited = true; - Invalidate(); - } - } - return bRet; - } - -// Message map and handlers - BEGIN_MSG_MAP(CHyperLinkImpl) - MESSAGE_HANDLER(WM_CREATE, OnCreate) -#ifndef _WIN32_WCE - MESSAGE_HANDLER(WM_DESTROY, OnDestroy) - MESSAGE_RANGE_HANDLER(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseMessage) -#endif // !_WIN32_WCE - MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) - MESSAGE_HANDLER(WM_PAINT, OnPaint) -#ifndef _WIN32_WCE - MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) -#endif // !_WIN32_WCE - MESSAGE_HANDLER(WM_SETFOCUS, OnFocus) - MESSAGE_HANDLER(WM_KILLFOCUS, OnFocus) - MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove) -#ifndef _WIN32_WCE - MESSAGE_HANDLER(WM_MOUSELEAVE, OnMouseLeave) -#endif // !_WIN32_WCE - MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown) - MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp) - MESSAGE_HANDLER(WM_CHAR, OnChar) - MESSAGE_HANDLER(WM_GETDLGCODE, OnGetDlgCode) - MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor) - MESSAGE_HANDLER(WM_ENABLE, OnEnable) - MESSAGE_HANDLER(WM_GETFONT, OnGetFont) - MESSAGE_HANDLER(WM_SETFONT, OnSetFont) - MESSAGE_HANDLER(WM_UPDATEUISTATE, OnUpdateUiState) - MESSAGE_HANDLER(WM_SIZE, OnSize) - END_MSG_MAP() - - LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - pT->Init(); - return 0; - } - -#ifndef _WIN32_WCE - LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - if(m_tip.IsWindow()) - { - m_tip.DestroyWindow(); - m_tip.m_hWnd = NULL; - } - bHandled = FALSE; - return 1; - } - - LRESULT OnMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - MSG msg = { m_hWnd, uMsg, wParam, lParam }; - if(m_tip.IsWindow() && IsUsingToolTip()) - m_tip.RelayEvent(&msg); - bHandled = FALSE; - return 1; - } -#endif // !_WIN32_WCE - - LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - return 1; // no background painting needed (we do it all during WM_PAINT) - } - - LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) - { - if(!m_bPaintLabel) - { - bHandled = FALSE; - return 1; - } - - T* pT = static_cast(this); - if(wParam != NULL) - { - pT->DoEraseBackground((HDC)wParam); - pT->DoPaint((HDC)wParam); - } - else - { - CPaintDC dc(m_hWnd); - pT->DoEraseBackground(dc.m_hDC); - pT->DoPaint(dc.m_hDC); - } - - return 0; - } - - LRESULT OnFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - if(m_bPaintLabel) - Invalidate(); - else - bHandled = FALSE; - return 0; - } - - LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) - { - POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; - if((m_lpstrHyperLink != NULL || IsCommandButton()) && ::PtInRect(&m_rcLink, pt)) - { - ::SetCursor(m_hCursor); - if(IsUnderlineHover()) - { - if(!m_bHover) - { - m_bHover = true; - InvalidateRect(&m_rcLink); - UpdateWindow(); -#ifndef _WIN32_WCE - StartTrackMouseLeave(); -#endif // !_WIN32_WCE - } - } - } - else - { - if(IsUnderlineHover()) - { - if(m_bHover) - { - m_bHover = false; - InvalidateRect(&m_rcLink); - UpdateWindow(); - } - } - bHandled = FALSE; - } - return 0; - } - -#ifndef _WIN32_WCE - LRESULT OnMouseLeave(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - if(IsUnderlineHover() && m_bHover) - { - m_bHover = false; - InvalidateRect(&m_rcLink); - UpdateWindow(); - } - return 0; - } -#endif // !_WIN32_WCE - - LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) - { - POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; - if(::PtInRect(&m_rcLink, pt)) - { - SetFocus(); - SetCapture(); - } - return 0; - } - - LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) - { - if(GetCapture() == m_hWnd) - { - ReleaseCapture(); - POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; - if(::PtInRect(&m_rcLink, pt)) - { - T* pT = static_cast(this); - pT->Navigate(); - } - } - return 0; - } - - LRESULT OnChar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - if(wParam == VK_RETURN || wParam == VK_SPACE) - { - T* pT = static_cast(this); - pT->Navigate(); - } - return 0; - } - - LRESULT OnGetDlgCode(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - return DLGC_WANTCHARS; - } - - LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - POINT pt = { 0, 0 }; - GetCursorPos(&pt); - ScreenToClient(&pt); - if((m_lpstrHyperLink != NULL || IsCommandButton()) && ::PtInRect(&m_rcLink, pt)) - { - return TRUE; - } - bHandled = FALSE; - return FALSE; - } - - LRESULT OnEnable(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - Invalidate(); - UpdateWindow(); - return 0; - } - - LRESULT OnGetFont(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - return (LRESULT)m_hFontNormal; - } - - LRESULT OnSetFont(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) - { - m_hFontNormal = (HFONT)wParam; - if((BOOL)lParam) - { - Invalidate(); - UpdateWindow(); - } - return 0; - } - - LRESULT OnUpdateUiState(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - // If the control is subclassed or superclassed, this message can cause - // repainting without WM_PAINT. We don't use this state, so just do nothing. - return 0; - } - - LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - pT->CalcLabelRect(); - pT->Invalidate(); - return 0; - } - -// Implementation - void Init() - { - ATLASSERT(::IsWindow(m_hWnd)); - - // Check if we should paint a label - const int cchBuff = 8; - TCHAR szBuffer[cchBuff] = { 0 }; - if(::GetClassName(m_hWnd, szBuffer, cchBuff)) - { - if(lstrcmpi(szBuffer, _T("static")) == 0) - { - ModifyStyle(0, SS_NOTIFY); // we need this - DWORD dwStyle = GetStyle() & 0x000000FF; -#ifndef _WIN32_WCE - if(dwStyle == SS_ICON || dwStyle == SS_BLACKRECT || dwStyle == SS_GRAYRECT || - dwStyle == SS_WHITERECT || dwStyle == SS_BLACKFRAME || dwStyle == SS_GRAYFRAME || - dwStyle == SS_WHITEFRAME || dwStyle == SS_OWNERDRAW || - dwStyle == SS_BITMAP || dwStyle == SS_ENHMETAFILE) -#else // CE specific - if(dwStyle == SS_ICON || dwStyle == SS_BITMAP) -#endif // _WIN32_WCE - m_bPaintLabel = false; - } - } - - // create or load a cursor -#if (WINVER >= 0x0500) || defined(_WIN32_WCE) - m_hCursor = ::LoadCursor(NULL, IDC_HAND); -#else - m_hCursor = ::CreateCursor(ModuleHelper::GetModuleInstance(), _AtlHyperLink_CursorData.xHotSpot, _AtlHyperLink_CursorData.yHotSpot, _AtlHyperLink_CursorData.cxWidth, _AtlHyperLink_CursorData.cyHeight, _AtlHyperLink_CursorData.arrANDPlane, _AtlHyperLink_CursorData.arrXORPlane); -#endif - ATLASSERT(m_hCursor != NULL); - - // set font - if(m_bPaintLabel) - { - ATL::CWindow wnd = GetParent(); - m_hFontNormal = wnd.GetFont(); - if(m_hFontNormal == NULL) - m_hFontNormal = (HFONT)::GetStockObject(SYSTEM_FONT); - if(m_hFontNormal != NULL && m_hFont == NULL) - { - LOGFONT lf = { 0 }; - CFontHandle font = m_hFontNormal; - font.GetLogFont(&lf); - if(IsUsingTagsBold()) - lf.lfWeight = FW_BOLD; - else if(!IsNotUnderlined()) - lf.lfUnderline = TRUE; - m_hFont = ::CreateFontIndirect(&lf); - m_bInternalLinkFont = true; - ATLASSERT(m_hFont != NULL); - } - } - -#ifndef _WIN32_WCE - // create a tool tip - m_tip.Create(m_hWnd); - ATLASSERT(m_tip.IsWindow()); -#endif // !_WIN32_WCE - - // set label (defaults to window text) - if(m_lpstrLabel == NULL) - { - int nLen = GetWindowTextLength(); - if(nLen > 0) - { - CTempBuffer buff; - LPTSTR lpstrText = buff.Allocate(nLen + 1); - ATLASSERT(lpstrText != NULL); - if((lpstrText != NULL) && (GetWindowText(lpstrText, nLen + 1) > 0)) - SetLabel(lpstrText); - } - } - - T* pT = static_cast(this); - pT->CalcLabelRect(); - - // set hyperlink (defaults to label), or just activate tool tip if already set - if(m_lpstrHyperLink == NULL && !IsCommandButton()) - { - if(m_lpstrLabel != NULL) - SetHyperLink(m_lpstrLabel); - } -#ifndef _WIN32_WCE - else - { - m_tip.Activate(TRUE); - m_tip.AddTool(m_hWnd, m_lpstrHyperLink, &m_rcLink, 1); - } -#endif // !_WIN32_WCE - - // set link colors - if(m_bPaintLabel) - { - ATL::CRegKey rk; - LONG lRet = rk.Open(HKEY_CURRENT_USER, _T("Software\\Microsoft\\Internet Explorer\\Settings")); - if(lRet == 0) - { - const int cchValue = 12; - TCHAR szValue[cchValue] = { 0 }; -#if (_ATL_VER >= 0x0700) - ULONG ulCount = cchValue; - lRet = rk.QueryStringValue(_T("Anchor Color"), szValue, &ulCount); -#else - DWORD dwCount = cchValue * sizeof(TCHAR); - lRet = rk.QueryValue(szValue, _T("Anchor Color"), &dwCount); -#endif - if(lRet == 0) - { - COLORREF clr = pT->_ParseColorString(szValue); - ATLASSERT(clr != CLR_INVALID); - if(clr != CLR_INVALID) - m_clrLink = clr; - } - -#if (_ATL_VER >= 0x0700) - ulCount = cchValue; - lRet = rk.QueryStringValue(_T("Anchor Color Visited"), szValue, &ulCount); -#else - dwCount = cchValue * sizeof(TCHAR); - lRet = rk.QueryValue(szValue, _T("Anchor Color Visited"), &dwCount); -#endif - if(lRet == 0) - { - COLORREF clr = pT->_ParseColorString(szValue); - ATLASSERT(clr != CLR_INVALID); - if(clr != CLR_INVALID) - m_clrVisited = clr; - } - } - } - } - - static COLORREF _ParseColorString(LPTSTR lpstr) - { - int c[3] = { -1, -1, -1 }; - LPTSTR p = NULL; - for(int i = 0; i < 2; i++) - { - for(p = lpstr; *p != _T('\0'); p = ::CharNext(p)) - { - if(*p == _T(',')) - { - *p = _T('\0'); - c[i] = T::_xttoi(lpstr); - lpstr = &p[1]; - break; - } - } - if(c[i] == -1) - return CLR_INVALID; - } - if(*lpstr == _T('\0')) - return CLR_INVALID; - c[2] = T::_xttoi(lpstr); - - return RGB(c[0], c[1], c[2]); - } - - bool CalcLabelRect() - { - if(!::IsWindow(m_hWnd)) - return false; - if(m_lpstrLabel == NULL && m_lpstrHyperLink == NULL) - return false; - - CClientDC dc(m_hWnd); - RECT rcClient = { 0 }; - GetClientRect(&rcClient); - m_rcLink = rcClient; - if(!m_bPaintLabel) - return true; - - if(IsUsingTags()) - { - // find tags and label parts - LPTSTR lpstrLeft = NULL; - int cchLeft = 0; - LPTSTR lpstrLink = NULL; - int cchLink = 0; - LPTSTR lpstrRight = NULL; - int cchRight = 0; - - T* pT = static_cast(this); - pT->CalcLabelParts(lpstrLeft, cchLeft, lpstrLink, cchLink, lpstrRight, cchRight); - ATLASSERT(lpstrLink != NULL); - ATLASSERT(cchLink > 0); - - // get label part rects - HFONT hFontOld = dc.SelectFont(m_hFontNormal); - - RECT rcLeft = rcClient; - if(lpstrLeft != NULL) - dc.DrawText(lpstrLeft, cchLeft, &rcLeft, DT_LEFT | DT_WORDBREAK | DT_CALCRECT); - - dc.SelectFont(m_hFont); - RECT rcLink = rcClient; - if(lpstrLeft != NULL) - rcLink.left = rcLeft.right; - dc.DrawText(lpstrLink, cchLink, &rcLink, DT_LEFT | DT_WORDBREAK | DT_CALCRECT); - - dc.SelectFont(hFontOld); - - m_rcLink = rcLink; - } - else - { - HFONT hOldFont = NULL; - if(m_hFont != NULL) - hOldFont = dc.SelectFont(m_hFont); - LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink; - DWORD dwStyle = GetStyle(); - int nDrawStyle = DT_LEFT; - if (dwStyle & SS_CENTER) - nDrawStyle = DT_CENTER; - else if (dwStyle & SS_RIGHT) - nDrawStyle = DT_RIGHT; - dc.DrawText(lpstrText, -1, &m_rcLink, nDrawStyle | DT_WORDBREAK | DT_CALCRECT); - if(m_hFont != NULL) - dc.SelectFont(hOldFont); - if (dwStyle & SS_CENTER) - { - int dx = (rcClient.right - m_rcLink.right) / 2; - ::OffsetRect(&m_rcLink, dx, 0); - } - else if (dwStyle & SS_RIGHT) - { - int dx = rcClient.right - m_rcLink.right; - ::OffsetRect(&m_rcLink, dx, 0); - } - } - - return true; - } - - void CalcLabelParts(LPTSTR& lpstrLeft, int& cchLeft, LPTSTR& lpstrLink, int& cchLink, LPTSTR& lpstrRight, int& cchRight) const - { - lpstrLeft = NULL; - cchLeft = 0; - lpstrLink = NULL; - cchLink = 0; - lpstrRight = NULL; - cchRight = 0; - - LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink; - int cchText = lstrlen(lpstrText); - bool bOutsideLink = true; - for(int i = 0; i < cchText; i++) - { - if(lpstrText[i] != _T('<')) - continue; - - if(bOutsideLink) - { - if(::CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, &lpstrText[i], 3, _T(""), 3) == CSTR_EQUAL) - { - if(i > 0) - { - lpstrLeft = lpstrText; - cchLeft = i; - } - lpstrLink = &lpstrText[i + 3]; - bOutsideLink = false; - } - } - else - { - if(::CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, &lpstrText[i], 4, _T(""), 4) == CSTR_EQUAL) - { - cchLink = i - 3 - cchLeft; - if(lpstrText[i + 4] != 0) - { - lpstrRight = &lpstrText[i + 4]; - cchRight = cchText - (i + 4); - break; - } - } - } - } - - } - - void DoEraseBackground(CDCHandle dc) - { - HBRUSH hBrush = (HBRUSH)::SendMessage(GetParent(), WM_CTLCOLORSTATIC, (WPARAM)dc.m_hDC, (LPARAM)m_hWnd); - if(hBrush != NULL) - { - RECT rect = { 0 }; - GetClientRect(&rect); - dc.FillRect(&rect, hBrush); - } - } - - void DoPaint(CDCHandle dc) - { - if(IsUsingTags()) - { - // find tags and label parts - LPTSTR lpstrLeft = NULL; - int cchLeft = 0; - LPTSTR lpstrLink = NULL; - int cchLink = 0; - LPTSTR lpstrRight = NULL; - int cchRight = 0; - - T* pT = static_cast(this); - pT->CalcLabelParts(lpstrLeft, cchLeft, lpstrLink, cchLink, lpstrRight, cchRight); - - // get label part rects - RECT rcClient = { 0 }; - GetClientRect(&rcClient); - - dc.SetBkMode(TRANSPARENT); - HFONT hFontOld = dc.SelectFont(m_hFontNormal); - - if(lpstrLeft != NULL) - dc.DrawText(lpstrLeft, cchLeft, &rcClient, DT_LEFT | DT_WORDBREAK); - - COLORREF clrOld = dc.SetTextColor(IsWindowEnabled() ? (m_bVisited ? m_clrVisited : m_clrLink) : (::GetSysColor(COLOR_GRAYTEXT))); - if(m_hFont != NULL && (!IsUnderlineHover() || (IsUnderlineHover() && m_bHover))) - dc.SelectFont(m_hFont); - else - dc.SelectFont(m_hFontNormal); - - dc.DrawText(lpstrLink, cchLink, &m_rcLink, DT_LEFT | DT_WORDBREAK); - - dc.SetTextColor(clrOld); - dc.SelectFont(m_hFontNormal); - if(lpstrRight != NULL) - { - RECT rcRight = { m_rcLink.right, m_rcLink.top, rcClient.right, rcClient.bottom }; - dc.DrawText(lpstrRight, cchRight, &rcRight, DT_LEFT | DT_WORDBREAK); - } - - if(GetFocus() == m_hWnd) - dc.DrawFocusRect(&m_rcLink); - - dc.SelectFont(hFontOld); - } - else - { - dc.SetBkMode(TRANSPARENT); - COLORREF clrOld = dc.SetTextColor(IsWindowEnabled() ? (m_bVisited ? m_clrVisited : m_clrLink) : (::GetSysColor(COLOR_GRAYTEXT))); - - HFONT hFontOld = NULL; - if(m_hFont != NULL && (!IsUnderlineHover() || (IsUnderlineHover() && m_bHover))) - hFontOld = dc.SelectFont(m_hFont); - else - hFontOld = dc.SelectFont(m_hFontNormal); - - LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink; - - DWORD dwStyle = GetStyle(); - int nDrawStyle = DT_LEFT; - if (dwStyle & SS_CENTER) - nDrawStyle = DT_CENTER; - else if (dwStyle & SS_RIGHT) - nDrawStyle = DT_RIGHT; - - dc.DrawText(lpstrText, -1, &m_rcLink, nDrawStyle | DT_WORDBREAK); - - if(GetFocus() == m_hWnd) - dc.DrawFocusRect(&m_rcLink); - - dc.SetTextColor(clrOld); - dc.SelectFont(hFontOld); - } - } - -#ifndef _WIN32_WCE - BOOL StartTrackMouseLeave() - { - TRACKMOUSEEVENT tme = { 0 }; - tme.cbSize = sizeof(tme); - tme.dwFlags = TME_LEAVE; - tme.hwndTrack = m_hWnd; - return _TrackMouseEvent(&tme); - } -#endif // !_WIN32_WCE - -// Implementation helpers - bool IsUnderlined() const - { - return ((m_dwExtendedStyle & (HLINK_NOTUNDERLINED | HLINK_UNDERLINEHOVER)) == 0); - } - - bool IsNotUnderlined() const - { - return ((m_dwExtendedStyle & HLINK_NOTUNDERLINED) != 0); - } - - bool IsUnderlineHover() const - { - return ((m_dwExtendedStyle & HLINK_UNDERLINEHOVER) != 0); - } - - bool IsCommandButton() const - { - return ((m_dwExtendedStyle & HLINK_COMMANDBUTTON) != 0); - } - - bool IsNotifyButton() const - { - return ((m_dwExtendedStyle & HLINK_NOTIFYBUTTON) == HLINK_NOTIFYBUTTON); - } - - bool IsUsingTags() const - { - return ((m_dwExtendedStyle & HLINK_USETAGS) != 0); - } - - bool IsUsingTagsBold() const - { - return ((m_dwExtendedStyle & HLINK_USETAGSBOLD) == HLINK_USETAGSBOLD); - } - - bool IsUsingToolTip() const - { - return ((m_dwExtendedStyle & HLINK_NOTOOLTIP) == 0); - } - - static int _xttoi(const TCHAR* nptr) - { -#ifndef _ATL_MIN_CRT - return _ttoi(nptr); -#else // _ATL_MIN_CRT - while(*nptr == _T(' ')) // skip spaces - ++nptr; - - int c = (int)(_TUCHAR)*nptr++; - int sign = c; // save sign indication - if (c == _T('-') || c == _T('+')) - c = (int)(_TUCHAR)*nptr++; // skip sign - - int total = 0; - while((TCHAR)c >= _T('0') && (TCHAR)c <= _T('9')) - { - total = 10 * total + ((TCHAR)c - _T('0')); // accumulate digit - c = (int)(_TUCHAR)*nptr++; // get next char - } - - // return result, negated if necessary - return ((TCHAR)sign != _T('-')) ? total : -total; -#endif // _ATL_MIN_CRT - } -}; - - -class CHyperLink : public CHyperLinkImpl -{ -public: - DECLARE_WND_CLASS(_T("WTL_HyperLink")) -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CWaitCursor - displays a wait cursor - -class CWaitCursor -{ -public: -// Data - HCURSOR m_hWaitCursor; - HCURSOR m_hOldCursor; - bool m_bInUse; - -// Constructor/destructor - CWaitCursor(bool bSet = true, LPCTSTR lpstrCursor = IDC_WAIT, bool bSys = true) : m_hOldCursor(NULL), m_bInUse(false) - { - HINSTANCE hInstance = bSys ? NULL : ModuleHelper::GetResourceInstance(); - m_hWaitCursor = ::LoadCursor(hInstance, lpstrCursor); - ATLASSERT(m_hWaitCursor != NULL); - - if(bSet) - Set(); - } - - ~CWaitCursor() - { - Restore(); - } - -// Methods - bool Set() - { - if(m_bInUse) - return false; - m_hOldCursor = ::SetCursor(m_hWaitCursor); - m_bInUse = true; - return true; - } - - bool Restore() - { - if(!m_bInUse) - return false; - ::SetCursor(m_hOldCursor); - m_bInUse = false; - return true; - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CCustomWaitCursor - for custom and animated cursors - -class CCustomWaitCursor : public CWaitCursor -{ -public: -// Constructor/destructor - CCustomWaitCursor(ATL::_U_STRINGorID cursor, bool bSet = true, HINSTANCE hInstance = NULL) : - CWaitCursor(false, IDC_WAIT, true) - { - if(hInstance == NULL) - hInstance = ModuleHelper::GetResourceInstance(); - m_hWaitCursor = (HCURSOR)::LoadImage(hInstance, cursor.m_lpstr, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE); - - if(bSet) - Set(); - } - - ~CCustomWaitCursor() - { - Restore(); -#if !defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP))) - ::DestroyCursor(m_hWaitCursor); -#endif // !defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP))) - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CMultiPaneStatusBarCtrl - Status Bar with multiple panes - -template -class ATL_NO_VTABLE CMultiPaneStatusBarCtrlImpl : public ATL::CWindowImpl< T, TBase > -{ -public: - DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName()) - -// Data - enum { m_cxPaneMargin = 3 }; - - int m_nPanes; - int* m_pPane; - -// Constructor/destructor - CMultiPaneStatusBarCtrlImpl() : m_nPanes(0), m_pPane(NULL) - { } - - ~CMultiPaneStatusBarCtrlImpl() - { - delete [] m_pPane; - } - -// Methods - HWND Create(HWND hWndParent, LPCTSTR lpstrText, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL_IDW_STATUS_BAR) - { -#if (_MSC_VER >= 1300) - return ATL::CWindowImpl< T, TBase >::Create(hWndParent, rcDefault, lpstrText, dwStyle, 0, nID); -#else // !(_MSC_VER >= 1300) - typedef ATL::CWindowImpl< T, TBase > _baseClass; - return _baseClass::Create(hWndParent, rcDefault, lpstrText, dwStyle, 0, nID); -#endif // !(_MSC_VER >= 1300) - } - - HWND Create(HWND hWndParent, UINT nTextID = ATL_IDS_IDLEMESSAGE, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL_IDW_STATUS_BAR) - { - const int cchMax = 128; // max text length is 127 for status bars (+1 for null) - TCHAR szText[cchMax]; - szText[0] = 0; - ::LoadString(ModuleHelper::GetResourceInstance(), nTextID, szText, cchMax); - return Create(hWndParent, szText, dwStyle, nID); - } - - BOOL SetPanes(int* pPanes, int nPanes, bool bSetText = true) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(nPanes > 0); - - m_nPanes = nPanes; - delete [] m_pPane; - m_pPane = NULL; - - ATLTRY(m_pPane = new int[nPanes]); - ATLASSERT(m_pPane != NULL); - if(m_pPane == NULL) - return FALSE; - - CTempBuffer buff; - int* pPanesPos = buff.Allocate(nPanes); - ATLASSERT(pPanesPos != NULL); - if(pPanesPos == NULL) - return FALSE; - - SecureHelper::memcpy_x(m_pPane, nPanes * sizeof(int), pPanes, nPanes * sizeof(int)); - - // get status bar DC and set font - CClientDC dc(m_hWnd); - HFONT hOldFont = dc.SelectFont(GetFont()); - - // get status bar borders - int arrBorders[3] = { 0 }; - GetBorders(arrBorders); - - const int cchBuff = 128; - TCHAR szBuff[cchBuff] = { 0 }; - SIZE size = { 0, 0 }; - int cxLeft = arrBorders[0]; - - // calculate right edge of each part - for(int i = 0; i < nPanes; i++) - { - if(pPanes[i] == ID_DEFAULT_PANE) - { - // make very large, will be resized later - pPanesPos[i] = INT_MAX / 2; - } - else - { - ::LoadString(ModuleHelper::GetResourceInstance(), pPanes[i], szBuff, cchBuff); - dc.GetTextExtent(szBuff, lstrlen(szBuff), &size); - T* pT = static_cast(this); - pT; - pPanesPos[i] = cxLeft + size.cx + arrBorders[2] + 2 * pT->m_cxPaneMargin; - } - cxLeft = pPanesPos[i]; - } - - BOOL bRet = SetParts(nPanes, pPanesPos); - - if(bRet && bSetText) - { - for(int i = 0; i < nPanes; i++) - { - if(pPanes[i] != ID_DEFAULT_PANE) - { - ::LoadString(ModuleHelper::GetResourceInstance(), pPanes[i], szBuff, cchBuff); - SetPaneText(m_pPane[i], szBuff); - } - } - } - - dc.SelectFont(hOldFont); - return bRet; - } - - bool GetPaneTextLength(int nPaneID, int* pcchLength = NULL, int* pnType = NULL) const - { - ATLASSERT(::IsWindow(m_hWnd)); - int nIndex = GetPaneIndexFromID(nPaneID); - if(nIndex == -1) - return false; - - int nLength = GetTextLength(nIndex, pnType); - if(pcchLength != NULL) - *pcchLength = nLength; - - return true; - } - - BOOL GetPaneText(int nPaneID, LPTSTR lpstrText, int* pcchLength = NULL, int* pnType = NULL) const - { - ATLASSERT(::IsWindow(m_hWnd)); - int nIndex = GetPaneIndexFromID(nPaneID); - if(nIndex == -1) - return FALSE; - - int nLength = GetText(nIndex, lpstrText, pnType); - if(pcchLength != NULL) - *pcchLength = nLength; - - return TRUE; - } - - BOOL SetPaneText(int nPaneID, LPCTSTR lpstrText, int nType = 0) - { - ATLASSERT(::IsWindow(m_hWnd)); - int nIndex = GetPaneIndexFromID(nPaneID); - if(nIndex == -1) - return FALSE; - - return SetText(nIndex, lpstrText, nType); - } - - BOOL GetPaneRect(int nPaneID, LPRECT lpRect) const - { - ATLASSERT(::IsWindow(m_hWnd)); - int nIndex = GetPaneIndexFromID(nPaneID); - if(nIndex == -1) - return FALSE; - - return GetRect(nIndex, lpRect); - } - - BOOL SetPaneWidth(int nPaneID, int cxWidth) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(nPaneID != ID_DEFAULT_PANE); // Can't resize this one - int nIndex = GetPaneIndexFromID(nPaneID); - if(nIndex == -1) - return FALSE; - - // get pane positions - CTempBuffer buff; - int* pPanesPos = buff.Allocate(m_nPanes); - if(pPanesPos == NULL) - return FALSE; - GetParts(m_nPanes, pPanesPos); - // calculate offset - int cxPaneWidth = pPanesPos[nIndex] - ((nIndex == 0) ? 0 : pPanesPos[nIndex - 1]); - int cxOff = cxWidth - cxPaneWidth; - // find variable width pane - int nDef = m_nPanes; - for(int i = 0; i < m_nPanes; i++) - { - if(m_pPane[i] == ID_DEFAULT_PANE) - { - nDef = i; - break; - } - } - // resize - if(nIndex < nDef) // before default pane - { - for(int i = nIndex; i < nDef; i++) - pPanesPos[i] += cxOff; - - } - else // after default one - { - for(int i = nDef; i < nIndex; i++) - pPanesPos[i] -= cxOff; - } - // set pane postions - return SetParts(m_nPanes, pPanesPos); - } - -#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) - BOOL GetPaneTipText(int nPaneID, LPTSTR lpstrText, int nSize) const - { - ATLASSERT(::IsWindow(m_hWnd)); - int nIndex = GetPaneIndexFromID(nPaneID); - if(nIndex == -1) - return FALSE; - - GetTipText(nIndex, lpstrText, nSize); - return TRUE; - } - - BOOL SetPaneTipText(int nPaneID, LPCTSTR lpstrText) - { - ATLASSERT(::IsWindow(m_hWnd)); - int nIndex = GetPaneIndexFromID(nPaneID); - if(nIndex == -1) - return FALSE; - - SetTipText(nIndex, lpstrText); - return TRUE; - } -#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) - -#if ((_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 0x0500)) - BOOL GetPaneIcon(int nPaneID, HICON& hIcon) const - { - ATLASSERT(::IsWindow(m_hWnd)); - int nIndex = GetPaneIndexFromID(nPaneID); - if(nIndex == -1) - return FALSE; - - hIcon = GetIcon(nIndex); - return TRUE; - } - - BOOL SetPaneIcon(int nPaneID, HICON hIcon) - { - ATLASSERT(::IsWindow(m_hWnd)); - int nIndex = GetPaneIndexFromID(nPaneID); - if(nIndex == -1) - return FALSE; - - return SetIcon(nIndex, hIcon); - } -#endif // ((_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 0x0500)) - -// Message map and handlers - BEGIN_MSG_MAP(CMultiPaneStatusBarCtrlImpl< T >) - MESSAGE_HANDLER(WM_SIZE, OnSize) - END_MSG_MAP() - - LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) - { - LRESULT lRet = DefWindowProc(uMsg, wParam, lParam); - if(wParam != SIZE_MINIMIZED && m_nPanes > 0) - { - T* pT = static_cast(this); - pT->UpdatePanesLayout(); - } - return lRet; - } - -// Implementation - BOOL UpdatePanesLayout() - { - // get pane positions - CTempBuffer buff; - int* pPanesPos = buff.Allocate(m_nPanes); - ATLASSERT(pPanesPos != NULL); - if(pPanesPos == NULL) - return FALSE; - int nRet = GetParts(m_nPanes, pPanesPos); - ATLASSERT(nRet == m_nPanes); - if(nRet != m_nPanes) - return FALSE; - // calculate offset - RECT rcClient = { 0 }; - GetClientRect(&rcClient); - int cxOff = rcClient.right - pPanesPos[m_nPanes - 1]; -#ifndef _WIN32_WCE - // Move panes left if size grip box is present - if((GetStyle() & SBARS_SIZEGRIP) != 0) - cxOff -= ::GetSystemMetrics(SM_CXVSCROLL) + ::GetSystemMetrics(SM_CXEDGE); -#endif // !_WIN32_WCE - // find variable width pane - int i; - for(i = 0; i < m_nPanes; i++) - { - if(m_pPane[i] == ID_DEFAULT_PANE) - break; - } - // resize all panes from the variable one to the right - if((i < m_nPanes) && (pPanesPos[i] + cxOff) > ((i == 0) ? 0 : pPanesPos[i - 1])) - { - for(; i < m_nPanes; i++) - pPanesPos[i] += cxOff; - } - // set pane postions - return SetParts(m_nPanes, pPanesPos); - } - - int GetPaneIndexFromID(int nPaneID) const - { - for(int i = 0; i < m_nPanes; i++) - { - if(m_pPane[i] == nPaneID) - return i; - } - - return -1; // not found - } -}; - -class CMultiPaneStatusBarCtrl : public CMultiPaneStatusBarCtrlImpl -{ -public: - DECLARE_WND_SUPERCLASS(_T("WTL_MultiPaneStatusBar"), GetWndClassName()) -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CPaneContainer - provides header with title and close button for panes - -// pane container extended styles -#define PANECNT_NOCLOSEBUTTON 0x00000001 -#define PANECNT_VERTICAL 0x00000002 -#define PANECNT_FLATBORDER 0x00000004 -#define PANECNT_NOBORDER 0x00000008 - -template -class ATL_NO_VTABLE CPaneContainerImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CCustomDraw< T > -{ -public: - DECLARE_WND_CLASS_EX(NULL, 0, -1) - -// Constants - enum - { - m_cxyBorder = 2, - m_cxyTextOffset = 4, - m_cxyBtnOffset = 1, - - m_cchTitle = 80, - - m_cxImageTB = 13, - m_cyImageTB = 11, - m_cxyBtnAddTB = 7, - - m_cxToolBar = m_cxImageTB + m_cxyBtnAddTB + m_cxyBorder + m_cxyBtnOffset, - - m_xBtnImageLeft = 6, - m_yBtnImageTop = 5, - m_xBtnImageRight = 12, - m_yBtnImageBottom = 11, - - m_nCloseBtnID = ID_PANE_CLOSE - }; - -// Data members - CToolBarCtrl m_tb; - ATL::CWindow m_wndClient; - int m_cxyHeader; - TCHAR m_szTitle[m_cchTitle]; - DWORD m_dwExtendedStyle; // Pane container specific extended styles - - -// Constructor - CPaneContainerImpl() : m_cxyHeader(0), m_dwExtendedStyle(0) - { - m_szTitle[0] = 0; - } - -// Attributes - DWORD GetPaneContainerExtendedStyle() const - { - return m_dwExtendedStyle; - } - - DWORD SetPaneContainerExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0) - { - DWORD dwPrevStyle = m_dwExtendedStyle; - if(dwMask == 0) - m_dwExtendedStyle = dwExtendedStyle; - else - m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask); - if(m_hWnd != NULL) - { - T* pT = static_cast(this); - bool bUpdate = false; - - if(((dwPrevStyle & PANECNT_NOCLOSEBUTTON) != 0) && ((m_dwExtendedStyle & PANECNT_NOCLOSEBUTTON) == 0)) // add close button - { - pT->CreateCloseButton(); - bUpdate = true; - } - else if(((dwPrevStyle & PANECNT_NOCLOSEBUTTON) == 0) && ((m_dwExtendedStyle & PANECNT_NOCLOSEBUTTON) != 0)) // remove close button - { - pT->DestroyCloseButton(); - bUpdate = true; - } - - if((dwPrevStyle & PANECNT_VERTICAL) != (m_dwExtendedStyle & PANECNT_VERTICAL)) // change orientation - { - pT->CalcSize(); - bUpdate = true; - } - - if((dwPrevStyle & (PANECNT_FLATBORDER | PANECNT_NOBORDER)) != - (m_dwExtendedStyle & (PANECNT_FLATBORDER | PANECNT_NOBORDER))) // change border - { - bUpdate = true; - } - - if(bUpdate) - pT->UpdateLayout(); - } - return dwPrevStyle; - } - - HWND GetClient() const - { - return m_wndClient; - } - - HWND SetClient(HWND hWndClient) - { - HWND hWndOldClient = m_wndClient; - m_wndClient = hWndClient; - if(m_hWnd != NULL) - { - T* pT = static_cast(this); - pT->UpdateLayout(); - } - return hWndOldClient; - } - - BOOL GetTitle(LPTSTR lpstrTitle, int cchLength) const - { - ATLASSERT(lpstrTitle != NULL); - - errno_t nRet = SecureHelper::strncpy_x(lpstrTitle, cchLength, m_szTitle, _TRUNCATE); - - return (nRet == 0 || nRet == STRUNCATE); - } - - BOOL SetTitle(LPCTSTR lpstrTitle) - { - ATLASSERT(lpstrTitle != NULL); - - errno_t nRet = SecureHelper::strncpy_x(m_szTitle, m_cchTitle, lpstrTitle, _TRUNCATE); - bool bRet = (nRet == 0 || nRet == STRUNCATE); - if(bRet && m_hWnd != NULL) - { - T* pT = static_cast(this); - pT->UpdateLayout(); - } - - return bRet; - } - - int GetTitleLength() const - { - return lstrlen(m_szTitle); - } - -// Methods - HWND Create(HWND hWndParent, LPCTSTR lpstrTitle = NULL, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, - DWORD dwExStyle = 0, UINT nID = 0, LPVOID lpCreateParam = NULL) - { - if(lpstrTitle != NULL) - SecureHelper::strncpy_x(m_szTitle, m_cchTitle, lpstrTitle, _TRUNCATE); -#if (_MSC_VER >= 1300) - return ATL::CWindowImpl< T, TBase, TWinTraits >::Create(hWndParent, rcDefault, NULL, dwStyle, dwExStyle, nID, lpCreateParam); -#else // !(_MSC_VER >= 1300) - typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass; - return _baseClass::Create(hWndParent, rcDefault, NULL, dwStyle, dwExStyle, nID, lpCreateParam); -#endif // !(_MSC_VER >= 1300) - } - - HWND Create(HWND hWndParent, UINT uTitleID, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, - DWORD dwExStyle = 0, UINT nID = 0, LPVOID lpCreateParam = NULL) - { - if(uTitleID != 0U) - ::LoadString(ModuleHelper::GetResourceInstance(), uTitleID, m_szTitle, m_cchTitle); -#if (_MSC_VER >= 1300) - return ATL::CWindowImpl< T, TBase, TWinTraits >::Create(hWndParent, rcDefault, NULL, dwStyle, dwExStyle, nID, lpCreateParam); -#else // !(_MSC_VER >= 1300) - typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass; - return _baseClass::Create(hWndParent, rcDefault, NULL, dwStyle, dwExStyle, nID, lpCreateParam); -#endif // !(_MSC_VER >= 1300) - } - - BOOL EnableCloseButton(BOOL bEnable) - { - ATLASSERT(::IsWindow(m_hWnd)); - T* pT = static_cast(this); - pT; // avoid level 4 warning - return (m_tb.m_hWnd != NULL) ? m_tb.EnableButton(pT->m_nCloseBtnID, bEnable) : FALSE; - } - - void UpdateLayout() - { - RECT rcClient = { 0 }; - GetClientRect(&rcClient); - T* pT = static_cast(this); - pT->UpdateLayout(rcClient.right, rcClient.bottom); - } - -// Message map and handlers - BEGIN_MSG_MAP(CPaneContainerImpl) - MESSAGE_HANDLER(WM_CREATE, OnCreate) - MESSAGE_HANDLER(WM_SIZE, OnSize) - MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) - MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) - MESSAGE_HANDLER(WM_PAINT, OnPaint) -#ifndef _WIN32_WCE - MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) -#endif // !_WIN32_WCE - MESSAGE_HANDLER(WM_NOTIFY, OnNotify) - MESSAGE_HANDLER(WM_COMMAND, OnCommand) - FORWARD_NOTIFICATIONS() - END_MSG_MAP() - - LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - pT->CalcSize(); - - if((m_dwExtendedStyle & PANECNT_NOCLOSEBUTTON) == 0) - pT->CreateCloseButton(); - - return 0; - } - - LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - pT->UpdateLayout(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); - return 0; - } - - LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - if(m_wndClient.m_hWnd != NULL) - m_wndClient.SetFocus(); - return 0; - } - - LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - return 1; // no background needed - } - - LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - if(wParam != NULL) - { - pT->DrawPaneTitle((HDC)wParam); - - if(m_wndClient.m_hWnd == NULL) // no client window - pT->DrawPane((HDC)wParam); - } - else - { - CPaintDC dc(m_hWnd); - pT->DrawPaneTitle(dc.m_hDC); - - if(m_wndClient.m_hWnd == NULL) // no client window - pT->DrawPane(dc.m_hDC); - } - - return 0; - } - - LRESULT OnNotify(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) - { - if(m_tb.m_hWnd == NULL) - { - bHandled = FALSE; - return 1; - } - - T* pT = static_cast(this); - pT; - LPNMHDR lpnmh = (LPNMHDR)lParam; - LRESULT lRet = 0; - - // pass toolbar custom draw notifications to the base class - if(lpnmh->code == NM_CUSTOMDRAW && lpnmh->hwndFrom == m_tb.m_hWnd) - lRet = CCustomDraw< T >::OnCustomDraw(0, lpnmh, bHandled); -#ifndef _WIN32_WCE - // tooltip notifications come with the tooltip window handle and button ID, - // pass them to the parent if we don't handle them - else if(lpnmh->code == TTN_GETDISPINFO && lpnmh->idFrom == pT->m_nCloseBtnID) - bHandled = pT->GetToolTipText(lpnmh); -#endif // !_WIN32_WCE - // only let notifications not from the toolbar go to the parent - else if(lpnmh->hwndFrom != m_tb.m_hWnd && lpnmh->idFrom != pT->m_nCloseBtnID) - bHandled = FALSE; - - return lRet; - } - - LRESULT OnCommand(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - // if command comes from the close button, substitute HWND of the pane container instead - if(m_tb.m_hWnd != NULL && (HWND)lParam == m_tb.m_hWnd) - return ::SendMessage(GetParent(), WM_COMMAND, wParam, (LPARAM)m_hWnd); - - bHandled = FALSE; - return 1; - } - -// Custom draw overrides - DWORD OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/) - { - return CDRF_NOTIFYITEMDRAW; // we need per-item notifications - } - - DWORD OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw) - { - CDCHandle dc = lpNMCustomDraw->hdc; -#if (_WIN32_IE >= 0x0400) - RECT& rc = lpNMCustomDraw->rc; -#else // !(_WIN32_IE >= 0x0400) - RECT rc; - m_tb.GetItemRect(0, &rc); -#endif // !(_WIN32_IE >= 0x0400) - - dc.FillRect(&rc, COLOR_3DFACE); - - return CDRF_NOTIFYPOSTPAINT; - } - - DWORD OnItemPostPaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw) - { - CDCHandle dc = lpNMCustomDraw->hdc; -#if (_WIN32_IE >= 0x0400) - RECT& rc = lpNMCustomDraw->rc; -#else // !(_WIN32_IE >= 0x0400) - RECT rc = { 0 }; - m_tb.GetItemRect(0, &rc); -#endif // !(_WIN32_IE >= 0x0400) - - RECT rcImage = { m_xBtnImageLeft, m_yBtnImageTop, m_xBtnImageRight + 1, m_yBtnImageBottom + 1 }; - ::OffsetRect(&rcImage, rc.left, rc.top); - T* pT = static_cast(this); - - if((lpNMCustomDraw->uItemState & CDIS_DISABLED) != 0) - { - RECT rcShadow = rcImage; - ::OffsetRect(&rcShadow, 1, 1); - CPen pen1; - pen1.CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_3DHILIGHT)); - pT->DrawButtonImage(dc, rcShadow, pen1); - CPen pen2; - pen2.CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_3DSHADOW)); - pT->DrawButtonImage(dc, rcImage, pen2); - } - else - { - if((lpNMCustomDraw->uItemState & CDIS_SELECTED) != 0) - ::OffsetRect(&rcImage, 1, 1); - CPen pen; - pen.CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_BTNTEXT)); - pT->DrawButtonImage(dc, rcImage, pen); - } - - return CDRF_DODEFAULT; // continue with the default item painting - } - -// Implementation - overrideable methods - void UpdateLayout(int cxWidth, int cyHeight) - { - ATLASSERT(::IsWindow(m_hWnd)); - RECT rect = { 0 }; - - if(IsVertical()) - { - ::SetRect(&rect, 0, 0, m_cxyHeader, cyHeight); - if(m_tb.m_hWnd != NULL) - m_tb.SetWindowPos(NULL, m_cxyBorder, m_cxyBorder + m_cxyBtnOffset, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); - - if(m_wndClient.m_hWnd != NULL) - m_wndClient.SetWindowPos(NULL, m_cxyHeader, 0, cxWidth - m_cxyHeader, cyHeight, SWP_NOZORDER); - else - rect.right = cxWidth; - } - else - { - ::SetRect(&rect, 0, 0, cxWidth, m_cxyHeader); - if(m_tb.m_hWnd != NULL) - m_tb.SetWindowPos(NULL, rect.right - m_cxToolBar, m_cxyBorder + m_cxyBtnOffset, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); - - if(m_wndClient.m_hWnd != NULL) - m_wndClient.SetWindowPos(NULL, 0, m_cxyHeader, cxWidth, cyHeight - m_cxyHeader, SWP_NOZORDER); - else - rect.bottom = cyHeight; - } - - InvalidateRect(&rect); - } - - void CreateCloseButton() - { - ATLASSERT(m_tb.m_hWnd == NULL); - // create toolbar for the "x" button - m_tb.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NORESIZE | CCS_NOPARENTALIGN | CCS_NOMOVEY | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT, 0); - ATLASSERT(m_tb.IsWindow()); - - if(m_tb.m_hWnd != NULL) - { - T* pT = static_cast(this); - pT; // avoid level 4 warning - - m_tb.SetButtonStructSize(); - - TBBUTTON tbbtn = { 0 }; - tbbtn.idCommand = pT->m_nCloseBtnID; - tbbtn.fsState = TBSTATE_ENABLED; - tbbtn.fsStyle = TBSTYLE_BUTTON; - m_tb.AddButtons(1, &tbbtn); - - m_tb.SetBitmapSize(m_cxImageTB, m_cyImageTB); - m_tb.SetButtonSize(m_cxImageTB + m_cxyBtnAddTB, m_cyImageTB + m_cxyBtnAddTB); - - if(IsVertical()) - m_tb.SetWindowPos(NULL, m_cxyBorder + m_cxyBtnOffset, m_cxyBorder + m_cxyBtnOffset, m_cxImageTB + m_cxyBtnAddTB, m_cyImageTB + m_cxyBtnAddTB, SWP_NOZORDER | SWP_NOACTIVATE); - else - m_tb.SetWindowPos(NULL, 0, 0, m_cxImageTB + m_cxyBtnAddTB, m_cyImageTB + m_cxyBtnAddTB, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE); - } - } - - void DestroyCloseButton() - { - if(m_tb.m_hWnd != NULL) - m_tb.DestroyWindow(); - } - - void CalcSize() - { - T* pT = static_cast(this); - CFontHandle font = pT->GetTitleFont(); - LOGFONT lf = { 0 }; - font.GetLogFont(lf); - if(IsVertical()) - { - m_cxyHeader = m_cxImageTB + m_cxyBtnAddTB + m_cxyBorder; - } - else - { - int cyFont = abs(lf.lfHeight) + m_cxyBorder + 2 * m_cxyTextOffset; - int cyBtn = m_cyImageTB + m_cxyBtnAddTB + m_cxyBorder + 2 * m_cxyBtnOffset; - m_cxyHeader = max(cyFont, cyBtn); - } - } - - HFONT GetTitleFont() const - { - return AtlGetDefaultGuiFont(); - } - -#ifndef _WIN32_WCE - BOOL GetToolTipText(LPNMHDR /*lpnmh*/) - { - return FALSE; - } -#endif // !_WIN32_WCE - - void DrawPaneTitle(CDCHandle dc) - { - RECT rect = { 0 }; - GetClientRect(&rect); - - UINT uBorder = BF_LEFT | BF_TOP | BF_ADJUST; - if(IsVertical()) - { - rect.right = rect.left + m_cxyHeader; - uBorder |= BF_BOTTOM; - } - else - { - rect.bottom = rect.top + m_cxyHeader; - uBorder |= BF_RIGHT; - } - - if((m_dwExtendedStyle & PANECNT_NOBORDER) == 0) - { - if((m_dwExtendedStyle & PANECNT_FLATBORDER) != 0) - uBorder |= BF_FLAT; - dc.DrawEdge(&rect, EDGE_ETCHED, uBorder); - } - dc.FillRect(&rect, COLOR_3DFACE); - - if(!IsVertical()) // draw title only for horizontal pane container - { - dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT)); - dc.SetBkMode(TRANSPARENT); - T* pT = static_cast(this); - HFONT hFontOld = dc.SelectFont(pT->GetTitleFont()); - rect.left += m_cxyTextOffset; - rect.right -= m_cxyTextOffset; - if(m_tb.m_hWnd != NULL) - rect.right -= m_cxToolBar;; -#ifndef _WIN32_WCE - dc.DrawText(m_szTitle, -1, &rect, DT_LEFT | DT_SINGLELINE | DT_VCENTER | DT_END_ELLIPSIS); -#else // CE specific - dc.DrawText(m_szTitle, -1, &rect, DT_LEFT | DT_SINGLELINE | DT_VCENTER); -#endif // _WIN32_WCE - dc.SelectFont(hFontOld); - } - } - - // called only if pane is empty - void DrawPane(CDCHandle dc) - { - RECT rect = { 0 }; - GetClientRect(&rect); - if(IsVertical()) - rect.left += m_cxyHeader; - else - rect.top += m_cxyHeader; - if((GetExStyle() & WS_EX_CLIENTEDGE) == 0) - dc.DrawEdge(&rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST); - dc.FillRect(&rect, COLOR_APPWORKSPACE); - } - - // drawing helper - draws "x" button image - void DrawButtonImage(CDCHandle dc, RECT& rcImage, HPEN hPen) - { -#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) - HPEN hPenOld = dc.SelectPen(hPen); - - dc.MoveTo(rcImage.left, rcImage.top); - dc.LineTo(rcImage.right, rcImage.bottom); - dc.MoveTo(rcImage.left + 1, rcImage.top); - dc.LineTo(rcImage.right + 1, rcImage.bottom); - - dc.MoveTo(rcImage.left, rcImage.bottom - 1); - dc.LineTo(rcImage.right, rcImage.top - 1); - dc.MoveTo(rcImage.left + 1, rcImage.bottom - 1); - dc.LineTo(rcImage.right + 1, rcImage.top - 1); - - dc.SelectPen(hPenOld); -#else // (_WIN32_WCE < 400) - rcImage; - hPen; - // no support for the "x" button image -#endif // (_WIN32_WCE < 400) - } - - bool IsVertical() const - { - return ((m_dwExtendedStyle & PANECNT_VERTICAL) != 0); - } -}; - -class CPaneContainer : public CPaneContainerImpl -{ -public: - DECLARE_WND_CLASS_EX(_T("WTL_PaneContainer"), 0, -1) -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CSortListViewCtrl - implements sorting for a listview control - -// sort listview extended styles -#define SORTLV_USESHELLBITMAPS 0x00000001 - -// Notification sent to parent when sort column is changed by user clicking header. -#define SLVN_SORTCHANGED LVN_LAST - -// A LPNMSORTLISTVIEW is sent with the SLVN_SORTCHANGED notification -typedef struct tagNMSORTLISTVIEW -{ - NMHDR hdr; - int iNewSortColumn; - int iOldSortColumn; -} NMSORTLISTVIEW, *LPNMSORTLISTVIEW; - -// Column sort types. Can be set on a per-column basis with the SetColumnSortType method. -enum -{ - LVCOLSORT_NONE, - LVCOLSORT_TEXT, // default - LVCOLSORT_TEXTNOCASE, - LVCOLSORT_LONG, - LVCOLSORT_DOUBLE, - LVCOLSORT_DECIMAL, - LVCOLSORT_DATETIME, - LVCOLSORT_DATE, - LVCOLSORT_TIME, - LVCOLSORT_CUSTOM, - LVCOLSORT_LAST = LVCOLSORT_CUSTOM -}; - - -template -class CSortListViewImpl -{ -public: - enum - { - m_cchCmpTextMax = 32, // overrideable - m_cxSortImage = 16, - m_cySortImage = 15, - m_cxSortArrow = 11, - m_cySortArrow = 6, - m_iSortUp = 0, // index of sort bitmaps - m_iSortDown = 1, - m_nShellSortUpID = 133 - }; - - // passed to LVCompare functions as lParam1 and lParam2 - struct LVCompareParam - { - int iItem; - DWORD_PTR dwItemData; - union - { - long lValue; - double dblValue; - DECIMAL decValue; - LPCTSTR pszValue; - }; - }; - - // passed to LVCompare functions as the lParamSort parameter - struct LVSortInfo - { - T* pT; - int iSortCol; - bool bDescending; - }; - - bool m_bSortDescending; - bool m_bCommCtrl6; - int m_iSortColumn; - CBitmap m_bmSort[2]; - int m_fmtOldSortCol; - HBITMAP m_hbmOldSortCol; - DWORD m_dwSortLVExtendedStyle; - ATL::CSimpleArray m_arrColSortType; - bool m_bUseWaitCursor; - - CSortListViewImpl() : - m_bSortDescending(false), - m_bCommCtrl6(false), - m_iSortColumn(-1), - m_fmtOldSortCol(0), - m_hbmOldSortCol(NULL), - m_dwSortLVExtendedStyle(SORTLV_USESHELLBITMAPS), - m_bUseWaitCursor(true) - { -#ifndef _WIN32_WCE - DWORD dwMajor = 0; - DWORD dwMinor = 0; - HRESULT hRet = ATL::AtlGetCommCtrlVersion(&dwMajor, &dwMinor); - m_bCommCtrl6 = SUCCEEDED(hRet) && dwMajor >= 6; -#endif // !_WIN32_WCE - } - -// Attributes - void SetSortColumn(int iCol) - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - CHeaderCtrl header = pT->GetHeader(); - ATLASSERT(header.m_hWnd != NULL); - ATLASSERT(iCol >= -1 && iCol < m_arrColSortType.GetSize()); - - int iOldSortCol = m_iSortColumn; - m_iSortColumn = iCol; - if(m_bCommCtrl6) - { -#ifndef HDF_SORTUP - const int HDF_SORTUP = 0x0400; -#endif // HDF_SORTUP -#ifndef HDF_SORTDOWN - const int HDF_SORTDOWN = 0x0200; -#endif // HDF_SORTDOWN - const int nMask = HDF_SORTUP | HDF_SORTDOWN; - HDITEM hditem = { HDI_FORMAT }; - if(iOldSortCol != iCol && iOldSortCol >= 0 && header.GetItem(iOldSortCol, &hditem)) - { - hditem.fmt &= ~nMask; - header.SetItem(iOldSortCol, &hditem); - } - if(iCol >= 0 && header.GetItem(iCol, &hditem)) - { - hditem.fmt &= ~nMask; - hditem.fmt |= m_bSortDescending ? HDF_SORTDOWN : HDF_SORTUP; - header.SetItem(iCol, &hditem); - } - return; - } - - if(m_bmSort[m_iSortUp].IsNull()) - pT->CreateSortBitmaps(); - - // restore previous sort column's bitmap, if any, and format - HDITEM hditem = { HDI_BITMAP | HDI_FORMAT }; - if(iOldSortCol != iCol && iOldSortCol >= 0) - { - hditem.hbm = m_hbmOldSortCol; - hditem.fmt = m_fmtOldSortCol; - header.SetItem(iOldSortCol, &hditem); - } - - // save new sort column's bitmap and format, and add our sort bitmap - if(iCol >= 0 && header.GetItem(iCol, &hditem)) - { - if(iOldSortCol != iCol) - { - m_fmtOldSortCol = hditem.fmt; - m_hbmOldSortCol = hditem.hbm; - } - hditem.fmt &= ~HDF_IMAGE; - hditem.fmt |= HDF_BITMAP | HDF_BITMAP_ON_RIGHT; - int i = m_bSortDescending ? m_iSortDown : m_iSortUp; - hditem.hbm = m_bmSort[i]; - header.SetItem(iCol, &hditem); - } - } - - int GetSortColumn() const - { - return m_iSortColumn; - } - - void SetColumnSortType(int iCol, WORD wType) - { - ATLASSERT(iCol >= 0 && iCol < m_arrColSortType.GetSize()); - ATLASSERT(wType >= LVCOLSORT_NONE && wType <= LVCOLSORT_LAST); - m_arrColSortType[iCol] = wType; - } - - WORD GetColumnSortType(int iCol) const - { - ATLASSERT((iCol >= 0) && iCol < m_arrColSortType.GetSize()); - return m_arrColSortType[iCol]; - } - - int GetColumnCount() const - { - const T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - CHeaderCtrl header = pT->GetHeader(); - return header.m_hWnd != NULL ? header.GetItemCount() : 0; - } - - bool IsSortDescending() const - { - return m_bSortDescending; - } - - DWORD GetSortListViewExtendedStyle() const - { - return m_dwSortLVExtendedStyle; - } - - DWORD SetSortListViewExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0) - { - DWORD dwPrevStyle = m_dwSortLVExtendedStyle; - if(dwMask == 0) - m_dwSortLVExtendedStyle = dwExtendedStyle; - else - m_dwSortLVExtendedStyle = (m_dwSortLVExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask); - return dwPrevStyle; - } - -// Operations - bool DoSortItems(int iCol, bool bDescending = false) - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - ATLASSERT(iCol >= 0 && iCol < m_arrColSortType.GetSize()); - - WORD wType = m_arrColSortType[iCol]; - if(wType == LVCOLSORT_NONE) - return false; - - int nCount = pT->GetItemCount(); - if(nCount < 2) - { - m_bSortDescending = bDescending; - SetSortColumn(iCol); - return true; - } - - CWaitCursor waitCursor(false); - if(m_bUseWaitCursor) - waitCursor.Set(); - - LVCompareParam* pParam = NULL; - ATLTRY(pParam = new LVCompareParam[nCount]); - PFNLVCOMPARE pFunc = NULL; - TCHAR pszTemp[pT->m_cchCmpTextMax]; - bool bStrValue = false; - - switch(wType) - { - case LVCOLSORT_TEXT: - pFunc = (PFNLVCOMPARE)pT->LVCompareText; - case LVCOLSORT_TEXTNOCASE: - if(pFunc == NULL) - pFunc = (PFNLVCOMPARE)pT->LVCompareTextNoCase; - case LVCOLSORT_CUSTOM: - { - if(pFunc == NULL) - pFunc = (PFNLVCOMPARE)pT->LVCompareCustom; - - for(int i = 0; i < nCount; i++) - { - pParam[i].iItem = i; - pParam[i].dwItemData = pT->GetItemData(i); - pParam[i].pszValue = new TCHAR[pT->m_cchCmpTextMax]; - pT->GetItemText(i, iCol, (LPTSTR)pParam[i].pszValue, pT->m_cchCmpTextMax); - pT->SetItemData(i, (DWORD_PTR)&pParam[i]); - } - bStrValue = true; - } - break; - case LVCOLSORT_LONG: - { - pFunc = (PFNLVCOMPARE)pT->LVCompareLong; - for(int i = 0; i < nCount; i++) - { - pParam[i].iItem = i; - pParam[i].dwItemData = pT->GetItemData(i); - pT->GetItemText(i, iCol, pszTemp, pT->m_cchCmpTextMax); - pParam[i].lValue = pT->StrToLong(pszTemp); - pT->SetItemData(i, (DWORD_PTR)&pParam[i]); - } - } - break; - case LVCOLSORT_DOUBLE: - { - pFunc = (PFNLVCOMPARE)pT->LVCompareDouble; - for(int i = 0; i < nCount; i++) - { - pParam[i].iItem = i; - pParam[i].dwItemData = pT->GetItemData(i); - pT->GetItemText(i, iCol, pszTemp, pT->m_cchCmpTextMax); - pParam[i].dblValue = pT->StrToDouble(pszTemp); - pT->SetItemData(i, (DWORD_PTR)&pParam[i]); - } - } - break; - case LVCOLSORT_DECIMAL: - { - pFunc = (PFNLVCOMPARE)pT->LVCompareDecimal; - for(int i = 0; i < nCount; i++) - { - pParam[i].iItem = i; - pParam[i].dwItemData = pT->GetItemData(i); - pT->GetItemText(i, iCol, pszTemp, pT->m_cchCmpTextMax); - pT->StrToDecimal(pszTemp, &pParam[i].decValue); - pT->SetItemData(i, (DWORD_PTR)&pParam[i]); - } - } - break; - case LVCOLSORT_DATETIME: - case LVCOLSORT_DATE: - case LVCOLSORT_TIME: - { - pFunc = (PFNLVCOMPARE)pT->LVCompareDouble; - DWORD dwFlags = LOCALE_NOUSEROVERRIDE; - if(wType == LVCOLSORT_DATE) - dwFlags |= VAR_DATEVALUEONLY; - else if(wType == LVCOLSORT_TIME) - dwFlags |= VAR_TIMEVALUEONLY; - for(int i = 0; i < nCount; i++) - { - pParam[i].iItem = i; - pParam[i].dwItemData = pT->GetItemData(i); - pT->GetItemText(i, iCol, pszTemp, pT->m_cchCmpTextMax); - pParam[i].dblValue = pT->DateStrToDouble(pszTemp, dwFlags); - pT->SetItemData(i, (DWORD_PTR)&pParam[i]); - } - } - break; - default: - ATLTRACE2(atlTraceUI, 0, _T("Unknown value for sort type in CSortListViewImpl::DoSortItems()\n")); - break; - } // switch(wType) - - ATLASSERT(pFunc != NULL); - LVSortInfo lvsi = { pT, iCol, bDescending }; - bool bRet = ((BOOL)pT->DefWindowProc(LVM_SORTITEMS, (WPARAM)&lvsi, (LPARAM)pFunc) != FALSE); - for(int i = 0; i < nCount; i++) - { - DWORD_PTR dwItemData = pT->GetItemData(i); - LVCompareParam* p = (LVCompareParam*)dwItemData; - ATLASSERT(p != NULL); - if(bStrValue) - delete [] (TCHAR*)p->pszValue; - pT->SetItemData(i, p->dwItemData); - } - delete [] pParam; - - if(bRet) - { - m_bSortDescending = bDescending; - SetSortColumn(iCol); - } - - if(m_bUseWaitCursor) - waitCursor.Restore(); - - return bRet; - } - - void CreateSortBitmaps() - { - if((m_dwSortLVExtendedStyle & SORTLV_USESHELLBITMAPS) != 0) - { - bool bFree = false; - LPCTSTR pszModule = _T("shell32.dll"); - HINSTANCE hShell = ::GetModuleHandle(pszModule); - - if (hShell == NULL) - { - hShell = ::LoadLibrary(pszModule); - bFree = true; - } - - if (hShell != NULL) - { - bool bSuccess = true; - for(int i = m_iSortUp; i <= m_iSortDown; i++) - { - if(!m_bmSort[i].IsNull()) - m_bmSort[i].DeleteObject(); - m_bmSort[i] = (HBITMAP)::LoadImage(hShell, MAKEINTRESOURCE(m_nShellSortUpID + i), -#ifndef _WIN32_WCE - IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS); -#else // CE specific - IMAGE_BITMAP, 0, 0, 0); -#endif // _WIN32_WCE - if(m_bmSort[i].IsNull()) - { - bSuccess = false; - break; - } - } - if(bFree) - ::FreeLibrary(hShell); - if(bSuccess) - return; - } - } - - T* pT = static_cast(this); - for(int i = m_iSortUp; i <= m_iSortDown; i++) - { - if(!m_bmSort[i].IsNull()) - m_bmSort[i].DeleteObject(); - - CDC dcMem; - CClientDC dc(::GetDesktopWindow()); - dcMem.CreateCompatibleDC(dc.m_hDC); - m_bmSort[i].CreateCompatibleBitmap(dc.m_hDC, m_cxSortImage, m_cySortImage); - HBITMAP hbmOld = dcMem.SelectBitmap(m_bmSort[i]); - RECT rc = {0,0,m_cxSortImage, m_cySortImage}; - pT->DrawSortBitmap(dcMem.m_hDC, i, &rc); - dcMem.SelectBitmap(hbmOld); - dcMem.DeleteDC(); - } - } - - void NotifyParentSortChanged(int iNewSortCol, int iOldSortCol) - { - T* pT = static_cast(this); - int nID = pT->GetDlgCtrlID(); - NMSORTLISTVIEW nm = { { pT->m_hWnd, nID, SLVN_SORTCHANGED }, iNewSortCol, iOldSortCol }; - ::SendMessage(pT->GetParent(), WM_NOTIFY, (WPARAM)nID, (LPARAM)&nm); - } - -// Overrideables - int CompareItemsCustom(LVCompareParam* /*pItem1*/, LVCompareParam* /*pItem2*/, int /*iSortCol*/) - { - // pItem1 and pItem2 contain valid iItem, dwItemData, and pszValue members. - // If item1 > item2 return 1, if item1 < item2 return -1, else return 0. - return 0; - } - - void DrawSortBitmap(CDCHandle dc, int iBitmap, LPRECT prc) - { - dc.FillRect(prc, ::GetSysColorBrush(COLOR_BTNFACE)); - HBRUSH hbrOld = dc.SelectBrush(::GetSysColorBrush(COLOR_BTNSHADOW)); - CPen pen; - pen.CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_BTNSHADOW)); - HPEN hpenOld = dc.SelectPen(pen); - POINT ptOrg = { (m_cxSortImage - m_cxSortArrow) / 2, (m_cySortImage - m_cySortArrow) / 2 }; - if(iBitmap == m_iSortUp) - { - POINT pts[3] = - { - { ptOrg.x + m_cxSortArrow / 2, ptOrg.y }, - { ptOrg.x, ptOrg.y + m_cySortArrow - 1 }, - { ptOrg.x + m_cxSortArrow - 1, ptOrg.y + m_cySortArrow - 1 } - }; - dc.Polygon(pts, 3); - } - else - { - POINT pts[3] = - { - { ptOrg.x, ptOrg.y }, - { ptOrg.x + m_cxSortArrow / 2, ptOrg.y + m_cySortArrow - 1 }, - { ptOrg.x + m_cxSortArrow - 1, ptOrg.y } - }; - dc.Polygon(pts, 3); - } - dc.SelectBrush(hbrOld); - dc.SelectPen(hpenOld); - } - - double DateStrToDouble(LPCTSTR lpstr, DWORD dwFlags) - { - ATLASSERT(lpstr != NULL); - if(lpstr == NULL || lpstr[0] == _T('\0')) - return 0; - - USES_CONVERSION; - HRESULT hRet = E_FAIL; - DATE dRet = 0; - if (FAILED(hRet = ::VarDateFromStr((LPOLESTR)T2COLE(lpstr), LANG_USER_DEFAULT, dwFlags, &dRet))) - { - ATLTRACE2(atlTraceUI, 0, _T("VarDateFromStr failed with result of 0x%8.8X\n"), hRet); - dRet = 0; - } - return dRet; - } - - long StrToLong(LPCTSTR lpstr) - { - ATLASSERT(lpstr != NULL); - if(lpstr == NULL || lpstr[0] == _T('\0')) - return 0; - - USES_CONVERSION; - HRESULT hRet = E_FAIL; - long lRet = 0; - if (FAILED(hRet = ::VarI4FromStr((LPOLESTR)T2COLE(lpstr), LANG_USER_DEFAULT, LOCALE_NOUSEROVERRIDE, &lRet))) - { - ATLTRACE2(atlTraceUI, 0, _T("VarI4FromStr failed with result of 0x%8.8X\n"), hRet); - lRet = 0; - } - return lRet; - } - - double StrToDouble(LPCTSTR lpstr) - { - ATLASSERT(lpstr != NULL); - if(lpstr == NULL || lpstr[0] == _T('\0')) - return 0; - - USES_CONVERSION; - HRESULT hRet = E_FAIL; - double dblRet = 0; - if (FAILED(hRet = ::VarR8FromStr((LPOLESTR)T2COLE(lpstr), LANG_USER_DEFAULT, LOCALE_NOUSEROVERRIDE, &dblRet))) - { - ATLTRACE2(atlTraceUI, 0, _T("VarR8FromStr failed with result of 0x%8.8X\n"), hRet); - dblRet = 0; - } - return dblRet; - } - - bool StrToDecimal(LPCTSTR lpstr, DECIMAL* pDecimal) - { - ATLASSERT(lpstr != NULL); - ATLASSERT(pDecimal != NULL); - if(lpstr == NULL || pDecimal == NULL) - return false; - - USES_CONVERSION; - HRESULT hRet = E_FAIL; - if (FAILED(hRet = ::VarDecFromStr((LPOLESTR)T2COLE(lpstr), LANG_USER_DEFAULT, LOCALE_NOUSEROVERRIDE, pDecimal))) - { - ATLTRACE2(atlTraceUI, 0, _T("VarDecFromStr failed with result of 0x%8.8X\n"), hRet); - pDecimal->Lo64 = 0; - pDecimal->Hi32 = 0; - pDecimal->signscale = 0; - return false; - } - return true; - } - -// Overrideable PFNLVCOMPARE functions - static int CALLBACK LVCompareText(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) - { - ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL); - - LVCompareParam* pParam1 = (LVCompareParam*)lParam1; - LVCompareParam* pParam2 = (LVCompareParam*)lParam2; - LVSortInfo* pInfo = (LVSortInfo*)lParamSort; - - int nRet = lstrcmp(pParam1->pszValue, pParam2->pszValue); - return pInfo->bDescending ? -nRet : nRet; - } - - static int CALLBACK LVCompareTextNoCase(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) - { - ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL); - - LVCompareParam* pParam1 = (LVCompareParam*)lParam1; - LVCompareParam* pParam2 = (LVCompareParam*)lParam2; - LVSortInfo* pInfo = (LVSortInfo*)lParamSort; - - int nRet = lstrcmpi(pParam1->pszValue, pParam2->pszValue); - return pInfo->bDescending ? -nRet : nRet; - } - - static int CALLBACK LVCompareLong(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) - { - ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL); - - LVCompareParam* pParam1 = (LVCompareParam*)lParam1; - LVCompareParam* pParam2 = (LVCompareParam*)lParam2; - LVSortInfo* pInfo = (LVSortInfo*)lParamSort; - - int nRet = 0; - if(pParam1->lValue > pParam2->lValue) - nRet = 1; - else if(pParam1->lValue < pParam2->lValue) - nRet = -1; - return pInfo->bDescending ? -nRet : nRet; - } - - static int CALLBACK LVCompareDouble(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) - { - ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL); - - LVCompareParam* pParam1 = (LVCompareParam*)lParam1; - LVCompareParam* pParam2 = (LVCompareParam*)lParam2; - LVSortInfo* pInfo = (LVSortInfo*)lParamSort; - - int nRet = 0; - if(pParam1->dblValue > pParam2->dblValue) - nRet = 1; - else if(pParam1->dblValue < pParam2->dblValue) - nRet = -1; - return pInfo->bDescending ? -nRet : nRet; - } - - static int CALLBACK LVCompareCustom(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) - { - ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL); - - LVCompareParam* pParam1 = (LVCompareParam*)lParam1; - LVCompareParam* pParam2 = (LVCompareParam*)lParam2; - LVSortInfo* pInfo = (LVSortInfo*)lParamSort; - - int nRet = pInfo->pT->CompareItemsCustom(pParam1, pParam2, pInfo->iSortCol); - return pInfo->bDescending ? -nRet : nRet; - } - -#ifndef _WIN32_WCE - static int CALLBACK LVCompareDecimal(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) - { - ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL); - - LVCompareParam* pParam1 = (LVCompareParam*)lParam1; - LVCompareParam* pParam2 = (LVCompareParam*)lParam2; - LVSortInfo* pInfo = (LVSortInfo*)lParamSort; - - int nRet = (int)::VarDecCmp(&pParam1->decValue, &pParam2->decValue); - nRet--; - return pInfo->bDescending ? -nRet : nRet; - } -#else - // Compare mantissas, ignore sign and scale - static int CompareMantissas(const DECIMAL& decLeft, const DECIMAL& decRight) - { - if (decLeft.Hi32 < decRight.Hi32) - { - return -1; - } - if (decLeft.Hi32 > decRight.Hi32) - { - return 1; - } - // Here, decLeft.Hi32 == decRight.Hi32 - if (decLeft.Lo64 < decRight.Lo64) - { - return -1; - } - if (decLeft.Lo64 > decRight.Lo64) - { - return 1; - } - return 0; - } - - // return values: VARCMP_LT, VARCMP_EQ, VARCMP_GT, VARCMP_NULL - static HRESULT VarDecCmp(const DECIMAL* pdecLeft, const DECIMAL* pdecRight) - { - static const ULONG powersOfTen[] = - { - 10ul, - 100ul, - 1000ul, - 10000ul, - 100000ul, - 1000000ul, - 10000000ul, - 100000000ul, - 1000000000ul - }; - static const int largestPower = sizeof(powersOfTen) / sizeof(powersOfTen[0]); - if (!pdecLeft || !pdecRight) - { - return VARCMP_NULL; - } - - // Degenerate case - at least one comparand is of the form - // [+-]0*10^N (denormalized zero) - bool bLeftZero = (!pdecLeft->Lo64 && !pdecLeft->Hi32); - bool bRightZero = (!pdecRight->Lo64 && !pdecRight->Hi32); - if (bLeftZero && bRightZero) - { - return VARCMP_EQ; - } - bool bLeftNeg = ((pdecLeft->sign & DECIMAL_NEG) != 0); - bool bRightNeg = ((pdecRight->sign & DECIMAL_NEG) != 0); - if (bLeftZero) - { - return (bRightNeg ? VARCMP_GT : VARCMP_LT); - } - // This also covers the case where the comparands have different signs - if (bRightZero || bLeftNeg != bRightNeg) - { - return (bLeftNeg ? VARCMP_LT : VARCMP_GT); - } - - // Here both comparands have the same sign and need to be compared - // on mantissa and scale. The result is obvious when - // 1. Scales are equal (then compare mantissas) - // 2. A number with smaller scale is also the one with larger mantissa - // (then this number is obviously larger) - // In the remaining case, we would multiply the number with smaller - // scale by 10 and simultaneously increment its scale (which amounts to - // adding trailing zeros after decimal point), until the numbers fall under - // one of the two cases above - DECIMAL temp; - bool bInvert = bLeftNeg; // the final result needs to be inverted - if (pdecLeft->scale < pdecRight->scale) - { - temp = *pdecLeft; - } - else - { - temp = *pdecRight; - pdecRight = pdecLeft; - bInvert = !bInvert; - } - - // Now temp is the number with smaller (or equal) scale, and - // we can modify it freely without touching original parameters - int comp; - while ((comp = CompareMantissas(temp, *pdecRight)) < 0 && - temp.scale < pdecRight->scale) - { - // Multiply by an appropriate power of 10 - int scaleDiff = pdecRight->scale - temp.scale; - if (scaleDiff > largestPower) - { - // Keep the multiplier representable in 32bit - scaleDiff = largestPower; - } - DWORDLONG power = powersOfTen[scaleDiff - 1]; - // Multiply temp's mantissa by power - DWORDLONG product = temp.Lo32 * power; - ULONG carry = static_cast(product >> 32); - temp.Lo32 = static_cast(product); - product = temp.Mid32 * power + carry; - carry = static_cast(product >> 32); - temp.Mid32 = static_cast(product); - product = temp.Hi32 * power + carry; - if (static_cast(product >> 32)) - { - // Multiplication overflowed - pdecLeft is clearly larger - break; - } - temp.Hi32 = static_cast(product); - temp.scale = (BYTE)(temp.scale + scaleDiff); - } - if (temp.scale < pdecRight->scale) - { - comp = 1; - } - if (bInvert) - { - comp = -comp; - } - return (comp > 0 ? VARCMP_GT : comp < 0 ? VARCMP_LT : VARCMP_EQ); - } - - static int CALLBACK LVCompareDecimal(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) - { - ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL); - - LVCompareParam* pParam1 = (LVCompareParam*)lParam1; - LVCompareParam* pParam2 = (LVCompareParam*)lParam2; - LVSortInfo* pInfo = (LVSortInfo*)lParamSort; - - int nRet = (int)VarDecCmp(&pParam1->decValue, &pParam2->decValue); - nRet--; - return pInfo->bDescending ? -nRet : nRet; - } -#endif // !_WIN32_WCE - - BEGIN_MSG_MAP(CSortListViewImpl) - MESSAGE_HANDLER(LVM_INSERTCOLUMN, OnInsertColumn) - MESSAGE_HANDLER(LVM_DELETECOLUMN, OnDeleteColumn) - NOTIFY_CODE_HANDLER(HDN_ITEMCLICKA, OnHeaderItemClick) - NOTIFY_CODE_HANDLER(HDN_ITEMCLICKW, OnHeaderItemClick) - MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange) - END_MSG_MAP() - - LRESULT OnInsertColumn(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - LRESULT lRet = pT->DefWindowProc(uMsg, wParam, lParam); - if(lRet == -1) - return -1; - - WORD wType = 0; - m_arrColSortType.Add(wType); - int nCount = m_arrColSortType.GetSize(); - ATLASSERT(nCount == GetColumnCount()); - - for(int i = nCount - 1; i > lRet; i--) - m_arrColSortType[i] = m_arrColSortType[i - 1]; - m_arrColSortType[(int)lRet] = LVCOLSORT_TEXT; - - if(lRet <= m_iSortColumn) - m_iSortColumn++; - - return lRet; - } - - LRESULT OnDeleteColumn(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - LRESULT lRet = pT->DefWindowProc(uMsg, wParam, lParam); - if(lRet == 0) - return 0; - - int iCol = (int)wParam; - if(m_iSortColumn == iCol) - m_iSortColumn = -1; - else if(m_iSortColumn > iCol) - m_iSortColumn--; - m_arrColSortType.RemoveAt(iCol); - - return lRet; - } - - LRESULT OnHeaderItemClick(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled) - { - LPNMHEADER p = (LPNMHEADER)pnmh; - if(p->iButton == 0) - { - int iOld = m_iSortColumn; - bool bDescending = (m_iSortColumn == p->iItem) ? !m_bSortDescending : false; - if(DoSortItems(p->iItem, bDescending)) - NotifyParentSortChanged(p->iItem, iOld); - } - bHandled = FALSE; - return 0; - } - - LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) - { -#ifndef _WIN32_WCE - if(wParam == SPI_SETNONCLIENTMETRICS) - GetSystemSettings(); -#else // CE specific - wParam; // avoid level 4 warning - GetSystemSettings(); -#endif // _WIN32_WCE - bHandled = FALSE; - return 0; - } - - void GetSystemSettings() - { - if(!m_bCommCtrl6 && !m_bmSort[m_iSortUp].IsNull()) - { - T* pT = static_cast(this); - pT->CreateSortBitmaps(); - if(m_iSortColumn != -1) - SetSortColumn(m_iSortColumn); - } - } - -}; - - -typedef ATL::CWinTraits CSortListViewCtrlTraits; - -template -class ATL_NO_VTABLE CSortListViewCtrlImpl: public ATL::CWindowImpl, public CSortListViewImpl -{ -public: - DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName()) - - bool SortItems(int iCol, bool bDescending = false) - { - return DoSortItems(iCol, bDescending); - } - - BEGIN_MSG_MAP(CSortListViewCtrlImpl) - MESSAGE_HANDLER(LVM_INSERTCOLUMN, CSortListViewImpl::OnInsertColumn) - MESSAGE_HANDLER(LVM_DELETECOLUMN, CSortListViewImpl::OnDeleteColumn) - NOTIFY_CODE_HANDLER(HDN_ITEMCLICKA, CSortListViewImpl::OnHeaderItemClick) - NOTIFY_CODE_HANDLER(HDN_ITEMCLICKW, CSortListViewImpl::OnHeaderItemClick) - MESSAGE_HANDLER(WM_SETTINGCHANGE, CSortListViewImpl::OnSettingChange) - END_MSG_MAP() -}; - -class CSortListViewCtrl : public CSortListViewCtrlImpl -{ -public: - DECLARE_WND_SUPERCLASS(_T("WTL_SortListViewCtrl"), GetWndClassName()) -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CTabView - implements tab view window - -// TabView Notifications -#define TBVN_PAGEACTIVATED (0U-741) -#define TBVN_CONTEXTMENU (0U-742) - -// Notification data for TBVN_CONTEXTMENU -struct TBVCONTEXTMENUINFO -{ - NMHDR hdr; - POINT pt; -}; - -typedef TBVCONTEXTMENUINFO* LPTBVCONTEXTMENUINFO; - - -template -class ATL_NO_VTABLE CTabViewImpl : public ATL::CWindowImpl -{ -public: - DECLARE_WND_CLASS_EX(NULL, 0, COLOR_APPWORKSPACE) - -// Declarations and enums - struct TABVIEWPAGE - { - HWND hWnd; - LPTSTR lpstrTitle; - LPVOID pData; - }; - - struct TCITEMEXTRA - { - TCITEMHEADER tciheader; - TABVIEWPAGE tvpage; - - operator LPTCITEM() { return (LPTCITEM)this; } - }; - - enum - { - m_nTabID = 1313, - m_cxMoveMark = 6, - m_cyMoveMark = 3, - m_nMenuItemsMax = (ID_WINDOW_TABLAST - ID_WINDOW_TABFIRST + 1) - }; - -// Data members - ATL::CContainedWindowT m_tab; - int m_cyTabHeight; - - int m_nActivePage; - - int m_nInsertItem; - POINT m_ptStartDrag; - - CMenuHandle m_menu; - - int m_cchTabTextLength; - - int m_nMenuItemsCount; - - ATL::CWindow m_wndTitleBar; - LPTSTR m_lpstrTitleBarBase; - int m_cchTitleBarLength; - - CImageList m_ilDrag; - - bool m_bDestroyPageOnRemove:1; - bool m_bDestroyImageList:1; - bool m_bActivePageMenuItem:1; - bool m_bActiveAsDefaultMenuItem:1; - bool m_bEmptyMenuItem:1; - bool m_bWindowsMenuItem:1; - // internal - bool m_bTabCapture:1; - bool m_bTabDrag:1; - -// Constructor/destructor - CTabViewImpl() : - m_nActivePage(-1), - m_cyTabHeight(0), - m_tab(this, 1), - m_nInsertItem(-1), - m_cchTabTextLength(30), - m_nMenuItemsCount(10), - m_lpstrTitleBarBase(NULL), - m_cchTitleBarLength(100), - m_bDestroyPageOnRemove(true), - m_bDestroyImageList(true), - m_bActivePageMenuItem(true), - m_bActiveAsDefaultMenuItem(false), - m_bEmptyMenuItem(false), - m_bWindowsMenuItem(false), - m_bTabCapture(false), - m_bTabDrag(false) - { - m_ptStartDrag.x = 0; - m_ptStartDrag.y = 0; - } - - ~CTabViewImpl() - { - delete [] m_lpstrTitleBarBase; - } - -// Message filter function - to be called from PreTranslateMessage of the main window - BOOL PreTranslateMessage(MSG* pMsg) - { - if(IsWindow() == FALSE) - return FALSE; - - BOOL bRet = FALSE; - - // Check for TabView built-in accelerators (Ctrl+Tab/Ctrl+Shift+Tab - next/previous page) - int nCount = GetPageCount(); - if(nCount > 0) - { - bool bControl = (::GetKeyState(VK_CONTROL) < 0); - if((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_TAB) && bControl) - { - if(nCount > 1) - { - int nPage = m_nActivePage; - bool bShift = (::GetKeyState(VK_SHIFT) < 0); - if(bShift) - nPage = (nPage > 0) ? (nPage - 1) : (nCount - 1); - else - nPage = ((nPage >= 0) && (nPage < (nCount - 1))) ? (nPage + 1) : 0; - - SetActivePage(nPage); - T* pT = static_cast(this); - pT->OnPageActivated(m_nActivePage); - } - - bRet = TRUE; - } - } - - // If we are doing drag-drop, check for Escape key that cancels it - if(bRet == FALSE) - { - if(m_bTabCapture && pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE) - { - ::ReleaseCapture(); - bRet = TRUE; - } - } - - // Pass the message to the active page - if(bRet == FALSE) - { - if(m_nActivePage != -1) - bRet = (BOOL)::SendMessage(GetPageHWND(m_nActivePage), WM_FORWARDMSG, 0, (LPARAM)pMsg); - } - - return bRet; - } - -// Attributes - int GetPageCount() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return m_tab.GetItemCount(); - } - - int GetActivePage() const - { - return m_nActivePage; - } - - void SetActivePage(int nPage) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(IsValidPageIndex(nPage)); - - T* pT = static_cast(this); - - SetRedraw(FALSE); - - if(m_nActivePage != -1) - ::ShowWindow(GetPageHWND(m_nActivePage), FALSE); - m_nActivePage = nPage; - m_tab.SetCurSel(m_nActivePage); - ::ShowWindow(GetPageHWND(m_nActivePage), TRUE); - - pT->UpdateLayout(); - - SetRedraw(TRUE); - RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN); - - if(::GetFocus() != m_tab.m_hWnd) - ::SetFocus(GetPageHWND(m_nActivePage)); - - pT->UpdateTitleBar(); - pT->UpdateMenu(); - } - - HIMAGELIST GetImageList() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return m_tab.GetImageList(); - } - - HIMAGELIST SetImageList(HIMAGELIST hImageList) - { - ATLASSERT(::IsWindow(m_hWnd)); - return m_tab.SetImageList(hImageList); - } - - void SetWindowMenu(HMENU hMenu) - { - ATLASSERT(::IsWindow(m_hWnd)); - - m_menu = hMenu; - - T* pT = static_cast(this); - pT->UpdateMenu(); - } - - void SetTitleBarWindow(HWND hWnd) - { - ATLASSERT(::IsWindow(m_hWnd)); - - delete [] m_lpstrTitleBarBase; - m_lpstrTitleBarBase = NULL; - - m_wndTitleBar = hWnd; - if(hWnd == NULL) - return; - - int cchLen = m_wndTitleBar.GetWindowTextLength() + 1; - ATLTRY(m_lpstrTitleBarBase = new TCHAR[cchLen]); - if(m_lpstrTitleBarBase != NULL) - { - m_wndTitleBar.GetWindowText(m_lpstrTitleBarBase, cchLen); - T* pT = static_cast(this); - pT->UpdateTitleBar(); - } - } - -// Page attributes - HWND GetPageHWND(int nPage) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(IsValidPageIndex(nPage)); - - TCITEMEXTRA tcix = { 0 }; - tcix.tciheader.mask = TCIF_PARAM; - m_tab.GetItem(nPage, tcix); - - return tcix.tvpage.hWnd; - } - - LPCTSTR GetPageTitle(int nPage) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(IsValidPageIndex(nPage)); - - TCITEMEXTRA tcix = { 0 }; - tcix.tciheader.mask = TCIF_PARAM; - if(m_tab.GetItem(nPage, tcix) == FALSE) - return NULL; - - return tcix.tvpage.lpstrTitle; - } - - bool SetPageTitle(int nPage, LPCTSTR lpstrTitle) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(IsValidPageIndex(nPage)); - - T* pT = static_cast(this); - - int cchBuff = lstrlen(lpstrTitle) + 1; - LPTSTR lpstrBuff = NULL; - ATLTRY(lpstrBuff = new TCHAR[cchBuff]); - if(lpstrBuff == NULL) - return false; - - SecureHelper::strcpy_x(lpstrBuff, cchBuff, lpstrTitle); - TCITEMEXTRA tcix = { 0 }; - tcix.tciheader.mask = TCIF_PARAM; - if(m_tab.GetItem(nPage, tcix) == FALSE) - return false; - - CTempBuffer buff; - LPTSTR lpstrTabText = buff.Allocate(m_cchTabTextLength + 1); - if(lpstrTabText == NULL) - return false; - - delete [] tcix.tvpage.lpstrTitle; - - pT->ShortenTitle(lpstrTitle, lpstrTabText, m_cchTabTextLength + 1); - - tcix.tciheader.mask = TCIF_TEXT | TCIF_PARAM; - tcix.tciheader.pszText = lpstrTabText; - tcix.tvpage.lpstrTitle = lpstrBuff; - if(m_tab.SetItem(nPage, tcix) == FALSE) - return false; - - pT->UpdateTitleBar(); - pT->UpdateMenu(); - - return true; - } - - LPVOID GetPageData(int nPage) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(IsValidPageIndex(nPage)); - - TCITEMEXTRA tcix = { 0 }; - tcix.tciheader.mask = TCIF_PARAM; - m_tab.GetItem(nPage, tcix); - - return tcix.tvpage.pData; - } - - LPVOID SetPageData(int nPage, LPVOID pData) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(IsValidPageIndex(nPage)); - - TCITEMEXTRA tcix = { 0 }; - tcix.tciheader.mask = TCIF_PARAM; - m_tab.GetItem(nPage, tcix); - LPVOID pDataOld = tcix.tvpage.pData; - - tcix.tvpage.pData = pData; - m_tab.SetItem(nPage, tcix); - - return pDataOld; - } - - int GetPageImage(int nPage) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(IsValidPageIndex(nPage)); - - TCITEMEXTRA tcix = { 0 }; - tcix.tciheader.mask = TCIF_IMAGE; - m_tab.GetItem(nPage, tcix); - - return tcix.tciheader.iImage; - } - - int SetPageImage(int nPage, int nImage) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(IsValidPageIndex(nPage)); - - TCITEMEXTRA tcix = { 0 }; - tcix.tciheader.mask = TCIF_IMAGE; - m_tab.GetItem(nPage, tcix); - int nImageOld = tcix.tciheader.iImage; - - tcix.tciheader.iImage = nImage; - m_tab.SetItem(nPage, tcix); - - return nImageOld; - } - -// Operations - bool AddPage(HWND hWndView, LPCTSTR lpstrTitle, int nImage = -1, LPVOID pData = NULL) - { - return InsertPage(GetPageCount(), hWndView, lpstrTitle, nImage, pData); - } - - bool InsertPage(int nPage, HWND hWndView, LPCTSTR lpstrTitle, int nImage = -1, LPVOID pData = NULL) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(nPage == GetPageCount() || IsValidPageIndex(nPage)); - - T* pT = static_cast(this); - - int cchBuff = lstrlen(lpstrTitle) + 1; - LPTSTR lpstrBuff = NULL; - ATLTRY(lpstrBuff = new TCHAR[cchBuff]); - if(lpstrBuff == NULL) - return false; - - SecureHelper::strcpy_x(lpstrBuff, cchBuff, lpstrTitle); - - CTempBuffer buff; - LPTSTR lpstrTabText = buff.Allocate(m_cchTabTextLength + 1); - if(lpstrTabText == NULL) - return false; - - pT->ShortenTitle(lpstrTitle, lpstrTabText, m_cchTabTextLength + 1); - - SetRedraw(FALSE); - - TCITEMEXTRA tcix = { 0 }; - tcix.tciheader.mask = TCIF_TEXT | TCIF_IMAGE | TCIF_PARAM; - tcix.tciheader.pszText = lpstrTabText; - tcix.tciheader.iImage = nImage; - tcix.tvpage.hWnd = hWndView; - tcix.tvpage.lpstrTitle = lpstrBuff; - tcix.tvpage.pData = pData; - int nItem = m_tab.InsertItem(nPage, tcix); - if(nItem == -1) - { - delete [] lpstrBuff; - SetRedraw(TRUE); - return false; - } - - SetActivePage(nItem); - pT->OnPageActivated(m_nActivePage); - - if(GetPageCount() == 1) - pT->ShowTabControl(true); - - pT->UpdateLayout(); - - SetRedraw(TRUE); - RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN); - - return true; - } - - void RemovePage(int nPage) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(IsValidPageIndex(nPage)); - - T* pT = static_cast(this); - - SetRedraw(FALSE); - - if(GetPageCount() == 1) - pT->ShowTabControl(false); - - if(m_bDestroyPageOnRemove) - ::DestroyWindow(GetPageHWND(nPage)); - else - ::ShowWindow(GetPageHWND(nPage), FALSE); - LPTSTR lpstrTitle = (LPTSTR)GetPageTitle(nPage); - delete [] lpstrTitle; - - ATLVERIFY(m_tab.DeleteItem(nPage) != FALSE); - - if(m_nActivePage == nPage) - { - m_nActivePage = -1; - - if(nPage > 0) - { - SetActivePage(nPage - 1); - } - else if(GetPageCount() > 0) - { - SetActivePage(nPage); - } - else - { - SetRedraw(TRUE); - Invalidate(); - UpdateWindow(); - pT->UpdateTitleBar(); - pT->UpdateMenu(); - } - } - else - { - nPage = (nPage < m_nActivePage) ? (m_nActivePage - 1) : m_nActivePage; - m_nActivePage = -1; - SetActivePage(nPage); - } - - pT->OnPageActivated(m_nActivePage); - } - - void RemoveAllPages() - { - ATLASSERT(::IsWindow(m_hWnd)); - - if(GetPageCount() == 0) - return; - - T* pT = static_cast(this); - - SetRedraw(FALSE); - - pT->ShowTabControl(false); - - for(int i = 0; i < GetPageCount(); i++) - { - if(m_bDestroyPageOnRemove) - ::DestroyWindow(GetPageHWND(i)); - else - ::ShowWindow(GetPageHWND(i), FALSE); - LPTSTR lpstrTitle = (LPTSTR)GetPageTitle(i); - delete [] lpstrTitle; - } - m_tab.DeleteAllItems(); - - m_nActivePage = -1; - pT->OnPageActivated(m_nActivePage); - - SetRedraw(TRUE); - Invalidate(); - UpdateWindow(); - - pT->UpdateTitleBar(); - pT->UpdateMenu(); - } - - int PageIndexFromHwnd(HWND hWnd) const - { - int nIndex = -1; - - for(int i = 0; i < GetPageCount(); i++) - { - if(GetPageHWND(i) == hWnd) - { - nIndex = i; - break; - } - } - - return nIndex; - } - - void BuildWindowMenu(HMENU hMenu, int nMenuItemsCount = 10, bool bEmptyMenuItem = true, bool bWindowsMenuItem = true, bool bActivePageMenuItem = true, bool bActiveAsDefaultMenuItem = false) - { - ATLASSERT(::IsWindow(m_hWnd)); - - CMenuHandle menu = hMenu; - T* pT = static_cast(this); - pT; // avoid level 4 warning - int nFirstPos = 0; - - // Find first menu item in our range -#ifndef _WIN32_WCE - for(nFirstPos = 0; nFirstPos < menu.GetMenuItemCount(); nFirstPos++) - { - UINT nID = menu.GetMenuItemID(nFirstPos); - if((nID >= ID_WINDOW_TABFIRST && nID <= ID_WINDOW_TABLAST) || nID == ID_WINDOW_SHOWTABLIST) - break; - } -#else // CE specific - for(nFirstPos = 0; ; nFirstPos++) - { - CMenuItemInfo mii; - mii.fMask = MIIM_ID; - BOOL bRet = menu.GetMenuItemInfo(nFirstPos, TRUE, &mii); - if(bRet == FALSE) - break; - if((mii.wID >= ID_WINDOW_TABFIRST && mii.wID <= ID_WINDOW_TABLAST) || mii.wID == ID_WINDOW_SHOWTABLIST) - break; - } -#endif // _WIN32_WCE - - // Remove all menu items for tab pages - BOOL bRet = TRUE; - while(bRet != FALSE) - bRet = menu.DeleteMenu(nFirstPos, MF_BYPOSITION); - - // Add separator if it's not already there - int nPageCount = GetPageCount(); - if((bWindowsMenuItem || (nPageCount > 0)) && (nFirstPos > 0)) - { - CMenuItemInfo mii; - mii.fMask = MIIM_TYPE; - menu.GetMenuItemInfo(nFirstPos - 1, TRUE, &mii); - if((nFirstPos <= 0) || ((mii.fType & MFT_SEPARATOR) == 0)) - { - menu.AppendMenu(MF_SEPARATOR); - nFirstPos++; - } - } - - // Add menu items for all pages - if(nPageCount > 0) - { - // Append menu items for all pages - const int cchPrefix = 3; // 2 digits + space - nMenuItemsCount = min(min(nPageCount, nMenuItemsCount), (int)m_nMenuItemsMax); - ATLASSERT(nMenuItemsCount < 100); // 2 digits only - if(nMenuItemsCount >= 100) - nMenuItemsCount = 99; - - for(int i = 0; i < nMenuItemsCount; i++) - { - LPCTSTR lpstrTitle = GetPageTitle(i); - int nLen = lstrlen(lpstrTitle); - CTempBuffer buff; - LPTSTR lpstrText = buff.Allocate(cchPrefix + nLen + 1); - ATLASSERT(lpstrText != NULL); - if(lpstrText != NULL) - { - LPCTSTR lpstrFormat = (i < 9) ? _T("&%i %s") : _T("%i %s"); - SecureHelper::wsprintf_x(lpstrText, cchPrefix + nLen + 1, lpstrFormat, i + 1, lpstrTitle); - menu.AppendMenu(MF_STRING, ID_WINDOW_TABFIRST + i, lpstrText); - } - } - - // Mark active page - if(bActivePageMenuItem && (m_nActivePage != -1)) - { -#ifndef _WIN32_WCE - if(bActiveAsDefaultMenuItem) - { - menu.SetMenuDefaultItem((UINT)-1, TRUE); - menu.SetMenuDefaultItem(nFirstPos + m_nActivePage, TRUE); - } - else -#else // CE specific - bActiveAsDefaultMenuItem; // avoid level 4 warning -#endif // _WIN32_WCE - { - menu.CheckMenuRadioItem(nFirstPos, nFirstPos + nMenuItemsCount, nFirstPos + m_nActivePage, MF_BYPOSITION); - } - } - } - else - { - if(bEmptyMenuItem) - { - menu.AppendMenu(MF_BYPOSITION | MF_STRING, ID_WINDOW_TABFIRST, pT->GetEmptyListText()); - menu.EnableMenuItem(ID_WINDOW_TABFIRST, MF_GRAYED); - } - - // Remove separator if nothing else is there - if(!bEmptyMenuItem && !bWindowsMenuItem && (nFirstPos > 0)) - { - CMenuItemInfo mii; - mii.fMask = MIIM_TYPE; - menu.GetMenuItemInfo(nFirstPos - 1, TRUE, &mii); - if((mii.fType & MFT_SEPARATOR) != 0) - menu.DeleteMenu(nFirstPos - 1, MF_BYPOSITION); - } - } - - // Add "Windows..." menu item - if(bWindowsMenuItem) - menu.AppendMenu(MF_BYPOSITION | MF_STRING, ID_WINDOW_SHOWTABLIST, pT->GetWindowsMenuItemText()); - } - -// Message map and handlers - BEGIN_MSG_MAP(CTabViewImpl) - MESSAGE_HANDLER(WM_CREATE, OnCreate) - MESSAGE_HANDLER(WM_DESTROY, OnDestroy) - MESSAGE_HANDLER(WM_SIZE, OnSize) - MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) - NOTIFY_HANDLER(m_nTabID, TCN_SELCHANGE, OnTabChanged) - NOTIFY_ID_HANDLER(m_nTabID, OnTabNotification) -#ifndef _WIN32_WCE - NOTIFY_CODE_HANDLER(TTN_GETDISPINFO, OnTabGetDispInfo) -#endif // !_WIN32_WCE - FORWARD_NOTIFICATIONS() - ALT_MSG_MAP(1) // tab control - MESSAGE_HANDLER(WM_LBUTTONDOWN, OnTabLButtonDown) - MESSAGE_HANDLER(WM_LBUTTONUP, OnTabLButtonUp) - MESSAGE_HANDLER(WM_CAPTURECHANGED, OnTabCaptureChanged) - MESSAGE_HANDLER(WM_MOUSEMOVE, OnTabMouseMove) - MESSAGE_HANDLER(WM_RBUTTONUP, OnTabRButtonUp) - MESSAGE_HANDLER(WM_SYSKEYDOWN, OnTabSysKeyDown) - END_MSG_MAP() - - LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - pT->CreateTabControl(); - - return 0; - } - - LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - RemoveAllPages(); - - if(m_bDestroyImageList) - { - CImageList il = m_tab.SetImageList(NULL); - if(il.m_hImageList != NULL) - il.Destroy(); - } - - return 0; - } - - LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - pT->UpdateLayout(); - return 0; - } - - LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - if(m_nActivePage != -1) - ::SetFocus(GetPageHWND(m_nActivePage)); - return 0; - } - - LRESULT OnTabChanged(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) - { - SetActivePage(m_tab.GetCurSel()); - T* pT = static_cast(this); - pT->OnPageActivated(m_nActivePage); - - return 0; - } - - LRESULT OnTabNotification(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) - { - // nothing to do - this just blocks all tab control - // notifications from being propagated further - return 0; - } - -#ifndef _WIN32_WCE - LRESULT OnTabGetDispInfo(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled) - { - LPNMTTDISPINFO pTTDI = (LPNMTTDISPINFO)pnmh; - if(pTTDI->hdr.hwndFrom == m_tab.GetTooltips()) - { - T* pT = static_cast(this); - pT->UpdateTooltipText(pTTDI); - } - else - { - bHandled = FALSE; - } - - return 0; - } -#endif // !_WIN32_WCE - -// Tab control message handlers - LRESULT OnTabLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) - { - if(m_tab.GetItemCount() > 1) - { - m_bTabCapture = true; - m_tab.SetCapture(); - - m_ptStartDrag.x = GET_X_LPARAM(lParam); - m_ptStartDrag.y = GET_Y_LPARAM(lParam); - } - - bHandled = FALSE; - return 0; - } - - LRESULT OnTabLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) - { - if(m_bTabCapture) - { - if(m_bTabDrag) - { - TCHITTESTINFO hti = { 0 }; - hti.pt.x = GET_X_LPARAM(lParam); - hti.pt.y = GET_Y_LPARAM(lParam); - int nItem = m_tab.HitTest(&hti); - if(nItem != -1) - MovePage(m_nActivePage, nItem); - } - - ::ReleaseCapture(); - } - - bHandled = FALSE; - return 0; - } - - LRESULT OnTabCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - if(m_bTabCapture) - { - m_bTabCapture = false; - - if(m_bTabDrag) - { - m_bTabDrag = false; - T* pT = static_cast(this); - pT->DrawMoveMark(-1); - -#ifndef _WIN32_WCE - m_ilDrag.DragLeave(GetDesktopWindow()); -#endif // !_WIN32_WCE - m_ilDrag.EndDrag(); - - m_ilDrag.Destroy(); - m_ilDrag.m_hImageList = NULL; - } - } - - bHandled = FALSE; - return 0; - } - - LRESULT OnTabMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) - { - bHandled = FALSE; - - if(m_bTabCapture) - { - POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; - - if(!m_bTabDrag) - { -#ifndef _WIN32_WCE - if(abs(m_ptStartDrag.x - GET_X_LPARAM(lParam)) >= ::GetSystemMetrics(SM_CXDRAG) || - abs(m_ptStartDrag.y - GET_Y_LPARAM(lParam)) >= ::GetSystemMetrics(SM_CYDRAG)) -#else // CE specific - if(abs(m_ptStartDrag.x - GET_X_LPARAM(lParam)) >= 4 || - abs(m_ptStartDrag.y - GET_Y_LPARAM(lParam)) >= 4) -#endif // _WIN32_WCE - { - T* pT = static_cast(this); - pT->GenerateDragImage(m_nActivePage); - - int cxCursor = ::GetSystemMetrics(SM_CXCURSOR); - int cyCursor = ::GetSystemMetrics(SM_CYCURSOR); - m_ilDrag.BeginDrag(0, -(cxCursor / 2), -(cyCursor / 2)); -#ifndef _WIN32_WCE - POINT ptEnter = m_ptStartDrag; - m_tab.ClientToScreen(&ptEnter); - m_ilDrag.DragEnter(GetDesktopWindow(), ptEnter); -#endif // !_WIN32_WCE - - m_bTabDrag = true; - } - } - - if(m_bTabDrag) - { - TCHITTESTINFO hti = { 0 }; - hti.pt = pt; - int nItem = m_tab.HitTest(&hti); - - T* pT = static_cast(this); - pT->SetMoveCursor(nItem != -1); - - if(m_nInsertItem != nItem) - pT->DrawMoveMark(nItem); - - m_ilDrag.DragShowNolock((nItem != -1) ? TRUE : FALSE); - m_tab.ClientToScreen(&pt); - m_ilDrag.DragMove(pt); - - bHandled = TRUE; - } - } - - return 0; - } - - LRESULT OnTabRButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) - { - TCHITTESTINFO hti = { 0 }; - hti.pt.x = GET_X_LPARAM(lParam); - hti.pt.y = GET_Y_LPARAM(lParam); - int nItem = m_tab.HitTest(&hti); - if(nItem != -1) - { - T* pT = static_cast(this); - pT->OnContextMenu(nItem, hti.pt); - } - - return 0; - } - - LRESULT OnTabSysKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) - { - bool bShift = (::GetKeyState(VK_SHIFT) < 0); - if(wParam == VK_F10 && bShift) - { - if(m_nActivePage != -1) - { - RECT rect = { 0 }; - m_tab.GetItemRect(m_nActivePage, &rect); - POINT pt = { rect.left, rect.bottom }; - T* pT = static_cast(this); - pT->OnContextMenu(m_nActivePage, pt); - } - } - else - { - bHandled = FALSE; - } - - return 0; - } - -// Implementation helpers - bool IsValidPageIndex(int nPage) const - { - return (nPage >= 0 && nPage < GetPageCount()); - } - - bool MovePage(int nMovePage, int nInsertBeforePage) - { - ATLASSERT(IsValidPageIndex(nMovePage)); - ATLASSERT(IsValidPageIndex(nInsertBeforePage)); - - if(!IsValidPageIndex(nMovePage) || !IsValidPageIndex(nInsertBeforePage)) - return false; - - if(nMovePage == nInsertBeforePage) - return true; // nothing to do - - CTempBuffer buff; - LPTSTR lpstrTabText = buff.Allocate(m_cchTabTextLength + 1); - if(lpstrTabText == NULL) - return false; - TCITEMEXTRA tcix = { 0 }; - tcix.tciheader.mask = TCIF_TEXT | TCIF_IMAGE | TCIF_PARAM; - tcix.tciheader.pszText = lpstrTabText; - tcix.tciheader.cchTextMax = m_cchTabTextLength + 1; - BOOL bRet = m_tab.GetItem(nMovePage, tcix); - ATLASSERT(bRet != FALSE); - if(bRet == FALSE) - return false; - - int nInsertItem = (nInsertBeforePage > nMovePage) ? nInsertBeforePage + 1 : nInsertBeforePage; - int nNewItem = m_tab.InsertItem(nInsertItem, tcix); - ATLASSERT(nNewItem == nInsertItem); - if(nNewItem != nInsertItem) - { - ATLVERIFY(m_tab.DeleteItem(nNewItem)); - return false; - } - - if(nMovePage > nInsertBeforePage) - ATLVERIFY(m_tab.DeleteItem(nMovePage + 1) != FALSE); - else if(nMovePage < nInsertBeforePage) - ATLVERIFY(m_tab.DeleteItem(nMovePage) != FALSE); - - SetActivePage(nInsertBeforePage); - T* pT = static_cast(this); - pT->OnPageActivated(m_nActivePage); - - return true; - } - -// Implementation overrideables - bool CreateTabControl() - { -#ifndef _WIN32_WCE - m_tab.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_TOOLTIPS, 0, m_nTabID); -#else // CE specific - m_tab.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, m_nTabID); -#endif // _WIN32_WCE - ATLASSERT(m_tab.m_hWnd != NULL); - if(m_tab.m_hWnd == NULL) - return false; - - m_tab.SetFont(AtlGetDefaultGuiFont()); - - m_tab.SetItemExtra(sizeof(TABVIEWPAGE)); - - T* pT = static_cast(this); - m_cyTabHeight = pT->CalcTabHeight(); - - return true; - } - - int CalcTabHeight() - { - int nCount = m_tab.GetItemCount(); - TCITEMEXTRA tcix = { 0 }; - tcix.tciheader.mask = TCIF_TEXT; - tcix.tciheader.pszText = _T("NS"); - int nIndex = m_tab.InsertItem(nCount, tcix); - - RECT rect = { 0, 0, 1000, 1000 }; - m_tab.AdjustRect(FALSE, &rect); - - RECT rcWnd = { 0, 0, 1000, rect.top }; - ::AdjustWindowRectEx(&rcWnd, m_tab.GetStyle(), FALSE, m_tab.GetExStyle()); - - int nHeight = rcWnd.bottom - rcWnd.top; - - m_tab.DeleteItem(nIndex); - - return nHeight; - } - - void ShowTabControl(bool bShow) - { - m_tab.ShowWindow(bShow ? SW_SHOWNOACTIVATE : SW_HIDE); - } - - void UpdateLayout() - { - RECT rect; - GetClientRect(&rect); - - if(m_tab.IsWindow() && ((m_tab.GetStyle() & WS_VISIBLE) != 0)) - m_tab.SetWindowPos(NULL, 0, 0, rect.right - rect.left, m_cyTabHeight, SWP_NOZORDER); - - if(m_nActivePage != -1) - ::SetWindowPos(GetPageHWND(m_nActivePage), NULL, 0, m_cyTabHeight, rect.right - rect.left, rect.bottom - rect.top - m_cyTabHeight, SWP_NOZORDER); - } - - void UpdateMenu() - { - if(m_menu.m_hMenu != NULL) - BuildWindowMenu(m_menu, m_nMenuItemsCount, m_bEmptyMenuItem, m_bWindowsMenuItem, m_bActivePageMenuItem, m_bActiveAsDefaultMenuItem); - } - - void UpdateTitleBar() - { - if(!m_wndTitleBar.IsWindow() || m_lpstrTitleBarBase == NULL) - return; // nothing to do - - if(m_nActivePage != -1) - { - T* pT = static_cast(this); - LPCTSTR lpstrTitle = pT->GetPageTitle(m_nActivePage); - LPCTSTR lpstrDivider = pT->GetTitleDividerText(); - int cchBuffer = m_cchTitleBarLength + lstrlen(lpstrDivider) + lstrlen(m_lpstrTitleBarBase) + 1; - CTempBuffer buff; - LPTSTR lpstrPageTitle = buff.Allocate(cchBuffer); - ATLASSERT(lpstrPageTitle != NULL); - if(lpstrPageTitle != NULL) - { - pT->ShortenTitle(lpstrTitle, lpstrPageTitle, m_cchTitleBarLength + 1); - SecureHelper::strcat_x(lpstrPageTitle, cchBuffer, lpstrDivider); - SecureHelper::strcat_x(lpstrPageTitle, cchBuffer, m_lpstrTitleBarBase); - } - else - { - lpstrPageTitle = m_lpstrTitleBarBase; - } - - m_wndTitleBar.SetWindowText(lpstrPageTitle); - } - else - { - m_wndTitleBar.SetWindowText(m_lpstrTitleBarBase); - } - } - - void DrawMoveMark(int nItem) - { - T* pT = static_cast(this); - - if(m_nInsertItem != -1) - { - RECT rect = { 0 }; - pT->GetMoveMarkRect(rect); - m_tab.InvalidateRect(&rect); - } - - m_nInsertItem = nItem; - - if(m_nInsertItem != -1) - { - CClientDC dc(m_tab.m_hWnd); - - RECT rect = { 0 }; - pT->GetMoveMarkRect(rect); - - CPen pen; - pen.CreatePen(PS_SOLID, 1, ::GetSysColor(COLOR_WINDOWTEXT)); - CBrush brush; - brush.CreateSolidBrush(::GetSysColor(COLOR_WINDOWTEXT)); - - HPEN hPenOld = dc.SelectPen(pen); - HBRUSH hBrushOld = dc.SelectBrush(brush); - - int x = rect.left; - int y = rect.top; - POINT ptsTop[3] = { { x, y }, { x + m_cxMoveMark, y }, { x + (m_cxMoveMark / 2), y + m_cyMoveMark } }; - dc.Polygon(ptsTop, 3); - - y = rect.bottom - 1; - POINT ptsBottom[3] = { { x, y }, { x + m_cxMoveMark, y }, { x + (m_cxMoveMark / 2), y - m_cyMoveMark } }; - dc.Polygon(ptsBottom, 3); - - dc.SelectPen(hPenOld); - dc.SelectBrush(hBrushOld); - } - } - - void GetMoveMarkRect(RECT& rect) const - { - m_tab.GetClientRect(&rect); - - RECT rcItem = { 0 }; - m_tab.GetItemRect(m_nInsertItem, &rcItem); - - if(m_nInsertItem <= m_nActivePage) - { - rect.left = rcItem.left - m_cxMoveMark / 2 - 1; - rect.right = rcItem.left + m_cxMoveMark / 2; - } - else - { - rect.left = rcItem.right - m_cxMoveMark / 2 - 1; - rect.right = rcItem.right + m_cxMoveMark / 2; - } - } - - void SetMoveCursor(bool bCanMove) - { - ::SetCursor(::LoadCursor(NULL, bCanMove ? IDC_ARROW : IDC_NO)); - } - - void GenerateDragImage(int nItem) - { - ATLASSERT(IsValidPageIndex(nItem)); - -#ifndef _WIN32_WCE - RECT rcItem = { 0 }; - m_tab.GetItemRect(nItem, &rcItem); - ::InflateRect(&rcItem, 2, 2); // make bigger to cover selected item -#else // CE specific - nItem; // avoid level 4 warning - RECT rcItem = { 0, 0, 40, 20 }; -#endif // _WIN32_WCE - - ATLASSERT(m_ilDrag.m_hImageList == NULL); - m_ilDrag.Create(rcItem.right - rcItem.left, rcItem.bottom - rcItem.top, ILC_COLORDDB | ILC_MASK, 1, 1); - - CClientDC dc(m_hWnd); - CDC dcMem; - dcMem.CreateCompatibleDC(dc); - ATLASSERT(dcMem.m_hDC != NULL); - dcMem.SetViewportOrg(-rcItem.left, -rcItem.top); - - CBitmap bmp; - bmp.CreateCompatibleBitmap(dc, rcItem.right - rcItem.left, rcItem.bottom - rcItem.top); - ATLASSERT(bmp.m_hBitmap != NULL); - - HBITMAP hBmpOld = dcMem.SelectBitmap(bmp); -#ifndef _WIN32_WCE - m_tab.SendMessage(WM_PRINTCLIENT, (WPARAM)dcMem.m_hDC); -#else // CE specific - dcMem.Rectangle(&rcItem); -#endif // _WIN32_WCE - dcMem.SelectBitmap(hBmpOld); - - ATLVERIFY(m_ilDrag.Add(bmp.m_hBitmap, RGB(255, 0, 255)) != -1); - } - - void ShortenTitle(LPCTSTR lpstrTitle, LPTSTR lpstrShortTitle, int cchShortTitle) - { - if(lstrlen(lpstrTitle) >= cchShortTitle) - { - LPCTSTR lpstrEllipsis = _T("..."); - int cchEllipsis = lstrlen(lpstrEllipsis); - SecureHelper::strncpy_x(lpstrShortTitle, cchShortTitle, lpstrTitle, cchShortTitle - cchEllipsis - 1); - SecureHelper::strcat_x(lpstrShortTitle, cchShortTitle, lpstrEllipsis); - } - else - { - SecureHelper::strcpy_x(lpstrShortTitle, cchShortTitle, lpstrTitle); - } - } - -#ifndef _WIN32_WCE - void UpdateTooltipText(LPNMTTDISPINFO pTTDI) - { - ATLASSERT(pTTDI != NULL); - pTTDI->lpszText = (LPTSTR)GetPageTitle((int)pTTDI->hdr.idFrom); - } -#endif // !_WIN32_WCE - -// Text for menu items and title bar - override to provide different strings - static LPCTSTR GetEmptyListText() - { - return _T("(Empty)"); - } - - static LPCTSTR GetWindowsMenuItemText() - { - return _T("&Windows..."); - } - - static LPCTSTR GetTitleDividerText() - { - return _T(" - "); - } - -// Notifications - override to provide different behavior - void OnPageActivated(int nPage) - { - NMHDR nmhdr = { 0 }; - nmhdr.hwndFrom = m_hWnd; - nmhdr.idFrom = nPage; - nmhdr.code = TBVN_PAGEACTIVATED; - ::SendMessage(GetParent(), WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmhdr); - } - - void OnContextMenu(int nPage, POINT pt) - { - m_tab.ClientToScreen(&pt); - - TBVCONTEXTMENUINFO cmi = { 0 }; - cmi.hdr.hwndFrom = m_hWnd; - cmi.hdr.idFrom = nPage; - cmi.hdr.code = TBVN_CONTEXTMENU; - cmi.pt = pt; - ::SendMessage(GetParent(), WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&cmi); - } -}; - - -class CTabView : public CTabViewImpl -{ -public: - DECLARE_WND_CLASS_EX(_T("WTL_TabView"), 0, COLOR_APPWORKSPACE) -}; - -}; // namespace WTL - -#endif // __ATLCTRLX_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/atlddx.h b/prog/3rdPartyLibs/wtl-8.1/include/atlddx.h deleted file mode 100644 index 31456a40a..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/atlddx.h +++ /dev/null @@ -1,624 +0,0 @@ -// Windows Template Library - WTL version 8.1 -// Copyright (C) Microsoft Corporation. All rights reserved. -// -// This file is a part of the Windows Template Library. -// The use and distribution terms for this software are covered by the -// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php) -// which can be found in the file CPL.TXT at the root of this distribution. -// By using this software in any fashion, you are agreeing to be bound by -// the terms of this license. You must not remove this notice, or -// any other, from this software. - -#ifndef __ATLDDX_H__ -#define __ATLDDX_H__ - -#pragma once - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#ifndef __ATLAPP_H__ - #error atlddx.h requires atlapp.h to be included first -#endif - -#if defined(_ATL_USE_DDX_FLOAT) && defined(_ATL_MIN_CRT) - #error Cannot use floating point DDX with _ATL_MIN_CRT defined -#endif // defined(_ATL_USE_DDX_FLOAT) && defined(_ATL_MIN_CRT) - -#ifdef _ATL_USE_DDX_FLOAT - #include -#endif // _ATL_USE_DDX_FLOAT - - -/////////////////////////////////////////////////////////////////////////////// -// Classes in this file: -// -// CWinDataExchange - - -namespace WTL -{ - -// Constants -#define DDX_LOAD FALSE -#define DDX_SAVE TRUE - -// DDX map macros -#define BEGIN_DDX_MAP(thisClass) \ - BOOL DoDataExchange(BOOL bSaveAndValidate = FALSE, UINT nCtlID = (UINT)-1) \ - { \ - bSaveAndValidate; \ - nCtlID; - -#define DDX_TEXT(nID, var) \ - if(nCtlID == (UINT)-1 || nCtlID == nID) \ - { \ - if(!DDX_Text(nID, var, sizeof(var), bSaveAndValidate)) \ - return FALSE; \ - } - -#define DDX_TEXT_LEN(nID, var, len) \ - if(nCtlID == (UINT)-1 || nCtlID == nID) \ - { \ - if(!DDX_Text(nID, var, sizeof(var), bSaveAndValidate, TRUE, len)) \ - return FALSE; \ - } - -#define DDX_INT(nID, var) \ - if(nCtlID == (UINT)-1 || nCtlID == nID) \ - { \ - if(!DDX_Int(nID, var, TRUE, bSaveAndValidate)) \ - return FALSE; \ - } - -#define DDX_INT_RANGE(nID, var, min, max) \ - if(nCtlID == (UINT)-1 || nCtlID == nID) \ - { \ - if(!DDX_Int(nID, var, TRUE, bSaveAndValidate, TRUE, min, max)) \ - return FALSE; \ - } - -#define DDX_UINT(nID, var) \ - if(nCtlID == (UINT)-1 || nCtlID == nID) \ - { \ - if(!DDX_Int(nID, var, FALSE, bSaveAndValidate)) \ - return FALSE; \ - } - -#define DDX_UINT_RANGE(nID, var, min, max) \ - if(nCtlID == (UINT)-1 || nCtlID == nID) \ - { \ - if(!DDX_Int(nID, var, FALSE, bSaveAndValidate, TRUE, min, max)) \ - return FALSE; \ - } - -#ifdef _ATL_USE_DDX_FLOAT -#define DDX_FLOAT(nID, var) \ - if(nCtlID == (UINT)-1 || nCtlID == nID) \ - { \ - if(!DDX_Float(nID, var, bSaveAndValidate)) \ - return FALSE; \ - } - -#define DDX_FLOAT_RANGE(nID, var, min, max) \ - if(nCtlID == (UINT)-1 || nCtlID == nID) \ - { \ - if(!DDX_Float(nID, var, bSaveAndValidate, TRUE, min, max)) \ - return FALSE; \ - } -#define DDX_FLOAT_P(nID, var, precision) \ - if(nCtlID == (UINT)-1 || nCtlID == nID) \ - { \ - if(!DDX_Float(nID, var, bSaveAndValidate, FALSE, 0, 0, precision)) \ - return FALSE; \ - } - -#define DDX_FLOAT_P_RANGE(nID, var, min, max, precision) \ - if(nCtlID == (UINT)-1 || nCtlID == nID) \ - { \ - if(!DDX_Float(nID, var, bSaveAndValidate, TRUE, min, max, precision)) \ - return FALSE; \ - } -#endif // _ATL_USE_DDX_FLOAT - -#define DDX_CONTROL(nID, obj) \ - if(nCtlID == (UINT)-1 || nCtlID == nID) \ - DDX_Control(nID, obj, bSaveAndValidate); - -#define DDX_CONTROL_HANDLE(nID, obj) \ - if(nCtlID == (UINT)-1 || nCtlID == nID) \ - DDX_Control_Handle(nID, obj, bSaveAndValidate); - -#define DDX_CHECK(nID, var) \ - if(nCtlID == (UINT)-1 || nCtlID == nID) \ - DDX_Check(nID, var, bSaveAndValidate); - -#define DDX_RADIO(nID, var) \ - if(nCtlID == (UINT)-1 || nCtlID == nID) \ - DDX_Radio(nID, var, bSaveAndValidate); - -#define END_DDX_MAP() \ - return TRUE; \ - } - - -/////////////////////////////////////////////////////////////////////////////// -// CWinDataExchange - provides support for DDX - -template -class CWinDataExchange -{ -public: -// Data exchange method - override in your derived class - BOOL DoDataExchange(BOOL /*bSaveAndValidate*/ = FALSE, UINT /*nCtlID*/ = (UINT)-1) - { - // this one should never be called, override it in - // your derived class by implementing DDX map - ATLASSERT(FALSE); - return FALSE; - } - -// Helpers for validation error reporting - enum _XDataType - { - ddxDataNull = 0, - ddxDataText = 1, - ddxDataInt = 2, - ddxDataFloat = 3, - ddxDataDouble = 4 - }; - - struct _XTextData - { - int nLength; - int nMaxLength; - }; - - struct _XIntData - { - long nVal; - long nMin; - long nMax; - }; - - struct _XFloatData - { - double nVal; - double nMin; - double nMax; - }; - - struct _XData - { - _XDataType nDataType; - union - { - _XTextData textData; - _XIntData intData; - _XFloatData floatData; - }; - }; - -// Text exchange - BOOL DDX_Text(UINT nID, LPTSTR lpstrText, int cbSize, BOOL bSave, BOOL bValidate = FALSE, int nLength = 0) - { - T* pT = static_cast(this); - BOOL bSuccess = TRUE; - - if(bSave) - { - HWND hWndCtrl = pT->GetDlgItem(nID); - int nRetLen = ::GetWindowText(hWndCtrl, lpstrText, cbSize / sizeof(TCHAR)); - if(nRetLen < ::GetWindowTextLength(hWndCtrl)) - bSuccess = FALSE; - } - else - { - ATLASSERT(!bValidate || lstrlen(lpstrText) <= nLength); - bSuccess = pT->SetDlgItemText(nID, lpstrText); - } - - if(!bSuccess) - { - pT->OnDataExchangeError(nID, bSave); - } - else if(bSave && bValidate) // validation - { - ATLASSERT(nLength > 0); - if(lstrlen(lpstrText) > nLength) - { - _XData data = { ddxDataText }; - data.textData.nLength = lstrlen(lpstrText); - data.textData.nMaxLength = nLength; - pT->OnDataValidateError(nID, bSave, data); - bSuccess = FALSE; - } - } - return bSuccess; - } - - BOOL DDX_Text(UINT nID, BSTR& bstrText, int /*cbSize*/, BOOL bSave, BOOL bValidate = FALSE, int nLength = 0) - { - T* pT = static_cast(this); - BOOL bSuccess = TRUE; - - if(bSave) - { - bSuccess = pT->GetDlgItemText(nID, bstrText); - } - else - { - USES_CONVERSION; - LPTSTR lpstrText = OLE2T(bstrText); - ATLASSERT(!bValidate || lstrlen(lpstrText) <= nLength); - bSuccess = pT->SetDlgItemText(nID, lpstrText); - } - - if(!bSuccess) - { - pT->OnDataExchangeError(nID, bSave); - } - else if(bSave && bValidate) // validation - { - ATLASSERT(nLength > 0); - if((int)::SysStringLen(bstrText) > nLength) - { - _XData data = { ddxDataText }; - data.textData.nLength = (int)::SysStringLen(bstrText); - data.textData.nMaxLength = nLength; - pT->OnDataValidateError(nID, bSave, data); - bSuccess = FALSE; - } - } - return bSuccess; - } - - BOOL DDX_Text(UINT nID, ATL::CComBSTR& bstrText, int /*cbSize*/, BOOL bSave, BOOL bValidate = FALSE, int nLength = 0) - { - T* pT = static_cast(this); - BOOL bSuccess = TRUE; - - if(bSave) - { - bSuccess = pT->GetDlgItemText(nID, (BSTR&)bstrText); - } - else - { - USES_CONVERSION; - LPTSTR lpstrText = OLE2T(bstrText); - ATLASSERT(!bValidate || lstrlen(lpstrText) <= nLength); - bSuccess = pT->SetDlgItemText(nID, lpstrText); - } - - if(!bSuccess) - { - pT->OnDataExchangeError(nID, bSave); - } - else if(bSave && bValidate) // validation - { - ATLASSERT(nLength > 0); - if((int)bstrText.Length() > nLength) - { - _XData data = { ddxDataText }; - data.textData.nLength = (int)bstrText.Length(); - data.textData.nMaxLength = nLength; - pT->OnDataValidateError(nID, bSave, data); - bSuccess = FALSE; - } - } - return bSuccess; - } - -#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - BOOL DDX_Text(UINT nID, _CSTRING_NS::CString& strText, int /*cbSize*/, BOOL bSave, BOOL bValidate = FALSE, int nLength = 0) - { - T* pT = static_cast(this); - BOOL bSuccess = TRUE; - - if(bSave) - { - HWND hWndCtrl = pT->GetDlgItem(nID); - int nLen = ::GetWindowTextLength(hWndCtrl); - int nRetLen = -1; - LPTSTR lpstr = strText.GetBufferSetLength(nLen); - if(lpstr != NULL) - { - nRetLen = ::GetWindowText(hWndCtrl, lpstr, nLen + 1); - strText.ReleaseBuffer(); - } - if(nRetLen < nLen) - bSuccess = FALSE; - } - else - { - bSuccess = pT->SetDlgItemText(nID, strText); - } - - if(!bSuccess) - { - pT->OnDataExchangeError(nID, bSave); - } - else if(bSave && bValidate) // validation - { - ATLASSERT(nLength > 0); - if(strText.GetLength() > nLength) - { - _XData data = { ddxDataText }; - data.textData.nLength = strText.GetLength(); - data.textData.nMaxLength = nLength; - pT->OnDataValidateError(nID, bSave, data); - bSuccess = FALSE; - } - } - return bSuccess; - } -#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - -// Numeric exchange - template - BOOL DDX_Int(UINT nID, Type& nVal, BOOL bSigned, BOOL bSave, BOOL bValidate = FALSE, Type nMin = 0, Type nMax = 0) - { - T* pT = static_cast(this); - BOOL bSuccess = TRUE; - - if(bSave) - { - nVal = (Type)pT->GetDlgItemInt(nID, &bSuccess, bSigned); - } - else - { - ATLASSERT(!bValidate || nVal >= nMin && nVal <= nMax); - bSuccess = pT->SetDlgItemInt(nID, nVal, bSigned); - } - - if(!bSuccess) - { - pT->OnDataExchangeError(nID, bSave); - } - else if(bSave && bValidate) // validation - { - ATLASSERT(nMin != nMax); - if(nVal < nMin || nVal > nMax) - { - _XData data = { ddxDataInt }; - data.intData.nVal = (long)nVal; - data.intData.nMin = (long)nMin; - data.intData.nMax = (long)nMax; - pT->OnDataValidateError(nID, bSave, data); - bSuccess = FALSE; - } - } - return bSuccess; - } - -// Float exchange -#ifdef _ATL_USE_DDX_FLOAT - static BOOL _AtlSimpleFloatParse(LPCTSTR lpszText, double& d) - { - ATLASSERT(lpszText != NULL); - while (*lpszText == _T(' ') || *lpszText == _T('\t')) - lpszText++; - - TCHAR chFirst = lpszText[0]; - d = _tcstod(lpszText, (LPTSTR*)&lpszText); - if (d == 0.0 && chFirst != _T('0')) - return FALSE; // could not convert - while (*lpszText == _T(' ') || *lpszText == _T('\t')) - lpszText++; - - if (*lpszText != _T('\0')) - return FALSE; // not terminated properly - - return TRUE; - } - - BOOL DDX_Float(UINT nID, float& nVal, BOOL bSave, BOOL bValidate = FALSE, float nMin = 0.F, float nMax = 0.F, int nPrecision = FLT_DIG) - { - T* pT = static_cast(this); - BOOL bSuccess = TRUE; - const int cchBuff = 32; - TCHAR szBuff[cchBuff] = { 0 }; - - if(bSave) - { - pT->GetDlgItemText(nID, szBuff, cchBuff); - double d = 0; - if(_AtlSimpleFloatParse(szBuff, d)) - nVal = (float)d; - else - bSuccess = FALSE; - } - else - { - ATLASSERT(!bValidate || nVal >= nMin && nVal <= nMax); - SecureHelper::sprintf_x(szBuff, cchBuff, _T("%.*g"), nPrecision, nVal); - bSuccess = pT->SetDlgItemText(nID, szBuff); - } - - if(!bSuccess) - { - pT->OnDataExchangeError(nID, bSave); - } - else if(bSave && bValidate) // validation - { - ATLASSERT(nMin != nMax); - if(nVal < nMin || nVal > nMax) - { - _XData data = { ddxDataFloat }; - data.floatData.nVal = (double)nVal; - data.floatData.nMin = (double)nMin; - data.floatData.nMax = (double)nMax; - pT->OnDataValidateError(nID, bSave, data); - bSuccess = FALSE; - } - } - return bSuccess; - } - - BOOL DDX_Float(UINT nID, double& nVal, BOOL bSave, BOOL bValidate = FALSE, double nMin = 0., double nMax = 0., int nPrecision = DBL_DIG) - { - T* pT = static_cast(this); - BOOL bSuccess = TRUE; - const int cchBuff = 32; - TCHAR szBuff[cchBuff] = { 0 }; - - if(bSave) - { - pT->GetDlgItemText(nID, szBuff, cchBuff); - double d = 0; - if(_AtlSimpleFloatParse(szBuff, d)) - nVal = d; - else - bSuccess = FALSE; - } - else - { - ATLASSERT(!bValidate || nVal >= nMin && nVal <= nMax); - SecureHelper::sprintf_x(szBuff, cchBuff, _T("%.*g"), nPrecision, nVal); - bSuccess = pT->SetDlgItemText(nID, szBuff); - } - - if(!bSuccess) - { - pT->OnDataExchangeError(nID, bSave); - } - else if(bSave && bValidate) // validation - { - ATLASSERT(nMin != nMax); - if(nVal < nMin || nVal > nMax) - { - _XData data = { ddxDataFloat }; - data.floatData.nVal = nVal; - data.floatData.nMin = nMin; - data.floatData.nMax = nMax; - pT->OnDataValidateError(nID, bSave, data); - bSuccess = FALSE; - } - } - return bSuccess; - } -#endif // _ATL_USE_DDX_FLOAT - -// Full control subclassing (for CWindowImpl derived controls) - template - void DDX_Control(UINT nID, TControl& ctrl, BOOL bSave) - { - if(!bSave && ctrl.m_hWnd == NULL) - { - T* pT = static_cast(this); - ctrl.SubclassWindow(pT->GetDlgItem(nID)); - } - } - -// Simple control attaching (for HWND wrapper controls) - template - void DDX_Control_Handle(UINT nID, TControl& ctrl, BOOL bSave) - { - if(!bSave && ctrl.m_hWnd == NULL) - { - T* pT = static_cast(this); - ctrl = pT->GetDlgItem(nID); - } - } - -// Control state - void DDX_Check(UINT nID, int& nValue, BOOL bSave) - { - T* pT = static_cast(this); - HWND hWndCtrl = pT->GetDlgItem(nID); - if(bSave) - { - nValue = (int)::SendMessage(hWndCtrl, BM_GETCHECK, 0, 0L); - ATLASSERT(nValue >= 0 && nValue <= 2); - } - else - { - if(nValue < 0 || nValue > 2) - { - ATLTRACE2(atlTraceUI, 0, _T("ATL: Warning - dialog data checkbox value (%d) out of range.\n"), nValue); - nValue = 0; // default to off - } - ::SendMessage(hWndCtrl, BM_SETCHECK, nValue, 0L); - } - } - - // variant that supports bool (checked/not-checked, no intermediate state) - void DDX_Check(UINT nID, bool& bCheck, BOOL bSave) - { - int nValue = bCheck ? 1 : 0; - DDX_Check(nID, nValue, bSave); - - if(bSave) - { - if(nValue == 2) - ATLTRACE2(atlTraceUI, 0, _T("ATL: Warning - checkbox state (%d) out of supported range.\n"), nValue); - bCheck = (nValue == 1); - } - } - - void DDX_Radio(UINT nID, int& nValue, BOOL bSave) - { - T* pT = static_cast(this); - HWND hWndCtrl = pT->GetDlgItem(nID); - ATLASSERT(hWndCtrl != NULL); - - // must be first in a group of auto radio buttons - ATLASSERT(::GetWindowLong(hWndCtrl, GWL_STYLE) & WS_GROUP); - ATLASSERT(::SendMessage(hWndCtrl, WM_GETDLGCODE, 0, 0L) & DLGC_RADIOBUTTON); - - if(bSave) - nValue = -1; // value if none found - - // walk all children in group - int nButton = 0; - do - { - if(::SendMessage(hWndCtrl, WM_GETDLGCODE, 0, 0L) & DLGC_RADIOBUTTON) - { - // control in group is a radio button - if(bSave) - { - if(::SendMessage(hWndCtrl, BM_GETCHECK, 0, 0L) != 0) - { - ATLASSERT(nValue == -1); // only set once - nValue = nButton; - } - } - else - { - // select button - ::SendMessage(hWndCtrl, BM_SETCHECK, (nButton == nValue), 0L); - } - nButton++; - } - else - { - ATLTRACE2(atlTraceUI, 0, _T("ATL: Warning - skipping non-radio button in group.\n")); - } - hWndCtrl = ::GetWindow(hWndCtrl, GW_HWNDNEXT); - } - while (hWndCtrl != NULL && !(GetWindowLong(hWndCtrl, GWL_STYLE) & WS_GROUP)); - } - -// Overrideables - void OnDataExchangeError(UINT nCtrlID, BOOL /*bSave*/) - { - // Override to display an error message - ::MessageBeep((UINT)-1); - T* pT = static_cast(this); - ::SetFocus(pT->GetDlgItem(nCtrlID)); - } - - void OnDataValidateError(UINT nCtrlID, BOOL /*bSave*/, _XData& /*data*/) - { - // Override to display an error message - ::MessageBeep((UINT)-1); - T* pT = static_cast(this); - ::SetFocus(pT->GetDlgItem(nCtrlID)); - } -}; - -}; // namespace WTL - -#endif // __ATLDDX_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/atldlgs.h b/prog/3rdPartyLibs/wtl-8.1/include/atldlgs.h deleted file mode 100644 index feb72519b..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/atldlgs.h +++ /dev/null @@ -1,6407 +0,0 @@ -// Windows Template Library - WTL version 8.1 -// Copyright (C) Microsoft Corporation. All rights reserved. -// -// This file is a part of the Windows Template Library. -// The use and distribution terms for this software are covered by the -// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php) -// which can be found in the file CPL.TXT at the root of this distribution. -// By using this software in any fashion, you are agreeing to be bound by -// the terms of this license. You must not remove this notice, or -// any other, from this software. - -#ifndef __ATLDLGS_H__ -#define __ATLDLGS_H__ - -#pragma once - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#ifndef __ATLAPP_H__ - #error atldlgs.h requires atlapp.h to be included first -#endif - -#ifndef __ATLWIN_H__ - #error atldlgs.h requires atlwin.h to be included first -#endif - -#include -#include - -#if (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE) - #include -#endif // (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE) - - -/////////////////////////////////////////////////////////////////////////////// -// Classes in this file: -// -// CFileDialogImpl -// CFileDialog -// CFileDialogEx -// CMultiFileDialogImpl -// CMultiFileDialog -// CShellFileDialogImpl -// CShellFileOpenDialogImpl -// CShellFileOpenDialog -// CShellFileSaveDialogImpl -// CShellFileSaveDialog -// CFolderDialogImpl -// CFolderDialog -// CFontDialogImpl -// CFontDialog -// CRichEditFontDialogImpl -// CRichEditFontDialog -// CColorDialogImpl -// CColorDialog -// CPrintDialogImpl -// CPrintDialog -// CPrintDialogExImpl -// CPrintDialogEx -// CPageSetupDialogImpl -// CPageSetupDialog -// CFindReplaceDialogImpl -// CFindReplaceDialog -// -// CDialogBaseUnits -// CMemDlgTemplate -// CIndirectDialogImpl -// -// CPropertySheetWindow -// CPropertySheetImpl -// CPropertySheet -// CPropertyPageWindow -// CPropertyPageImpl -// CPropertyPage -// CAxPropertyPageImpl -// CAxPropertyPage -// -// CWizard97SheetWindow -// CWizard97SheetImpl -// CWizard97Sheet -// CWizard97PageWindow -// CWizard97PageImpl -// CWizard97ExteriorPageImpl -// CWizard97InteriorPageImpl -// -// CAeroWizardFrameWindow -// CAeroWizardFrameImpl -// CAeroWizardFrame -// CAeroWizardPageWindow -// CAeroWizardPageImpl -// CAeroWizardPage -// CAeroWizardAxPageImpl -// CAeroWizardAxPage -// -// CTaskDialogConfig -// CTaskDialogImpl -// CTaskDialog -// -// Global functions: -// AtlTaskDialog() - - -namespace WTL -{ - -/////////////////////////////////////////////////////////////////////////////// -// CFileDialogImpl - used for File Open or File Save As - -// compatibility with the old (vc6.0) headers -#if (_WIN32_WINNT >= 0x0500) && !defined(OPENFILENAME_SIZE_VERSION_400) - #ifndef CDSIZEOF_STRUCT - #define CDSIZEOF_STRUCT(structname, member) (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member)) - #endif - #define OPENFILENAME_SIZE_VERSION_400A CDSIZEOF_STRUCT(OPENFILENAMEA,lpTemplateName) - #define OPENFILENAME_SIZE_VERSION_400W CDSIZEOF_STRUCT(OPENFILENAMEW,lpTemplateName) - #ifdef UNICODE - #define OPENFILENAME_SIZE_VERSION_400 OPENFILENAME_SIZE_VERSION_400W - #else - #define OPENFILENAME_SIZE_VERSION_400 OPENFILENAME_SIZE_VERSION_400A - #endif // !UNICODE -#endif // (_WIN32_WINNT >= 0x0500) && !defined(OPENFILENAME_SIZE_VERSION_400) - -#if !defined(_WIN32_WCE) && !defined(CDN_INCLUDEITEM) - #define CDN_INCLUDEITEM (CDN_FIRST - 0x0007) -#endif - -template -class ATL_NO_VTABLE CFileDialogImpl : public ATL::CDialogImplBase -{ -public: -#if defined(__AYGSHELL_H__) && (_WIN32_WCE >= 0x0501) - OPENFILENAMEEX m_ofn; -#else - OPENFILENAME m_ofn; -#endif - BOOL m_bOpenFileDialog; // TRUE for file open, FALSE for file save - TCHAR m_szFileTitle[_MAX_FNAME]; // contains file title after return - TCHAR m_szFileName[_MAX_PATH]; // contains full path name after return - - CFileDialogImpl(BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs - LPCTSTR lpszDefExt = NULL, - LPCTSTR lpszFileName = NULL, - DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, - LPCTSTR lpszFilter = NULL, - HWND hWndParent = NULL) - { - memset(&m_ofn, 0, sizeof(m_ofn)); // initialize structure to 0/NULL - m_szFileName[0] = _T('\0'); - m_szFileTitle[0] = _T('\0'); - - m_bOpenFileDialog = bOpenFileDialog; - -#if defined(__AYGSHELL_H__) && (_WIN32_WCE >= 0x0501) - m_ofn.lStructSize = bOpenFileDialog ? sizeof(m_ofn) : sizeof(OPENFILENAME); -#else - m_ofn.lStructSize = sizeof(m_ofn); -#endif - -#if (_WIN32_WINNT >= 0x0500) - // adjust struct size if running on older version of Windows - if(AtlIsOldWindows()) - { - ATLASSERT(sizeof(m_ofn) > OPENFILENAME_SIZE_VERSION_400); // must be - m_ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; - } -#endif // (_WIN32_WINNT >= 0x0500) - m_ofn.lpstrFile = m_szFileName; - m_ofn.nMaxFile = _MAX_PATH; - m_ofn.lpstrDefExt = lpszDefExt; - m_ofn.lpstrFileTitle = (LPTSTR)m_szFileTitle; - m_ofn.nMaxFileTitle = _MAX_FNAME; -#ifndef _WIN32_WCE - m_ofn.Flags = dwFlags | OFN_EXPLORER | OFN_ENABLEHOOK | OFN_ENABLESIZING; -#else // CE specific - m_ofn.Flags = dwFlags | OFN_EXPLORER | OFN_ENABLEHOOK; -#endif // !_WIN32_WCE - m_ofn.lpstrFilter = lpszFilter; - m_ofn.hInstance = ModuleHelper::GetResourceInstance(); - m_ofn.lpfnHook = (LPOFNHOOKPROC)T::StartDialogProc; - m_ofn.hwndOwner = hWndParent; - - // setup initial file name - if(lpszFileName != NULL) - SecureHelper::strncpy_x(m_szFileName, _countof(m_szFileName), lpszFileName, _TRUNCATE); - } - - INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow()) - { - ATLASSERT((m_ofn.Flags & OFN_ENABLEHOOK) != 0); - ATLASSERT(m_ofn.lpfnHook != NULL); // can still be a user hook - - ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0); - - if(m_ofn.hwndOwner == NULL) // set only if not specified before - m_ofn.hwndOwner = hWndParent; - - ATLASSERT(m_hWnd == NULL); - ModuleHelper::AddCreateWndData(&m_thunk.cd, (ATL::CDialogImplBase*)this); - - BOOL bRet; - if(m_bOpenFileDialog) -#if defined(__AYGSHELL_H__) && (_WIN32_WCE >= 0x0501) - bRet = ::GetOpenFileNameEx(&m_ofn); - else - bRet = ::GetSaveFileName((LPOPENFILENAME)&m_ofn); -#else - bRet = ::GetOpenFileName(&m_ofn); - else - bRet = ::GetSaveFileName(&m_ofn); -#endif - - m_hWnd = NULL; - - return bRet ? IDOK : IDCANCEL; - } - -// Attributes - ATL::CWindow GetFileDialogWindow() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return ATL::CWindow(GetParent()); - } - - int GetFilePath(LPTSTR lpstrFilePath, int nLength) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0); - - return (int)GetFileDialogWindow().SendMessage(CDM_GETFILEPATH, nLength, (LPARAM)lpstrFilePath); - } - - int GetFolderIDList(LPVOID lpBuff, int nLength) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0); - - return (int)GetFileDialogWindow().SendMessage(CDM_GETFOLDERIDLIST, nLength, (LPARAM)lpBuff); - } - - int GetFolderPath(LPTSTR lpstrFolderPath, int nLength) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0); - - return (int)GetFileDialogWindow().SendMessage(CDM_GETFOLDERPATH, nLength, (LPARAM)lpstrFolderPath); - } - - int GetSpec(LPTSTR lpstrSpec, int nLength) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0); - - return (int)GetFileDialogWindow().SendMessage(CDM_GETSPEC, nLength, (LPARAM)lpstrSpec); - } - - void SetControlText(int nCtrlID, LPCTSTR lpstrText) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0); - - GetFileDialogWindow().SendMessage(CDM_SETCONTROLTEXT, nCtrlID, (LPARAM)lpstrText); - } - - void SetDefExt(LPCTSTR lpstrExt) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0); - - GetFileDialogWindow().SendMessage(CDM_SETDEFEXT, 0, (LPARAM)lpstrExt); - } - - BOOL GetReadOnlyPref() const // return TRUE if readonly checked - { - return ((m_ofn.Flags & OFN_READONLY) != 0) ? TRUE : FALSE; - } - -// Operations - void HideControl(int nCtrlID) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0); - - GetFileDialogWindow().SendMessage(CDM_HIDECONTROL, nCtrlID); - } - -// Special override for common dialogs - BOOL EndDialog(INT_PTR /*nRetCode*/ = 0) - { - ATLASSERT(::IsWindow(m_hWnd)); - GetFileDialogWindow().SendMessage(WM_COMMAND, MAKEWPARAM(IDCANCEL, 0)); - return TRUE; - } - -// Message map and handlers - BEGIN_MSG_MAP(CFileDialogImpl) - NOTIFY_CODE_HANDLER(CDN_FILEOK, _OnFileOK) - NOTIFY_CODE_HANDLER(CDN_FOLDERCHANGE, _OnFolderChange) - NOTIFY_CODE_HANDLER(CDN_HELP, _OnHelp) - NOTIFY_CODE_HANDLER(CDN_INITDONE, _OnInitDone) - NOTIFY_CODE_HANDLER(CDN_SELCHANGE, _OnSelChange) - NOTIFY_CODE_HANDLER(CDN_SHAREVIOLATION, _OnShareViolation) - NOTIFY_CODE_HANDLER(CDN_TYPECHANGE, _OnTypeChange) -#ifndef _WIN32_WCE - NOTIFY_CODE_HANDLER(CDN_INCLUDEITEM, _OnIncludeItem) -#endif // !_WIN32_WCE - END_MSG_MAP() - - LRESULT _OnFileOK(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) - { - ATLASSERT(::IsWindow(m_hWnd)); - T* pT = static_cast(this); - return !pT->OnFileOK((LPOFNOTIFY)pnmh); - } - - LRESULT _OnFolderChange(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) - { - ATLASSERT(::IsWindow(m_hWnd)); - T* pT = static_cast(this); - pT->OnFolderChange((LPOFNOTIFY)pnmh); - return 0; - } - - LRESULT _OnHelp(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) - { - ATLASSERT(::IsWindow(m_hWnd)); - T* pT = static_cast(this); - pT->OnHelp((LPOFNOTIFY)pnmh); - return 0; - } - - LRESULT _OnInitDone(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) - { - ATLASSERT(::IsWindow(m_hWnd)); - T* pT = static_cast(this); - pT->OnInitDone((LPOFNOTIFY)pnmh); - return 0; - } - - LRESULT _OnSelChange(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) - { - ATLASSERT(::IsWindow(m_hWnd)); - T* pT = static_cast(this); - pT->OnSelChange((LPOFNOTIFY)pnmh); - return 0; - } - - LRESULT _OnShareViolation(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) - { - ATLASSERT(::IsWindow(m_hWnd)); - T* pT = static_cast(this); - return pT->OnShareViolation((LPOFNOTIFY)pnmh); - } - - LRESULT _OnTypeChange(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) - { - ATLASSERT(::IsWindow(m_hWnd)); - T* pT = static_cast(this); - pT->OnTypeChange((LPOFNOTIFY)pnmh); - return 0; - } - -#ifndef _WIN32_WCE - LRESULT _OnIncludeItem(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) - { - ATLASSERT(::IsWindow(m_hWnd)); - T* pT = static_cast(this); - return pT->OnIncludeItem((LPOFNOTIFYEX)pnmh); - } -#endif // !_WIN32_WCE - -// Overrideables - BOOL OnFileOK(LPOFNOTIFY /*lpon*/) - { - return TRUE; - } - - void OnFolderChange(LPOFNOTIFY /*lpon*/) - { - } - - void OnHelp(LPOFNOTIFY /*lpon*/) - { - } - - void OnInitDone(LPOFNOTIFY /*lpon*/) - { - } - - void OnSelChange(LPOFNOTIFY /*lpon*/) - { - } - - int OnShareViolation(LPOFNOTIFY /*lpon*/) - { - return 0; - } - - void OnTypeChange(LPOFNOTIFY /*lpon*/) - { - } - -#ifndef _WIN32_WCE - BOOL OnIncludeItem(LPOFNOTIFYEX /*lponex*/) - { - return TRUE; // include item - } -#endif // !_WIN32_WCE -}; - -class CFileDialog : public CFileDialogImpl -{ -public: - CFileDialog(BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs - LPCTSTR lpszDefExt = NULL, - LPCTSTR lpszFileName = NULL, - DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, - LPCTSTR lpszFilter = NULL, - HWND hWndParent = NULL) - : CFileDialogImpl(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, hWndParent) - { } - - // override base class map and references to handlers - DECLARE_EMPTY_MSG_MAP() -}; - -#if defined(__AYGSHELL_H__) && (_WIN32_WCE >= 0x0501) -class CFileDialogEx : public CFileDialogImpl -{ -public: - CFileDialogEx( // Supports only FileOpen - LPCTSTR lpszDefExt = NULL, - LPCTSTR lpszFileName = NULL, - DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, - OFN_EXFLAG ExFlags = OFN_EXFLAG_THUMBNAILVIEW, - OFN_SORTORDER dwSortOrder = OFN_SORTORDER_AUTO, - LPCTSTR lpszFilter = NULL, - HWND hWndParent = NULL) - : CFileDialogImpl(TRUE, lpszDefExt, lpszFileName, dwFlags, lpszFilter, hWndParent) - { - m_ofn.ExFlags = ExFlags; - m_ofn.dwSortOrder = dwSortOrder; - } - - // override base class map and references to handlers - DECLARE_EMPTY_MSG_MAP() -}; -#endif // defined(__AYGSHELL_H__) && (_WIN32_WCE >= 0x0501) - - -/////////////////////////////////////////////////////////////////////////////// -// Multi File Dialog - Multi-select File Open dialog - -#ifndef _WIN32_WCE - -// The class dynamically resizes the buffer as the file selection changes -// (as described in Knowledge Base article 131462). It also expands selected -// shortcut files to take into account the full path of the target file. -// Note that this doesn't work on Win9x for the old style dialogs, as well as -// on NT for non-Unicode builds. - -#ifndef _WTL_FIXED_OFN_BUFFER_LENGTH - #define _WTL_FIXED_OFN_BUFFER_LENGTH 0x10000 -#endif - -template -class ATL_NO_VTABLE CMultiFileDialogImpl : public CFileDialogImpl< T > -{ -public: - mutable LPCTSTR m_pNextFile; -#ifndef _UNICODE - bool m_bIsNT; -#endif - - CMultiFileDialogImpl( - LPCTSTR lpszDefExt = NULL, - LPCTSTR lpszFileName = NULL, - DWORD dwFlags = OFN_HIDEREADONLY, - LPCTSTR lpszFilter = NULL, - HWND hWndParent = NULL) - : CFileDialogImpl(TRUE, lpszDefExt, lpszFileName, dwFlags, lpszFilter, hWndParent), - m_pNextFile(NULL) - { - m_ofn.Flags |= OFN_ALLOWMULTISELECT; // Force multiple selection mode - -#ifndef _UNICODE - OSVERSIONINFO ovi = { sizeof(ovi) }; - ::GetVersionEx(&ovi); - m_bIsNT = (ovi.dwPlatformId == VER_PLATFORM_WIN32_NT); - if (m_bIsNT) - { - // On NT platforms, GetOpenFileNameA thunks to GetOpenFileNameW and there - // is absolutely nothing we can do except to start off with a large buffer. - ATLVERIFY(ResizeFilenameBuffer(_WTL_FIXED_OFN_BUFFER_LENGTH)); - } -#endif - } - - ~CMultiFileDialogImpl() - { - if (m_ofn.lpstrFile != m_szFileName) // Free the buffer if we allocated it - delete[] m_ofn.lpstrFile; - } - -// Operations - // Get the directory that the files were chosen from. - // The function returns the number of characters copied, not including the terminating zero. - // If the buffer is NULL, the function returns the required size, in characters, including the terminating zero. - // If the function fails, the return value is zero. - int GetDirectory(LPTSTR pBuffer, int nBufLen) const - { - if (m_ofn.lpstrFile == NULL) - return 0; - - LPCTSTR pStr = m_ofn.lpstrFile; - int nLength = lstrlen(pStr); - if (pStr[nLength + 1] == 0) - { - // The OFN buffer contains a single item so extract its path. - LPCTSTR pSep = _strrchr(pStr, _T('\\')); - if (pSep != NULL) - nLength = (int)(DWORD_PTR)(pSep - pStr); - } - - int nRet = 0; - if (pBuffer == NULL) // If the buffer is NULL, return the required length - { - nRet = nLength + 1; - } - else if (nBufLen > nLength) - { - SecureHelper::strncpy_x(pBuffer, nBufLen, pStr, nLength); - nRet = nLength; - } - - return nRet; - } - -#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - bool GetDirectory(_CSTRING_NS::CString& strDir) const - { - bool bRet = false; - - int nLength = GetDirectory(NULL, 0); - if (nLength > 0) - { - bRet = (GetDirectory(strDir.GetBuffer(nLength), nLength) > 0); - strDir.ReleaseBuffer(nLength - 1); - } - - return bRet; - } -#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - - // Get the first filename as a pointer into the buffer. - LPCTSTR GetFirstFileName() const - { - if (m_ofn.lpstrFile == NULL) - return NULL; - - m_pNextFile = NULL; // Reset internal buffer pointer - - LPCTSTR pStr = m_ofn.lpstrFile; - int nLength = lstrlen(pStr); - if (pStr[nLength + 1] != 0) - { - // Multiple items were selected. The first string is the directory, - // so skip forwards to the second string. - pStr += nLength + 1; - - // Set up m_pNext so it points to the second item (or null). - m_pNextFile = pStr; - GetNextFileName(); - } - else - { - // A single item was selected. Skip forward past the path. - LPCTSTR pSep = _strrchr(pStr, _T('\\')); - if (pSep != NULL) - pStr = pSep + 1; - } - - return pStr; - } - - // Get the next filename as a pointer into the buffer. - LPCTSTR GetNextFileName() const - { - if (m_pNextFile == NULL) - return NULL; - - LPCTSTR pStr = m_pNextFile; - // Set "m_pNextFile" to point to the next file name, or null if we - // have reached the last file in the list. - int nLength = lstrlen(pStr); - m_pNextFile = (pStr[nLength + 1] != 0) ? &pStr[nLength + 1] : NULL; - - return pStr; - } - - // Get the first filename as a full path. - // The function returns the number of characters copied, not including the terminating zero. - // If the buffer is NULL, the function returns the required size, in characters, including the terminating zero. - // If the function fails, the return value is zero. - int GetFirstPathName(LPTSTR pBuffer, int nBufLen) const - { - LPCTSTR pStr = GetFirstFileName(); - int nLengthDir = GetDirectory(NULL, 0); - if((pStr == NULL) || (nLengthDir == 0)) - return 0; - - // Figure out the required length. - int nLengthTotal = nLengthDir + lstrlen(pStr); - - int nRet = 0; - if(pBuffer == NULL) // If the buffer is NULL, return the required length - { - nRet = nLengthTotal + 1; - } - else if (nBufLen > nLengthTotal) // If the buffer is big enough, go ahead and construct the path - { - GetDirectory(pBuffer, nBufLen); - SecureHelper::strcat_x(pBuffer, nBufLen, _T("\\")); - SecureHelper::strcat_x(pBuffer, nBufLen, pStr); - nRet = nLengthTotal; - } - - return nRet; - } - -#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - bool GetFirstPathName(_CSTRING_NS::CString& strPath) const - { - bool bRet = false; - - int nLength = GetFirstPathName(NULL, 0); - if (nLength > 0) - { - bRet = (GetFirstPathName(strPath.GetBuffer(nLength), nLength) > 0); - strPath.ReleaseBuffer(nLength - 1); - } - - return bRet; - } -#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - - // Get the next filename as a full path. - // The function returns the number of characters copied, not including the terminating zero. - // If the buffer is NULL, the function returns the required size, in characters, including the terminating zero. - // If the function fails, the return value is zero. - // The internal position marker is moved forward only if the function succeeds and the buffer was large enough. - int GetNextPathName(LPTSTR pBuffer, int nBufLen) const - { - if (m_pNextFile == NULL) - return 0; - - int nRet = 0; - LPCTSTR pStr = m_pNextFile; - // Does the filename contain a backslash? - if (_strrchr(pStr, _T('\\')) != NULL) - { - // Yes, so we'll assume it's a full path. - int nLength = lstrlen(pStr); - - if (pBuffer == NULL) // If the buffer is NULL, return the required length - { - nRet = nLength + 1; - } - else if (nBufLen > nLength) // The buffer is big enough, so go ahead and copy the filename - { - SecureHelper::strcpy_x(pBuffer, nBufLen, GetNextFileName()); - nRet = nBufLen; - } - } - else - { - // The filename is relative, so construct the full path. - int nLengthDir = GetDirectory(NULL, 0); - if (nLengthDir > 0) - { - // Calculate the required space. - int nLengthTotal = nLengthDir + lstrlen(pStr); - - if(pBuffer == NULL) // If the buffer is NULL, return the required length - { - nRet = nLengthTotal + 1; - } - else if (nBufLen > nLengthTotal) // If the buffer is big enough, go ahead and construct the path - { - GetDirectory(pBuffer, nBufLen); - SecureHelper::strcat_x(pBuffer, nBufLen, _T("\\")); - SecureHelper::strcat_x(pBuffer, nBufLen, GetNextFileName()); - nRet = nLengthTotal; - } - } - } - - return nRet; - } - -#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - bool GetNextPathName(_CSTRING_NS::CString& strPath) const - { - bool bRet = false; - - int nLength = GetNextPathName(NULL, 0); - if (nLength > 0) - { - bRet = (GetNextPathName(strPath.GetBuffer(nLength), nLength) > 0); - strPath.ReleaseBuffer(nLength - 1); - } - - return bRet; - } -#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - -// Implementation - bool ResizeFilenameBuffer(DWORD dwLength) - { - if (dwLength > m_ofn.nMaxFile) - { - // Free the old buffer. - if (m_ofn.lpstrFile != m_szFileName) - { - delete[] m_ofn.lpstrFile; - m_ofn.lpstrFile = NULL; - m_ofn.nMaxFile = 0; - } - - // Allocate the new buffer. - LPTSTR lpstrBuff = NULL; - ATLTRY(lpstrBuff = new TCHAR[dwLength]); - if (lpstrBuff != NULL) - { - m_ofn.lpstrFile = lpstrBuff; - m_ofn.lpstrFile[0] = 0; - m_ofn.nMaxFile = dwLength; - } - } - - return (m_ofn.lpstrFile != NULL); - } - - void OnSelChange(LPOFNOTIFY /*lpon*/) - { -#ifndef _UNICODE - // There is no point resizing the buffer in ANSI builds running on NT. - if (m_bIsNT) - return; -#endif - - // Get the buffer length required to hold the spec. - int nLength = GetSpec(NULL, 0); - if (nLength <= 1) - return; // no files are selected, presumably - - // Add room for the directory, and an extra terminating zero. - nLength += GetFolderPath(NULL, 0) + 1; - - if (!ResizeFilenameBuffer(nLength)) - { - ATLASSERT(FALSE); - return; - } - - // If we are not following links then our work is done. - if ((m_ofn.Flags & OFN_NODEREFERENCELINKS) != 0) - return; - - // Get the file spec, which is the text in the edit control. - if (GetSpec(m_ofn.lpstrFile, m_ofn.nMaxFile) <= 0) - return; - - // Get the ID-list of the current folder. - int nBytes = GetFolderIDList(NULL, 0); - CTempBuffer idlist; - idlist.AllocateBytes(nBytes); - if ((nBytes <= 0) || (GetFolderIDList(idlist, nBytes) <= 0)) - return; - - // First bind to the desktop folder, then to the current folder. - ATL::CComPtr pDesktop, pFolder; - if (FAILED(::SHGetDesktopFolder(&pDesktop))) - return; - if (FAILED(pDesktop->BindToObject(idlist, NULL, IID_IShellFolder, (void**)&pFolder))) - return; - - // Work through the file spec, looking for quoted filenames. If we find a shortcut file, then - // we need to add enough extra buffer space to hold its target path. - DWORD nExtraChars = 0; - bool bInsideQuotes = false; - LPCTSTR pAnchor = m_ofn.lpstrFile; - LPCTSTR pChar = m_ofn.lpstrFile; - for ( ; *pChar; ++pChar) - { - // Look for quotation marks. - if (*pChar == _T('\"')) - { - // We are either entering or leaving a passage of quoted text. - bInsideQuotes = !bInsideQuotes; - - // Is it an opening or closing quote? - if (bInsideQuotes) - { - // We found an opening quote, so set "pAnchor" to the following character. - pAnchor = pChar + 1; - } - else // closing quote - { - // Each quoted entity should be shorter than MAX_PATH. - if (pChar - pAnchor >= MAX_PATH) - return; - - // Get the ID-list and attributes of the file. - USES_CONVERSION; - int nFileNameLength = (int)(DWORD_PTR)(pChar - pAnchor); - TCHAR szFileName[MAX_PATH]; - SecureHelper::strncpy_x(szFileName, MAX_PATH, pAnchor, nFileNameLength); - LPITEMIDLIST pidl = NULL; - DWORD dwAttrib = SFGAO_LINK; - if (SUCCEEDED(pFolder->ParseDisplayName(NULL, NULL, T2W(szFileName), NULL, &pidl, &dwAttrib))) - { - // Is it a shortcut file? - if (dwAttrib & SFGAO_LINK) - { - // Bind to its IShellLink interface. - ATL::CComPtr pLink; - if (SUCCEEDED(pFolder->BindToObject(pidl, NULL, IID_IShellLink, (void**)&pLink))) - { - // Get the shortcut's target path. - TCHAR szPath[MAX_PATH]; - if (SUCCEEDED(pLink->GetPath(szPath, MAX_PATH, NULL, 0))) - { - // If the target path is longer than the shortcut name, then add on the number - // of extra characters that are required. - int nNewLength = lstrlen(szPath); - if (nNewLength > nFileNameLength) - nExtraChars += nNewLength - nFileNameLength; - } - } - } - - // Free the ID-list returned by ParseDisplayName. - ::CoTaskMemFree(pidl); - } - } - } - } - - // If we need more space for shortcut targets, then reallocate. - if (nExtraChars > 0) - ATLVERIFY(ResizeFilenameBuffer(m_ofn.nMaxFile + nExtraChars)); - } - - // Helper for _ATM_MIN_CRT - static const TCHAR* _strrchr(const TCHAR* p, TCHAR ch) - { -#ifndef _ATL_MIN_CRT - return _tcsrchr(p, ch); -#else // _ATL_MIN_CRT - const TCHAR* lpsz = NULL; - while (*p != 0) - { - if (*p == ch) - lpsz = p; - p = ::CharNext(p); - } - return lpsz; -#endif // _ATL_MIN_CRT - } -}; - -class CMultiFileDialog : public CMultiFileDialogImpl -{ -public: - CMultiFileDialog( - LPCTSTR lpszDefExt = NULL, - LPCTSTR lpszFileName = NULL, - DWORD dwFlags = OFN_HIDEREADONLY, - LPCTSTR lpszFilter = NULL, - HWND hWndParent = NULL) - : CMultiFileDialogImpl(lpszDefExt, lpszFileName, dwFlags, lpszFilter, hWndParent) - { } - - BEGIN_MSG_MAP(CMultiFileDialog) - CHAIN_MSG_MAP(CMultiFileDialogImpl) - END_MSG_MAP() -}; - -#endif // !_WIN32_WCE - - -/////////////////////////////////////////////////////////////////////////////// -// Shell File Dialog - new Shell File Open and Save dialogs in Vista - -// Note: Use GetPtr() to access dialog interface methods. -// Example: -// CShellFileOpenDialog dlg; -// dlg.GetPtr()->SetTitle(L"MyFileOpenDialog"); - -#if (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE) - -/////////////////////////////////////////////////////////////////////////////// -// CShellFileDialogImpl - base class for CShellFileOpenDialogImpl and CShellFileSaveDialogImpl - -template -class ATL_NO_VTABLE CShellFileDialogImpl : public IFileDialogEvents -{ -public: -// Operations - INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow()) - { - INT_PTR nRet = -1; - - T* pT = static_cast(this); - if(pT->m_spFileDlg == NULL) - { - ATLASSERT(FALSE); - return nRet; - } - - DWORD dwCookie = 0; - pT->_Advise(dwCookie); - - HRESULT hRet = pT->m_spFileDlg->Show(hWndParent); - if(SUCCEEDED(hRet)) - nRet = IDOK; - else if(hRet == HRESULT_FROM_WIN32(ERROR_CANCELLED)) - nRet = IDCANCEL; - else - ATLASSERT(FALSE); // error - - pT->_Unadvise(dwCookie); - - return nRet; - } - - bool IsNull() const - { - const T* pT = static_cast(this); - return (pT->m_spFileDlg == NULL); - } - -// Operations - get file path after dialog returns - HRESULT GetFilePath(LPWSTR lpstrFilePath, int cchLength) - { - T* pT = static_cast(this); - ATLASSERT(pT->m_spFileDlg != NULL); - - ATL::CComPtr spItem; - HRESULT hRet = pT->m_spFileDlg->GetResult(&spItem); - - if(SUCCEEDED(hRet)) - hRet = GetFileNameFromShellItem(spItem, SIGDN_FILESYSPATH, lpstrFilePath, cchLength); - - return hRet; - } - - HRESULT GetFileTitle(LPWSTR lpstrFileTitle, int cchLength) - { - T* pT = static_cast(this); - ATLASSERT(pT->m_spFileDlg != NULL); - - ATL::CComPtr spItem; - HRESULT hRet = pT->m_spFileDlg->GetResult(&spItem); - - if(SUCCEEDED(hRet)) - hRet = GetFileNameFromShellItem(spItem, SIGDN_NORMALDISPLAY, lpstrFileTitle, cchLength); - - return hRet; - } - -#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - HRESULT GetFilePath(_CSTRING_NS::CString& strFilePath) - { - T* pT = static_cast(this); - ATLASSERT(pT->m_spFileDlg != NULL); - - ATL::CComPtr spItem; - HRESULT hRet = pT->m_spFileDlg->GetResult(&spItem); - - if(SUCCEEDED(hRet)) - hRet = GetFileNameFromShellItem(spItem, SIGDN_FILESYSPATH, strFilePath); - - return hRet; - } - - HRESULT GetFileTitle(_CSTRING_NS::CString& strFileTitle) - { - T* pT = static_cast(this); - ATLASSERT(pT->m_spFileDlg != NULL); - - ATL::CComPtr spItem; - HRESULT hRet = pT->m_spFileDlg->GetResult(&spItem); - - if(SUCCEEDED(hRet)) - hRet = GetFileNameFromShellItem(spItem, SIGDN_NORMALDISPLAY, strFileTitle); - - return hRet; - } -#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - -// Helpers for IShellItem - static HRESULT GetFileNameFromShellItem(IShellItem* pShellItem, SIGDN type, LPWSTR lpstr, int cchLength) - { - ATLASSERT(pShellItem != NULL); - - LPWSTR lpstrName = NULL; - HRESULT hRet = pShellItem->GetDisplayName(type, &lpstrName); - - if(SUCCEEDED(hRet)) - { - if(lstrlenW(lpstrName) < cchLength) - { - SecureHelper::strcpyW_x(lpstr, cchLength, lpstrName); - } - else - { - ATLASSERT(FALSE); - hRet = DISP_E_BUFFERTOOSMALL; - } - - ::CoTaskMemFree(lpstrName); - } - - return hRet; - } - -#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - static HRESULT GetFileNameFromShellItem(IShellItem* pShellItem, SIGDN type, _CSTRING_NS::CString& str) - { - ATLASSERT(pShellItem != NULL); - - LPWSTR lpstrName = NULL; - HRESULT hRet = pShellItem->GetDisplayName(type, &lpstrName); - - if(SUCCEEDED(hRet)) - { - str = lpstrName; - ::CoTaskMemFree(lpstrName); - } - - return hRet; - } -#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - -// Implementation - void _Advise(DWORD& dwCookie) - { - T* pT = static_cast(this); - ATLASSERT(pT->m_spFileDlg != NULL); - HRESULT hRet = pT->m_spFileDlg->Advise((IFileDialogEvents*)this, &dwCookie); - ATLVERIFY(SUCCEEDED(hRet)); - } - - void _Unadvise(DWORD dwCookie) - { - T* pT = static_cast(this); - ATLASSERT(pT->m_spFileDlg != NULL); - HRESULT hRet = pT->m_spFileDlg->Unadvise(dwCookie); - ATLVERIFY(SUCCEEDED(hRet)); - } - - void _Init(LPCWSTR lpszFileName, DWORD dwOptions, LPCWSTR lpszDefExt, const COMDLG_FILTERSPEC* arrFilterSpec, UINT uFilterSpecCount) - { - T* pT = static_cast(this); - ATLASSERT(pT->m_spFileDlg != NULL); - - HRESULT hRet = E_FAIL; - - if(lpszFileName != NULL) - { - hRet = pT->m_spFileDlg->SetFileName(lpszFileName); - ATLASSERT(SUCCEEDED(hRet)); - } - - hRet = pT->m_spFileDlg->SetOptions(dwOptions); - ATLASSERT(SUCCEEDED(hRet)); - - if(lpszDefExt != NULL) - { - hRet = pT->m_spFileDlg->SetDefaultExtension(lpszDefExt); - ATLASSERT(SUCCEEDED(hRet)); - } - - if(arrFilterSpec != NULL && uFilterSpecCount != 0U) - { - hRet = pT->m_spFileDlg->SetFileTypes(uFilterSpecCount, arrFilterSpec); - ATLASSERT(SUCCEEDED(hRet)); - } - } - -// Implementation - IUnknown interface - STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject) - { - if(ppvObject == NULL) - return E_POINTER; - - T* pT = static_cast(this); - if(IsEqualGUID(riid, IID_IUnknown) || IsEqualGUID(riid, IID_IFileDialogEvents)) - { - *ppvObject = (IFileDialogEvents*)pT; - // AddRef() not needed - return S_OK; - } - - return E_NOINTERFACE; - } - - virtual ULONG STDMETHODCALLTYPE AddRef() - { - return 1; - } - - virtual ULONG STDMETHODCALLTYPE Release() - { - return 1; - } - -// Implementation - IFileDialogEvents interface - virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnFileOk(IFileDialog* pfd) - { - T* pT = static_cast(this); - ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd)); - pfd; // avoid level 4 warning - return pT->OnFileOk(); - } - - virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnFolderChanging(IFileDialog* pfd, IShellItem* psiFolder) - { - T* pT = static_cast(this); - ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd)); - pfd; // avoid level 4 warning - return pT->OnFolderChanging(psiFolder); - } - - virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnFolderChange(IFileDialog* pfd) - { - T* pT = static_cast(this); - ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd)); - pfd; // avoid level 4 warning - return pT->OnFolderChange(); - } - - virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnSelectionChange(IFileDialog* pfd) - { - T* pT = static_cast(this); - ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd)); - pfd; // avoid level 4 warning - return pT->OnSelectionChange(); - } - - virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnShareViolation(IFileDialog* pfd, IShellItem* psi, FDE_SHAREVIOLATION_RESPONSE* pResponse) - { - T* pT = static_cast(this); - ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd)); - pfd; // avoid level 4 warning - return pT->OnShareViolation(psi, pResponse); - } - - virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnTypeChange(IFileDialog* pfd) - { - T* pT = static_cast(this); - ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd)); - pfd; // avoid level 4 warning - return pT->OnTypeChange(); - } - - virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnOverwrite(IFileDialog* pfd, IShellItem* psi, FDE_OVERWRITE_RESPONSE* pResponse) - { - T* pT = static_cast(this); - ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd)); - pfd; // avoid level 4 warning - return pT->OnOverwrite(psi, pResponse); - } - -// Overrideables - Event handlers - HRESULT OnFileOk() - { - return E_NOTIMPL; - } - - HRESULT OnFolderChanging(IShellItem* /*psiFolder*/) - { - return E_NOTIMPL; - } - - HRESULT OnFolderChange() - { - return E_NOTIMPL; - } - - HRESULT OnSelectionChange() - { - return E_NOTIMPL; - } - - HRESULT OnShareViolation(IShellItem* /*psi*/, FDE_SHAREVIOLATION_RESPONSE* /*pResponse*/) - { - return E_NOTIMPL; - } - - HRESULT OnTypeChange() - { - return E_NOTIMPL; - } - - HRESULT OnOverwrite(IShellItem* /*psi*/, FDE_OVERWRITE_RESPONSE* /*pResponse*/) - { - return E_NOTIMPL; - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CShellFileOpenDialogImpl - implements new Shell File Open dialog - -template -class ATL_NO_VTABLE CShellFileOpenDialogImpl : public CShellFileDialogImpl< T > -{ -public: - ATL::CComPtr m_spFileDlg; - - CShellFileOpenDialogImpl(LPCWSTR lpszFileName = NULL, - DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST, - LPCWSTR lpszDefExt = NULL, - const COMDLG_FILTERSPEC* arrFilterSpec = NULL, - UINT uFilterSpecCount = 0U) - { - HRESULT hRet = m_spFileDlg.CoCreateInstance(CLSID_FileOpenDialog); - - if(SUCCEEDED(hRet)) - _Init(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount); - } - - IFileOpenDialog* GetPtr() - { - return m_spFileDlg; - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CShellFileOpenDialog - new Shell File Open dialog without events - -class CShellFileOpenDialog : public CShellFileOpenDialogImpl -{ -public: - CShellFileOpenDialog(LPCWSTR lpszFileName = NULL, - DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST, - LPCWSTR lpszDefExt = NULL, - const COMDLG_FILTERSPEC* arrFilterSpec = NULL, - UINT uFilterSpecCount = 0U) : CShellFileOpenDialogImpl(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount) - { } - -// Implementation (remove _Advise/_Unadvise code using template magic) - void _Advise(DWORD& /*dwCookie*/) - { } - - void _Unadvise(DWORD /*dwCookie*/) - { } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CShellFileSaveDialogImpl - implements new Shell File Save dialog - -template -class ATL_NO_VTABLE CShellFileSaveDialogImpl : public CShellFileDialogImpl< T > -{ -public: - ATL::CComPtr m_spFileDlg; - - CShellFileSaveDialogImpl(LPCWSTR lpszFileName = NULL, - DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_OVERWRITEPROMPT, - LPCWSTR lpszDefExt = NULL, - const COMDLG_FILTERSPEC* arrFilterSpec = NULL, - UINT uFilterSpecCount = 0U) - { - HRESULT hRet = m_spFileDlg.CoCreateInstance(CLSID_FileSaveDialog); - - if(SUCCEEDED(hRet)) - _Init(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount); - } - - IFileSaveDialog* GetPtr() - { - return m_spFileDlg; - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CShellFileSaveDialog - new Shell File Save dialog without events - -class CShellFileSaveDialog : public CShellFileSaveDialogImpl -{ -public: - CShellFileSaveDialog(LPCWSTR lpszFileName = NULL, - DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_OVERWRITEPROMPT, - LPCWSTR lpszDefExt = NULL, - const COMDLG_FILTERSPEC* arrFilterSpec = NULL, - UINT uFilterSpecCount = 0U) : CShellFileSaveDialogImpl(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount) - { } - -// Implementation (remove _Advise/_Unadvise code using template magic) - void _Advise(DWORD& /*dwCookie*/) - { } - - void _Unadvise(DWORD /*dwCookie*/) - { } -}; - -#endif // (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE) - - -/////////////////////////////////////////////////////////////////////////////// -// CFolderDialogImpl - used for browsing for a folder - -#ifndef _WIN32_WCE - -template -class ATL_NO_VTABLE CFolderDialogImpl -{ -public: - BROWSEINFO m_bi; - LPCTSTR m_lpstrInitialFolder; - LPCITEMIDLIST m_pidlInitialSelection; - bool m_bExpandInitialSelection; - TCHAR m_szFolderDisplayName[MAX_PATH]; - TCHAR m_szFolderPath[MAX_PATH]; - LPITEMIDLIST m_pidlSelected; - HWND m_hWnd; // used only in the callback function - -// Constructor - CFolderDialogImpl(HWND hWndParent = NULL, LPCTSTR lpstrTitle = NULL, UINT uFlags = BIF_RETURNONLYFSDIRS) : - m_lpstrInitialFolder(NULL), m_pidlInitialSelection(NULL), m_bExpandInitialSelection(false), m_pidlSelected(NULL), m_hWnd(NULL) - { - memset(&m_bi, 0, sizeof(m_bi)); // initialize structure to 0/NULL - - m_bi.hwndOwner = hWndParent; - m_bi.pidlRoot = NULL; - m_bi.pszDisplayName = m_szFolderDisplayName; - m_bi.lpszTitle = lpstrTitle; - m_bi.ulFlags = uFlags; - m_bi.lpfn = BrowseCallbackProc; - m_bi.lParam = (LPARAM)static_cast(this); - - m_szFolderPath[0] = 0; - m_szFolderDisplayName[0] = 0; - } - - ~CFolderDialogImpl() - { - ::CoTaskMemFree(m_pidlSelected); - } - -// Operations - INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow()) - { - if(m_bi.hwndOwner == NULL) // set only if not specified before - m_bi.hwndOwner = hWndParent; - - // Clear out any previous results - m_szFolderPath[0] = 0; - m_szFolderDisplayName[0] = 0; - ::CoTaskMemFree(m_pidlSelected); - - INT_PTR nRet = IDCANCEL; - m_pidlSelected = ::SHBrowseForFolder(&m_bi); - - if(m_pidlSelected != NULL) - { - nRet = IDOK; - - // If BIF_RETURNONLYFSDIRS is set, we try to get the filesystem path. - // Otherwise, the caller must handle the ID-list directly. - if((m_bi.ulFlags & BIF_RETURNONLYFSDIRS) != 0) - { - if(::SHGetPathFromIDList(m_pidlSelected, m_szFolderPath) == FALSE) - nRet = IDCANCEL; - } - } - - return nRet; - } - - // Methods to call before DoModal - void SetInitialFolder(LPCTSTR lpstrInitialFolder, bool bExpand = true) - { - // lpstrInitialFolder may be a file if BIF_BROWSEINCLUDEFILES is specified - m_lpstrInitialFolder = lpstrInitialFolder; - m_bExpandInitialSelection = bExpand; - } - - void SetInitialSelection(LPCITEMIDLIST pidl, bool bExpand = true) - { - m_pidlInitialSelection = pidl; - m_bExpandInitialSelection = bExpand; - } - - // Methods to call after DoModal - LPITEMIDLIST GetSelectedItem(bool bDetach = false) - { - LPITEMIDLIST pidl = m_pidlSelected; - if(bDetach) - m_pidlSelected = NULL; - - return pidl; - } - - LPCTSTR GetFolderPath() const - { - return m_szFolderPath; - } - - LPCTSTR GetFolderDisplayName() const - { - return m_szFolderDisplayName; - } - - int GetFolderImageIndex() const - { - return m_bi.iImage; - } - -// Callback function and overrideables - static int CALLBACK BrowseCallbackProc(HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData) - { -#ifndef BFFM_VALIDATEFAILED - #ifdef UNICODE - const int BFFM_VALIDATEFAILED = 4; - #else - const int BFFM_VALIDATEFAILED = 3; - #endif -#endif // !BFFM_VALIDATEFAILED -#ifndef BFFM_IUNKNOWN - const int BFFM_IUNKNOWN = 5; -#endif // !BFFM_IUNKNOWN -#ifndef BIF_NEWDIALOGSTYLE - const UINT BIF_NEWDIALOGSTYLE = 0x0040; -#endif // !BIF_NEWDIALOGSTYLE - - int nRet = 0; - T* pT = (T*)lpData; - bool bClear = false; - if(pT->m_hWnd == NULL) - { - pT->m_hWnd = hWnd; - bClear = true; - } - else - { - ATLASSERT(pT->m_hWnd == hWnd); - } - - switch(uMsg) - { - case BFFM_INITIALIZED: - // Set initial selection - // Note that m_pidlInitialSelection, if set, takes precedence over m_lpstrInitialFolder - if(pT->m_pidlInitialSelection != NULL) - pT->SetSelection(pT->m_pidlInitialSelection); - else if(pT->m_lpstrInitialFolder != NULL) - pT->SetSelection(pT->m_lpstrInitialFolder); - - // Expand initial selection if appropriate - if(pT->m_bExpandInitialSelection && ((pT->m_bi.ulFlags & BIF_NEWDIALOGSTYLE) != 0)) - { - if(pT->m_pidlInitialSelection != NULL) - pT->SetExpanded(pT->m_pidlInitialSelection); - else if(pT->m_lpstrInitialFolder != NULL) - pT->SetExpanded(pT->m_lpstrInitialFolder); - } - pT->OnInitialized(); - break; - case BFFM_SELCHANGED: - pT->OnSelChanged((LPITEMIDLIST)lParam); - break; - case BFFM_VALIDATEFAILED: - nRet = pT->OnValidateFailed((LPCTSTR)lParam); - break; - case BFFM_IUNKNOWN: - pT->OnIUnknown((IUnknown*)lParam); - break; - default: - ATLTRACE2(atlTraceUI, 0, _T("Unknown message received in CFolderDialogImpl::BrowseCallbackProc\n")); - break; - } - - if(bClear) - pT->m_hWnd = NULL; - return nRet; - } - - void OnInitialized() - { - } - - void OnSelChanged(LPITEMIDLIST /*pItemIDList*/) - { - } - - int OnValidateFailed(LPCTSTR /*lpstrFolderPath*/) - { - return 1; // 1=continue, 0=EndDialog - } - - void OnIUnknown(IUnknown* /*pUnknown*/) - { - } - - // Commands - valid to call only from handlers - void EnableOK(BOOL bEnable) - { - ATLASSERT(m_hWnd != NULL); - ::SendMessage(m_hWnd, BFFM_ENABLEOK, 0, bEnable); - } - - void SetSelection(LPCITEMIDLIST pItemIDList) - { - ATLASSERT(m_hWnd != NULL); - ::SendMessage(m_hWnd, BFFM_SETSELECTION, FALSE, (LPARAM)pItemIDList); - } - - void SetSelection(LPCTSTR lpstrFolderPath) - { - ATLASSERT(m_hWnd != NULL); - ::SendMessage(m_hWnd, BFFM_SETSELECTION, TRUE, (LPARAM)lpstrFolderPath); - } - - void SetStatusText(LPCTSTR lpstrText) - { - ATLASSERT(m_hWnd != NULL); - ::SendMessage(m_hWnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)lpstrText); - } - - void SetOKText(LPCTSTR lpstrOKText) - { -#ifndef BFFM_SETOKTEXT - const UINT BFFM_SETOKTEXT = WM_USER + 105; -#endif - ATLASSERT(m_hWnd != NULL); - USES_CONVERSION; - LPCWSTR lpstr = T2CW(lpstrOKText); - ::SendMessage(m_hWnd, BFFM_SETOKTEXT, (WPARAM)lpstr, 0L); - } - - void SetExpanded(LPCITEMIDLIST pItemIDList) - { -#ifndef BFFM_SETEXPANDED - const UINT BFFM_SETEXPANDED = WM_USER + 106; -#endif - ATLASSERT(m_hWnd != NULL); - ::SendMessage(m_hWnd, BFFM_SETEXPANDED, FALSE, (LPARAM)pItemIDList); - } - - void SetExpanded(LPCTSTR lpstrFolderPath) - { -#ifndef BFFM_SETEXPANDED - const UINT BFFM_SETEXPANDED = WM_USER + 106; -#endif - ATLASSERT(m_hWnd != NULL); - USES_CONVERSION; - LPCWSTR lpstr = T2CW(lpstrFolderPath); - ::SendMessage(m_hWnd, BFFM_SETEXPANDED, TRUE, (LPARAM)lpstr); - } -}; - -class CFolderDialog : public CFolderDialogImpl -{ -public: - CFolderDialog(HWND hWndParent = NULL, LPCTSTR lpstrTitle = NULL, UINT uFlags = BIF_RETURNONLYFSDIRS) - : CFolderDialogImpl(hWndParent, lpstrTitle, uFlags) - { } -}; - -#endif // !_WIN32_WCE - - -/////////////////////////////////////////////////////////////////////////////// -// CCommonDialogImplBase - base class for common dialog classes - -class ATL_NO_VTABLE CCommonDialogImplBase : public ATL::CWindowImplBase -{ -public: - static UINT_PTR APIENTRY HookProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) - { - if(uMsg != WM_INITDIALOG) - return 0; - CCommonDialogImplBase* pT = (CCommonDialogImplBase*)ModuleHelper::ExtractCreateWndData(); - ATLASSERT(pT != NULL); - ATLASSERT(pT->m_hWnd == NULL); - ATLASSERT(::IsWindow(hWnd)); - // subclass dialog's window - if(!pT->SubclassWindow(hWnd)) - { - ATLTRACE2(atlTraceUI, 0, _T("Subclassing a common dialog failed\n")); - return 0; - } - // check message map for WM_INITDIALOG handler - LRESULT lRes = 0; - if(pT->ProcessWindowMessage(pT->m_hWnd, uMsg, wParam, lParam, lRes, 0) == FALSE) - return 0; - return lRes; - } - -// Special override for common dialogs - BOOL EndDialog(INT_PTR /*nRetCode*/ = 0) - { - ATLASSERT(::IsWindow(m_hWnd)); - SendMessage(WM_COMMAND, MAKEWPARAM(IDABORT, 0)); - return TRUE; - } - -// Implementation - try to override these, to prevent errors - HWND Create(HWND, ATL::_U_RECT, LPCTSTR, DWORD, DWORD, ATL::_U_MENUorID, ATOM, LPVOID) - { - ATLASSERT(FALSE); // should not be called - return NULL; - } - - static LRESULT CALLBACK StartWindowProc(HWND /*hWnd*/, UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/) - { - ATLASSERT(FALSE); // should not be called - return 0; - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CFontDialogImpl - font selection dialog - -#ifndef _WIN32_WCE - -template -class ATL_NO_VTABLE CFontDialogImpl : public CCommonDialogImplBase -{ -public: - enum { _cchStyleName = 64 }; - - CHOOSEFONT m_cf; - TCHAR m_szStyleName[_cchStyleName]; // contains style name after return - LOGFONT m_lf; // default LOGFONT to store the info - -// Constructors - CFontDialogImpl(LPLOGFONT lplfInitial = NULL, - DWORD dwFlags = CF_EFFECTS | CF_SCREENFONTS, - HDC hDCPrinter = NULL, - HWND hWndParent = NULL) - { - memset(&m_cf, 0, sizeof(m_cf)); - memset(&m_lf, 0, sizeof(m_lf)); - memset(&m_szStyleName, 0, sizeof(m_szStyleName)); - - m_cf.lStructSize = sizeof(m_cf); - m_cf.hwndOwner = hWndParent; - m_cf.rgbColors = RGB(0, 0, 0); - m_cf.lpszStyle = (LPTSTR)&m_szStyleName; - m_cf.Flags = dwFlags | CF_ENABLEHOOK; - m_cf.lpfnHook = (LPCFHOOKPROC)T::HookProc; - - if(lplfInitial != NULL) - { - m_cf.lpLogFont = lplfInitial; - m_cf.Flags |= CF_INITTOLOGFONTSTRUCT; - m_lf = *lplfInitial; - } - else - { - m_cf.lpLogFont = &m_lf; - } - - if(hDCPrinter != NULL) - { - m_cf.hDC = hDCPrinter; - m_cf.Flags |= CF_PRINTERFONTS; - } - } - -// Operations - INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow()) - { - ATLASSERT((m_cf.Flags & CF_ENABLEHOOK) != 0); - ATLASSERT(m_cf.lpfnHook != NULL); // can still be a user hook - - if(m_cf.hwndOwner == NULL) // set only if not specified before - m_cf.hwndOwner = hWndParent; - - ATLASSERT(m_hWnd == NULL); - ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this); - - BOOL bRet = ::ChooseFont(&m_cf); - - m_hWnd = NULL; - - if(bRet) // copy logical font from user's initialization buffer (if needed) - SecureHelper::memcpy_x(&m_lf, sizeof(m_lf), m_cf.lpLogFont, sizeof(m_lf)); - - return bRet ? IDOK : IDCANCEL; - } - - // works only when the dialog is dislayed or after - void GetCurrentFont(LPLOGFONT lplf) const - { - ATLASSERT(lplf != NULL); - - if(m_hWnd != NULL) - ::SendMessage(m_hWnd, WM_CHOOSEFONT_GETLOGFONT, 0, (LPARAM)lplf); - else - *lplf = m_lf; - } - - // works only when the dialog is dislayed or before -#ifndef _WIN32_WCE - void SetLogFont(LPLOGFONT lplf) - { - ATLASSERT(lplf != NULL); -#ifndef WM_CHOOSEFONT_SETLOGFONT - const UINT WM_CHOOSEFONT_SETLOGFONT = (WM_USER + 101); -#endif - if(m_hWnd != NULL) - { - ::SendMessage(m_hWnd, WM_CHOOSEFONT_SETLOGFONT, 0, (LPARAM)lplf); - } - else - { - m_lf = *lplf; - m_cf.Flags |= CF_INITTOLOGFONTSTRUCT; - } - } - - void SetFlags(DWORD dwFlags) - { -#ifndef WM_CHOOSEFONT_SETFLAGS - const UINT WM_CHOOSEFONT_SETFLAGS = (WM_USER + 102); -#endif - if(m_hWnd != NULL) - { - CHOOSEFONT cf = { sizeof(CHOOSEFONT) }; - cf.Flags = dwFlags; - ::SendMessage(m_hWnd, WM_CHOOSEFONT_SETFLAGS, 0, (LPARAM)&cf); - } - else - { - m_cf.Flags = dwFlags; - } - } -#endif // !_WIN32_WCE - - // Helpers for parsing information after successful return - LPCTSTR GetFaceName() const // return the face name of the font - { - return (LPCTSTR)m_cf.lpLogFont->lfFaceName; - } - - LPCTSTR GetStyleName() const // return the style name of the font - { - return m_cf.lpszStyle; - } - - int GetSize() const // return the pt size of the font - { - return m_cf.iPointSize; - } - - COLORREF GetColor() const // return the color of the font - { - return m_cf.rgbColors; - } - - int GetWeight() const // return the chosen font weight - { - return (int)m_cf.lpLogFont->lfWeight; - } - - BOOL IsStrikeOut() const // return TRUE if strikeout - { - return (m_cf.lpLogFont->lfStrikeOut) ? TRUE : FALSE; - } - - BOOL IsUnderline() const // return TRUE if underline - { - return (m_cf.lpLogFont->lfUnderline) ? TRUE : FALSE; - } - - BOOL IsBold() const // return TRUE if bold font - { - return (m_cf.lpLogFont->lfWeight == FW_BOLD) ? TRUE : FALSE; - } - - BOOL IsItalic() const // return TRUE if italic font - { - return m_cf.lpLogFont->lfItalic ? TRUE : FALSE; - } -}; - -class CFontDialog : public CFontDialogImpl -{ -public: - CFontDialog(LPLOGFONT lplfInitial = NULL, - DWORD dwFlags = CF_EFFECTS | CF_SCREENFONTS, - HDC hDCPrinter = NULL, - HWND hWndParent = NULL) - : CFontDialogImpl(lplfInitial, dwFlags, hDCPrinter, hWndParent) - { } - - DECLARE_EMPTY_MSG_MAP() -}; - -#endif // _WIN32_WCE - - -/////////////////////////////////////////////////////////////////////////////// -// CRichEditFontDialogImpl - font selection for the Rich Edit ctrl - -#if defined(_RICHEDIT_) && !defined(_WIN32_WCE) - -template -class ATL_NO_VTABLE CRichEditFontDialogImpl : public CFontDialogImpl< T > -{ -public: - CRichEditFontDialogImpl(const CHARFORMAT& charformat, - DWORD dwFlags = CF_SCREENFONTS, - HDC hDCPrinter = NULL, - HWND hWndParent = NULL) - : CFontDialogImpl< T >(NULL, dwFlags, hDCPrinter, hWndParent) - { - m_cf.Flags |= CF_INITTOLOGFONTSTRUCT; - m_cf.Flags |= FillInLogFont(charformat); - m_cf.lpLogFont = &m_lf; - - if((charformat.dwMask & CFM_COLOR) != 0) - m_cf.rgbColors = charformat.crTextColor; - } - - void GetCharFormat(CHARFORMAT& cf) const - { - USES_CONVERSION; - cf.dwEffects = 0; - cf.dwMask = 0; - if((m_cf.Flags & CF_NOSTYLESEL) == 0) - { - cf.dwMask |= CFM_BOLD | CFM_ITALIC; - cf.dwEffects |= IsBold() ? CFE_BOLD : 0; - cf.dwEffects |= IsItalic() ? CFE_ITALIC : 0; - } - if((m_cf.Flags & CF_NOSIZESEL) == 0) - { - cf.dwMask |= CFM_SIZE; - // GetSize() returns in tenths of points so mulitply by 2 to get twips - cf.yHeight = GetSize() * 2; - } - - if((m_cf.Flags & CF_NOFACESEL) == 0) - { - cf.dwMask |= CFM_FACE; - cf.bPitchAndFamily = m_cf.lpLogFont->lfPitchAndFamily; -#if (_RICHEDIT_VER >= 0x0200) - SecureHelper::strcpy_x(cf.szFaceName, _countof(cf.szFaceName), GetFaceName()); -#else // !(_RICHEDIT_VER >= 0x0200) - SecureHelper::strcpyA_x(cf.szFaceName, _countof(cf.szFaceName), T2A((LPTSTR)(LPCTSTR)GetFaceName())); -#endif // !(_RICHEDIT_VER >= 0x0200) - } - - if((m_cf.Flags & CF_EFFECTS) != 0) - { - cf.dwMask |= CFM_UNDERLINE | CFM_STRIKEOUT | CFM_COLOR; - cf.dwEffects |= IsUnderline() ? CFE_UNDERLINE : 0; - cf.dwEffects |= IsStrikeOut() ? CFE_STRIKEOUT : 0; - cf.crTextColor = GetColor(); - } - if((m_cf.Flags & CF_NOSCRIPTSEL) == 0) - { - cf.bCharSet = m_cf.lpLogFont->lfCharSet; - cf.dwMask |= CFM_CHARSET; - } - cf.yOffset = 0; - } - - DWORD FillInLogFont(const CHARFORMAT& cf) - { - USES_CONVERSION; - DWORD dwFlags = 0; - if((cf.dwMask & CFM_SIZE) != 0) - { - HDC hDC = ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL); - LONG yPerInch = ::GetDeviceCaps(hDC, LOGPIXELSY); - m_lf.lfHeight = -(int)((cf.yHeight * yPerInch) / 1440); - } - else - m_lf.lfHeight = 0; - - m_lf.lfWidth = 0; - m_lf.lfEscapement = 0; - m_lf.lfOrientation = 0; - - if((cf.dwMask & (CFM_ITALIC | CFM_BOLD)) == (CFM_ITALIC | CFM_BOLD)) - { - m_lf.lfWeight = ((cf.dwEffects & CFE_BOLD) != 0) ? FW_BOLD : FW_NORMAL; - m_lf.lfItalic = (BYTE)(((cf.dwEffects & CFE_ITALIC) != 0) ? TRUE : FALSE); - } - else - { - dwFlags |= CF_NOSTYLESEL; - m_lf.lfWeight = FW_DONTCARE; - m_lf.lfItalic = FALSE; - } - - if((cf.dwMask & (CFM_UNDERLINE | CFM_STRIKEOUT | CFM_COLOR)) == (CFM_UNDERLINE|CFM_STRIKEOUT|CFM_COLOR)) - { - dwFlags |= CF_EFFECTS; - m_lf.lfUnderline = (BYTE)(((cf.dwEffects & CFE_UNDERLINE) != 0) ? TRUE : FALSE); - m_lf.lfStrikeOut = (BYTE)(((cf.dwEffects & CFE_STRIKEOUT) != 0) ? TRUE : FALSE); - } - else - { - m_lf.lfUnderline = (BYTE)FALSE; - m_lf.lfStrikeOut = (BYTE)FALSE; - } - - if((cf.dwMask & CFM_CHARSET) != 0) - m_lf.lfCharSet = cf.bCharSet; - else - dwFlags |= CF_NOSCRIPTSEL; - m_lf.lfOutPrecision = OUT_DEFAULT_PRECIS; - m_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; - m_lf.lfQuality = DEFAULT_QUALITY; - if((cf.dwMask & CFM_FACE) != 0) - { - m_lf.lfPitchAndFamily = cf.bPitchAndFamily; -#if (_RICHEDIT_VER >= 0x0200) - SecureHelper::strcpy_x(m_lf.lfFaceName, _countof(m_lf.lfFaceName), cf.szFaceName); -#else // !(_RICHEDIT_VER >= 0x0200) - SecureHelper::strcpy_x(m_lf.lfFaceName, _countof(m_lf.lfFaceName), A2T((LPSTR)cf.szFaceName)); -#endif // !(_RICHEDIT_VER >= 0x0200) - } - else - { - m_lf.lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE; - m_lf.lfFaceName[0] = (TCHAR)0; - } - return dwFlags; - } -}; - -class CRichEditFontDialog : public CRichEditFontDialogImpl -{ -public: - CRichEditFontDialog(const CHARFORMAT& charformat, - DWORD dwFlags = CF_SCREENFONTS, - HDC hDCPrinter = NULL, - HWND hWndParent = NULL) - : CRichEditFontDialogImpl(charformat, dwFlags, hDCPrinter, hWndParent) - { } - - DECLARE_EMPTY_MSG_MAP() -}; - -#endif // defined(_RICHEDIT_) && !defined(_WIN32_WCE) - - -/////////////////////////////////////////////////////////////////////////////// -// CColorDialogImpl - color selection - -#if !defined(_WIN32_WCE) || ((_WIN32_WCE > 420) && !(defined(WIN32_PLATFORM_WFSP) && (_WIN32_WCE > 0x0500))) - -#ifdef _WIN32_WCE - #pragma comment(lib, "commdlg.lib") - - #ifndef SETRGBSTRING - #define SETRGBSTRING _T("commdlg_SetRGBColor") - #endif - - #ifndef COLOROKSTRING - #define COLOROKSTRING _T("commdlg_ColorOK") - #endif -#endif - -template -class ATL_NO_VTABLE CColorDialogImpl : public CCommonDialogImplBase -{ -public: - CHOOSECOLOR m_cc; - -// Constructor - CColorDialogImpl(COLORREF clrInit = 0, DWORD dwFlags = 0, HWND hWndParent = NULL) - { - memset(&m_cc, 0, sizeof(m_cc)); - - m_cc.lStructSize = sizeof(m_cc); - m_cc.lpCustColors = GetCustomColors(); - m_cc.hwndOwner = hWndParent; - m_cc.Flags = dwFlags | CC_ENABLEHOOK; - m_cc.lpfnHook = (LPCCHOOKPROC)T::HookProc; - - if(clrInit != 0) - { - m_cc.rgbResult = clrInit; - m_cc.Flags |= CC_RGBINIT; - } - } - -// Operations - INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow()) - { - ATLASSERT((m_cc.Flags & CC_ENABLEHOOK) != 0); - ATLASSERT(m_cc.lpfnHook != NULL); // can still be a user hook - - if(m_cc.hwndOwner == NULL) // set only if not specified before - m_cc.hwndOwner = hWndParent; - - ATLASSERT(m_hWnd == NULL); - ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this); - - BOOL bRet = ::ChooseColor(&m_cc); - - m_hWnd = NULL; - - return bRet ? IDOK : IDCANCEL; - } - - // Set the current color while dialog is displayed - void SetCurrentColor(COLORREF clr) - { - ATLASSERT(::IsWindow(m_hWnd)); - SendMessage(_GetSetRGBMessage(), 0, (LPARAM)clr); - } - - // Get the selected color after DoModal returns, or in OnColorOK - COLORREF GetColor() const - { - return m_cc.rgbResult; - } - -// Special override for the color dialog - static UINT_PTR APIENTRY HookProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) - { - if(uMsg != WM_INITDIALOG && uMsg != _GetColorOKMessage()) - return 0; - - LPCHOOSECOLOR lpCC = (LPCHOOSECOLOR)lParam; - CCommonDialogImplBase* pT = NULL; - - if(uMsg == WM_INITDIALOG) - { - pT = (CCommonDialogImplBase*)ModuleHelper::ExtractCreateWndData(); - lpCC->lCustData = (LPARAM)pT; - ATLASSERT(pT != NULL); - ATLASSERT(pT->m_hWnd == NULL); - ATLASSERT(::IsWindow(hWnd)); - // subclass dialog's window - if(!pT->SubclassWindow(hWnd)) - { - ATLTRACE2(atlTraceUI, 0, _T("Subclassing a Color common dialog failed\n")); - return 0; - } - } - else if(uMsg == _GetColorOKMessage()) - { - pT = (CCommonDialogImplBase*)lpCC->lCustData; - ATLASSERT(pT != NULL); - ATLASSERT(::IsWindow(pT->m_hWnd)); - } - - // pass to the message map - LRESULT lRes; - if(pT->ProcessWindowMessage(pT->m_hWnd, uMsg, wParam, lParam, lRes, 0) == FALSE) - return 0; - return lRes; - } - -// Helpers - static COLORREF* GetCustomColors() - { - static COLORREF rgbCustomColors[16] = - { - RGB(255, 255, 255), RGB(255, 255, 255), - RGB(255, 255, 255), RGB(255, 255, 255), - RGB(255, 255, 255), RGB(255, 255, 255), - RGB(255, 255, 255), RGB(255, 255, 255), - RGB(255, 255, 255), RGB(255, 255, 255), - RGB(255, 255, 255), RGB(255, 255, 255), - RGB(255, 255, 255), RGB(255, 255, 255), - RGB(255, 255, 255), RGB(255, 255, 255), - }; - - return rgbCustomColors; - } - - static UINT _GetSetRGBMessage() - { - static UINT uSetRGBMessage = 0; - if(uSetRGBMessage == 0) - { - CStaticDataInitCriticalSectionLock lock; - if(FAILED(lock.Lock())) - { - ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CColorDialogImpl::_GetSetRGBMessage.\n")); - ATLASSERT(FALSE); - return 0; - } - - if(uSetRGBMessage == 0) - uSetRGBMessage = ::RegisterWindowMessage(SETRGBSTRING); - - lock.Unlock(); - } - ATLASSERT(uSetRGBMessage != 0); - return uSetRGBMessage; - } - - static UINT _GetColorOKMessage() - { - static UINT uColorOKMessage = 0; - if(uColorOKMessage == 0) - { - CStaticDataInitCriticalSectionLock lock; - if(FAILED(lock.Lock())) - { - ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CColorDialogImpl::_GetColorOKMessage.\n")); - ATLASSERT(FALSE); - return 0; - } - - if(uColorOKMessage == 0) - uColorOKMessage = ::RegisterWindowMessage(COLOROKSTRING); - - lock.Unlock(); - } - ATLASSERT(uColorOKMessage != 0); - return uColorOKMessage; - } - -// Message map and handlers - BEGIN_MSG_MAP(CColorDialogImpl) - MESSAGE_HANDLER(_GetColorOKMessage(), _OnColorOK) - END_MSG_MAP() - - LRESULT _OnColorOK(UINT, WPARAM, LPARAM, BOOL&) - { - T* pT = static_cast(this); - return pT->OnColorOK(); - } - -// Overrideable - BOOL OnColorOK() // validate color - { - return FALSE; - } -}; - -class CColorDialog : public CColorDialogImpl -{ -public: - CColorDialog(COLORREF clrInit = 0, DWORD dwFlags = 0, HWND hWndParent = NULL) - : CColorDialogImpl(clrInit, dwFlags, hWndParent) - { } - - // override base class map and references to handlers - DECLARE_EMPTY_MSG_MAP() -}; - -#endif // !defined(_WIN32_WCE) || ((_WIN32_WCE > 420) && !(defined(WIN32_PLATFORM_WFSP) && (_WIN32_WCE > 0x0500))) - - -/////////////////////////////////////////////////////////////////////////////// -// CPrintDialogImpl - used for Print... and PrintSetup... - -#ifndef _WIN32_WCE - -// global helper -static HDC _AtlCreateDC(HGLOBAL hDevNames, HGLOBAL hDevMode) -{ - if(hDevNames == NULL) - return NULL; - - LPDEVNAMES lpDevNames = (LPDEVNAMES)::GlobalLock(hDevNames); - LPDEVMODE lpDevMode = (hDevMode != NULL) ? (LPDEVMODE)::GlobalLock(hDevMode) : NULL; - - if(lpDevNames == NULL) - return NULL; - - HDC hDC = ::CreateDC((LPCTSTR)lpDevNames + lpDevNames->wDriverOffset, - (LPCTSTR)lpDevNames + lpDevNames->wDeviceOffset, - (LPCTSTR)lpDevNames + lpDevNames->wOutputOffset, - lpDevMode); - - ::GlobalUnlock(hDevNames); - if(hDevMode != NULL) - ::GlobalUnlock(hDevMode); - return hDC; -} - -template -class ATL_NO_VTABLE CPrintDialogImpl : public CCommonDialogImplBase -{ -public: - // print dialog parameter block (note this is a reference) - PRINTDLG& m_pd; - -// Constructors - CPrintDialogImpl(BOOL bPrintSetupOnly = FALSE, // TRUE for Print Setup, FALSE for Print Dialog - DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_NOSELECTION, - HWND hWndParent = NULL) - : m_pd(m_pdActual) - { - memset(&m_pdActual, 0, sizeof(m_pdActual)); - - m_pd.lStructSize = sizeof(m_pdActual); - m_pd.hwndOwner = hWndParent; - m_pd.Flags = (dwFlags | PD_ENABLEPRINTHOOK | PD_ENABLESETUPHOOK); - m_pd.lpfnPrintHook = (LPPRINTHOOKPROC)T::HookProc; - m_pd.lpfnSetupHook = (LPSETUPHOOKPROC)T::HookProc; - - if(bPrintSetupOnly) - m_pd.Flags |= PD_PRINTSETUP; - else - m_pd.Flags |= PD_RETURNDC; - - m_pd.Flags &= ~PD_RETURNIC; // do not support information context - } - -// Operations - INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow()) - { - ATLASSERT((m_pd.Flags & PD_ENABLEPRINTHOOK) != 0); - ATLASSERT((m_pd.Flags & PD_ENABLESETUPHOOK) != 0); - ATLASSERT(m_pd.lpfnPrintHook != NULL); // can still be a user hook - ATLASSERT(m_pd.lpfnSetupHook != NULL); // can still be a user hook - ATLASSERT((m_pd.Flags & PD_RETURNDEFAULT) == 0); // use GetDefaults for this - - if(m_pd.hwndOwner == NULL) // set only if not specified before - m_pd.hwndOwner = hWndParent; - - ATLASSERT(m_hWnd == NULL); - ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this); - - BOOL bRet = ::PrintDlg(&m_pd); - - m_hWnd = NULL; - - return bRet ? IDOK : IDCANCEL; - } - - // GetDefaults will not display a dialog but will get device defaults - BOOL GetDefaults() - { - m_pd.Flags |= PD_RETURNDEFAULT; - ATLASSERT(m_pd.hDevMode == NULL); // must be NULL - ATLASSERT(m_pd.hDevNames == NULL); // must be NULL - - return ::PrintDlg(&m_pd); - } - - // Helpers for parsing information after successful return num. copies requested - int GetCopies() const - { - if((m_pd.Flags & PD_USEDEVMODECOPIES) != 0) - { - LPDEVMODE lpDevMode = GetDevMode(); - return (lpDevMode != NULL) ? lpDevMode->dmCopies : -1; - } - - return m_pd.nCopies; - } - - BOOL PrintCollate() const // TRUE if collate checked - { - return ((m_pd.Flags & PD_COLLATE) != 0) ? TRUE : FALSE; - } - - BOOL PrintSelection() const // TRUE if printing selection - { - return ((m_pd.Flags & PD_SELECTION) != 0) ? TRUE : FALSE; - } - - BOOL PrintAll() const // TRUE if printing all pages - { - return (!PrintRange() && !PrintSelection()) ? TRUE : FALSE; - } - - BOOL PrintRange() const // TRUE if printing page range - { - return ((m_pd.Flags & PD_PAGENUMS) != 0) ? TRUE : FALSE; - } - - BOOL PrintToFile() const // TRUE if printing to a file - { - return ((m_pd.Flags & PD_PRINTTOFILE) != 0) ? TRUE : FALSE; - } - - int GetFromPage() const // starting page if valid - { - return PrintRange() ? m_pd.nFromPage : -1; - } - - int GetToPage() const // ending page if valid - { - return PrintRange() ? m_pd.nToPage : -1; - } - - LPDEVMODE GetDevMode() const // return DEVMODE - { - if(m_pd.hDevMode == NULL) - return NULL; - - return (LPDEVMODE)::GlobalLock(m_pd.hDevMode); - } - - LPCTSTR GetDriverName() const // return driver name - { - if(m_pd.hDevNames == NULL) - return NULL; - - LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pd.hDevNames); - if(lpDev == NULL) - return NULL; - - return (LPCTSTR)lpDev + lpDev->wDriverOffset; - } - - LPCTSTR GetDeviceName() const // return device name - { - if(m_pd.hDevNames == NULL) - return NULL; - - LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pd.hDevNames); - if(lpDev == NULL) - return NULL; - - return (LPCTSTR)lpDev + lpDev->wDeviceOffset; - } - - LPCTSTR GetPortName() const // return output port name - { - if(m_pd.hDevNames == NULL) - return NULL; - - LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pd.hDevNames); - if(lpDev == NULL) - return NULL; - - return (LPCTSTR)lpDev + lpDev->wOutputOffset; - } - - HDC GetPrinterDC() const // return HDC (caller must delete) - { - ATLASSERT((m_pd.Flags & PD_RETURNDC) != 0); - return m_pd.hDC; - } - - // This helper creates a DC based on the DEVNAMES and DEVMODE structures. - // This DC is returned, but also stored in m_pd.hDC as though it had been - // returned by CommDlg. It is assumed that any previously obtained DC - // has been/will be deleted by the user. This may be - // used without ever invoking the print/print setup dialogs. - HDC CreatePrinterDC() - { - m_pd.hDC = _AtlCreateDC(m_pd.hDevNames, m_pd.hDevMode); - return m_pd.hDC; - } - -// Implementation - PRINTDLG m_pdActual; // the Print/Print Setup need to share this - - // The following handle the case of print setup... from the print dialog - CPrintDialogImpl(PRINTDLG& pdInit) : m_pd(pdInit) - { } - - BEGIN_MSG_MAP(CPrintDialogImpl) -#ifdef psh1 - COMMAND_ID_HANDLER(psh1, OnPrintSetup) // print setup button when print is displayed -#else // !psh1 - COMMAND_ID_HANDLER(0x0400, OnPrintSetup) // value from dlgs.h -#endif // !psh1 - END_MSG_MAP() - - LRESULT OnPrintSetup(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& /*bHandled*/) - { - T dlgSetup(m_pd); - ModuleHelper::AddCreateWndData(&dlgSetup.m_thunk.cd, (CCommonDialogImplBase*)&dlgSetup); - return DefWindowProc(WM_COMMAND, MAKEWPARAM(wID, wNotifyCode), (LPARAM)hWndCtl); - } -}; - -class CPrintDialog : public CPrintDialogImpl -{ -public: - CPrintDialog(BOOL bPrintSetupOnly = FALSE, - DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_NOSELECTION, - HWND hWndParent = NULL) - : CPrintDialogImpl(bPrintSetupOnly, dwFlags, hWndParent) - { } - - CPrintDialog(PRINTDLG& pdInit) : CPrintDialogImpl(pdInit) - { } -}; - -#endif // _WIN32_WCE - - -/////////////////////////////////////////////////////////////////////////////// -// CPrintDialogExImpl - new print dialog for Windows 2000 - -#if (WINVER >= 0x0500) && !defined(_WIN32_WCE) - -}; // namespace WTL - -#include - -extern "C" const __declspec(selectany) IID IID_IPrintDialogCallback = {0x5852a2c3, 0x6530, 0x11d1, {0xb6, 0xa3, 0x0, 0x0, 0xf8, 0x75, 0x7b, 0xf9}}; -extern "C" const __declspec(selectany) IID IID_IPrintDialogServices = {0x509aaeda, 0x5639, 0x11d1, {0xb6, 0xa1, 0x0, 0x0, 0xf8, 0x75, 0x7b, 0xf9}}; - -namespace WTL -{ - -template -class ATL_NO_VTABLE CPrintDialogExImpl : - public ATL::CWindow, - public ATL::CMessageMap, - public IPrintDialogCallback, - public ATL::IObjectWithSiteImpl< T > -{ -public: - PRINTDLGEX m_pdex; - -// Constructor - CPrintDialogExImpl(DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_NOSELECTION | PD_NOCURRENTPAGE, - HWND hWndParent = NULL) - { - memset(&m_pdex, 0, sizeof(m_pdex)); - - m_pdex.lStructSize = sizeof(PRINTDLGEX); - m_pdex.hwndOwner = hWndParent; - m_pdex.Flags = dwFlags; - m_pdex.nStartPage = START_PAGE_GENERAL; - // callback object will be set in DoModal - - m_pdex.Flags &= ~PD_RETURNIC; // do not support information context - } - -// Operations - HRESULT DoModal(HWND hWndParent = ::GetActiveWindow()) - { - ATLASSERT(m_hWnd == NULL); - ATLASSERT((m_pdex.Flags & PD_RETURNDEFAULT) == 0); // use GetDefaults for this - - if(m_pdex.hwndOwner == NULL) // set only if not specified before - m_pdex.hwndOwner = hWndParent; - - T* pT = static_cast(this); - m_pdex.lpCallback = (IUnknown*)(IPrintDialogCallback*)pT; - - HRESULT hResult = ::PrintDlgEx(&m_pdex); - - m_hWnd = NULL; - - return hResult; - } - - BOOL EndDialog(INT_PTR /*nRetCode*/ = 0) - { - ATLASSERT(::IsWindow(m_hWnd)); - SendMessage(WM_COMMAND, MAKEWPARAM(IDABORT, 0)); - return TRUE; - } - - // GetDefaults will not display a dialog but will get device defaults - HRESULT GetDefaults() - { - m_pdex.Flags |= PD_RETURNDEFAULT; - ATLASSERT(m_pdex.hDevMode == NULL); // must be NULL - ATLASSERT(m_pdex.hDevNames == NULL); // must be NULL - - return ::PrintDlgEx(&m_pdex); - } - - // Helpers for parsing information after successful return num. copies requested - int GetCopies() const - { - if((m_pdex.Flags & PD_USEDEVMODECOPIES) != 0) - { - LPDEVMODE lpDevMode = GetDevMode(); - return (lpDevMode != NULL) ? lpDevMode->dmCopies : -1; - } - - return m_pdex.nCopies; - } - - BOOL PrintCollate() const // TRUE if collate checked - { - return ((m_pdex.Flags & PD_COLLATE) != 0) ? TRUE : FALSE; - } - - BOOL PrintSelection() const // TRUE if printing selection - { - return ((m_pdex.Flags & PD_SELECTION) != 0) ? TRUE : FALSE; - } - - BOOL PrintAll() const // TRUE if printing all pages - { - return (!PrintRange() && !PrintSelection()) ? TRUE : FALSE; - } - - BOOL PrintRange() const // TRUE if printing page range - { - return ((m_pdex.Flags & PD_PAGENUMS) != 0) ? TRUE : FALSE; - } - - BOOL PrintToFile() const // TRUE if printing to a file - { - return ((m_pdex.Flags & PD_PRINTTOFILE) != 0) ? TRUE : FALSE; - } - - LPDEVMODE GetDevMode() const // return DEVMODE - { - if(m_pdex.hDevMode == NULL) - return NULL; - - return (LPDEVMODE)::GlobalLock(m_pdex.hDevMode); - } - - LPCTSTR GetDriverName() const // return driver name - { - if(m_pdex.hDevNames == NULL) - return NULL; - - LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pdex.hDevNames); - if(lpDev == NULL) - return NULL; - - return (LPCTSTR)lpDev + lpDev->wDriverOffset; - } - - LPCTSTR GetDeviceName() const // return device name - { - if(m_pdex.hDevNames == NULL) - return NULL; - - LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pdex.hDevNames); - if(lpDev == NULL) - return NULL; - - return (LPCTSTR)lpDev + lpDev->wDeviceOffset; - } - - LPCTSTR GetPortName() const // return output port name - { - if(m_pdex.hDevNames == NULL) - return NULL; - - LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pdex.hDevNames); - if(lpDev == NULL) - return NULL; - - return (LPCTSTR)lpDev + lpDev->wOutputOffset; - } - - HDC GetPrinterDC() const // return HDC (caller must delete) - { - ATLASSERT((m_pdex.Flags & PD_RETURNDC) != 0); - return m_pdex.hDC; - } - - // This helper creates a DC based on the DEVNAMES and DEVMODE structures. - // This DC is returned, but also stored in m_pdex.hDC as though it had been - // returned by CommDlg. It is assumed that any previously obtained DC - // has been/will be deleted by the user. This may be - // used without ever invoking the print/print setup dialogs. - HDC CreatePrinterDC() - { - m_pdex.hDC = _AtlCreateDC(m_pdex.hDevNames, m_pdex.hDevMode); - return m_pdex.hDC; - } - -// Implementation - interfaces - -// IUnknown - STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject) - { - if(ppvObject == NULL) - return E_POINTER; - - T* pT = static_cast(this); - if(IsEqualGUID(riid, IID_IUnknown) || IsEqualGUID(riid, IID_IPrintDialogCallback)) - { - *ppvObject = (IPrintDialogCallback*)pT; - // AddRef() not needed - return S_OK; - } - else if(IsEqualGUID(riid, IID_IObjectWithSite)) - { - *ppvObject = (IObjectWithSite*)pT; - // AddRef() not needed - return S_OK; - } - - return E_NOINTERFACE; - } - - virtual ULONG STDMETHODCALLTYPE AddRef() - { - return 1; - } - - virtual ULONG STDMETHODCALLTYPE Release() - { - return 1; - } - -// IPrintDialogCallback - STDMETHOD(InitDone)() - { - return S_FALSE; - } - - STDMETHOD(SelectionChange)() - { - return S_FALSE; - } - - STDMETHOD(HandleMessage)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* plResult) - { - // set up m_hWnd the first time - if(m_hWnd == NULL) - Attach(hWnd); - - // call message map - HRESULT hRet = ProcessWindowMessage(hWnd, uMsg, wParam, lParam, *plResult, 0) ? S_OK : S_FALSE; - if(hRet == S_OK && uMsg == WM_NOTIFY) // return in DWLP_MSGRESULT - ::SetWindowLongPtr(GetParent(), DWLP_MSGRESULT, (LONG_PTR)*plResult); - - if(uMsg == WM_INITDIALOG && hRet == S_OK && (BOOL)*plResult != FALSE) - hRet = S_FALSE; - - return hRet; - } -}; - -class CPrintDialogEx : public CPrintDialogExImpl -{ -public: - CPrintDialogEx( - DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_NOSELECTION | PD_NOCURRENTPAGE, - HWND hWndParent = NULL) - : CPrintDialogExImpl(dwFlags, hWndParent) - { } - - DECLARE_EMPTY_MSG_MAP() -}; - -#endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE) - - -/////////////////////////////////////////////////////////////////////////////// -// CPageSetupDialogImpl - Page Setup dialog - -#ifndef _WIN32_WCE - -template -class ATL_NO_VTABLE CPageSetupDialogImpl : public CCommonDialogImplBase -{ -public: - PAGESETUPDLG m_psd; - ATL::CWndProcThunk m_thunkPaint; - -// Constructors - CPageSetupDialogImpl(DWORD dwFlags = PSD_MARGINS | PSD_INWININIINTLMEASURE, HWND hWndParent = NULL) - { - memset(&m_psd, 0, sizeof(m_psd)); - - m_psd.lStructSize = sizeof(m_psd); - m_psd.hwndOwner = hWndParent; - m_psd.Flags = (dwFlags | PSD_ENABLEPAGESETUPHOOK | PSD_ENABLEPAGEPAINTHOOK); - m_psd.lpfnPageSetupHook = (LPPAGESETUPHOOK)T::HookProc; - m_thunkPaint.Init((WNDPROC)T::PaintHookProc, this); -#if (_ATL_VER >= 0x0700) - m_psd.lpfnPagePaintHook = (LPPAGEPAINTHOOK)m_thunkPaint.GetWNDPROC(); -#else - m_psd.lpfnPagePaintHook = (LPPAGEPAINTHOOK)&(m_thunkPaint.thunk); -#endif - } - - DECLARE_EMPTY_MSG_MAP() - -// Attributes - LPDEVMODE GetDevMode() const // return DEVMODE - { - if(m_psd.hDevMode == NULL) - return NULL; - - return (LPDEVMODE)::GlobalLock(m_psd.hDevMode); - } - - LPCTSTR GetDriverName() const // return driver name - { - if(m_psd.hDevNames == NULL) - return NULL; - - LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_psd.hDevNames); - return (LPCTSTR)lpDev + lpDev->wDriverOffset; - } - - LPCTSTR GetDeviceName() const // return device name - { - if(m_psd.hDevNames == NULL) - return NULL; - - LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_psd.hDevNames); - return (LPCTSTR)lpDev + lpDev->wDeviceOffset; - } - - LPCTSTR GetPortName() const // return output port name - { - if(m_psd.hDevNames == NULL) - return NULL; - - LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_psd.hDevNames); - return (LPCTSTR)lpDev + lpDev->wOutputOffset; - } - - HDC CreatePrinterDC() - { - return _AtlCreateDC(m_psd.hDevNames, m_psd.hDevMode); - } - - SIZE GetPaperSize() const - { - SIZE size; - size.cx = m_psd.ptPaperSize.x; - size.cy = m_psd.ptPaperSize.y; - return size; - } - - void GetMargins(LPRECT lpRectMargins, LPRECT lpRectMinMargins) const - { - if(lpRectMargins != NULL) - *lpRectMargins = m_psd.rtMargin; - if(lpRectMinMargins != NULL) - *lpRectMinMargins = m_psd.rtMinMargin; - } - -// Operations - INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow()) - { - ATLASSERT((m_psd.Flags & PSD_ENABLEPAGESETUPHOOK) != 0); - ATLASSERT((m_psd.Flags & PSD_ENABLEPAGEPAINTHOOK) != 0); - ATLASSERT(m_psd.lpfnPageSetupHook != NULL); // can still be a user hook - ATLASSERT(m_psd.lpfnPagePaintHook != NULL); // can still be a user hook - - if(m_psd.hwndOwner == NULL) // set only if not specified before - m_psd.hwndOwner = hWndParent; - - ATLASSERT(m_hWnd == NULL); - ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this); - - BOOL bRet = ::PageSetupDlg(&m_psd); - - m_hWnd = NULL; - - return bRet ? IDOK : IDCANCEL; - } - -// Implementation - static UINT_PTR CALLBACK PaintHookProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) - { - T* pT = (T*)hWnd; - UINT_PTR uRet = 0; - switch(uMsg) - { - case WM_PSD_PAGESETUPDLG: - uRet = pT->PreDrawPage(LOWORD(wParam), HIWORD(wParam), (LPPAGESETUPDLG)lParam); - break; - case WM_PSD_FULLPAGERECT: - case WM_PSD_MINMARGINRECT: - case WM_PSD_MARGINRECT: - case WM_PSD_GREEKTEXTRECT: - case WM_PSD_ENVSTAMPRECT: - case WM_PSD_YAFULLPAGERECT: - uRet = pT->OnDrawPage(uMsg, (HDC)wParam, (LPRECT)lParam); - break; - default: - ATLTRACE2(atlTraceUI, 0, _T("CPageSetupDialogImpl::PaintHookProc - unknown message received\n")); - break; - } - return uRet; - } - -// Overridables - UINT_PTR PreDrawPage(WORD /*wPaper*/, WORD /*wFlags*/, LPPAGESETUPDLG /*pPSD*/) - { - // return 1 to prevent any more drawing - return 0; - } - - UINT_PTR OnDrawPage(UINT /*uMsg*/, HDC /*hDC*/, LPRECT /*lpRect*/) - { - return 0; // do the default - } -}; - -class CPageSetupDialog : public CPageSetupDialogImpl -{ -public: - CPageSetupDialog(DWORD dwFlags = PSD_MARGINS | PSD_INWININIINTLMEASURE, HWND hWndParent = NULL) - : CPageSetupDialogImpl(dwFlags, hWndParent) - { } - - // override PaintHookProc and references to handlers - static UINT_PTR CALLBACK PaintHookProc(HWND, UINT, WPARAM, LPARAM) - { - return 0; - } -}; - -#endif // _WIN32_WCE - - -/////////////////////////////////////////////////////////////////////////////// -// CFindReplaceDialogImpl - Find/FindReplace modeless dialogs - -#ifndef _WIN32_WCE - -template -class ATL_NO_VTABLE CFindReplaceDialogImpl : public CCommonDialogImplBase -{ -public: - enum { _cchFindReplaceBuffer = 128 }; - - FINDREPLACE m_fr; - TCHAR m_szFindWhat[_cchFindReplaceBuffer]; - TCHAR m_szReplaceWith[_cchFindReplaceBuffer]; - -// Constructors - CFindReplaceDialogImpl() - { - memset(&m_fr, 0, sizeof(m_fr)); - m_szFindWhat[0] = _T('\0'); - m_szReplaceWith[0] = _T('\0'); - - m_fr.lStructSize = sizeof(m_fr); - m_fr.Flags = FR_ENABLEHOOK; - m_fr.lpfnHook = (LPFRHOOKPROC)T::HookProc; - m_fr.lpstrFindWhat = (LPTSTR)m_szFindWhat; - m_fr.wFindWhatLen = _cchFindReplaceBuffer; - m_fr.lpstrReplaceWith = (LPTSTR)m_szReplaceWith; - m_fr.wReplaceWithLen = _cchFindReplaceBuffer; - } - - // Note: You must allocate the object on the heap. - // If you do not, you must override OnFinalMessage() - virtual void OnFinalMessage(HWND /*hWnd*/) - { - delete this; - } - - HWND Create(BOOL bFindDialogOnly, // TRUE for Find, FALSE for FindReplace - LPCTSTR lpszFindWhat, - LPCTSTR lpszReplaceWith = NULL, - DWORD dwFlags = FR_DOWN, - HWND hWndParent = NULL) - { - ATLASSERT((m_fr.Flags & FR_ENABLEHOOK) != 0); - ATLASSERT(m_fr.lpfnHook != NULL); - - m_fr.Flags |= dwFlags; - - if(hWndParent == NULL) - m_fr.hwndOwner = ::GetActiveWindow(); - else - m_fr.hwndOwner = hWndParent; - ATLASSERT(m_fr.hwndOwner != NULL); // must have an owner for modeless dialog - - if(lpszFindWhat != NULL) - SecureHelper::strncpy_x(m_szFindWhat, _countof(m_szFindWhat), lpszFindWhat, _TRUNCATE); - - if(lpszReplaceWith != NULL) - SecureHelper::strncpy_x(m_szReplaceWith, _countof(m_szReplaceWith), lpszReplaceWith, _TRUNCATE); - - ATLASSERT(m_hWnd == NULL); - ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this); - - HWND hWnd = NULL; - if(bFindDialogOnly) - hWnd = ::FindText(&m_fr); - else - hWnd = ::ReplaceText(&m_fr); - - ATLASSERT(m_hWnd == hWnd); - return hWnd; - } - - static const UINT GetFindReplaceMsg() - { - static const UINT nMsgFindReplace = ::RegisterWindowMessage(FINDMSGSTRING); - return nMsgFindReplace; - } - // call while handling FINDMSGSTRING registered message - // to retreive the object - static T* PASCAL GetNotifier(LPARAM lParam) - { - ATLASSERT(lParam != NULL); - T* pDlg = (T*)(lParam - offsetof(T, m_fr)); - return pDlg; - } - -// Operations - // Helpers for parsing information after successful return - LPCTSTR GetFindString() const // get find string - { - return (LPCTSTR)m_fr.lpstrFindWhat; - } - - LPCTSTR GetReplaceString() const // get replacement string - { - return (LPCTSTR)m_fr.lpstrReplaceWith; - } - - BOOL SearchDown() const // TRUE if search down, FALSE is up - { - return ((m_fr.Flags & FR_DOWN) != 0) ? TRUE : FALSE; - } - - BOOL FindNext() const // TRUE if command is find next - { - return ((m_fr.Flags & FR_FINDNEXT) != 0) ? TRUE : FALSE; - } - - BOOL MatchCase() const // TRUE if matching case - { - return ((m_fr.Flags & FR_MATCHCASE) != 0) ? TRUE : FALSE; - } - - BOOL MatchWholeWord() const // TRUE if matching whole words only - { - return ((m_fr.Flags & FR_WHOLEWORD) != 0) ? TRUE : FALSE; - } - - BOOL ReplaceCurrent() const // TRUE if replacing current string - { - return ((m_fr. Flags & FR_REPLACE) != 0) ? TRUE : FALSE; - } - - BOOL ReplaceAll() const // TRUE if replacing all occurrences - { - return ((m_fr.Flags & FR_REPLACEALL) != 0) ? TRUE : FALSE; - } - - BOOL IsTerminating() const // TRUE if terminating dialog - { - return ((m_fr.Flags & FR_DIALOGTERM) != 0) ? TRUE : FALSE ; - } -}; - -class CFindReplaceDialog : public CFindReplaceDialogImpl -{ -public: - DECLARE_EMPTY_MSG_MAP() -}; - -#endif // !_WIN32_WCE - - -///////////////////////////////////////////////////////////////////////// -// CDialogBaseUnits - Dialog Units helper -// - -class CDialogBaseUnits -{ -public: - SIZE m_sizeUnits; - -// Constructors - CDialogBaseUnits() - { - // The base units of the out-dated System Font - LONG nDlgBaseUnits = ::GetDialogBaseUnits(); - m_sizeUnits.cx = LOWORD(nDlgBaseUnits); - m_sizeUnits.cy = HIWORD(nDlgBaseUnits); - } - - CDialogBaseUnits(HWND hWnd) - { - if(!InitDialogBaseUnits(hWnd)) { - LONG nDlgBaseUnits = ::GetDialogBaseUnits(); - m_sizeUnits.cx = LOWORD(nDlgBaseUnits); - m_sizeUnits.cy = HIWORD(nDlgBaseUnits); - } - } - - CDialogBaseUnits(HFONT hFont, HWND hWnd = NULL) - { - if(!InitDialogBaseUnits(hFont, hWnd)) { - LONG nDlgBaseUnits = ::GetDialogBaseUnits(); - m_sizeUnits.cx = LOWORD(nDlgBaseUnits); - m_sizeUnits.cy = HIWORD(nDlgBaseUnits); - } - } - - CDialogBaseUnits(LOGFONT lf, HWND hWnd = NULL) - { - if(!InitDialogBaseUnits(lf, hWnd)) { - LONG nDlgBaseUnits = ::GetDialogBaseUnits(); - m_sizeUnits.cx = LOWORD(nDlgBaseUnits); - m_sizeUnits.cy = HIWORD(nDlgBaseUnits); - } - } - -// Operations - BOOL InitDialogBaseUnits(HWND hWnd) - { - ATLASSERT(::IsWindow(hWnd)); - RECT rc = { 0, 0, 4, 8 }; - if(!::MapDialogRect(hWnd, &rc)) return FALSE; - m_sizeUnits.cx = rc.right; - m_sizeUnits.cy = rc.bottom; - return TRUE; - } - - BOOL InitDialogBaseUnits(LOGFONT lf, HWND hWnd = NULL) - { - CFont font; - font.CreateFontIndirect(&lf); - if(font.IsNull()) return FALSE; - return InitDialogBaseUnits(font, hWnd); - } - - BOOL InitDialogBaseUnits(HFONT hFont, HWND hWnd = NULL) - { - ATLASSERT(hFont != NULL); - CWindowDC dc = hWnd; - TEXTMETRIC tmText = { 0 }; - SIZE sizeText = { 0 }; - HFONT hFontOld = dc.SelectFont(hFont); - dc.GetTextMetrics(&tmText); - m_sizeUnits.cy = tmText.tmHeight + tmText.tmExternalLeading; - dc.GetTextExtent(_T("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"), 52, &sizeText); - m_sizeUnits.cx = (sizeText.cx + 26) / 52; - dc.SelectFont(hFontOld); - return TRUE; - } - - SIZE GetDialogBaseUnits() const - { - return m_sizeUnits; - } - - INT MapDialogPixelsX(INT x) const - { - return ::MulDiv(x, 4, m_sizeUnits.cx); // Pixels X to DLU - } - - INT MapDialogPixelsY(INT y) const - { - return ::MulDiv(y, 8, m_sizeUnits.cy); // Pixels Y to DLU - } - - POINT MapDialogPixels(POINT pt) const - { - POINT out = { MapDialogPixelsX(pt.x), MapDialogPixelsY(pt.y) }; - return out; - } - - SIZE MapDialogPixels(SIZE input) const - { - SIZE out = { MapDialogPixelsX(input.cx), MapDialogPixelsY(input.cy) }; - return out; - } - - RECT MapDialogPixels(RECT input) const - { - RECT out = { MapDialogPixelsX(input.left), MapDialogPixelsY(input.top), MapDialogPixelsX(input.right), MapDialogPixelsY(input.bottom) }; - return out; - } - - INT MapDialogUnitsX(INT x) const - { - return ::MulDiv(x, m_sizeUnits.cx, 4); // DLU to Pixels X - } - - INT MapDialogUnitsY(INT y) const - { - return ::MulDiv(y, m_sizeUnits.cx, 8); // DLU to Pixels Y - } - - POINT MapDialogUnits(POINT pt) const - { - POINT out = { MapDialogUnitsX(pt.x), MapDialogUnitsY(pt.y) }; - return out; - } - - SIZE MapDialogUnits(SIZE input) const - { - SIZE out = { MapDialogUnitsX(input.cx), MapDialogUnitsY(input.cy) }; - return out; - } - - RECT MapDialogUnits(RECT input) const - { - RECT out = { MapDialogUnitsX(input.left), MapDialogUnitsY(input.top), MapDialogUnitsX(input.right), MapDialogUnitsY(input.bottom) }; - return out; - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CMemDlgTemplate - in-memory dialog template - DLGTEMPLATE or DLGTEMPLATEEX - -#if (_ATL_VER >= 0x800) -typedef ATL::_DialogSplitHelper::DLGTEMPLATEEX DLGTEMPLATEEX; -typedef ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX DLGITEMTEMPLATEEX; -#else // (_ATL_VER >= 0x800) -typedef ATL::_DialogSizeHelper::_ATL_DLGTEMPLATEEX DLGTEMPLATEEX; -#pragma pack(push, 4) -struct DLGITEMTEMPLATEEX -{ - DWORD helpID; - DWORD exStyle; - DWORD style; - short x; - short y; - short cx; - short cy; - DWORD id; -}; -#pragma pack(pop) -#endif // (_ATL_VER >= 0x800) - - -class CMemDlgTemplate -{ -public: - enum StdCtrlType - { - CTRL_BUTTON = 0x0080, - CTRL_EDIT = 0x0081, - CTRL_STATIC = 0x0082, - CTRL_LISTBOX = 0x0083, - CTRL_SCROLLBAR = 0x0084, - CTRL_COMBOBOX = 0x0085 - }; - - CMemDlgTemplate() : m_hData(NULL), m_pData(NULL), m_pPtr(NULL), m_cAllocated(0) - { } - - ~CMemDlgTemplate() - { - Reset(); - } - - bool IsValid() const - { - return (m_pData != NULL); - } - - bool IsTemplateEx() const - { - return (IsValid() && ((DLGTEMPLATEEX*)m_pData)->signature == 0xFFFF); - } - - LPDLGTEMPLATE GetTemplatePtr() - { - return reinterpret_cast(m_pData); - } - - DLGTEMPLATEEX* GetTemplateExPtr() - { - return reinterpret_cast(m_pData); - } - - void Reset() - { - if (IsValid()) { -#ifndef UNDER_CE - ::GlobalUnlock(m_pData); -#endif - ATLVERIFY(::GlobalFree(m_hData) == NULL); - } - - m_hData = NULL; - m_pData = NULL; - m_pPtr = NULL; - m_cAllocated = 0; - } - - void Create(bool bDlgEx, LPCTSTR lpszCaption, RECT rc, DWORD dwStyle = 0, DWORD dwExStyle = 0, - LPCTSTR lpstrFontName = NULL, WORD wFontSize = 0, WORD wWeight = 0, BYTE bItalic = 0, BYTE bCharset = 0, DWORD dwHelpID = 0, - ATL::_U_STRINGorID ClassName = 0U, ATL::_U_STRINGorID Menu = 0U) - { - Create(bDlgEx, lpszCaption, (short) rc.left, (short) rc.top, (short) (rc.right - rc.left), (short) (rc.bottom - rc.top), dwStyle, dwExStyle, - lpstrFontName, wFontSize, wWeight, bItalic, bCharset, dwHelpID, ClassName.m_lpstr, Menu.m_lpstr); - } - - void Create(bool bDlgEx, LPCTSTR lpszCaption, short nX, short nY, short nWidth, short nHeight, DWORD dwStyle = 0, DWORD dwExStyle = 0, - LPCTSTR lpstrFontName = NULL, WORD wFontSize = 0, WORD wWeight = 0, BYTE bItalic = 0, BYTE bCharset = 0, DWORD dwHelpID = 0, - ATL::_U_STRINGorID ClassName = 0U, ATL::_U_STRINGorID Menu = 0U) - { - // Should have DS_SETFONT style to set the dialog font name and size - if (lpstrFontName != NULL) - { - dwStyle |= DS_SETFONT; - } - else - { - dwStyle &= ~DS_SETFONT; - } - - if (bDlgEx) - { - DLGTEMPLATEEX dlg = {1, 0xFFFF, dwHelpID, dwExStyle, dwStyle, 0, nX, nY, nWidth, nHeight}; - AddData(&dlg, sizeof(dlg)); - } - else - { - DLGTEMPLATE dlg = {dwStyle, dwExStyle, 0, nX, nY, nWidth, nHeight}; - AddData(&dlg, sizeof(dlg)); - } - -#ifndef _WIN32_WCE - if (Menu.m_lpstr == NULL) - { - WORD menuData = 0; - AddData(&menuData, sizeof(WORD)); - } - else if (IS_INTRESOURCE(Menu.m_lpstr)) - { - WORD menuData[] = {0xFFFF, (WORD)Menu.m_lpstr}; - AddData(menuData, sizeof(menuData)); - } - else - { - AddString(Menu.m_lpstr); - } -#else // _WIN32_WCE - // Windows CE doesn't support the addition of menus to a dialog box - ATLASSERT(Menu.m_lpstr == NULL); - Menu.m_lpstr; // avoid level 4 warning - WORD menuData = 0; - AddData(&menuData, sizeof(WORD)); -#endif // _WIN32_WCE - - if (ClassName.m_lpstr == NULL) - { - WORD classData = 0; - AddData(&classData, sizeof(WORD)); - } - else if (IS_INTRESOURCE(ClassName.m_lpstr)) - { - WORD classData[] = {0xFFFF, (WORD)ClassName.m_lpstr}; - AddData(classData, sizeof(classData)); - } - else - { - AddString(ClassName.m_lpstr); - } - - // Set dialog caption - AddString(lpszCaption); - - if (lpstrFontName != NULL) - { - AddData(&wFontSize, sizeof(wFontSize)); - - if (bDlgEx) - { - AddData(&wWeight, sizeof(wWeight)); - AddData(&bItalic, sizeof(bItalic)); - AddData(&bCharset, sizeof(bCharset)); - } - - AddString(lpstrFontName); - } - } - - void AddControl(ATL::_U_STRINGorID ClassName, WORD wId, RECT rc, DWORD dwStyle, DWORD dwExStyle, - ATL::_U_STRINGorID Text, const WORD* pCreationData = NULL, WORD nCreationData = 0, DWORD dwHelpID = 0) - { - AddControl(ClassName.m_lpstr, wId, (short) rc.left, (short) rc.top, (short) (rc.right - rc.left), (short) (rc.bottom - rc.top), dwStyle, dwExStyle, - Text.m_lpstr, pCreationData, nCreationData, dwHelpID); - } - - void AddControl(ATL::_U_STRINGorID ClassName, WORD wId, short nX, short nY, short nWidth, short nHeight, DWORD dwStyle, DWORD dwExStyle, - ATL::_U_STRINGorID Text, const WORD* pCreationData = NULL, WORD nCreationData = 0, DWORD dwHelpID = 0) - { - ATLASSERT(IsValid()); - - // DWORD align data - m_pPtr = (LPBYTE)(DWORD_PTR)((DWORD)(DWORD_PTR)(m_pPtr + 3) & (~3)); - - if (IsTemplateEx()) - { - DLGTEMPLATEEX* dlg = (DLGTEMPLATEEX*)m_pData; - dlg->cDlgItems++; - - DLGITEMTEMPLATEEX item = {dwHelpID, ATL::CControlWinTraits::GetWndExStyle(0) | dwExStyle, ATL::CControlWinTraits::GetWndStyle(0) | dwStyle, nX, nY, nWidth, nHeight, wId}; - AddData(&item, sizeof(item)); - } - else - { - LPDLGTEMPLATE dlg = (LPDLGTEMPLATE)m_pData; - dlg->cdit++; - - DLGITEMTEMPLATE item = {ATL::CControlWinTraits::GetWndStyle(0) | dwStyle, ATL::CControlWinTraits::GetWndExStyle(0) | dwExStyle, nX, nY, nWidth, nHeight, wId}; - AddData(&item, sizeof(item)); - } - - ATLASSERT(ClassName.m_lpstr != NULL); - if (IS_INTRESOURCE(ClassName.m_lpstr)) - { - WORD wData[] = {0xFFFF, (WORD)ClassName.m_lpstr}; - AddData(wData, sizeof(wData)); - } - else - { - AddString(ClassName.m_lpstr); - } - - if (Text.m_lpstr == NULL) - { - WORD classData = 0; - AddData(&classData, sizeof(WORD)); - } - else if (IS_INTRESOURCE(Text.m_lpstr)) - { - WORD wData[] = {0xFFFF, (WORD)Text.m_lpstr}; - AddData(wData, sizeof(wData)); - } - else - { - AddString(Text.m_lpstr); - } - - AddData(&nCreationData, sizeof(nCreationData)); - - if ((nCreationData != 0)) - { - ATLASSERT(pCreationData != NULL); - AddData(pCreationData, nCreationData * sizeof(WORD)); - } - } - - void AddStdControl(StdCtrlType CtrlType, WORD wId, short nX, short nY, short nWidth, short nHeight, - DWORD dwStyle, DWORD dwExStyle, ATL::_U_STRINGorID Text, const WORD* pCreationData = NULL, WORD nCreationData = 0, DWORD dwHelpID = 0) - { - AddControl(CtrlType, wId, nX, nY, nWidth, nHeight, dwStyle, dwExStyle, Text, pCreationData, nCreationData, dwHelpID); - } - - void AddData(LPCVOID pData, size_t nData) - { - ATLASSERT(pData != NULL); - - const SIZE_T ALLOCATION_INCREMENT = 1024; - - if (m_pData == NULL) - { - m_cAllocated = ((nData / ALLOCATION_INCREMENT) + 1) * ALLOCATION_INCREMENT; - m_hData = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, m_cAllocated); - ATLASSERT(m_hData != NULL); -#ifndef UNDER_CE - m_pPtr = m_pData = static_cast(::GlobalLock(m_hData)); -#else - m_pPtr = m_pData = static_cast(m_hData); -#endif - ATLASSERT(m_pData != NULL); - } - else if (((m_pPtr - m_pData) + nData) > m_cAllocated) - { - SIZE_T ptrPos = (m_pPtr - m_pData); - m_cAllocated += ((nData / ALLOCATION_INCREMENT) + 1) * ALLOCATION_INCREMENT; -#ifndef UNDER_CE - ::GlobalUnlock(m_pData); -#endif - m_hData = ::GlobalReAlloc(m_hData, m_cAllocated, GMEM_MOVEABLE | GMEM_ZEROINIT); - ATLASSERT(m_hData != NULL); -#ifndef UNDER_CE - m_pData = static_cast(::GlobalLock(m_hData)); -#else - m_pData = static_cast(m_hData); -#endif - ATLASSERT(m_pData != NULL); - m_pPtr = m_pData + ptrPos; - } - - SecureHelper::memcpy_x(m_pPtr, m_cAllocated - (m_pPtr - m_pData), pData, nData); - - m_pPtr += nData; - } - - void AddString(LPCTSTR lpszStr) - { - if (lpszStr == NULL) - { - WCHAR szEmpty = 0; - AddData(&szEmpty, sizeof(szEmpty)); - } - else - { - USES_CONVERSION; - LPCWSTR lpstr = T2CW(lpszStr); - int nSize = lstrlenW(lpstr) + 1; - AddData(lpstr, nSize * sizeof(WCHAR)); - } - } - - HANDLE m_hData; - LPBYTE m_pData; - LPBYTE m_pPtr; - SIZE_T m_cAllocated; -}; - - -/////////////////////////////////////////////////////////////////////////////// -// Dialog and control macros for indirect dialogs - -// for DLGTEMPLATE -#define BEGIN_DIALOG(x, y, width, height) \ - void DoInitTemplate() \ - { \ - bool bExTemplate = false; \ - short nX = x, nY = y, nWidth = width, nHeight = height; \ - LPCTSTR szCaption = NULL; \ - DWORD dwStyle = WS_POPUP | WS_BORDER | WS_SYSMENU; \ - DWORD dwExStyle = 0; \ - LPCTSTR szFontName = NULL; \ - WORD wFontSize = 0; \ - WORD wWeight = 0; \ - BYTE bItalic = 0; \ - BYTE bCharset = 0; \ - DWORD dwHelpID = 0; \ - ATL::_U_STRINGorID Menu = 0U; \ - ATL::_U_STRINGorID ClassName = 0U; - -// for DLGTEMPLATEEX -#define BEGIN_DIALOG_EX(x, y, width, height, helpID) \ - void DoInitTemplate() \ - { \ - bool bExTemplate = true; \ - short nX = x, nY = y, nWidth = width, nHeight = height; \ - LPCTSTR szCaption = NULL; \ - DWORD dwStyle = WS_POPUP | WS_BORDER | WS_SYSMENU; \ - DWORD dwExStyle = 0; \ - LPCTSTR szFontName = NULL; \ - WORD wFontSize = 0; \ - WORD wWeight = 0; \ - BYTE bItalic = 0; \ - BYTE bCharset = 0; \ - DWORD dwHelpID = helpID; \ - ATL::_U_STRINGorID Menu = 0U; \ - ATL::_U_STRINGorID ClassName = 0U; - -#define END_DIALOG() \ - m_Template.Create(bExTemplate, szCaption, nX, nY, nWidth, nHeight, dwStyle, dwExStyle, szFontName, wFontSize, wWeight, bItalic, bCharset, dwHelpID, ClassName, Menu); \ - }; - -#define DIALOG_CAPTION(caption) \ - szCaption = caption; -#define DIALOG_STYLE(style) \ - dwStyle = style; -#define DIALOG_EXSTYLE(exStyle) \ - dwExStyle = exStyle; -#define DIALOG_FONT(pointSize, typeFace) \ - wFontSize = pointSize; \ - szFontName = typeFace; -#define DIALOG_FONT_EX(pointsize, typeface, weight, italic, charset) \ - ATLASSERT(bExTemplate); \ - wFontSize = pointsize; \ - szFontName = typeface; \ - wWeight = weight; \ - bItalic = italic; \ - bCharset = charset; -#define DIALOG_MENU(menuName) \ - Menu = menuName; -#define DIALOG_CLASS(className) \ - ClassName = className; - -#define BEGIN_CONTROLS_MAP() \ - void DoInitControls() \ - { - -#define END_CONTROLS_MAP() \ - }; - - -#define CONTROL_LTEXT(text, id, x, y, width, height, style, exStyle) \ - m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_STATIC, (WORD)id, x, y, width, height, style | SS_LEFT | WS_GROUP, exStyle, text, NULL, 0); -#define CONTROL_CTEXT(text, id, x, y, width, height, style, exStyle) \ - m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_STATIC, (WORD)id, x, y, width, height, style | SS_CENTER | WS_GROUP, exStyle, text, NULL, 0); -#define CONTROL_RTEXT(text, id, x, y, width, height, style, exStyle) \ - m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_STATIC, (WORD)id, x, y, width, height, style | SS_RIGHT | WS_GROUP, exStyle, text, NULL, 0); -#define CONTROL_PUSHBUTTON(text, id, x, y, width, height, style, exStyle) \ - m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_PUSHBUTTON | WS_TABSTOP, exStyle, text, NULL, 0); -#define CONTROL_DEFPUSHBUTTON(text, id, x, y, width, height, style, exStyle) \ - m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_DEFPUSHBUTTON | WS_TABSTOP, exStyle, text, NULL, 0); -#ifndef _WIN32_WCE -#define CONTROL_PUSHBOX(text, id, x, y, width, height, style, exStyle) \ - m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_PUSHBOX | WS_TABSTOP, exStyle, text, NULL, 0); -#endif // !_WIN32_WCE -#define CONTROL_STATE3(text, id, x, y, width, height, style, exStyle) \ - m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_3STATE | WS_TABSTOP, exStyle, text, NULL, 0); -#define CONTROL_AUTO3STATE(text, id, x, y, width, height, style, exStyle) \ - m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_AUTO3STATE | WS_TABSTOP, exStyle, text, NULL, 0); -#define CONTROL_CHECKBOX(text, id, x, y, width, height, style, exStyle) \ - m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_CHECKBOX | WS_TABSTOP, exStyle, text, NULL, 0); -#define CONTROL_AUTOCHECKBOX(text, id, x, y, width, height, style, exStyle) \ - m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_AUTOCHECKBOX | WS_TABSTOP, exStyle, text, NULL, 0); -#define CONTROL_RADIOBUTTON(text, id, x, y, width, height, style, exStyle) \ - m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_RADIOBUTTON | WS_TABSTOP, exStyle, text, NULL, 0); -#define CONTROL_AUTORADIOBUTTON(text, id, x, y, width, height, style, exStyle) \ - m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_AUTORADIOBUTTON | WS_TABSTOP, exStyle, text, NULL, 0); -#define CONTROL_COMBOBOX(id, x, y, width, height, style, exStyle) \ - m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_COMBOBOX, (WORD)id, x, y, width, height, style | CBS_DROPDOWN | WS_TABSTOP, exStyle, (LPCTSTR)NULL, NULL, 0); -#define CONTROL_EDITTEXT(id, x, y, width, height, style, exStyle) \ - m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_EDIT, (WORD)id, x, y, width, height, style | ES_LEFT | WS_BORDER | WS_TABSTOP, exStyle, (LPCTSTR)NULL, NULL, 0); -#define CONTROL_GROUPBOX(text, id, x, y, width, height, style, exStyle) \ - m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_GROUPBOX, exStyle, text, NULL, 0); -#define CONTROL_LISTBOX(id, x, y, width, height, style, exStyle) \ - m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_LISTBOX, (WORD)id, x, y, width, height, style | LBS_NOTIFY | WS_BORDER, exStyle, (LPCTSTR)NULL, NULL, 0); -#define CONTROL_SCROLLBAR(id, x, y, width, height, style, exStyle) \ - m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_SCROLLBAR, (WORD)id, x, y, width, height, style | SBS_HORZ, exStyle, (LPCTSTR)NULL, NULL, 0); -#define CONTROL_ICON(text, id, x, y, width, height, style, exStyle) \ - m_Template.AddStdControl(WTL::CMemDlgTemplate::CTRL_STATIC, (WORD)id, x, y, width, height, style | SS_ICON, exStyle, text, NULL, 0); -#define CONTROL_CONTROL(text, id, className, style, x, y, width, height, exStyle) \ - m_Template.AddControl(className, (WORD)id, x, y, width, height, style, exStyle, text, NULL, 0); - - -/////////////////////////////////////////////////////////////////////////////// -// CIndirectDialogImpl - dialogs with template in memory - -template > -class ATL_NO_VTABLE CIndirectDialogImpl : public TBase -{ -public: - enum { IDD = 0 }; // no dialog template resource - - TDlgTemplate m_Template; - - void CreateTemplate() - { - T* pT = static_cast(this); - pT->DoInitTemplate(); - pT->DoInitControls(); - } - - INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow(), LPARAM dwInitParam = NULL) - { - T* pT = static_cast(this); - ATLASSERT(pT->m_hWnd == NULL); - - if (!m_Template.IsValid()) - CreateTemplate(); - -#if (_ATL_VER >= 0x0800) - // Allocate the thunk structure here, where we can fail gracefully. - BOOL result = m_thunk.Init(NULL, NULL); - if (result == FALSE) - { - SetLastError(ERROR_OUTOFMEMORY); - return -1; - } -#endif // (_ATL_VER >= 0x0800) - - ModuleHelper::AddCreateWndData(&m_thunk.cd, pT); - -#ifdef _DEBUG - m_bModal = true; -#endif // _DEBUG - - return ::DialogBoxIndirectParam(ModuleHelper::GetResourceInstance(), m_Template.GetTemplatePtr(), hWndParent, (DLGPROC)T::StartDialogProc, dwInitParam); - } - - HWND Create(HWND hWndParent, LPARAM dwInitParam = NULL) - { - T* pT = static_cast(this); - ATLASSERT(pT->m_hWnd == NULL); - - if (!m_Template.IsValid()) - CreateTemplate(); - -#if (_ATL_VER >= 0x0800) - // Allocate the thunk structure here, where we can fail gracefully. - BOOL result = m_thunk.Init(NULL, NULL); - if (result == FALSE) - { - SetLastError(ERROR_OUTOFMEMORY); - return NULL; - } -#endif // (_ATL_VER >= 0x0800) - - ModuleHelper::AddCreateWndData(&m_thunk.cd, pT); - -#ifdef _DEBUG - m_bModal = false; -#endif // _DEBUG - - HWND hWnd = ::CreateDialogIndirectParam(ModuleHelper::GetResourceInstance(), (LPCDLGTEMPLATE)m_Template.GetTemplatePtr(), hWndParent, (DLGPROC)T::StartDialogProc, dwInitParam); - ATLASSERT(m_hWnd == hWnd); - - return hWnd; - } - - // for CComControl - HWND Create(HWND hWndParent, RECT&, LPARAM dwInitParam = NULL) - { - return Create(hWndParent, dwInitParam); - } - - void DoInitTemplate() - { - ATLASSERT(FALSE); // MUST be defined in derived class - } - - void DoInitControls() - { - ATLASSERT(FALSE); // MUST be defined in derived class - } -}; - -/////////////////////////////////////////////////////////////////////////////// -// CPropertySheetWindow - client side for a property sheet - -class CPropertySheetWindow : public ATL::CWindow -{ -public: -// Constructors - CPropertySheetWindow(HWND hWnd = NULL) : ATL::CWindow(hWnd) - { } - - CPropertySheetWindow& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - -// Attributes - int GetPageCount() const - { - ATLASSERT(::IsWindow(m_hWnd)); - HWND hWndTabCtrl = GetTabControl(); - ATLASSERT(hWndTabCtrl != NULL); - return (int)::SendMessage(hWndTabCtrl, TCM_GETITEMCOUNT, 0, 0L); - } - - HWND GetActivePage() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HWND)::SendMessage(m_hWnd, PSM_GETCURRENTPAGEHWND, 0, 0L); - } - - int GetActiveIndex() const - { - ATLASSERT(::IsWindow(m_hWnd)); - HWND hWndTabCtrl = GetTabControl(); - ATLASSERT(hWndTabCtrl != NULL); - return (int)::SendMessage(hWndTabCtrl, TCM_GETCURSEL, 0, 0L); - } - - BOOL SetActivePage(int nPageIndex) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, PSM_SETCURSEL, nPageIndex, 0L); - } - - BOOL SetActivePage(HPROPSHEETPAGE hPage) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(hPage != NULL); - return (BOOL)::SendMessage(m_hWnd, PSM_SETCURSEL, 0, (LPARAM)hPage); - } - - BOOL SetActivePageByID(int nPageID) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, PSM_SETCURSELID, 0, nPageID); - } - - void SetTitle(LPCTSTR lpszText, UINT nStyle = 0) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT((nStyle & ~PSH_PROPTITLE) == 0); // only PSH_PROPTITLE is valid - ATLASSERT(lpszText != NULL); - ::SendMessage(m_hWnd, PSM_SETTITLE, nStyle, (LPARAM)lpszText); - } - - HWND GetTabControl() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HWND)::SendMessage(m_hWnd, PSM_GETTABCONTROL, 0, 0L); - } - - void SetFinishText(LPCTSTR lpszText) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, PSM_SETFINISHTEXT, 0, (LPARAM)lpszText); - } - - void SetWizardButtons(DWORD dwFlags) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::PostMessage(m_hWnd, PSM_SETWIZBUTTONS, 0, dwFlags); - } - -// Operations - BOOL AddPage(HPROPSHEETPAGE hPage) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(hPage != NULL); - return (BOOL)::SendMessage(m_hWnd, PSM_ADDPAGE, 0, (LPARAM)hPage); - } - - BOOL AddPage(LPCPROPSHEETPAGE pPage) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(pPage != NULL); - HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(pPage); - if(hPage == NULL) - return FALSE; - return (BOOL)::SendMessage(m_hWnd, PSM_ADDPAGE, 0, (LPARAM)hPage); - } - -#ifndef _WIN32_WCE - BOOL InsertPage(int nNewPageIndex, HPROPSHEETPAGE hPage) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(hPage != NULL); - return (BOOL)::SendMessage(m_hWnd, PSM_INSERTPAGE, nNewPageIndex, (LPARAM)hPage); - } - - BOOL InsertPage(int nNewPageIndex, LPCPROPSHEETPAGE pPage) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(pPage != NULL); - HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(pPage); - if(hPage == NULL) - return FALSE; - return (BOOL)::SendMessage(m_hWnd, PSM_INSERTPAGE, nNewPageIndex, (LPARAM)hPage); - } - - BOOL InsertPage(HPROPSHEETPAGE hPageInsertAfter, HPROPSHEETPAGE hPage) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(hPage != NULL); - return (BOOL)::SendMessage(m_hWnd, PSM_INSERTPAGE, (WPARAM)hPageInsertAfter, (LPARAM)hPage); - } - - BOOL InsertPage(HPROPSHEETPAGE hPageInsertAfter, LPCPROPSHEETPAGE pPage) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(pPage != NULL); - HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(pPage); - if(hPage == NULL) - return FALSE; - return (BOOL)::SendMessage(m_hWnd, PSM_INSERTPAGE, (WPARAM)hPageInsertAfter, (LPARAM)hPage); - } -#endif // !_WIN32_WCE - - void RemovePage(int nPageIndex) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, PSM_REMOVEPAGE, nPageIndex, 0L); - } - - void RemovePage(HPROPSHEETPAGE hPage) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(hPage != NULL); - ::SendMessage(m_hWnd, PSM_REMOVEPAGE, 0, (LPARAM)hPage); - } - - BOOL PressButton(int nButton) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, PSM_PRESSBUTTON, nButton, 0L); - } - - BOOL Apply() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, PSM_APPLY, 0, 0L); - } - - void CancelToClose() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, PSM_CANCELTOCLOSE, 0, 0L); - } - - void SetModified(HWND hWndPage, BOOL bChanged = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(::IsWindow(hWndPage)); - UINT uMsg = bChanged ? PSM_CHANGED : PSM_UNCHANGED; - ::SendMessage(m_hWnd, uMsg, (WPARAM)hWndPage, 0L); - } - - LRESULT QuerySiblings(WPARAM wParam, LPARAM lParam) - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SendMessage(m_hWnd, PSM_QUERYSIBLINGS, wParam, lParam); - } - - void RebootSystem() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, PSM_REBOOTSYSTEM, 0, 0L); - } - - void RestartWindows() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, PSM_RESTARTWINDOWS, 0, 0L); - } - - BOOL IsDialogMessage(LPMSG lpMsg) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, PSM_ISDIALOGMESSAGE, 0, (LPARAM)lpMsg); - } - -#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) - int HwndToIndex(HWND hWnd) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, PSM_HWNDTOINDEX, (WPARAM)hWnd, 0L); - } - - HWND IndexToHwnd(int nIndex) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HWND)::SendMessage(m_hWnd, PSM_INDEXTOHWND, nIndex, 0L); - } - - int PageToIndex(HPROPSHEETPAGE hPage) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, PSM_PAGETOINDEX, 0, (LPARAM)hPage); - } - - HPROPSHEETPAGE IndexToPage(int nIndex) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HPROPSHEETPAGE)::SendMessage(m_hWnd, PSM_INDEXTOPAGE, nIndex, 0L); - } - - int IdToIndex(int nID) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, PSM_IDTOINDEX, 0, nID); - } - - int IndexToId(int nIndex) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, PSM_INDEXTOID, nIndex, 0L); - } - - int GetResult() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, PSM_GETRESULT, 0, 0L); - } - - BOOL RecalcPageSizes() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, PSM_RECALCPAGESIZES, 0, 0L); - } - - void SetHeaderTitle(int nIndex, LPCTSTR lpstrHeaderTitle) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, PSM_SETHEADERTITLE, nIndex, (LPARAM)lpstrHeaderTitle); - } - - void SetHeaderSubTitle(int nIndex, LPCTSTR lpstrHeaderSubTitle) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, PSM_SETHEADERSUBTITLE, nIndex, (LPARAM)lpstrHeaderSubTitle); - } -#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) - -// Implementation - override to prevent usage - HWND Create(LPCTSTR, HWND, ATL::_U_RECT = NULL, LPCTSTR = NULL, DWORD = 0, DWORD = 0, ATL::_U_MENUorID = 0U, LPVOID = NULL) - { - ATLASSERT(FALSE); - return NULL; - } -}; - -/////////////////////////////////////////////////////////////////////////////// -// CPropertySheetImpl - implements a property sheet - -template -class ATL_NO_VTABLE CPropertySheetImpl : public ATL::CWindowImplBaseT< TBase > -{ -public: - PROPSHEETHEADER m_psh; - ATL::CSimpleArray m_arrPages; - -#if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific - #ifndef PROPSHEET_LINK_SIZE - #define PROPSHEET_LINK_SIZE 128 - #endif // PROPSHEET_LINK_SIZE - TCHAR m_szLink[PROPSHEET_LINK_SIZE]; - static LPCTSTR m_pszTitle; - static LPCTSTR m_pszLink; -#endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) - -// Construction/Destruction - CPropertySheetImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL, UINT uStartPage = 0, HWND hWndParent = NULL) - { - memset(&m_psh, 0, sizeof(PROPSHEETHEADER)); - m_psh.dwSize = sizeof(PROPSHEETHEADER); - m_psh.dwFlags = PSH_USECALLBACK; - m_psh.hInstance = ModuleHelper::GetResourceInstance(); - m_psh.phpage = NULL; // will be set later - m_psh.nPages = 0; // will be set later - m_psh.pszCaption = title.m_lpstr; - m_psh.nStartPage = uStartPage; - m_psh.hwndParent = hWndParent; // if NULL, will be set in DoModal/Create - m_psh.pfnCallback = T::PropSheetCallback; - -#if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific - m_psh.dwFlags |= PSH_MAXIMIZE; - m_szLink[0] = 0; -#endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) - } - - ~CPropertySheetImpl() - { - if(m_arrPages.GetSize() > 0) // sheet never created, destroy all pages - { - for(int i = 0; i < m_arrPages.GetSize(); i++) - ::DestroyPropertySheetPage((HPROPSHEETPAGE)m_arrPages[i]); - } - } - -// Callback function and overrideables - static int CALLBACK PropSheetCallback(HWND hWnd, UINT uMsg, LPARAM lParam) - { - lParam; // avoid level 4 warning - int nRet = 0; - - if(uMsg == PSCB_INITIALIZED) - { - ATLASSERT(hWnd != NULL); - T* pT = (T*)ModuleHelper::ExtractCreateWndData(); - // subclass the sheet window - pT->SubclassWindow(hWnd); - // remove page handles array - pT->_CleanUpPages(); - -#if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific - m_pszTitle = pT->m_psh.pszCaption; - if(*pT->m_szLink != 0) - m_pszLink = pT->m_szLink; -#endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific - - pT->OnSheetInitialized(); - } -#if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific uMsg - else - { - switch(uMsg) - { - case PSCB_GETVERSION : - nRet = COMCTL32_VERSION; - break; - case PSCB_GETTITLE : - if(m_pszTitle != NULL) - { - lstrcpy((LPTSTR)lParam, m_pszTitle); - m_pszTitle = NULL; - } - break; - case PSCB_GETLINKTEXT: - if(m_pszLink != NULL) - { - lstrcpy((LPTSTR)lParam, m_pszLink); - m_pszLink = NULL; - } - break; - default: - break; - } - } -#endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) - - return nRet; - } - - void OnSheetInitialized() - { - } - -// Create method - HWND Create(HWND hWndParent = NULL) - { - ATLASSERT(m_hWnd == NULL); - - m_psh.dwFlags |= PSH_MODELESS; - if(m_psh.hwndParent == NULL) - m_psh.hwndParent = hWndParent; - m_psh.phpage = (HPROPSHEETPAGE*)m_arrPages.GetData(); - m_psh.nPages = m_arrPages.GetSize(); - - T* pT = static_cast(this); - ModuleHelper::AddCreateWndData(&pT->m_thunk.cd, pT); - - HWND hWnd = (HWND)::PropertySheet(&m_psh); - _CleanUpPages(); // ensure clean-up, required if call failed - - ATLASSERT(m_hWnd == hWnd); - - return hWnd; - } - - INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow()) - { - ATLASSERT(m_hWnd == NULL); - - m_psh.dwFlags &= ~PSH_MODELESS; - if(m_psh.hwndParent == NULL) - m_psh.hwndParent = hWndParent; - m_psh.phpage = (HPROPSHEETPAGE*)m_arrPages.GetData(); - m_psh.nPages = m_arrPages.GetSize(); - - T* pT = static_cast(this); - ModuleHelper::AddCreateWndData(&pT->m_thunk.cd, pT); - - INT_PTR nRet = ::PropertySheet(&m_psh); - _CleanUpPages(); // ensure clean-up, required if call failed - - return nRet; - } - - // implementation helper - clean up pages array - void _CleanUpPages() - { - m_psh.nPages = 0; - m_psh.phpage = NULL; - m_arrPages.RemoveAll(); - } - -// Attributes (extended overrides of client class methods) -// These now can be called before the sheet is created -// Note: Calling these after the sheet is created gives unpredictable results - int GetPageCount() const - { - if(m_hWnd == NULL) // not created yet - return m_arrPages.GetSize(); - return TBase::GetPageCount(); - } - - int GetActiveIndex() const - { - if(m_hWnd == NULL) // not created yet - return m_psh.nStartPage; - return TBase::GetActiveIndex(); - } - - HPROPSHEETPAGE GetPage(int nPageIndex) const - { - ATLASSERT(m_hWnd == NULL); // can't do this after it's created - return (HPROPSHEETPAGE)m_arrPages[nPageIndex]; - } - - int GetPageIndex(HPROPSHEETPAGE hPage) const - { - ATLASSERT(m_hWnd == NULL); // can't do this after it's created - return m_arrPages.Find((HPROPSHEETPAGE&)hPage); - } - - BOOL SetActivePage(int nPageIndex) - { - if(m_hWnd == NULL) // not created yet - { - ATLASSERT(nPageIndex >= 0 && nPageIndex < m_arrPages.GetSize()); - m_psh.nStartPage = nPageIndex; - return TRUE; - } - return TBase::SetActivePage(nPageIndex); - } - - BOOL SetActivePage(HPROPSHEETPAGE hPage) - { - ATLASSERT(hPage != NULL); - if (m_hWnd == NULL) // not created yet - { - int nPageIndex = GetPageIndex(hPage); - if(nPageIndex == -1) - return FALSE; - - return SetActivePage(nPageIndex); - } - return TBase::SetActivePage(hPage); - - } - - void SetTitle(LPCTSTR lpszText, UINT nStyle = 0) - { - ATLASSERT((nStyle & ~PSH_PROPTITLE) == 0); // only PSH_PROPTITLE is valid - ATLASSERT(lpszText != NULL); - - if(m_hWnd == NULL) - { - // set internal state - m_psh.pszCaption = lpszText; // must exist until sheet is created - m_psh.dwFlags &= ~PSH_PROPTITLE; - m_psh.dwFlags |= nStyle; - } - else - { - // set external state - TBase::SetTitle(lpszText, nStyle); - } - } - -#if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific Link field - void SetLinkText(LPCTSTR lpszText) - { - ATLASSERT(lpszText != NULL); - ATLASSERT(lstrlen(lpszText) < PROPSHEET_LINK_SIZE); - lstrcpy(m_szLink, lpszText); - } -#endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) - - void SetWizardMode() - { - m_psh.dwFlags |= PSH_WIZARD; - } - - void EnableHelp() - { - m_psh.dwFlags |= PSH_HASHELP; - } - -// Operations - BOOL AddPage(HPROPSHEETPAGE hPage) - { - ATLASSERT(hPage != NULL); - BOOL bRet = FALSE; - if(m_hWnd != NULL) - bRet = TBase::AddPage(hPage); - else // sheet not created yet, use internal data - bRet = m_arrPages.Add((HPROPSHEETPAGE&)hPage); - return bRet; - } - - BOOL AddPage(LPCPROPSHEETPAGE pPage) - { - ATLASSERT(pPage != NULL); - HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(pPage); - if(hPage == NULL) - return FALSE; - BOOL bRet = AddPage(hPage); - if(!bRet) - ::DestroyPropertySheetPage(hPage); - return bRet; - } - - BOOL RemovePage(HPROPSHEETPAGE hPage) - { - ATLASSERT(hPage != NULL); - if (m_hWnd == NULL) // not created yet - { - int nPage = GetPageIndex(hPage); - if(nPage == -1) - return FALSE; - return RemovePage(nPage); - } - TBase::RemovePage(hPage); - return TRUE; - - } - - BOOL RemovePage(int nPageIndex) - { - BOOL bRet = TRUE; - if(m_hWnd != NULL) - TBase::RemovePage(nPageIndex); - else // sheet not created yet, use internal data - bRet = m_arrPages.RemoveAt(nPageIndex); - return bRet; - } - -#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) - void SetHeader(LPCTSTR szbmHeader) - { - ATLASSERT(m_hWnd == NULL); // can't do this after it's created - - m_psh.dwFlags &= ~PSH_WIZARD; - m_psh.dwFlags |= (PSH_HEADER | PSH_WIZARD97); - m_psh.pszbmHeader = szbmHeader; - } - - void SetHeader(HBITMAP hbmHeader) - { - ATLASSERT(m_hWnd == NULL); // can't do this after it's created - - m_psh.dwFlags &= ~PSH_WIZARD; - m_psh.dwFlags |= (PSH_HEADER | PSH_USEHBMHEADER | PSH_WIZARD97); - m_psh.hbmHeader = hbmHeader; - } - - void SetWatermark(LPCTSTR szbmWatermark, HPALETTE hplWatermark = NULL) - { - ATLASSERT(m_hWnd == NULL); // can't do this after it's created - - m_psh.dwFlags &= ~PSH_WIZARD; - m_psh.dwFlags |= PSH_WATERMARK | PSH_WIZARD97; - m_psh.pszbmWatermark = szbmWatermark; - - if (hplWatermark != NULL) - { - m_psh.dwFlags |= PSH_USEHPLWATERMARK; - m_psh.hplWatermark = hplWatermark; - } - } - - void SetWatermark(HBITMAP hbmWatermark, HPALETTE hplWatermark = NULL) - { - ATLASSERT(m_hWnd == NULL); // can't do this after it's created - - m_psh.dwFlags &= ~PSH_WIZARD; - m_psh.dwFlags |= (PSH_WATERMARK | PSH_USEHBMWATERMARK | PSH_WIZARD97); - m_psh.hbmWatermark = hbmWatermark; - - if (hplWatermark != NULL) - { - m_psh.dwFlags |= PSH_USEHPLWATERMARK; - m_psh.hplWatermark = hplWatermark; - } - } - - void StretchWatermark(bool bStretchWatermark) - { - ATLASSERT(m_hWnd == NULL); // can't do this after it's created - if (bStretchWatermark) - m_psh.dwFlags |= PSH_STRETCHWATERMARK; - else - m_psh.dwFlags &= ~PSH_STRETCHWATERMARK; - } -#endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) - -// Message map and handlers - BEGIN_MSG_MAP(CPropertySheetImpl) - MESSAGE_HANDLER(WM_COMMAND, OnCommand) - MESSAGE_HANDLER(WM_SYSCOMMAND, OnSysCommand) - END_MSG_MAP() - - LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) - { - LRESULT lRet = DefWindowProc(uMsg, wParam, lParam); - if(HIWORD(wParam) == BN_CLICKED && (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) && - ((m_psh.dwFlags & PSH_MODELESS) != 0) && (GetActivePage() == NULL)) - DestroyWindow(); - return lRet; - } - - LRESULT OnSysCommand(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) - { - if(((m_psh.dwFlags & PSH_MODELESS) == PSH_MODELESS) && ((wParam & 0xFFF0) == SC_CLOSE)) - SendMessage(WM_CLOSE); - else - bHandled = FALSE; - return 0; - } -}; - -#if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC static pointers -template < class T, class TBase > -LPCWSTR CPropertySheetImpl::m_pszTitle = NULL; -template < class T, class TBase> -LPCWSTR CPropertySheetImpl::m_pszLink = NULL; -#endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) - -// for non-customized sheets -class CPropertySheet : public CPropertySheetImpl -{ -public: - CPropertySheet(ATL::_U_STRINGorID title = (LPCTSTR)NULL, UINT uStartPage = 0, HWND hWndParent = NULL) - : CPropertySheetImpl(title, uStartPage, hWndParent) - { } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CPropertyPageWindow - client side for a property page - -class CPropertyPageWindow : public ATL::CWindow -{ -public: -// Constructors - CPropertyPageWindow(HWND hWnd = NULL) : ATL::CWindow(hWnd) - { } - - CPropertyPageWindow& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - -// Attributes - CPropertySheetWindow GetPropertySheet() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return CPropertySheetWindow(GetParent()); - } - -// Operations - BOOL Apply() - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(GetParent() != NULL); - return GetPropertySheet().Apply(); - } - - void CancelToClose() - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(GetParent() != NULL); - GetPropertySheet().CancelToClose(); - } - - void SetModified(BOOL bChanged = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(GetParent() != NULL); - GetPropertySheet().SetModified(m_hWnd, bChanged); - } - - LRESULT QuerySiblings(WPARAM wParam, LPARAM lParam) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(GetParent() != NULL); - return GetPropertySheet().QuerySiblings(wParam, lParam); - } - - void RebootSystem() - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(GetParent() != NULL); - GetPropertySheet().RebootSystem(); - } - - void RestartWindows() - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(GetParent() != NULL); - GetPropertySheet().RestartWindows(); - } - - void SetWizardButtons(DWORD dwFlags) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(GetParent() != NULL); - GetPropertySheet().SetWizardButtons(dwFlags); - } - -// Implementation - overrides to prevent usage - HWND Create(LPCTSTR, HWND, ATL::_U_RECT = NULL, LPCTSTR = NULL, DWORD = 0, DWORD = 0, ATL::_U_MENUorID = 0U, LPVOID = NULL) - { - ATLASSERT(FALSE); - return NULL; - } -}; - -/////////////////////////////////////////////////////////////////////////////// -// CPropertyPageImpl - implements a property page - -template -class ATL_NO_VTABLE CPropertyPageImpl : public ATL::CDialogImplBaseT< TBase > -{ -public: - PROPSHEETPAGE m_psp; - - operator PROPSHEETPAGE*() { return &m_psp; } - -// Construction - CPropertyPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) - { - // initialize PROPSHEETPAGE struct - memset(&m_psp, 0, sizeof(PROPSHEETPAGE)); - m_psp.dwSize = sizeof(PROPSHEETPAGE); - m_psp.dwFlags = PSP_USECALLBACK; - m_psp.hInstance = ModuleHelper::GetResourceInstance(); - T* pT = static_cast(this); - m_psp.pszTemplate = MAKEINTRESOURCE(pT->IDD); - m_psp.pfnDlgProc = (DLGPROC)T::StartDialogProc; - m_psp.pfnCallback = T::PropPageCallback; - m_psp.lParam = (LPARAM)pT; - - if(title.m_lpstr != NULL) - SetTitle(title); - } - -// Callback function and overrideables - static UINT CALLBACK PropPageCallback(HWND hWnd, UINT uMsg, LPPROPSHEETPAGE ppsp) - { - hWnd; // avoid level 4 warning - ATLASSERT(hWnd == NULL); - T* pT = (T*)ppsp->lParam; - UINT uRet = 0; - - switch(uMsg) - { - case PSPCB_CREATE: - { - ATL::CDialogImplBaseT< TBase >* pPage = (ATL::CDialogImplBaseT< TBase >*)pT; - ModuleHelper::AddCreateWndData(&pPage->m_thunk.cd, pPage); - uRet = pT->OnPageCreate() ? 1 : 0; - } - break; -#if (_WIN32_IE >= 0x0500) - case PSPCB_ADDREF: - pT->OnPageAddRef(); - break; -#endif // (_WIN32_IE >= 0x0500) - case PSPCB_RELEASE: - pT->OnPageRelease(); - break; - default: - break; - } - - return uRet; - } - - bool OnPageCreate() - { - return true; // true - allow page to be created, false - prevent creation - } - -#if (_WIN32_IE >= 0x0500) - void OnPageAddRef() - { - } -#endif // (_WIN32_IE >= 0x0500) - - void OnPageRelease() - { - } - -// Create method - HPROPSHEETPAGE Create() - { - return ::CreatePropertySheetPage(&m_psp); - } - -// Attributes - void SetTitle(ATL::_U_STRINGorID title) - { - m_psp.pszTitle = title.m_lpstr; - m_psp.dwFlags |= PSP_USETITLE; - } - -#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) - void SetHeaderTitle(LPCTSTR lpstrHeaderTitle) - { - ATLASSERT(m_hWnd == NULL); // can't do this after it's created - m_psp.dwFlags |= PSP_USEHEADERTITLE; - m_psp.pszHeaderTitle = lpstrHeaderTitle; - } - - void SetHeaderSubTitle(LPCTSTR lpstrHeaderSubTitle) - { - ATLASSERT(m_hWnd == NULL); // can't do this after it's created - m_psp.dwFlags |= PSP_USEHEADERSUBTITLE; - m_psp.pszHeaderSubTitle = lpstrHeaderSubTitle; - } -#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) - -// Operations - void EnableHelp() - { - m_psp.dwFlags |= PSP_HASHELP; - } - -// Message map and handlers - BEGIN_MSG_MAP(CPropertyPageImpl) - MESSAGE_HANDLER(WM_NOTIFY, OnNotify) - END_MSG_MAP() - - // NOTE: Define _WTL_NEW_PAGE_NOTIFY_HANDLERS to use new notification - // handlers that return direct values without any restrictions - LRESULT OnNotify(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) - { -#ifndef _WIN32_WCE - // This notification is sometimes received on Windows CE after the window is already destroyed - ATLASSERT(::IsWindow(m_hWnd)); -#endif - NMHDR* pNMHDR = (NMHDR*)lParam; - - // don't handle messages not from the page/sheet itself - if(pNMHDR->hwndFrom != m_hWnd && pNMHDR->hwndFrom != ::GetParent(m_hWnd)) - { - bHandled = FALSE; - return 1; - } -#ifdef _WIN32_WCE - ATLASSERT(::IsWindow(m_hWnd)); -#endif - - T* pT = static_cast(this); - LRESULT lResult = 0; - switch(pNMHDR->code) - { -#ifdef _WTL_NEW_PAGE_NOTIFY_HANDLERS - case PSN_SETACTIVE: - lResult = pT->OnSetActive(); - break; - case PSN_KILLACTIVE: - lResult = pT->OnKillActive(); - break; - case PSN_APPLY: - lResult = pT->OnApply(); - break; - case PSN_RESET: - pT->OnReset(); - break; - case PSN_QUERYCANCEL: - lResult = pT->OnQueryCancel(); - break; - case PSN_WIZNEXT: - lResult = pT->OnWizardNext(); - break; - case PSN_WIZBACK: - lResult = pT->OnWizardBack(); - break; - case PSN_WIZFINISH: - lResult = pT->OnWizardFinish(); - break; - case PSN_HELP: - pT->OnHelp(); - break; -#ifndef _WIN32_WCE -#if (_WIN32_IE >= 0x0400) - case PSN_GETOBJECT: - if(!pT->OnGetObject((LPNMOBJECTNOTIFY)lParam)) - bHandled = FALSE; - break; -#endif // (_WIN32_IE >= 0x0400) -#if (_WIN32_IE >= 0x0500) - case PSN_TRANSLATEACCELERATOR: - { - LPPSHNOTIFY lpPSHNotify = (LPPSHNOTIFY)lParam; - lResult = pT->OnTranslateAccelerator((LPMSG)lpPSHNotify->lParam); - } - break; - case PSN_QUERYINITIALFOCUS: - { - LPPSHNOTIFY lpPSHNotify = (LPPSHNOTIFY)lParam; - lResult = (LRESULT)pT->OnQueryInitialFocus((HWND)lpPSHNotify->lParam); - } - break; -#endif // (_WIN32_IE >= 0x0500) -#endif // !_WIN32_WCE - -#else // !_WTL_NEW_PAGE_NOTIFY_HANDLERS - case PSN_SETACTIVE: - lResult = pT->OnSetActive() ? 0 : -1; - break; - case PSN_KILLACTIVE: - lResult = !pT->OnKillActive(); - break; - case PSN_APPLY: - lResult = pT->OnApply() ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE; - break; - case PSN_RESET: - pT->OnReset(); - break; - case PSN_QUERYCANCEL: - lResult = !pT->OnQueryCancel(); - break; - case PSN_WIZNEXT: - lResult = pT->OnWizardNext(); - break; - case PSN_WIZBACK: - lResult = pT->OnWizardBack(); - break; - case PSN_WIZFINISH: - lResult = !pT->OnWizardFinish(); - break; - case PSN_HELP: - pT->OnHelp(); - break; -#ifndef _WIN32_WCE -#if (_WIN32_IE >= 0x0400) - case PSN_GETOBJECT: - if(!pT->OnGetObject((LPNMOBJECTNOTIFY)lParam)) - bHandled = FALSE; - break; -#endif // (_WIN32_IE >= 0x0400) -#if (_WIN32_IE >= 0x0500) - case PSN_TRANSLATEACCELERATOR: - { - LPPSHNOTIFY lpPSHNotify = (LPPSHNOTIFY)lParam; - lResult = pT->OnTranslateAccelerator((LPMSG)lpPSHNotify->lParam) ? PSNRET_MESSAGEHANDLED : PSNRET_NOERROR; - } - break; - case PSN_QUERYINITIALFOCUS: - { - LPPSHNOTIFY lpPSHNotify = (LPPSHNOTIFY)lParam; - lResult = (LRESULT)pT->OnQueryInitialFocus((HWND)lpPSHNotify->lParam); - } - break; -#endif // (_WIN32_IE >= 0x0500) -#endif // !_WIN32_WCE - -#endif // !_WTL_NEW_PAGE_NOTIFY_HANDLERS - default: - bHandled = FALSE; // not handled - } - - return lResult; - } - -// Overridables - // NOTE: Define _WTL_NEW_PAGE_NOTIFY_HANDLERS to use new notification - // handlers that return direct values without any restrictions -#ifdef _WTL_NEW_PAGE_NOTIFY_HANDLERS - int OnSetActive() - { - // 0 = allow activate - // -1 = go back that was active - // page ID = jump to page - return 0; - } - - BOOL OnKillActive() - { - // FALSE = allow deactivate - // TRUE = prevent deactivation - return FALSE; - } - - int OnApply() - { - // PSNRET_NOERROR = apply OK - // PSNRET_INVALID = apply not OK, return to this page - // PSNRET_INVALID_NOCHANGEPAGE = apply not OK, don't change focus - return PSNRET_NOERROR; - } - - void OnReset() - { - } - - BOOL OnQueryCancel() - { - // FALSE = allow cancel - // TRUE = prevent cancel - return FALSE; - } - - int OnWizardBack() - { - // 0 = goto previous page - // -1 = prevent page change - // >0 = jump to page by dlg ID - return 0; - } - - int OnWizardNext() - { - // 0 = goto next page - // -1 = prevent page change - // >0 = jump to page by dlg ID - return 0; - } - - INT_PTR OnWizardFinish() - { - // FALSE = allow finish - // TRUE = prevent finish - // HWND = prevent finish and set focus to HWND (CommCtrl 5.80 only) - return FALSE; - } - - void OnHelp() - { - } - -#ifndef _WIN32_WCE -#if (_WIN32_IE >= 0x0400) - BOOL OnGetObject(LPNMOBJECTNOTIFY /*lpObjectNotify*/) - { - return FALSE; // not processed - } -#endif // (_WIN32_IE >= 0x0400) - -#if (_WIN32_IE >= 0x0500) - int OnTranslateAccelerator(LPMSG /*lpMsg*/) - { - // PSNRET_NOERROR - message not handled - // PSNRET_MESSAGEHANDLED - message handled - return PSNRET_NOERROR; - } - - HWND OnQueryInitialFocus(HWND /*hWndFocus*/) - { - // NULL = set focus to default control - // HWND = set focus to HWND - return NULL; - } -#endif // (_WIN32_IE >= 0x0500) -#endif // !_WIN32_WCE - -#else // !_WTL_NEW_PAGE_NOTIFY_HANDLERS - BOOL OnSetActive() - { - return TRUE; - } - - BOOL OnKillActive() - { - return TRUE; - } - - BOOL OnApply() - { - return TRUE; - } - - void OnReset() - { - } - - BOOL OnQueryCancel() - { - return TRUE; // ok to cancel - } - - int OnWizardBack() - { - // 0 = goto previous page - // -1 = prevent page change - // >0 = jump to page by dlg ID - return 0; - } - - int OnWizardNext() - { - // 0 = goto next page - // -1 = prevent page change - // >0 = jump to page by dlg ID - return 0; - } - - BOOL OnWizardFinish() - { - return TRUE; - } - - void OnHelp() - { - } - -#ifndef _WIN32_WCE -#if (_WIN32_IE >= 0x0400) - BOOL OnGetObject(LPNMOBJECTNOTIFY /*lpObjectNotify*/) - { - return FALSE; // not processed - } -#endif // (_WIN32_IE >= 0x0400) - -#if (_WIN32_IE >= 0x0500) - BOOL OnTranslateAccelerator(LPMSG /*lpMsg*/) - { - return FALSE; // not translated - } - - HWND OnQueryInitialFocus(HWND /*hWndFocus*/) - { - return NULL; // default - } -#endif // (_WIN32_IE >= 0x0500) -#endif // !_WIN32_WCE - -#endif // !_WTL_NEW_PAGE_NOTIFY_HANDLERS -}; - -// for non-customized pages -template -class CPropertyPage : public CPropertyPageImpl > -{ -public: - enum { IDD = t_wDlgTemplateID }; - - CPropertyPage(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CPropertyPageImpl(title) - { } - - DECLARE_EMPTY_MSG_MAP() -}; - -/////////////////////////////////////////////////////////////////////////////// -// CAxPropertyPageImpl - property page that hosts ActiveX controls - -#ifndef _ATL_NO_HOSTING - -// Note: You must #include to use these classes - -template -class ATL_NO_VTABLE CAxPropertyPageImpl : public CPropertyPageImpl< T, TBase > -{ -public: -// Data members - HGLOBAL m_hInitData; - HGLOBAL m_hDlgRes; - HGLOBAL m_hDlgResSplit; - -// Constructor/destructor - CAxPropertyPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : - CPropertyPageImpl< T, TBase >(title), - m_hInitData(NULL), m_hDlgRes(NULL), m_hDlgResSplit(NULL) - { - T* pT = static_cast(this); - pT; // avoid level 4 warning - - // initialize ActiveX hosting and modify dialog template - ATL::AtlAxWinInit(); - - HINSTANCE hInstance = ModuleHelper::GetResourceInstance(); - LPCTSTR lpTemplateName = MAKEINTRESOURCE(pT->IDD); - HRSRC hDlg = ::FindResource(hInstance, lpTemplateName, (LPTSTR)RT_DIALOG); - if(hDlg != NULL) - { - HRSRC hDlgInit = ::FindResource(hInstance, lpTemplateName, (LPTSTR)_ATL_RT_DLGINIT); - - BYTE* pInitData = NULL; - if(hDlgInit != NULL) - { - m_hInitData = ::LoadResource(hInstance, hDlgInit); - pInitData = (BYTE*)::LockResource(m_hInitData); - } - - m_hDlgRes = ::LoadResource(hInstance, hDlg); - DLGTEMPLATE* pDlg = (DLGTEMPLATE*)::LockResource(m_hDlgRes); - LPCDLGTEMPLATE lpDialogTemplate = ATL::_DialogSplitHelper::SplitDialogTemplate(pDlg, pInitData); - if(lpDialogTemplate != pDlg) - m_hDlgResSplit = GlobalHandle(lpDialogTemplate); - - // set up property page to use in-memory dialog template - if(lpDialogTemplate != NULL) - { - m_psp.dwFlags |= PSP_DLGINDIRECT; - m_psp.pResource = lpDialogTemplate; - } - else - { - ATLASSERT(FALSE && _T("CAxPropertyPageImpl - ActiveX initializtion failed!")); - } - } - else - { - ATLASSERT(FALSE && _T("CAxPropertyPageImpl - Cannot find dialog template!")); - } - } - - ~CAxPropertyPageImpl() - { - if(m_hInitData != NULL) - { - UnlockResource(m_hInitData); - FreeResource(m_hInitData); - } - if(m_hDlgRes != NULL) - { - UnlockResource(m_hDlgRes); - FreeResource(m_hDlgRes); - } - if(m_hDlgResSplit != NULL) - { - ::GlobalFree(m_hDlgResSplit); - } - } - -// Methods - // call this one to handle keyboard message for ActiveX controls - BOOL PreTranslateMessage(LPMSG pMsg) - { - if ((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) && - (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST)) - return FALSE; - // find a direct child of the dialog from the window that has focus - HWND hWndCtl = ::GetFocus(); - if (IsChild(hWndCtl) && ::GetParent(hWndCtl) != m_hWnd) - { - do - { - hWndCtl = ::GetParent(hWndCtl); - } - while (::GetParent(hWndCtl) != m_hWnd); - } - // give controls a chance to translate this message - return (BOOL)::SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)pMsg); - } - -// Overridables -#if (_WIN32_IE >= 0x0500) - // new default implementation for ActiveX hosting pages -#ifdef _WTL_NEW_PAGE_NOTIFY_HANDLERS - int OnTranslateAccelerator(LPMSG lpMsg) - { - T* pT = static_cast(this); - return (pT->PreTranslateMessage(lpMsg) != FALSE) ? PSNRET_MESSAGEHANDLED : PSNRET_NOERROR; - } -#else // !_WTL_NEW_PAGE_NOTIFY_HANDLERS - BOOL OnTranslateAccelerator(LPMSG lpMsg) - { - T* pT = static_cast(this); - return pT->PreTranslateMessage(lpMsg); - } -#endif // !_WTL_NEW_PAGE_NOTIFY_HANDLERS -#endif // (_WIN32_IE >= 0x0500) - -// Support for new stuff in ATL7 -#if (_ATL_VER >= 0x0700) - int GetIDD() - { - return( static_cast(this)->IDD ); - } - - virtual DLGPROC GetDialogProc() - { - return DialogProc; - } - - static INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) - { - CAxPropertyPageImpl< T, TBase >* pThis = (CAxPropertyPageImpl< T, TBase >*)hWnd; - if (uMsg == WM_INITDIALOG) - { - HRESULT hr; - if (FAILED(hr = pThis->CreateActiveXControls(pThis->GetIDD()))) - { - ATLASSERT(FALSE); - return FALSE; - } - } - return CPropertyPageImpl< T, TBase >::DialogProc(hWnd, uMsg, wParam, lParam); - } - -// ActiveX controls creation - virtual HRESULT CreateActiveXControls(UINT nID) - { - // Load dialog template and InitData - HRSRC hDlgInit = ::FindResource(ATL::_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(nID), (LPTSTR)_ATL_RT_DLGINIT); - BYTE* pInitData = NULL; - HGLOBAL hData = NULL; - HRESULT hr = S_OK; - if (hDlgInit != NULL) - { - hData = ::LoadResource(ATL::_AtlBaseModule.GetResourceInstance(), hDlgInit); - if (hData != NULL) - pInitData = (BYTE*) ::LockResource(hData); - } - - HRSRC hDlg = ::FindResource(ATL::_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(nID), (LPTSTR)RT_DIALOG); - if (hDlg != NULL) - { - HGLOBAL hResource = ::LoadResource(ATL::_AtlBaseModule.GetResourceInstance(), hDlg); - DLGTEMPLATE* pDlg = NULL; - if (hResource != NULL) - { - pDlg = (DLGTEMPLATE*) ::LockResource(hResource); - if (pDlg != NULL) - { - // Get first control on the template - BOOL bDialogEx = ATL::_DialogSplitHelper::IsDialogEx(pDlg); - WORD nItems = ATL::_DialogSplitHelper::DlgTemplateItemCount(pDlg); - - // Get first control on the dialog - DLGITEMTEMPLATE* pItem = ATL::_DialogSplitHelper::FindFirstDlgItem(pDlg); - HWND hWndPrev = GetWindow(GW_CHILD); - - // Create all ActiveX cotnrols in the dialog template and place them in the correct tab order (z-order) - for (WORD nItem = 0; nItem < nItems; nItem++) - { - DWORD wID = bDialogEx ? ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->id : pItem->id; - if (ATL::_DialogSplitHelper::IsActiveXControl(pItem, bDialogEx)) - { - BYTE* pData = NULL; - DWORD dwLen = ATL::_DialogSplitHelper::FindCreateData(wID, pInitData, &pData); - ATL::CComPtr spStream; - if (dwLen != 0) - { - HGLOBAL h = GlobalAlloc(GHND, dwLen); - if (h != NULL) - { - BYTE* pBytes = (BYTE*) GlobalLock(h); - BYTE* pSource = pData; - SecureHelper::memcpy_x(pBytes, dwLen, pSource, dwLen); - GlobalUnlock(h); - CreateStreamOnHGlobal(h, TRUE, &spStream); - } - else - { - hr = E_OUTOFMEMORY; - break; - } - } - - ATL::CComBSTR bstrLicKey; - hr = ATL::_DialogSplitHelper::ParseInitData(spStream, &bstrLicKey.m_str); - if (SUCCEEDED(hr)) - { - ATL::CAxWindow2 wnd; - // Get control caption. - LPWSTR pszClassName = - bDialogEx ? - (LPWSTR)(((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem) + 1) : - (LPWSTR)(pItem + 1); - // Get control rect. - RECT rect; - rect.left = - bDialogEx ? - ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->x : - pItem->x; - rect.top = - bDialogEx ? - ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->y : - pItem->y; - rect.right = rect.left + - (bDialogEx ? - ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->cx : - pItem->cx); - rect.bottom = rect.top + - (bDialogEx ? - ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->cy : - pItem->cy); - - // Convert from dialog units to screen units - MapDialogRect(&rect); - - // Create AxWindow with a NULL caption. - wnd.Create(m_hWnd, - &rect, - NULL, - (bDialogEx ? - ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->style : - pItem->style) | WS_TABSTOP, - bDialogEx ? - ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->exStyle : - 0, - bDialogEx ? - ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->id : - pItem->id, - NULL); - - if (wnd != NULL) - { -#ifndef _WIN32_WCE - // Set the Help ID - if (bDialogEx && ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->helpID != 0) - wnd.SetWindowContextHelpId(((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->helpID); -#endif // !_WIN32_WCE - // Try to create the ActiveX control. - hr = wnd.CreateControlLic(pszClassName, spStream, NULL, bstrLicKey); - if (FAILED(hr)) - break; - // Set the correct tab position. - if (nItem == 0) - hWndPrev = HWND_TOP; - wnd.SetWindowPos(hWndPrev, 0,0,0,0,SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); - hWndPrev = wnd; - } - else - { - hr = ATL::AtlHresultFromLastError(); - } - } - } - else - { - if (nItem != 0) - hWndPrev = ::GetWindow(hWndPrev, GW_HWNDNEXT); - } - pItem = ATL::_DialogSplitHelper::FindNextDlgItem(pItem, bDialogEx); - } - } - else - hr = ATL::AtlHresultFromLastError(); - } - else - hr = ATL::AtlHresultFromLastError(); - } - return hr; - } - -// Event handling support - HRESULT AdviseSinkMap(bool bAdvise) - { - if(!bAdvise && m_hWnd == NULL) - { - // window is gone, controls are already unadvised - ATLTRACE2(atlTraceUI, 0, _T("CAxPropertyPageImpl::AdviseSinkMap called after the window was destroyed\n")); - return S_OK; - } - HRESULT hRet = E_NOTIMPL; - __if_exists(T::_GetSinkMapFinder) - { - T* pT = static_cast(this); - hRet = AtlAdviseSinkMap(pT, bAdvise); - } - return hRet; - } - -// Message map and handlers - typedef CPropertyPageImpl< T, TBase> _baseClass; - BEGIN_MSG_MAP(CAxPropertyPageImpl) - MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) - MESSAGE_HANDLER(WM_DESTROY, OnDestroy) - CHAIN_MSG_MAP(_baseClass) - END_MSG_MAP() - - LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - // initialize controls in dialog with DLGINIT resource section - ExecuteDlgInit(static_cast(this)->IDD); - AdviseSinkMap(true); - bHandled = FALSE; - return 1; - } - - LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - AdviseSinkMap(false); - bHandled = FALSE; - return 1; - } -#endif // (_ATL_VER >= 0x0700) -}; - -// for non-customized pages -template -class CAxPropertyPage : public CAxPropertyPageImpl > -{ -public: - enum { IDD = t_wDlgTemplateID }; - - CAxPropertyPage(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CAxPropertyPageImpl(title) - { } - -#if (_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700) - // not empty so we handle accelerators/create controls - BEGIN_MSG_MAP(CAxPropertyPage) - CHAIN_MSG_MAP(CAxPropertyPageImpl >) - END_MSG_MAP() -#else // !((_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700)) - DECLARE_EMPTY_MSG_MAP() -#endif // !((_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700)) -}; - -#endif // _ATL_NO_HOSTING - - -/////////////////////////////////////////////////////////////////////////////// -// Wizard97 Support - -#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) - -// Sample wizard dialog resources: -// -// IDD_WIZ97_INTERIOR_BLANK DIALOG 0, 0, 317, 143 -// STYLE DS_SETFONT | WS_CHILD | WS_DISABLED | WS_CAPTION -// CAPTION "Wizard97 Property Page - Interior" -// FONT 8, "MS Shell Dlg" -// BEGIN -// END -// -// IDD_WIZ97_EXTERIOR_BLANK DIALOGEX 0, 0, 317, 193 -// STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION -// CAPTION "Wizard97 Property Page - Welcome/Complete" -// FONT 8, "MS Shell Dlg", 0, 0, 0x0 -// BEGIN -// LTEXT "Welcome to the X Wizard",IDC_WIZ97_EXTERIOR_TITLE,115,8, -// 195,24 -// LTEXT "Wizard Explanation\r\n(The height of the static text should be in multiples of 8 dlus)", -// IDC_STATIC,115,40,195,16 -// LTEXT "h",IDC_WIZ97_BULLET1,118,64,8,8 -// LTEXT "List Item 1 (the h is turned into a bullet)",IDC_STATIC, -// 127,63,122,8 -// LTEXT "h",IDC_WIZ97_BULLET2,118,79,8,8 -// LTEXT "List Item 2. Keep 7 dlus between paragraphs",IDC_STATIC, -// 127,78,33,8 -// CONTROL "&Do not show this Welcome page again", -// IDC_WIZ97_WELCOME_NOTAGAIN,"Button",BS_AUTOCHECKBOX | -// WS_TABSTOP,115,169,138,10 -// END -// -// GUIDELINES DESIGNINFO -// BEGIN -// IDD_WIZ97_INTERIOR_BLANK, DIALOG -// BEGIN -// LEFTMARGIN, 7 -// RIGHTMARGIN, 310 -// VERTGUIDE, 21 -// VERTGUIDE, 31 -// VERTGUIDE, 286 -// VERTGUIDE, 296 -// TOPMARGIN, 7 -// BOTTOMMARGIN, 136 -// HORZGUIDE, 8 -// END -// -// IDD_WIZ97_EXTERIOR_BLANK, DIALOG -// BEGIN -// RIGHTMARGIN, 310 -// VERTGUIDE, 115 -// VERTGUIDE, 118 -// VERTGUIDE, 127 -// TOPMARGIN, 7 -// BOTTOMMARGIN, 186 -// HORZGUIDE, 8 -// HORZGUIDE, 32 -// HORZGUIDE, 40 -// HORZGUIDE, 169 -// END -// END - -/////////////////////////////////////////////////////////////////////////////// -// CWizard97SheetWindow - client side for a Wizard 97 style wizard sheet - -class CWizard97SheetWindow : public CPropertySheetWindow -{ -public: -// Constructors - CWizard97SheetWindow(HWND hWnd = NULL) : CPropertySheetWindow(hWnd) - { } - - CWizard97SheetWindow& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - -// Operations - HFONT GetExteriorPageTitleFont(void) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HFONT)::SendMessage(m_hWnd, GetMessage_GetExteriorPageTitleFont(), 0, 0L); - } - - HFONT GetBulletFont(void) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HFONT)::SendMessage(m_hWnd, GetMessage_GetBulletFont(), 0, 0L); - } - -// Helpers - static UINT GetMessage_GetExteriorPageTitleFont() - { - static UINT uGetExteriorPageTitleFont = 0; - if(uGetExteriorPageTitleFont == 0) - { - CStaticDataInitCriticalSectionLock lock; - if(FAILED(lock.Lock())) - { - ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CWizard97SheetWindow::GetMessage_GetExteriorPageTitleFont().\n")); - ATLASSERT(FALSE); - return 0; - } - - if(uGetExteriorPageTitleFont == 0) - uGetExteriorPageTitleFont = ::RegisterWindowMessage(_T("GetExteriorPageTitleFont_531AF056-B8BE-4c4c-B786-AC608DF0DF12")); - - lock.Unlock(); - } - ATLASSERT(uGetExteriorPageTitleFont != 0); - return uGetExteriorPageTitleFont; - } - - static UINT GetMessage_GetBulletFont() - { - static UINT uGetBulletFont = 0; - if(uGetBulletFont == 0) - { - CStaticDataInitCriticalSectionLock lock; - if(FAILED(lock.Lock())) - { - ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CWizard97SheetWindow::GetMessage_GetBulletFont().\n")); - ATLASSERT(FALSE); - return 0; - } - - if(uGetBulletFont == 0) - uGetBulletFont = ::RegisterWindowMessage(_T("GetBulletFont_AD347D08-8F65-45ef-982E-6352E8218AD5")); - - lock.Unlock(); - } - ATLASSERT(uGetBulletFont != 0); - return uGetBulletFont; - } - -// Implementation - override to prevent usage - HWND Create(LPCTSTR, HWND, ATL::_U_RECT = NULL, LPCTSTR = NULL, DWORD = 0, DWORD = 0, ATL::_U_MENUorID = 0U, LPVOID = NULL) - { - ATLASSERT(FALSE); - return NULL; - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CWizard97SheetImpl - implements a Wizard 97 style wizard sheet - -template -class ATL_NO_VTABLE CWizard97SheetImpl : public CPropertySheetImpl< T, TBase > -{ -protected: -// Typedefs - typedef CWizard97SheetImpl< T, TBase > thisClass; - typedef CPropertySheetImpl< T, TBase > baseClass; - -// Member variables - CFont m_fontExteriorPageTitle; // Welcome and Completion page title font - CFont m_fontBullet; // Bullet font (used on static text 'h' to produce a small bullet) - bool m_bReceivedFirstSizeMessage; - -public: - CWizard97SheetImpl(ATL::_U_STRINGorID title, ATL::_U_STRINGorID headerBitmap, ATL::_U_STRINGorID watermarkBitmap, UINT uStartPage = 0, HWND hWndParent = NULL) : - baseClass(title, uStartPage, hWndParent), - m_bReceivedFirstSizeMessage(false) - { - m_psh.dwFlags &= ~(PSH_NOCONTEXTHELP); - m_psh.dwFlags &= ~(PSH_WIZARD | PSH_WIZARD_LITE); - - m_psh.dwFlags |= (PSH_HASHELP | PSH_WIZARDCONTEXTHELP); - m_psh.dwFlags |= PSH_WIZARD97; - - baseClass::SetHeader(headerBitmap.m_lpstr); - baseClass::SetWatermark(watermarkBitmap.m_lpstr); - } - -// Overrides from base class - void OnSheetInitialized() - { - T* pT = static_cast(this); - pT->_InitializeFonts(); - - // We'd like to center the wizard here, but its too early. - // Instead, we'll do CenterWindow upon our first WM_SIZE message - } - -// Initialization - void _InitializeFonts() - { - // Setup the Title and Bullet Font - // (Property pages can send the "get external page title font" and "get bullet font" messages) - // The derived class needs to do the actual SetFont for the dialog items) - - CFontHandle fontThisDialog = this->GetFont(); - CClientDC dcScreen(NULL); - - LOGFONT titleLogFont = {0}; - LOGFONT bulletLogFont = {0}; - fontThisDialog.GetLogFont(&titleLogFont); - fontThisDialog.GetLogFont(&bulletLogFont); - - // The Wizard 97 Spec recommends to do the Title Font - // as Verdana Bold, 12pt. - titleLogFont.lfCharSet = DEFAULT_CHARSET; - titleLogFont.lfWeight = FW_BOLD; - SecureHelper::strcpy_x(titleLogFont.lfFaceName, _countof(titleLogFont.lfFaceName), _T("Verdana Bold")); - INT titleFontPointSize = 12; - titleLogFont.lfHeight = -::MulDiv(titleFontPointSize, dcScreen.GetDeviceCaps(LOGPIXELSY), 72); - m_fontExteriorPageTitle.CreateFontIndirect(&titleLogFont); - - // The Wizard 97 Spec recommends to do Bullets by having - // static text of "h" in the Marlett font. - bulletLogFont.lfCharSet = DEFAULT_CHARSET; - bulletLogFont.lfWeight = FW_NORMAL; - SecureHelper::strcpy_x(bulletLogFont.lfFaceName, _countof(bulletLogFont.lfFaceName), _T("Marlett")); - INT bulletFontSize = 8; - bulletLogFont.lfHeight = -::MulDiv(bulletFontSize, dcScreen.GetDeviceCaps(LOGPIXELSY), 72); - m_fontBullet.CreateFontIndirect(&bulletLogFont); - } - -// Message Handling - BEGIN_MSG_MAP(thisClass) - MESSAGE_HANDLER(CWizard97SheetWindow::GetMessage_GetExteriorPageTitleFont(), OnGetExteriorPageTitleFont) - MESSAGE_HANDLER(CWizard97SheetWindow::GetMessage_GetBulletFont(), OnGetBulletFont) - MESSAGE_HANDLER(WM_SIZE, OnSize) - CHAIN_MSG_MAP(baseClass) - END_MSG_MAP() - - LRESULT OnGetExteriorPageTitleFont(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - return (LRESULT)(HFONT)m_fontExteriorPageTitle; - } - - LRESULT OnGetBulletFont(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - return (LRESULT)(HFONT)m_fontBullet; - } - - LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - if(!m_bReceivedFirstSizeMessage) - { - m_bReceivedFirstSizeMessage = true; - this->CenterWindow(); - } - - bHandled = FALSE; - return 0; - } -}; - -// for non-customized sheets -class CWizard97Sheet : public CWizard97SheetImpl -{ -protected: -// Typedefs - typedef CWizard97Sheet thisClass; - typedef CWizard97SheetImpl baseClass; - -public: - CWizard97Sheet(ATL::_U_STRINGorID title, ATL::_U_STRINGorID headerBitmap, ATL::_U_STRINGorID watermarkBitmap, UINT uStartPage = 0, HWND hWndParent = NULL) : - baseClass(title, headerBitmap, watermarkBitmap, uStartPage, hWndParent) - { } - - BEGIN_MSG_MAP(thisClass) - CHAIN_MSG_MAP(baseClass) - END_MSG_MAP() -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CWizard97PageWindow - client side for a Wizard 97 style wizard page - -#define WIZARD97_EXTERIOR_CXDLG 317 -#define WIZARD97_EXTERIOR_CYDLG 193 - -#define WIZARD97_INTERIOR_CXDLG 317 -#define WIZARD97_INTERIOR_CYDLG 143 - -class CWizard97PageWindow : public CPropertyPageWindow -{ -public: -// Constructors - CWizard97PageWindow(HWND hWnd = NULL) : CPropertyPageWindow(hWnd) - { } - - CWizard97PageWindow& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - -// Attributes - CWizard97SheetWindow GetPropertySheet() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return CWizard97SheetWindow(GetParent()); - } - -// Operations - HFONT GetExteriorPageTitleFont(void) - { - ATLASSERT(::IsWindow(m_hWnd)); - return GetPropertySheet().GetExteriorPageTitleFont(); - } - - HFONT GetBulletFont(void) - { - ATLASSERT(::IsWindow(m_hWnd)); - return GetPropertySheet().GetBulletFont(); - } - -// Implementation - overrides to prevent usage - HWND Create(LPCTSTR, HWND, ATL::_U_RECT = NULL, LPCTSTR = NULL, DWORD = 0, DWORD = 0, ATL::_U_MENUorID = 0U, LPVOID = NULL) - { - ATLASSERT(FALSE); - return NULL; - } - -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CWizard97PageImpl - implements a Wizard 97 style wizard page - -template -class ATL_NO_VTABLE CWizard97PageImpl : public CPropertyPageImpl< T, TBase > -{ -protected: -// Typedefs - typedef CWizard97PageImpl< T, TBase > thisClass; - typedef CPropertyPageImpl< T, TBase > baseClass; - -public: - CWizard97PageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : baseClass(title) - { } - -// Message Handling - BEGIN_MSG_MAP(thisClass) - CHAIN_MSG_MAP(baseClass) - END_MSG_MAP() -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CWizard97ExteriorPageImpl - implements a Wizard 97 style exterior wizard page - -template -class ATL_NO_VTABLE CWizard97ExteriorPageImpl : public CPropertyPageImpl< T, TBase > -{ -protected: -// Typedefs - typedef CWizard97ExteriorPageImpl< T, TBase > thisClass; - typedef CPropertyPageImpl< T, TBase > baseClass; - -public: -// Constructors - CWizard97ExteriorPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : baseClass(title) - { - m_psp.dwFlags |= PSP_HASHELP; - m_psp.dwFlags |= PSP_HIDEHEADER; - } - -// Message Handling - BEGIN_MSG_MAP(thisClass) - CHAIN_MSG_MAP(baseClass) - END_MSG_MAP() -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CWizard97InteriorPageImpl - implements a Wizard 97 style interior wizard page - -template -class ATL_NO_VTABLE CWizard97InteriorPageImpl : public CPropertyPageImpl< T, TBase > -{ -protected: -// Typedefs - typedef CWizard97InteriorPageImpl< T, TBase > thisClass; - typedef CPropertyPageImpl< T, TBase > baseClass; - -public: -// Constructors - CWizard97InteriorPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : baseClass(title) - { - m_psp.dwFlags |= PSP_HASHELP; - m_psp.dwFlags &= ~PSP_HIDEHEADER; - m_psp.dwFlags |= PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; - - // Be sure to have the derived class define this in the constructor. - // We'll default it to something obvious in case its forgotten. - baseClass::SetHeaderTitle(_T("Call SetHeaderTitle in Derived Class")); - baseClass::SetHeaderSubTitle(_T("Call SetHeaderSubTitle in the constructor of the Derived Class.")); - } - -// Message Handling - BEGIN_MSG_MAP(thisClass) - CHAIN_MSG_MAP(baseClass) - END_MSG_MAP() -}; - -#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) - - -/////////////////////////////////////////////////////////////////////////////// -// Aero Wizard support - -#if (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE) - -/////////////////////////////////////////////////////////////////////////////// -// CAeroWizardFrameWindow - client side for an Aero Wizard frame window - -class CAeroWizardFrameWindow : public CPropertySheetWindow -{ -public: -// Constructors - CAeroWizardFrameWindow(HWND hWnd = NULL) : CPropertySheetWindow(hWnd) - { } - - CAeroWizardFrameWindow& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - -// Operations - new, Aero Wizard only - void SetNextText(LPCWSTR lpszText) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, PSM_SETNEXTTEXT, 0, (LPARAM)lpszText); - } - - void ShowWizardButtons(DWORD dwButtons, DWORD dwStates) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::PostMessage(m_hWnd, PSM_SHOWWIZBUTTONS, (WPARAM)dwStates, (LPARAM)dwButtons); - } - - void EnableWizardButtons(DWORD dwButtons, DWORD dwStates) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::PostMessage(m_hWnd, PSM_ENABLEWIZBUTTONS, (WPARAM)dwStates, (LPARAM)dwButtons); - } - - void SetButtonText(DWORD dwButton, LPCWSTR lpszText) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, PSM_SETBUTTONTEXT, (WPARAM)dwButton, (LPARAM)lpszText); - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CAeroWizardFrameImpl - implements an Aero Wizard frame - -template -class ATL_NO_VTABLE CAeroWizardFrameImpl : public CPropertySheetImpl -{ -public: -// Constructor - CAeroWizardFrameImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL, UINT uStartPage = 0, HWND hWndParent = NULL) : - CPropertySheetImpl(title, uStartPage, hWndParent) - { - m_psh.dwFlags |= PSH_WIZARD | PSH_AEROWIZARD; - } - -// Operations - void EnableResizing() - { - ATLASSERT(m_hWnd == NULL); // can't do this after it's created - m_psh.dwFlags |= PSH_RESIZABLE; - } - - void UseHeaderBitmap() - { - ATLASSERT(m_hWnd == NULL); // can't do this after it's created - m_psh.dwFlags |= PSH_HEADERBITMAP; - } - - void SetNoMargin() - { - ATLASSERT(m_hWnd == NULL); // can't do this after it's created - m_psh.dwFlags |= PSH_NOMARGIN; - } - -// Override to prevent use - HWND Create(HWND /*hWndParent*/ = NULL) - { - ATLASSERT(FALSE); // not supported for Aero Wizard - return NULL; - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CAeroWizardFrame - for non-customized frames - -class CAeroWizardFrame : public CAeroWizardFrameImpl -{ -public: - CAeroWizardFrame(ATL::_U_STRINGorID title = (LPCTSTR)NULL, UINT uStartPage = 0, HWND hWndParent = NULL) - : CAeroWizardFrameImpl(title, uStartPage, hWndParent) - { } - - BEGIN_MSG_MAP(CAeroWizardFrame) - MESSAGE_HANDLER(WM_COMMAND, CAeroWizardFrameImpl::OnCommand) - END_MSG_MAP() -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CAeroWizardPageWindow - client side for an Aero Wizard page - -class CAeroWizardPageWindow : public CPropertyPageWindow -{ -public: -// Constructors - CAeroWizardPageWindow(HWND hWnd = NULL) : CPropertyPageWindow(hWnd) - { } - - CAeroWizardPageWindow& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - -// Attributes - CAeroWizardFrameWindow GetAeroWizardFrame() const - { - ATLASSERT(::IsWindow(m_hWnd)); - // This is not really top-level frame window, but it processes all frame messages - return CAeroWizardFrameWindow(GetParent()); - } - -// Operations - new, Aero Wizard only - void SetNextText(LPCWSTR lpszText) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(GetParent() != NULL); - GetAeroWizardFrame().SetNextText(lpszText); - } - - void ShowWizardButtons(DWORD dwButtons, DWORD dwStates) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(GetParent() != NULL); - GetAeroWizardFrame().ShowWizardButtons(dwButtons, dwStates); - } - - void EnableWizardButtons(DWORD dwButtons, DWORD dwStates) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(GetParent() != NULL); - GetAeroWizardFrame().EnableWizardButtons(dwButtons, dwStates); - } - - void SetButtonText(DWORD dwButton, LPCWSTR lpszText) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(GetParent() != NULL); - GetAeroWizardFrame().SetButtonText(dwButton, lpszText); - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CAeroWizardPageImpl - implements an Aero Wizard page - -template -class ATL_NO_VTABLE CAeroWizardPageImpl : public CPropertyPageImpl -{ -public: - CAeroWizardPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CPropertyPageImpl(title) - { } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CAeroWizardPage - for non-customized pages - -template -class CAeroWizardPage : public CAeroWizardPageImpl > -{ -public: - enum { IDD = t_wDlgTemplateID }; - - CAeroWizardPage(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CAeroWizardPageImpl(title) - { } - - DECLARE_EMPTY_MSG_MAP() -}; - - -#ifndef _ATL_NO_HOSTING - -// Note: You must #include to use these classes - -/////////////////////////////////////////////////////////////////////////////// -// CAeroWizardAxPageImpl - Aero Wizard page that hosts ActiveX controls - -template -class ATL_NO_VTABLE CAeroWizardAxPageImpl : public CAxPropertyPageImpl< T, TBase > -{ -public: - CAeroWizardAxPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CAxPropertyPageImpl< T, TBase >(title) - { } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CAeroWizardAxPage - for non-customized pages - -template -class CAeroWizardAxPage : public CAeroWizardAxPageImpl > -{ -public: - enum { IDD = t_wDlgTemplateID }; - - CAeroWizardAxPage(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CAeroWizardAxPageImpl(title) - { } - -#if (_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700) - // not empty so we handle accelerators/create controls - BEGIN_MSG_MAP(CAeroWizardAxPage) - CHAIN_MSG_MAP(CAeroWizardAxPageImpl >) - END_MSG_MAP() -#else // !((_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700)) - DECLARE_EMPTY_MSG_MAP() -#endif // !((_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700)) -}; - -#endif // _ATL_NO_HOSTING - -#endif // (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE) - - -/////////////////////////////////////////////////////////////////////////////// -// TaskDialog support - -#if ((_WIN32_WINNT >= 0x0600) || defined(_WTL_TASKDIALOG)) && !defined(_WIN32_WCE) - -/////////////////////////////////////////////////////////////////////////////// -// AtlTaskDialog - support for TaskDialog() function - -inline int AtlTaskDialog(HWND hWndParent, - ATL::_U_STRINGorID WindowTitle, ATL::_U_STRINGorID MainInstructionText, ATL::_U_STRINGorID ContentText, - TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons = 0U, ATL::_U_STRINGorID Icon = (LPCTSTR)NULL) -{ - int nRet = -1; - -#ifdef _WTL_TASKDIALOG_DIRECT - USES_CONVERSION; - HRESULT hRet = ::TaskDialog(hWndParent, ModuleHelper::GetResourceInstance(), - IS_INTRESOURCE(WindowTitle.m_lpstr) ? (LPCWSTR) WindowTitle.m_lpstr : T2CW(WindowTitle.m_lpstr), - IS_INTRESOURCE(MainInstructionText.m_lpstr) ? (LPCWSTR) MainInstructionText.m_lpstr : T2CW(MainInstructionText.m_lpstr), - IS_INTRESOURCE(ContentText.m_lpstr) ? (LPCWSTR) ContentText.m_lpstr : T2CW(ContentText.m_lpstr), - dwCommonButtons, - IS_INTRESOURCE(Icon.m_lpstr) ? (LPCWSTR) Icon.m_lpstr : T2CW(Icon.m_lpstr), - &nRet); - ATLVERIFY(SUCCEEDED(hRet)); -#else - // This allows apps to run on older versions of Windows - typedef HRESULT (STDAPICALLTYPE *PFN_TaskDialog)(HWND hwndParent, HINSTANCE hInstance, PCWSTR pszWindowTitle, PCWSTR pszMainInstruction, PCWSTR pszContent, TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons, PCWSTR pszIcon, int* pnButton); - - HMODULE m_hCommCtrlDLL = ::LoadLibrary(_T("comctl32.dll")); - if(m_hCommCtrlDLL != NULL) - { - PFN_TaskDialog pfnTaskDialog = (PFN_TaskDialog)::GetProcAddress(m_hCommCtrlDLL, "TaskDialog"); - if(pfnTaskDialog != NULL) - { - USES_CONVERSION; - HRESULT hRet = pfnTaskDialog(hWndParent, ModuleHelper::GetResourceInstance(), - IS_INTRESOURCE(WindowTitle.m_lpstr) ? (LPCWSTR) WindowTitle.m_lpstr : T2CW(WindowTitle.m_lpstr), - IS_INTRESOURCE(MainInstructionText.m_lpstr) ? (LPCWSTR) MainInstructionText.m_lpstr : T2CW(MainInstructionText.m_lpstr), - IS_INTRESOURCE(ContentText.m_lpstr) ? (LPCWSTR) ContentText.m_lpstr : T2CW(ContentText.m_lpstr), - dwCommonButtons, - IS_INTRESOURCE(Icon.m_lpstr) ? (LPCWSTR) Icon.m_lpstr : T2CW(Icon.m_lpstr), - &nRet); - ATLVERIFY(SUCCEEDED(hRet)); - } - - ::FreeLibrary(m_hCommCtrlDLL); - } -#endif - - return nRet; -} - - -/////////////////////////////////////////////////////////////////////////////// -// CTaskDialogConfig - TASKDIALOGCONFIG wrapper - -class CTaskDialogConfig : public TASKDIALOGCONFIG -{ -public: -// Constructor - CTaskDialogConfig() - { - Init(); - } - - void Init() - { - memset(this, 0, sizeof(TASKDIALOGCONFIG)); // initialize structure to 0/NULL - this->cbSize = sizeof(TASKDIALOGCONFIG); - this->hInstance = ModuleHelper::GetResourceInstance(); - } - -// Operations - setting values - // common buttons - void SetCommonButtons(TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons) - { - this->dwCommonButtons = dwCommonButtons; - } - - // window title text - void SetWindowTitle(UINT nID) - { - this->pszWindowTitle = MAKEINTRESOURCEW(nID); - } - - void SetWindowTitle(LPCWSTR lpstrWindowTitle) - { - this->pszWindowTitle = lpstrWindowTitle; - } - - // main icon - void SetMainIcon(HICON hIcon) - { - this->dwFlags |= TDF_USE_HICON_MAIN; - this->hMainIcon = hIcon; - } - - void SetMainIcon(UINT nID) - { - this->dwFlags &= ~TDF_USE_HICON_MAIN; - this->pszMainIcon = MAKEINTRESOURCEW(nID); - } - - void SetMainIcon(LPCWSTR lpstrMainIcon) - { - this->dwFlags &= ~TDF_USE_HICON_MAIN; - this->pszMainIcon = lpstrMainIcon; - } - - // main instruction text - void SetMainInstructionText(UINT nID) - { - this->pszMainInstruction = MAKEINTRESOURCEW(nID); - } - - void SetMainInstructionText(LPCWSTR lpstrMainInstruction) - { - this->pszMainInstruction = lpstrMainInstruction; - } - - // content text - void SetContentText(UINT nID) - { - this->pszContent = MAKEINTRESOURCEW(nID); - } - - void SetContentText(LPCWSTR lpstrContent) - { - this->pszContent = lpstrContent; - } - - // buttons - void SetButtons(const TASKDIALOG_BUTTON* pButtons, UINT cButtons, int nDefaultButton = 0) - { - this->pButtons = pButtons; - this->cButtons = cButtons; - if(nDefaultButton != 0) - this->nDefaultButton = nDefaultButton; - } - - void SetDefaultButton(int nDefaultButton) - { - this->nDefaultButton = nDefaultButton; - } - - // radio buttons - void SetRadioButtons(const TASKDIALOG_BUTTON* pRadioButtons, UINT cRadioButtons, int nDefaultRadioButton = 0) - { - this->pRadioButtons = pRadioButtons; - this->cRadioButtons = cRadioButtons; - if(nDefaultRadioButton != 0) - this->nDefaultRadioButton = nDefaultRadioButton; - } - - void SetDefaultRadioButton(int nDefaultRadioButton) - { - this->nDefaultRadioButton = nDefaultRadioButton; - } - - // verification text - void SetVerificationText(UINT nID) - { - this->pszVerificationText = MAKEINTRESOURCEW(nID); - } - - void SetVerificationText(LPCWSTR lpstrVerificationText) - { - this->pszVerificationText = lpstrVerificationText; - } - - // expanded information text - void SetExpandedInformationText(UINT nID) - { - this->pszExpandedInformation = MAKEINTRESOURCEW(nID); - } - - void SetExpandedInformationText(LPCWSTR lpstrExpandedInformation) - { - this->pszExpandedInformation = lpstrExpandedInformation; - } - - // expanded control text - void SetExpandedControlText(UINT nID) - { - this->pszExpandedControlText = MAKEINTRESOURCEW(nID); - } - - void SetExpandedControlText(LPCWSTR lpstrExpandedControlText) - { - this->pszExpandedControlText = lpstrExpandedControlText; - } - - // collapsed control text - void SetCollapsedControlText(UINT nID) - { - this->pszCollapsedControlText = MAKEINTRESOURCEW(nID); - } - - void SetCollapsedControlText(LPCWSTR lpstrCollapsedControlText) - { - this->pszCollapsedControlText = lpstrCollapsedControlText; - } - - // footer icon - void SetFooterIcon(HICON hIcon) - { - this->dwFlags |= TDF_USE_HICON_FOOTER; - this->hFooterIcon = hIcon; - } - - void SetFooterIcon(UINT nID) - { - this->dwFlags &= ~TDF_USE_HICON_FOOTER; - this->pszFooterIcon = MAKEINTRESOURCEW(nID); - } - - void SetFooterIcon(LPCWSTR lpstrFooterIcon) - { - this->dwFlags &= ~TDF_USE_HICON_FOOTER; - this->pszFooterIcon = lpstrFooterIcon; - } - - // footer text - void SetFooterText(UINT nID) - { - this->pszFooter = MAKEINTRESOURCEW(nID); - } - - void SetFooterText(LPCWSTR lpstrFooterText) - { - this->pszFooter = lpstrFooterText; - } - - // width (in DLUs) - void SetWidth(UINT cxWidth) - { - this->cxWidth = cxWidth; - } - - // modify flags - void ModifyFlags(DWORD dwRemove, DWORD dwAdd) - { - this->dwFlags = (this->dwFlags & ~dwRemove) | dwAdd; - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CTaskDialogImpl - implements a Task Dialog - -template -class ATL_NO_VTABLE CTaskDialogImpl -{ -public: - CTaskDialogConfig m_tdc; - HWND m_hWnd; // used only in callback functions - -// Constructor - CTaskDialogImpl(HWND hWndParent = NULL) : m_hWnd(NULL) - { - m_tdc.hwndParent = hWndParent; - m_tdc.pfCallback = T::TaskDialogCallback; - m_tdc.lpCallbackData = (LONG_PTR)static_cast(this); - } - -// Operations - HRESULT DoModal(HWND hWndParent = ::GetActiveWindow(), int* pnButton = NULL, int* pnRadioButton = NULL, BOOL* pfVerificationFlagChecked = NULL) - { - if(m_tdc.hwndParent == NULL) - m_tdc.hwndParent = hWndParent; - -#ifdef _WTL_TASKDIALOG_DIRECT - return ::TaskDialogIndirect(&m_tdc, pnButton, pnRadioButton, pfVerificationFlagChecked); -#else - - // This allows apps to run on older versions of Windows - typedef HRESULT (STDAPICALLTYPE *PFN_TaskDialogIndirect)(const TASKDIALOGCONFIG* pTaskConfig, int* pnButton, int* pnRadioButton, BOOL* pfVerificationFlagChecked); - - HRESULT hRet = E_UNEXPECTED; - HMODULE m_hCommCtrlDLL = ::LoadLibrary(_T("comctl32.dll")); - if(m_hCommCtrlDLL != NULL) - { - PFN_TaskDialogIndirect pfnTaskDialogIndirect = (PFN_TaskDialogIndirect)::GetProcAddress(m_hCommCtrlDLL, "TaskDialogIndirect"); - if(pfnTaskDialogIndirect != NULL) - hRet = pfnTaskDialogIndirect(&m_tdc, pnButton, pnRadioButton, pfVerificationFlagChecked); - - ::FreeLibrary(m_hCommCtrlDLL); - } - - return hRet; -#endif - } - -// Operations - setting values of TASKDIALOGCONFIG - // common buttons - void SetCommonButtons(TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons) - { m_tdc.SetCommonButtons(dwCommonButtons); } - // window title text - void SetWindowTitle(UINT nID) - { m_tdc.SetWindowTitle(nID); } - void SetWindowTitle(LPCWSTR lpstrWindowTitle) - { m_tdc.SetWindowTitle(lpstrWindowTitle); } - // main icon - void SetMainIcon(HICON hIcon) - { m_tdc.SetMainIcon(hIcon); } - void SetMainIcon(UINT nID) - { m_tdc.SetMainIcon(nID); } - void SetMainIcon(LPCWSTR lpstrMainIcon) - { m_tdc.SetMainIcon(lpstrMainIcon); } - // main instruction text - void SetMainInstructionText(UINT nID) - { m_tdc.SetMainInstructionText(nID); } - void SetMainInstructionText(LPCWSTR lpstrMainInstruction) - { m_tdc.SetMainInstructionText(lpstrMainInstruction); } - // content text - void SetContentText(UINT nID) - { m_tdc.SetContentText(nID); } - void SetContentText(LPCWSTR lpstrContent) - { m_tdc.SetContentText(lpstrContent); } - // buttons - void SetButtons(const TASKDIALOG_BUTTON* pButtons, UINT cButtons, int nDefaultButton = 0) - { m_tdc.SetButtons(pButtons, cButtons, nDefaultButton); } - void SetDefaultButton(int nDefaultButton) - { m_tdc.SetDefaultButton(nDefaultButton); } - // radio buttons - void SetRadioButtons(const TASKDIALOG_BUTTON* pRadioButtons, UINT cRadioButtons, int nDefaultRadioButton = 0) - { m_tdc.SetRadioButtons(pRadioButtons, cRadioButtons, nDefaultRadioButton); } - void SetDefaultRadioButton(int nDefaultRadioButton) - { m_tdc.SetDefaultRadioButton(nDefaultRadioButton); } - // verification text - void SetVerificationText(UINT nID) - { m_tdc.SetVerificationText(nID); } - void SetVerificationText(LPCWSTR lpstrVerificationText) - { m_tdc.SetVerificationText(lpstrVerificationText); } - // expanded information text - void SetExpandedInformationText(UINT nID) - { m_tdc.SetExpandedInformationText(nID); } - void SetExpandedInformationText(LPCWSTR lpstrExpandedInformation) - { m_tdc.SetExpandedInformationText(lpstrExpandedInformation); } - // expanded control text - void SetExpandedControlText(UINT nID) - { m_tdc.SetExpandedControlText(nID); } - void SetExpandedControlText(LPCWSTR lpstrExpandedControlText) - { m_tdc.SetExpandedControlText(lpstrExpandedControlText); } - // collapsed control text - void SetCollapsedControlText(UINT nID) - { m_tdc.SetCollapsedControlText(nID); } - void SetCollapsedControlText(LPCWSTR lpstrCollapsedControlText) - { m_tdc.SetCollapsedControlText(lpstrCollapsedControlText); } - // footer icon - void SetFooterIcon(HICON hIcon) - { m_tdc.SetFooterIcon(hIcon); } - void SetFooterIcon(UINT nID) - { m_tdc.SetFooterIcon(nID); } - void SetFooterIcon(LPCWSTR lpstrFooterIcon) - { m_tdc.SetFooterIcon(lpstrFooterIcon); } - // footer text - void SetFooterText(UINT nID) - { m_tdc.SetFooterText(nID); } - void SetFooterText(LPCWSTR lpstrFooterText) - { m_tdc.SetFooterText(lpstrFooterText); } - // width (in DLUs) - void SetWidth(UINT cxWidth) - { m_tdc.SetWidth(cxWidth); } - // modify flags - void ModifyFlags(DWORD dwRemove, DWORD dwAdd) - { m_tdc.ModifyFlags(dwRemove, dwAdd); } - -// Implementation - static HRESULT CALLBACK TaskDialogCallback(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LONG_PTR lpRefData) - { - T* pT = (T*)lpRefData; - ATLASSERT(pT->m_hWnd == NULL || pT->m_hWnd == hWnd); - - BOOL bRet = FALSE; - switch(uMsg) - { - case TDN_DIALOG_CONSTRUCTED: - pT->m_hWnd = hWnd; - pT->OnDialogConstructed(); - break; - case TDN_CREATED: - pT->OnCreated(); - break; - case TDN_BUTTON_CLICKED: - bRet = pT->OnButtonClicked((int)wParam); - break; - case TDN_RADIO_BUTTON_CLICKED: - pT->OnRadioButtonClicked((int)wParam); - break; - case TDN_HYPERLINK_CLICKED: - pT->OnHyperlinkClicked((LPCWSTR)lParam); - break; - case TDN_EXPANDO_BUTTON_CLICKED: - pT->OnExpandoButtonClicked((wParam != 0)); - break; - case TDN_VERIFICATION_CLICKED: - pT->OnVerificationClicked((wParam != 0)); - break; - case TDN_HELP: - pT->OnHelp(); - break; - case TDN_TIMER: - bRet = pT->OnTimer((DWORD)wParam); - break; - case TDN_NAVIGATED: - pT->OnNavigated(); - break; - case TDN_DESTROYED: - pT->OnDestroyed(); - pT->m_hWnd = NULL; - break; - default: - ATLTRACE2(atlTraceUI, 0, _T("Unknown notification received in CTaskDialogImpl::TaskDialogCallback\n")); - break; - } - - return (HRESULT)bRet; - } - -// Overrideables - notification handlers - void OnDialogConstructed() - { - } - - void OnCreated() - { - } - - BOOL OnButtonClicked(int /*nButton*/) - { - return FALSE; // don't prevent dialog to close - } - - void OnRadioButtonClicked(int /*nRadioButton*/) - { - } - - void OnHyperlinkClicked(LPCWSTR /*pszHREF*/) - { - } - - void OnExpandoButtonClicked(bool /*bExpanded*/) - { - } - - void OnVerificationClicked(bool /*bChecked*/) - { - } - - void OnHelp() - { - } - - BOOL OnTimer(DWORD /*dwTickCount*/) - { - return FALSE; // don't reset counter - } - - void OnNavigated() - { - } - - void OnDestroyed() - { - } - -// Commands - valid to call only from handlers - void NavigatePage(TASKDIALOGCONFIG& tdc) - { - ATLASSERT(m_hWnd != NULL); - - tdc.cbSize = sizeof(TASKDIALOGCONFIG); - if(tdc.hwndParent == NULL) - tdc.hwndParent = m_tdc.hwndParent; - tdc.pfCallback = m_tdc.pfCallback; - tdc.lpCallbackData = m_tdc.lpCallbackData; - (TASKDIALOGCONFIG)m_tdc = tdc; - - ::SendMessage(m_hWnd, TDM_NAVIGATE_PAGE, 0, (LPARAM)&tdc); - } - - // modify TASKDIALOGCONFIG values, then call this to update task dialog - void NavigatePage() - { - ATLASSERT(m_hWnd != NULL); - ::SendMessage(m_hWnd, TDM_NAVIGATE_PAGE, 0, (LPARAM)&m_tdc); - } - - void ClickButton(int nButton) - { - ATLASSERT(m_hWnd != NULL); - ::SendMessage(m_hWnd, TDM_CLICK_BUTTON, nButton, 0L); - } - - void SetMarqueeProgressBar(BOOL bMarquee) - { - ATLASSERT(m_hWnd != NULL); - ::SendMessage(m_hWnd, TDM_SET_MARQUEE_PROGRESS_BAR, bMarquee, 0L); - } - - BOOL SetProgressBarState(int nNewState) - { - ATLASSERT(m_hWnd != NULL); - return (BOOL)::SendMessage(m_hWnd, TDM_SET_PROGRESS_BAR_STATE, nNewState, 0L); - } - - DWORD SetProgressBarRange(int nMinRange, int nMaxRange) - { - ATLASSERT(m_hWnd != NULL); - return (DWORD)::SendMessage(m_hWnd, TDM_SET_PROGRESS_BAR_RANGE, 0, MAKELPARAM(nMinRange, nMaxRange)); - } - - int SetProgressBarPos(int nNewPos) - { - ATLASSERT(m_hWnd != NULL); - return (int)::SendMessage(m_hWnd, TDM_SET_PROGRESS_BAR_POS, nNewPos, 0L); - } - - BOOL SetProgressBarMarquee(BOOL bMarquee, UINT uSpeed) - { - ATLASSERT(m_hWnd != NULL); - return (BOOL)::SendMessage(m_hWnd, TDM_SET_PROGRESS_BAR_MARQUEE, bMarquee, uSpeed); - } - - void SetElementText(TASKDIALOG_ELEMENTS element, LPCWSTR lpstrText) - { - ATLASSERT(m_hWnd != NULL); - ::SendMessage(m_hWnd, TDM_SET_ELEMENT_TEXT, element, (LPARAM)lpstrText); - } - - void ClickRadioButton(int nRadioButton) - { - ATLASSERT(m_hWnd != NULL); - ::SendMessage(m_hWnd, TDM_CLICK_RADIO_BUTTON, nRadioButton, 0L); - } - - void EnableButton(int nButton, BOOL bEnable) - { - ATLASSERT(m_hWnd != NULL); - ::SendMessage(m_hWnd, TDM_ENABLE_BUTTON, nButton, bEnable); - } - - void EnableRadioButton(int nButton, BOOL bEnable) - { - ATLASSERT(m_hWnd != NULL); - ::SendMessage(m_hWnd, TDM_ENABLE_RADIO_BUTTON, nButton, bEnable); - } - - void ClickVerification(BOOL bCheck, BOOL bFocus) - { - ATLASSERT(m_hWnd != NULL); - ::SendMessage(m_hWnd, TDM_CLICK_VERIFICATION, bCheck, bFocus); - } - - void UpdateElementText(TASKDIALOG_ELEMENTS element, LPCWSTR lpstrText) - { - ATLASSERT(m_hWnd != NULL); - ::SendMessage(m_hWnd, TDM_UPDATE_ELEMENT_TEXT, element, (LPARAM)lpstrText); - } - - void SetButtonElevationRequiredState(int nButton, BOOL bElevation) - { - ATLASSERT(m_hWnd != NULL); - ::SendMessage(m_hWnd, TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE, nButton, bElevation); - } - - void UpdateIcon(TASKDIALOG_ICON_ELEMENTS element, HICON hIcon) - { - ATLASSERT(m_hWnd != NULL); -#ifdef _DEBUG - if(element == TDIE_ICON_MAIN) - ATLASSERT((m_tdc.dwFlags & TDF_USE_HICON_MAIN) != 0); - else if(element == TDIE_ICON_FOOTER) - ATLASSERT((m_tdc.dwFlags & TDF_USE_HICON_FOOTER) != 0); -#endif // _DEBUG - ::SendMessage(m_hWnd, TDM_UPDATE_ICON, element, (LPARAM)hIcon); - } - - void UpdateIcon(TASKDIALOG_ICON_ELEMENTS element, LPCWSTR lpstrIcon) - { - ATLASSERT(m_hWnd != NULL); -#ifdef _DEBUG - if(element == TDIE_ICON_MAIN) - ATLASSERT((m_tdc.dwFlags & TDF_USE_HICON_MAIN) == 0); - else if(element == TDIE_ICON_FOOTER) - ATLASSERT((m_tdc.dwFlags & TDF_USE_HICON_FOOTER) == 0); -#endif // _DEBUG - ::SendMessage(m_hWnd, TDM_UPDATE_ICON, element, (LPARAM)lpstrIcon); - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CTaskDialog - for non-customized task dialogs - -class CTaskDialog : public CTaskDialogImpl -{ -public: - CTaskDialog(HWND hWndParent = NULL) : CTaskDialogImpl(hWndParent) - { - m_tdc.pfCallback = NULL; - } -}; - -#endif // ((_WIN32_WINNT >= 0x0600) || defined(_WTL_TASKDIALOG)) && !defined(_WIN32_WCE) - -}; // namespace WTL - -#endif // __ATLDLGS_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/atldwm.h b/prog/3rdPartyLibs/wtl-8.1/include/atldwm.h deleted file mode 100644 index 5f4bf1f6b..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/atldwm.h +++ /dev/null @@ -1,465 +0,0 @@ -// Windows Template Library - WTL version 8.1 -// Copyright (C) Microsoft Corporation. All rights reserved. -// -// This file is a part of the Windows Template Library. -// The use and distribution terms for this software are covered by the -// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php) -// which can be found in the file CPL.TXT at the root of this distribution. -// By using this software in any fashion, you are agreeing to be bound by -// the terms of this license. You must not remove this notice, or -// any other, from this software. - -#ifndef __ATLDWM_H__ -#define __ATLDWM_H__ - -#pragma once - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#ifdef _WIN32_WCE - #error atldwm.h is not supported on Windows CE -#endif - -#ifndef __ATLAPP_H__ - #error atldwm.h requires atlapp.h to be included first -#endif - -#ifndef __ATLWIN_H__ - #error atldwm.h requires atlwin.h to be included first -#endif - -#if (_WIN32_WINNT < 0x0600) - #error atldwm.h requires _WIN32_WINNT >= 0x0600 -#endif // (_WIN32_WINNT < 0x0600) - -#ifndef _DWMAPI_H_ -#include -#endif // _DWMAPI_H_ -#pragma comment(lib, "dwmapi.lib") - -// Note: To create an application that also runs on older versions of Windows, -// use delay load of dwmapi.dll and ensure that no calls to the DWM API are -// Delay load is NOT AUTOMATIC for VC++ 7, you have to link to delayimp.lib, -// and add dwmapi.dll in the Linker.Input.Delay Loaded DLLs section of the -// project properties. -#if (_MSC_VER < 1300) && !defined(_WTL_NO_DWMAPI_DELAYLOAD) - #pragma comment(lib, "delayimp.lib") - #pragma comment(linker, "/delayload:dwmapi.dll") -#endif // (_MSC_VER < 1300) && !defined(_WTL_NO_DWMAPI_DELAYLOAD) - -/////////////////////////////////////////////////////////////////////////////// -// Classes in this file: -// -// CDwm -// CDwmImpl -// CDwmWindowT - CDwmWindow -// CDwmThumbnailT -// CDwmThumbnail -// CDwmThumbnailHandle -// CAeroControlImpl - - -namespace WTL -{ - -/////////////////////////////////////////////////////////////////////////////// -// CDwm - wrapper for DWM handle - -class CDwm -{ -public: -// Data members - static int m_nIsDwmSupported; - -// Constructor - CDwm() - { - IsDwmSupported(); - } - -// Dwm support helper - static bool IsDwmSupported() - { - if(m_nIsDwmSupported == -1) - { - CStaticDataInitCriticalSectionLock lock; - if(FAILED(lock.Lock())) - { - ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CDwm::IsDwmSupported.\n")); - ATLASSERT(FALSE); - return false; - } - - if(m_nIsDwmSupported == -1) - { - HMODULE hDwmDLL = ::LoadLibrary(_T("dwmapi.dll")); - m_nIsDwmSupported = (hDwmDLL != NULL) ? 1 : 0; - if(hDwmDLL != NULL) - ::FreeLibrary(hDwmDLL); - } - - lock.Unlock(); - } - - ATLASSERT(m_nIsDwmSupported != -1); - return (m_nIsDwmSupported == 1); - } - -// Operations - BOOL DwmIsCompositionEnabled() const - { - if(!IsDwmSupported()) return FALSE; - BOOL bRes = FALSE; - return SUCCEEDED(::DwmIsCompositionEnabled(&bRes)) && bRes; - } - - BOOL DwmEnableComposition(UINT fEnable) - { - if(!IsDwmSupported()) return FALSE; - return SUCCEEDED(::DwmEnableComposition(fEnable)); - } - - BOOL DwmEnableMMCSS(BOOL fEnableMMCSS) - { - if(!IsDwmSupported()) return FALSE; - return SUCCEEDED(::DwmEnableMMCSS(fEnableMMCSS)); - } - - HRESULT DwmGetColorizationColor(DWORD* pcrColorization, BOOL* pfOpaqueBlend) - { - if(!IsDwmSupported()) return E_NOTIMPL; - return ::DwmGetColorizationColor(pcrColorization, pfOpaqueBlend); - } - - HRESULT DwmFlush() - { - if(!IsDwmSupported()) return E_NOTIMPL; - return ::DwmFlush(); - } -}; - -__declspec(selectany) int CDwm::m_nIsDwmSupported = -1; - - -/////////////////////////////////////////////////////////////////////////////// -// CDwmImpl - DWM window support - -template -class CDwmImpl : public TBase -{ -public: - HRESULT DwmEnableBlurBehindWindow(const DWM_BLURBEHIND* pBB) - { - if(!IsDwmSupported()) return E_NOTIMPL; - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - return ::DwmEnableBlurBehindWindow(pT->m_hWnd, pBB); - } - - HRESULT DwmExtendFrameIntoClientArea(const MARGINS* pMargins) - { - if(!IsDwmSupported()) return E_NOTIMPL; - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - return ::DwmExtendFrameIntoClientArea(pT->m_hWnd, pMargins); - } - - HRESULT DwmExtendFrameIntoEntireClientArea() - { - MARGINS margins = { -1 }; - return DwmExtendFrameIntoClientArea(&margins); - } - - HRESULT DwmGetCompositionTimingInfo(DWM_TIMING_INFO* pTimingInfo) - { - if(!IsDwmSupported()) return E_NOTIMPL; - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - return ::DwmGetCompositionTimingInfo(pT->m_hWnd, pTimingInfo); - } - - HRESULT DwmGetWindowAttribute(DWORD dwAttribute, PVOID pvAttribute, DWORD cbAttribute) - { - if(!IsDwmSupported()) return E_NOTIMPL; - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - return ::DwmGetWindowAttribute(pT->m_hWnd, dwAttribute, pvAttribute, cbAttribute); - } - - HRESULT DwmModifyPreviousDxFrameDuration(INT cRefreshes, BOOL fRelative) - { - if(!IsDwmSupported()) return E_NOTIMPL; - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - return ::DwmModifyPreviousDxFrameDuration(pT->m_hWnd, cRefreshes, fRelative); - } - - HRESULT DwmSetDxFrameDuration(INT cRefreshes) - { - if(!IsDwmSupported()) return E_NOTIMPL; - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - return ::DwmSetDxFrameDuration(pT->m_hWnd, cRefreshes); - } - - HRESULT DwmSetPresentParameters(DWM_PRESENT_PARAMETERS* pPresentParams) - { - if(!IsDwmSupported()) return E_NOTIMPL; - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - return ::DwmSetPresentParameters(pT->m_hWnd, pPresentParams); - } - - HRESULT DwmSetWindowAttribute(DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute) - { - if(!IsDwmSupported()) return E_NOTIMPL; - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - return ::DwmSetWindowAttribute(pT->m_hWnd, dwAttribute, pvAttribute, cbAttribute); - } - - HRESULT DwmAttachMilContent() - { - if(!IsDwmSupported()) return E_NOTIMPL; - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - return ::DwmAttachMilContent(pT->m_hWnd); - } - - HRESULT DwmDetachMilContent() - { - if(!IsDwmSupported()) return E_NOTIMPL; - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - return ::DwmDetachMilContent(pT->m_hWnd); - } -}; - -template -class CDwmWindowT : public TBase, public CDwmImpl > -{ -public: - CDwmWindowT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CDwmWindowT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } -}; - -typedef CDwmWindowT CDwmWindow; - - -/////////////////////////////////////////////////////////////////////////////// -// CDwmThumbnail - provides DWM thumbnail support - -template -class CDwmThumbnailT : public TBase -{ -public: -// Data members - HTHUMBNAIL m_hThumbnail; - -// Constructor - CDwmThumbnailT(HTHUMBNAIL hThumbnail = NULL) : m_hThumbnail(hThumbnail) - { - } - - ~CDwmThumbnailT() - { - if(t_bManaged && m_hThumbnail != NULL) - Unregister(); - } - -// Operations - CDwmThumbnailT& operator =(HTHUMBNAIL hThumbnail) - { - Attach(hThumbnail); - return *this; - } - - void Attach(HTHUMBNAIL hThumbnailNew) - { - if(t_bManaged && m_hThumbnail != NULL && m_hThumbnail != hThumbnailNew) - Unregister(); - m_hThumbnail = hThumbnailNew; - } - - HTHUMBNAIL Detach() - { - HTHUMBNAIL hThumbnail = m_hThumbnail; - m_hThumbnail = NULL; - return hThumbnail; - } - - HRESULT Register(HWND hwndDestination, HWND hwndSource) - { - ATLASSERT(::IsWindow(hwndDestination)); - ATLASSERT(::IsWindow(hwndSource)); - ATLASSERT(m_hThumbnail==NULL); - if(!IsDwmSupported()) return E_NOTIMPL; - return ::DwmRegisterThumbnail(hwndDestination, hwndSource, &m_hThumbnail); - } - - HRESULT Unregister() - { - if(!IsDwmSupported()) return E_NOTIMPL; - if(m_hThumbnail == NULL) return S_FALSE; - HRESULT Hr = ::DwmUnregisterThumbnail(m_hThumbnail); - if(SUCCEEDED(Hr)) m_hThumbnail = NULL; - return Hr; - } - - operator HTHUMBNAIL() const { return m_hThumbnail; } - - bool IsNull() const { return (m_hThumbnail == NULL); } - - HRESULT UpdateProperties(const DWM_THUMBNAIL_PROPERTIES* ptnProperties) - { - if(!IsDwmSupported()) return E_NOTIMPL; - ATLASSERT(m_hThumbnail != NULL); - return ::DwmUpdateThumbnailProperties(m_hThumbnail, ptnProperties); - } - -// Attributes - HRESULT QuerySourceSize(PSIZE pSize) - { - if(!IsDwmSupported()) return E_NOTIMPL; - ATLASSERT(m_hThumbnail != NULL); - return ::DwmQueryThumbnailSourceSize(m_hThumbnail, pSize); - } -}; - -typedef CDwmThumbnailT CDwmThumbnail; -typedef CDwmThumbnailT CDwmThumbnailHandle; - - -#ifdef __ATLTHEME_H__ - -/////////////////////////////////////////////////////////////////////////////// -// CAeroControlImpl - Base class for controls on Glass - -template -class CAeroControlImpl : - public CThemeImpl, - public CBufferedPaintImpl, - public ATL::CWindowImpl -{ -public: - typedef CThemeImpl _themeClass; - typedef CBufferedPaintImpl _baseClass; - typedef ATL::CWindowImpl _windowClass; - - CAeroControlImpl() - { - m_PaintParams.dwFlags = BPPF_ERASE; - } - - static LPCWSTR GetThemeName() - { -#ifdef _UNICODE - return TBase::GetWndClassName(); -#else - ATLASSERT(!_T("Return UNICODE string of window classname / theme class")); - return NULL; -#endif // _UNICODE - } - -// Message map and handlers - BEGIN_MSG_MAP(CAeroControlImpl) - MESSAGE_HANDLER(WM_CREATE, OnCreate) - MESSAGE_HANDLER(WM_ACTIVATE, OnActivate) - CHAIN_MSG_MAP(_themeClass) - CHAIN_MSG_MAP(_baseClass) - END_MSG_MAP() - - LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - T* pT = static_cast(this); - pT->Init(); - bHandled = FALSE; - return 0; - } - - LRESULT OnActivate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - if(IsThemingSupported()) Invalidate(FALSE); - bHandled = FALSE; - return 0; - } - -// Operations - BOOL SubclassWindow(HWND hWnd) - { - ATLASSERT(m_hWnd == NULL); - ATLASSERT(::IsWindow(hWnd)); - BOOL bRet = _windowClass::SubclassWindow(hWnd); - if(bRet) { - T* pT = static_cast(this); - pT->Init(); - } - return bRet; - } - -// Implementation - LRESULT DefWindowProc() - { - const _ATL_MSG* pMsg = m_pCurrentMsg; - LRESULT lRes = 0; - if(pMsg != NULL) - lRes = DefWindowProc(pMsg->message, pMsg->wParam, pMsg->lParam); - return lRes; - } - - LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) - { - T* pT = static_cast(this); - LRESULT lRes = 0; - if( ::DwmDefWindowProc(pT->m_hWnd, uMsg, wParam, lParam, &lRes) ) return lRes; - return _windowClass::DefWindowProc(uMsg, wParam, lParam); - } - - void DoBufferedPaint(HDC hDC, RECT& rcPaint) - { - T* pT = static_cast(this); - HDC hDCPaint = NULL; - RECT rcClient = { 0 }; - GetClientRect(&rcClient); - m_BufferedPaint.Begin(hDC, &rcClient, m_dwFormat, &m_PaintParams, &hDCPaint); - ATLASSERT(hDCPaint != NULL); - pT->DoAeroPaint(hDCPaint, rcClient, rcPaint); - m_BufferedPaint.End(); - } - - void DoPaint(HDC /*hdc*/, RECT& /*rcClient*/) - { - DefWindowProc(); - } - -// Overridables - void Init() - { - T* pT = static_cast(this); - SetThemeClassList(pT->GetThemeName()); - if(m_lpstrThemeClassList != NULL) - OpenThemeData(); - } - - void DoAeroPaint(HDC hDC, RECT& /*rcClient*/, RECT& rcPaint) - { - DefWindowProc(WM_PAINT, (WPARAM) hDC, 0L); - m_BufferedPaint.MakeOpaque(&rcPaint); - } -}; - -#endif // __ATLTHEME_H__ - - -}; // namespace WTL - - -#endif // __ATLDWM_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/atlfind.h b/prog/3rdPartyLibs/wtl-8.1/include/atlfind.h deleted file mode 100644 index c4a47a416..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/atlfind.h +++ /dev/null @@ -1,1036 +0,0 @@ -// Windows Template Library - WTL version 8.1 -// Copyright (C) Microsoft Corporation. All rights reserved. -// -// This file is a part of the Windows Template Library. -// The use and distribution terms for this software are covered by the -// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php) -// which can be found in the file CPL.TXT at the root of this distribution. -// By using this software in any fashion, you are agreeing to be bound by -// the terms of this license. You must not remove this notice, or -// any other, from this software. - -#ifndef __ATLFIND_H__ -#define __ATLFIND_H__ - -#pragma once - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#ifdef _WIN32_WCE - #error atlfind.h is not supported on Windows CE -#endif - -#ifndef __ATLCTRLS_H__ - #error atlfind.h requires atlctrls.h to be included first -#endif - -#ifndef __ATLDLGS_H__ - #error atlfind.h requires atldlgs.h to be included first -#endif - -#if !((defined(__ATLMISC_H__) && defined(_WTL_USE_CSTRING)) || defined(__ATLSTR_H__)) - #error atlfind.h requires CString (either from ATL's atlstr.h or WTL's atlmisc.h with _WTL_USE_CSTRING) -#endif - - -/////////////////////////////////////////////////////////////////////////////// -// Classes in this file: -// -// CEditFindReplaceImplBase -// CEditFindReplaceImpl -// CRichEditFindReplaceImpl - - -namespace WTL -{ - -/////////////////////////////////////////////////////////////////////////////// -// CEditFindReplaceImplBase - Base class for mixin classes that -// help implement Find/Replace for CEdit or CRichEditCtrl based window classes. - -template -class CEditFindReplaceImplBase -{ -protected: -// Typedefs - typedef CEditFindReplaceImplBase thisClass; - -// Data members - TFindReplaceDialog* m_pFindReplaceDialog; - _CSTRING_NS::CString m_sFindNext, m_sReplaceWith; - BOOL m_bFindOnly, m_bFirstSearch, m_bMatchCase, m_bWholeWord, m_bFindDown; - LONG m_nInitialSearchPos; - HCURSOR m_hOldCursor; - -// Enumerations - enum TranslationTextItem - { - eText_OnReplaceAllMessage = 0, - eText_OnReplaceAllTitle = 1, - eText_OnTextNotFoundMessage = 2, - eText_OnTextNotFoundTitle = 3 - }; - -public: -// Constructors - CEditFindReplaceImplBase() : - m_pFindReplaceDialog(NULL), - m_bFindOnly(TRUE), - m_bFirstSearch(TRUE), - m_bMatchCase(FALSE), - m_bWholeWord(FALSE), - m_bFindDown(TRUE), - m_nInitialSearchPos(0), - m_hOldCursor(NULL) - { - } - -// Message Handlers - BEGIN_MSG_MAP(thisClass) - ALT_MSG_MAP(1) - MESSAGE_HANDLER(WM_DESTROY, OnDestroy) - MESSAGE_HANDLER(TFindReplaceDialog::GetFindReplaceMsg(), OnFindReplaceCmd) - COMMAND_ID_HANDLER(ID_EDIT_FIND, OnEditFind) - COMMAND_ID_HANDLER(ID_EDIT_REPEAT, OnEditRepeat) - COMMAND_ID_HANDLER(ID_EDIT_REPLACE, OnEditReplace) - END_MSG_MAP() - - LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - if(m_pFindReplaceDialog != NULL) - { - m_pFindReplaceDialog->SendMessage(WM_CLOSE); - ATLASSERT(m_pFindReplaceDialog == NULL); - } - - bHandled = FALSE; - return 0; - } - - LRESULT OnFindReplaceCmd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - - TFindReplaceDialog* pDialog = TFindReplaceDialog::GetNotifier(lParam); - if(pDialog == NULL) - { - ATLASSERT(FALSE); - ::MessageBeep(MB_ICONERROR); - return 1; - } - ATLASSERT(pDialog == m_pFindReplaceDialog); - - LPFINDREPLACE findReplace = (LPFINDREPLACE)lParam; - if((m_pFindReplaceDialog != NULL) && (findReplace != NULL)) - { - if(pDialog->FindNext()) - { - pT->OnFindNext(pDialog->GetFindString(), pDialog->SearchDown(), - pDialog->MatchCase(), pDialog->MatchWholeWord()); - } - else if(pDialog->ReplaceCurrent()) - { - pT->OnReplaceSel(pDialog->GetFindString(), - pDialog->SearchDown(), pDialog->MatchCase(), pDialog->MatchWholeWord(), - pDialog->GetReplaceString()); - } - else if(pDialog->ReplaceAll()) - { - pT->OnReplaceAll(pDialog->GetFindString(), pDialog->GetReplaceString(), - pDialog->MatchCase(), pDialog->MatchWholeWord()); - } - else if(pDialog->IsTerminating()) - { - // Dialog is going away (but hasn't gone away yet) - // OnFinalMessage will "delete this" - pT->OnTerminatingFindReplaceDialog(m_pFindReplaceDialog); - m_pFindReplaceDialog = NULL; - } - } - - return 0; - } - - LRESULT OnEditFind(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - pT->FindReplace(TRUE); - - return 0; - } - - LRESULT OnEditRepeat(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - - // If the user is holding down SHIFT when hitting F3, we'll - // search in reverse. Otherwise, we'll search forward. - // (be sure to have an accelerator mapped to ID_EDIT_REPEAT - // for both F3 and Shift+F3) - m_bFindDown = !((::GetKeyState(VK_SHIFT) & 0x8000) == 0x8000); - - if(m_sFindNext.IsEmpty()) - { - pT->FindReplace(TRUE); - } - else - { - if(!pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWholeWord, m_bFindDown)) - pT->TextNotFound(m_sFindNext); - } - - return 0; - } - - LRESULT OnEditReplace(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& bHandled) - { - T* pT = static_cast(this); - - DWORD style = pT->GetStyle(); - if((style & ES_READONLY) != ES_READONLY) - { - pT->FindReplace(FALSE); - } - else - { - // Don't allow replace when the edit control is read only - bHandled = FALSE; - } - - return 0; - } - -// Operations (overrideable) - TFindReplaceDialog* CreateFindReplaceDialog(BOOL bFindOnly, // TRUE for Find, FALSE for FindReplace - LPCTSTR lpszFindWhat, - LPCTSTR lpszReplaceWith = NULL, - DWORD dwFlags = FR_DOWN, - HWND hWndParent = NULL) - { - // You can override all of this in a derived class - - TFindReplaceDialog* findReplaceDialog = new TFindReplaceDialog(); - if(findReplaceDialog == NULL) - { - ::MessageBeep(MB_ICONHAND); - } - else - { - HWND hWndFindReplace = findReplaceDialog->Create(bFindOnly, - lpszFindWhat, lpszReplaceWith, dwFlags, hWndParent); - if(hWndFindReplace == NULL) - { - delete findReplaceDialog; - findReplaceDialog = NULL; - } - else - { - findReplaceDialog->SetActiveWindow(); - findReplaceDialog->ShowWindow(SW_SHOW); - } - } - - return findReplaceDialog; - } - - void AdjustDialogPosition(HWND hWndDialog) - { - ATLASSERT((hWndDialog != NULL) && ::IsWindow(hWndDialog)); - - T* pT = static_cast(this); - LONG nStartChar = 0, nEndChar = 0; - // Send EM_GETSEL so we can use both Edit and RichEdit - // (CEdit::GetSel uses int&, and CRichEditCtrlT::GetSel uses LONG&) - ::SendMessage(pT->m_hWnd, EM_GETSEL, (WPARAM)&nStartChar, (LPARAM)&nEndChar); - POINT point = pT->PosFromChar(nStartChar); - ::ClientToScreen(pT->GetParent(), &point); - CRect rect; - ::GetWindowRect(hWndDialog, &rect); - if(rect.PtInRect(point)) - { - if(point.y > rect.Height()) - { - rect.OffsetRect(0, point.y - rect.bottom - 20); - } - else - { - int nVertExt = GetSystemMetrics(SM_CYSCREEN); - if(point.y + rect.Height() < nVertExt) - rect.OffsetRect(0, 40 + point.y - rect.top); - } - - ::MoveWindow(hWndDialog, rect.left, rect.top, rect.Width(), rect.Height(), TRUE); - } - } - - DWORD GetFindReplaceDialogFlags(void) const - { - DWORD dwFlags = 0; - - if(m_bFindDown) - dwFlags |= FR_DOWN; - if(m_bMatchCase) - dwFlags |= FR_MATCHCASE; - if(m_bWholeWord) - dwFlags |= FR_WHOLEWORD; - - return dwFlags; - } - - void FindReplace(BOOL bFindOnly) - { - T* pT = static_cast(this); - m_bFirstSearch = TRUE; - if(m_pFindReplaceDialog != NULL) - { - if(m_bFindOnly == bFindOnly) - { - m_pFindReplaceDialog->SetActiveWindow(); - m_pFindReplaceDialog->ShowWindow(SW_SHOW); - return; - } - else - { - m_pFindReplaceDialog->SendMessage(WM_CLOSE); - ATLASSERT(m_pFindReplaceDialog == NULL); - } - } - - ATLASSERT(m_pFindReplaceDialog == NULL); - - _CSTRING_NS::CString findNext; - pT->GetSelText(findNext); - // if selection is empty or spans multiple lines use old find text - if(findNext.IsEmpty() || (findNext.FindOneOf(_T("\n\r")) != -1)) - findNext = m_sFindNext; - _CSTRING_NS::CString replaceWith = m_sReplaceWith; - DWORD dwFlags = pT->GetFindReplaceDialogFlags(); - - m_pFindReplaceDialog = pT->CreateFindReplaceDialog(bFindOnly, - findNext, replaceWith, dwFlags, pT->operator HWND()); - ATLASSERT(m_pFindReplaceDialog != NULL); - if(m_pFindReplaceDialog != NULL) - m_bFindOnly = bFindOnly; - } - - BOOL SameAsSelected(LPCTSTR lpszCompare, BOOL bMatchCase, BOOL /*bWholeWord*/) - { - T* pT = static_cast(this); - - // check length first - size_t nLen = lstrlen(lpszCompare); - LONG nStartChar = 0, nEndChar = 0; - // Send EM_GETSEL so we can use both Edit and RichEdit - // (CEdit::GetSel uses int&, and CRichEditCtrlT::GetSel uses LONG&) - ::SendMessage(pT->m_hWnd, EM_GETSEL, (WPARAM)&nStartChar, (LPARAM)&nEndChar); - if(nLen != (size_t)(nEndChar - nStartChar)) - return FALSE; - - // length is the same, check contents - _CSTRING_NS::CString selectedText; - pT->GetSelText(selectedText); - - return (bMatchCase && selectedText.Compare(lpszCompare) == 0) || - (!bMatchCase && selectedText.CompareNoCase(lpszCompare) == 0); - } - - void TextNotFound(LPCTSTR lpszFind) - { - T* pT = static_cast(this); - m_bFirstSearch = TRUE; - pT->OnTextNotFound(lpszFind); - } - - _CSTRING_NS::CString GetTranslationText(enum TranslationTextItem eItem) const - { - _CSTRING_NS::CString text; - switch(eItem) - { - case eText_OnReplaceAllMessage: - text = _T("Replaced %d occurances of \"%s\" with \"%s\""); - break; - case eText_OnReplaceAllTitle: - text = _T("Replace All"); - break; - case eText_OnTextNotFoundMessage: - text = _T("Unable to find the text \"%s\""); - break; - case eText_OnTextNotFoundTitle: - text = _T("Text not found"); - break; - } - - return text; - } - -// Overrideable Handlers - void OnFindNext(LPCTSTR lpszFind, BOOL bFindDown, BOOL bMatchCase, BOOL bWholeWord) - { - T* pT = static_cast(this); - - m_sFindNext = lpszFind; - m_bMatchCase = bMatchCase; - m_bWholeWord = bWholeWord; - m_bFindDown = bFindDown; - - if(!pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWholeWord, m_bFindDown)) - pT->TextNotFound(m_sFindNext); - else - pT->AdjustDialogPosition(m_pFindReplaceDialog->operator HWND()); - } - - void OnReplaceSel(LPCTSTR lpszFind, BOOL bFindDown, BOOL bMatchCase, BOOL bWholeWord, LPCTSTR lpszReplace) - { - T* pT = static_cast(this); - - m_sFindNext = lpszFind; - m_sReplaceWith = lpszReplace; - m_bMatchCase = bMatchCase; - m_bWholeWord = bWholeWord; - m_bFindDown = bFindDown; - - if(pT->SameAsSelected(m_sFindNext, m_bMatchCase, m_bWholeWord)) - pT->ReplaceSel(m_sReplaceWith); - - if(!pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWholeWord, m_bFindDown)) - pT->TextNotFound(m_sFindNext); - else - pT->AdjustDialogPosition(m_pFindReplaceDialog->operator HWND()); - } - - void OnReplaceAll(LPCTSTR lpszFind, LPCTSTR lpszReplace, BOOL bMatchCase, BOOL bWholeWord) - { - T* pT = static_cast(this); - - m_sFindNext = lpszFind; - m_sReplaceWith = lpszReplace; - m_bMatchCase = bMatchCase; - m_bWholeWord = bWholeWord; - m_bFindDown = TRUE; - - // no selection or different than what looking for - if(!pT->SameAsSelected(m_sFindNext, m_bMatchCase, m_bWholeWord)) - { - if(!pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWholeWord, m_bFindDown)) - { - pT->TextNotFound(m_sFindNext); - return; - } - } - - pT->OnReplaceAllCoreBegin(); - - int replaceCount=0; - do - { - ++replaceCount; - pT->ReplaceSel(m_sReplaceWith); - } while(pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWholeWord, m_bFindDown)); - - pT->OnReplaceAllCoreEnd(replaceCount); - } - - void OnReplaceAllCoreBegin() - { - T* pT = static_cast(this); - - m_hOldCursor = ::SetCursor(::LoadCursor(NULL, IDC_WAIT)); - - pT->HideSelection(TRUE, FALSE); - - } - - void OnReplaceAllCoreEnd(int replaceCount) - { - T* pT = static_cast(this); - pT->HideSelection(FALSE, FALSE); - - ::SetCursor(m_hOldCursor); - - _CSTRING_NS::CString message = pT->GetTranslationText(eText_OnReplaceAllMessage); - if(message.GetLength() > 0) - { - _CSTRING_NS::CString formattedMessage; - formattedMessage.Format(message, - replaceCount, m_sFindNext, m_sReplaceWith); - if(m_pFindReplaceDialog != NULL) - { - m_pFindReplaceDialog->MessageBox(formattedMessage, - pT->GetTranslationText(eText_OnReplaceAllTitle), - MB_OK | MB_ICONINFORMATION | MB_APPLMODAL); - } - else - { - pT->MessageBox(formattedMessage, - pT->GetTranslationText(eText_OnReplaceAllTitle), - MB_OK | MB_ICONINFORMATION | MB_APPLMODAL); - } - } - } - - void OnTextNotFound(LPCTSTR lpszFind) - { - T* pT = static_cast(this); - _CSTRING_NS::CString message = pT->GetTranslationText(eText_OnTextNotFoundMessage); - if(message.GetLength() > 0) - { - _CSTRING_NS::CString formattedMessage; - formattedMessage.Format(message, lpszFind); - if(m_pFindReplaceDialog != NULL) - { - m_pFindReplaceDialog->MessageBox(formattedMessage, - pT->GetTranslationText(eText_OnTextNotFoundTitle), - MB_OK | MB_ICONINFORMATION | MB_APPLMODAL); - } - else - { - pT->MessageBox(formattedMessage, - pT->GetTranslationText(eText_OnTextNotFoundTitle), - MB_OK | MB_ICONINFORMATION | MB_APPLMODAL); - } - } - else - { - ::MessageBeep(MB_ICONHAND); - } - } - - void OnTerminatingFindReplaceDialog(TFindReplaceDialog*& /*findReplaceDialog*/) - { - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CEditFindReplaceImpl - Mixin class for implementing Find/Replace for CEdit -// based window classes. - -// Chain to CEditFindReplaceImpl message map. Your class must also derive from CEdit. -// Example: -// class CMyEdit : public CWindowImpl, -// public CEditFindReplaceImpl -// { -// public: -// BEGIN_MSG_MAP(CMyEdit) -// // your handlers... -// CHAIN_MSG_MAP_ALT(CEditFindReplaceImpl, 1) -// END_MSG_MAP() -// // other stuff... -// }; - -template -class CEditFindReplaceImpl : public CEditFindReplaceImplBase -{ -protected: - typedef CEditFindReplaceImpl thisClass; - typedef CEditFindReplaceImplBase baseClass; - -// Data members - LPTSTR m_pShadowBuffer; // Special shadow buffer only used in some cases. - UINT m_nShadowSize; - int m_bShadowBufferNeeded; // TRUE, FALSE, < 0 => Need to check - -public: -// Constructors - CEditFindReplaceImpl() : - m_pShadowBuffer(NULL), - m_nShadowSize(0), - m_bShadowBufferNeeded(-1) - { - } - - virtual ~CEditFindReplaceImpl() - { - if(m_pShadowBuffer != NULL) - { - delete [] m_pShadowBuffer; - m_pShadowBuffer = NULL; - } - } - -// Message Handlers - BEGIN_MSG_MAP(thisClass) - ALT_MSG_MAP(1) - CHAIN_MSG_MAP_ALT(baseClass, 1) - END_MSG_MAP() - -// Operations - // Supported only for RichEdit, so this does nothing for Edit - void HideSelection(BOOL /*bHide*/ = TRUE, BOOL /*bChangeStyle*/ = FALSE) - { - } - -// Operations (overrideable) - BOOL FindTextSimple(LPCTSTR lpszFind, BOOL bMatchCase, BOOL bWholeWord, BOOL bFindDown = TRUE) - { - T* pT = static_cast(this); - - ATLASSERT(lpszFind != NULL); - ATLASSERT(*lpszFind != _T('\0')); - - UINT nLen = pT->GetBufferLength(); - int nStartChar = 0, nEndChar = 0; - pT->GetSel(nStartChar, nEndChar); - UINT nStart = nStartChar; - int iDir = bFindDown ? +1 : -1; - - // can't find a match before the first character - if(nStart == 0 && iDir < 0) - return FALSE; - - LPCTSTR lpszText = pT->LockBuffer(); - - bool isDBCS = false; -#ifdef _MBCS - CPINFO info = { 0 }; - ::GetCPInfo(::GetOEMCP(), &info); - isDBCS = (info.MaxCharSize > 1); -#endif - - if(iDir < 0) - { - // always go back one for search backwards - nStart -= int((lpszText + nStart) - ::CharPrev(lpszText, lpszText + nStart)); - } - else if(nStartChar != nEndChar && pT->SameAsSelected(lpszFind, bMatchCase, bWholeWord)) - { - // easy to go backward/forward with SBCS -#ifndef _UNICODE - if(::IsDBCSLeadByte(lpszText[nStart])) - nStart++; -#endif - nStart += iDir; - } - - // handle search with nStart past end of buffer - UINT nLenFind = ::lstrlen(lpszFind); - if(nStart + nLenFind - 1 >= nLen) - { - if(iDir < 0 && nLen >= nLenFind) - { - if(isDBCS) - { - // walk back to previous character n times - nStart = nLen; - int n = nLenFind; - while(n--) - { - nStart -= int((lpszText + nStart) - ::CharPrev(lpszText, lpszText + nStart)); - } - } - else - { - // single-byte character set is easy and fast - nStart = nLen - nLenFind; - } - ATLASSERT(nStart + nLenFind - 1 <= nLen); - } - else - { - pT->UnlockBuffer(); - return FALSE; - } - } - - // start the search at nStart - LPCTSTR lpsz = lpszText + nStart; - typedef int (WINAPI* CompareProc)(LPCTSTR str1, LPCTSTR str2); - CompareProc pfnCompare = bMatchCase ? lstrcmp : lstrcmpi; - - if(isDBCS) - { - // double-byte string search - LPCTSTR lpszStop = NULL; - if(iDir > 0) - { - // start at current and find _first_ occurrance - lpszStop = lpszText + nLen - nLenFind + 1; - } - else - { - // start at top and find _last_ occurrance - lpszStop = lpsz; - lpsz = lpszText; - } - - LPCTSTR lpszFound = NULL; - while(lpsz <= lpszStop) - { -#ifndef _UNICODE - if(!bMatchCase || (*lpsz == *lpszFind && (!::IsDBCSLeadByte(*lpsz) || lpsz[1] == lpszFind[1]))) -#else - if(!bMatchCase || (*lpsz == *lpszFind && lpsz[1] == lpszFind[1])) -#endif - { - LPTSTR lpch = (LPTSTR)(lpsz + nLenFind); - TCHAR chSave = *lpch; - *lpch = _T('\0'); - int nResult = (*pfnCompare)(lpsz, lpszFind); - *lpch = chSave; - if(nResult == 0) - { - lpszFound = lpsz; - if(iDir > 0) - break; - } - } - lpsz = ::CharNext(lpsz); - } - pT->UnlockBuffer(); - - if(lpszFound != NULL) - { - int n = (int)(lpszFound - lpszText); - pT->SetSel(n, n + nLenFind); - return TRUE; - } - } - else - { - // single-byte string search - UINT nCompare; - if(iDir < 0) - nCompare = (UINT)(lpsz - lpszText) + 1; - else - nCompare = nLen - (UINT)(lpsz - lpszText) - nLenFind + 1; - - while(nCompare > 0) - { - ATLASSERT(lpsz >= lpszText); - ATLASSERT(lpsz + nLenFind - 1 <= lpszText + nLen - 1); - - LPSTR lpch = (LPSTR)(lpsz + nLenFind); - char chSave = *lpch; - *lpch = '\0'; - int nResult = (*pfnCompare)(lpsz, lpszFind); - *lpch = chSave; - if(nResult == 0) - { - pT->UnlockBuffer(); - int n = (int)(lpsz - lpszText); - pT->SetSel(n, n + nLenFind); - return TRUE; - } - - // restore character at end of search - *lpch = chSave; - - // move on to next substring - nCompare--; - lpsz += iDir; - } - pT->UnlockBuffer(); - } - - return FALSE; - } - - LPCTSTR LockBuffer() const - { - const T* pT = static_cast(this); - - ATLASSERT(pT->m_hWnd != NULL); - - BOOL useShadowBuffer = pT->UseShadowBuffer(); - if(useShadowBuffer) - { - if(m_pShadowBuffer == NULL || pT->GetModify()) - { - ATLASSERT(m_pShadowBuffer != NULL || m_nShadowSize == 0); - UINT nSize = pT->GetWindowTextLength() + 1; - if(nSize > m_nShadowSize) - { - // need more room for shadow buffer - T* pThisNoConst = const_cast(pT); - delete[] m_pShadowBuffer; - pThisNoConst->m_pShadowBuffer = NULL; - pThisNoConst->m_nShadowSize = 0; - pThisNoConst->m_pShadowBuffer = new TCHAR[nSize]; - pThisNoConst->m_nShadowSize = nSize; - } - - // update the shadow buffer with GetWindowText - ATLASSERT(m_nShadowSize >= nSize); - ATLASSERT(m_pShadowBuffer != NULL); - pT->GetWindowText(m_pShadowBuffer, nSize); - } - - return m_pShadowBuffer; - } - - HLOCAL hLocal = pT->GetHandle(); - ATLASSERT(hLocal != NULL); - LPCTSTR lpszText = (LPCTSTR)::LocalLock(hLocal); - ATLASSERT(lpszText != NULL); - - return lpszText; - } - - void UnlockBuffer() const - { - const T* pT = static_cast(this); - - ATLASSERT(pT->m_hWnd != NULL); - - BOOL useShadowBuffer = pT->UseShadowBuffer(); - if(!useShadowBuffer) - { - HLOCAL hLocal = pT->GetHandle(); - ATLASSERT(hLocal != NULL); - ::LocalUnlock(hLocal); - } - } - - UINT GetBufferLength() const - { - const T* pT = static_cast(this); - - ATLASSERT(pT->m_hWnd != NULL); - UINT nLen = 0; - LPCTSTR lpszText = pT->LockBuffer(); - if(lpszText != NULL) - nLen = ::lstrlen(lpszText); - pT->UnlockBuffer(); - - return nLen; - } - - LONG EndOfLine(LPCTSTR lpszText, UINT nLen, UINT nIndex) const - { - LPCTSTR lpsz = lpszText + nIndex; - LPCTSTR lpszStop = lpszText + nLen; - while(lpsz < lpszStop && *lpsz != _T('\r')) - ++lpsz; - return LONG(lpsz - lpszText); - } - - LONG GetSelText(_CSTRING_NS::CString& strText) const - { - const T* pT = static_cast(this); - - int nStartChar = 0, nEndChar = 0; - pT->GetSel(nStartChar, nEndChar); - ATLASSERT((UINT)nEndChar <= pT->GetBufferLength()); - LPCTSTR lpszText = pT->LockBuffer(); - LONG nLen = pT->EndOfLine(lpszText, nEndChar, nStartChar) - nStartChar; - SecureHelper::memcpy_x(strText.GetBuffer(nLen), nLen * sizeof(TCHAR), lpszText + nStartChar, nLen * sizeof(TCHAR)); - strText.ReleaseBuffer(nLen); - pT->UnlockBuffer(); - - return nLen; - } - - BOOL UseShadowBuffer(void) const - { - const T* pT = static_cast(this); - - if(pT->m_bShadowBufferNeeded < 0) - { - T* pThisNoConst = const_cast(pT); - - OSVERSIONINFO ovi = { 0 }; - ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - ::GetVersionEx(&ovi); - - bool bWin9x = (ovi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS); - if(bWin9x) - { - // Windows 95, 98, ME - // Under Win9x, it is necessary to maintain a shadow buffer. - // It is only updated when the control contents have been changed. - pThisNoConst->m_bShadowBufferNeeded = TRUE; - } - else - { - // Windows NT, 2000, XP, etc. - pThisNoConst->m_bShadowBufferNeeded = FALSE; - -#ifndef _UNICODE - // On Windows XP (or later), if common controls version 6 is in use - // (such as via theming), then EM_GETHANDLE will always return a UNICODE string. - // If theming is enabled and Common Controls version 6 is in use, - // you're really not suppose to superclass or subclass common controls - // with an ANSI windows procedure (so its best to only theme if you use UNICODE). - // Using a shadow buffer uses GetWindowText instead, so it solves - // this problem for us (although it makes it a little less efficient). - - if((ovi.dwMajorVersion == 5 && ovi.dwMinorVersion >= 1) || (ovi.dwMajorVersion > 5)) - { - // We use DLLVERSIONINFO_private so we don't have to depend on shlwapi.h - typedef struct _DLLVERSIONINFO_private - { - DWORD cbSize; - DWORD dwMajorVersion; - DWORD dwMinorVersion; - DWORD dwBuildNumber; - DWORD dwPlatformID; - } DLLVERSIONINFO_private; - - HMODULE hModule = ::LoadLibrary("comctl32.dll"); - if(hModule != NULL) - { - typedef HRESULT (CALLBACK *LPFN_DllGetVersion)(DLLVERSIONINFO_private *); - LPFN_DllGetVersion fnDllGetVersion = (LPFN_DllGetVersion)::GetProcAddress(hModule, "DllGetVersion"); - if(fnDllGetVersion != NULL) - { - DLLVERSIONINFO_private version = { 0 }; - version.cbSize = sizeof(DLLVERSIONINFO_private); - if(SUCCEEDED(fnDllGetVersion(&version))) - { - if(version.dwMajorVersion >= 6) - { - pThisNoConst->m_bShadowBufferNeeded = TRUE; - - ATLTRACE2(atlTraceUI, 0, _T("Warning: You have compiled for MBCS/ANSI but are using common controls version 6 or later (likely through a manifest file).\r\n")); - ATLTRACE2(atlTraceUI, 0, _T("If you use common controls version 6 or later, you should only do so for UNICODE builds.\r\n")); - } - } - } - - ::FreeLibrary(hModule); - hModule = NULL; - } - } -#endif // !_UNICODE - } - } - - return (pT->m_bShadowBufferNeeded == TRUE); - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CRichEditFindReplaceImpl - Mixin class for implementing Find/Replace for CRichEditCtrl -// based window classes. - -// Chain to CRichEditFindReplaceImpl message map. Your class must also derive from CRichEditCtrl. -// Example: -// class CMyRichEdit : public CWindowImpl, -// public CRichEditFindReplaceImpl -// { -// public: -// BEGIN_MSG_MAP(CMyRichEdit) -// // your handlers... -// CHAIN_MSG_MAP_ALT(CRichEditFindReplaceImpl, 1) -// END_MSG_MAP() -// // other stuff... -// }; - -template -class CRichEditFindReplaceImpl : public CEditFindReplaceImplBase -{ -protected: - typedef CRichEditFindReplaceImpl thisClass; - typedef CEditFindReplaceImplBase baseClass; - -public: - BEGIN_MSG_MAP(thisClass) - ALT_MSG_MAP(1) - CHAIN_MSG_MAP_ALT(baseClass, 1) - END_MSG_MAP() - -// Operations (overrideable) - BOOL FindTextSimple(LPCTSTR lpszFind, BOOL bMatchCase, BOOL bWholeWord, BOOL bFindDown = TRUE) - { - T* pT = static_cast(this); - - ATLASSERT(lpszFind != NULL); - FINDTEXTEX ft = { 0 }; - - pT->GetSel(ft.chrg); - if(m_bFirstSearch) - { - if(bFindDown) - m_nInitialSearchPos = ft.chrg.cpMin; - else - m_nInitialSearchPos = ft.chrg.cpMax; - m_bFirstSearch = FALSE; - } - -#if (_RICHEDIT_VER >= 0x0200) - ft.lpstrText = (LPTSTR)lpszFind; -#else // !(_RICHEDIT_VER >= 0x0200) - USES_CONVERSION; - ft.lpstrText = T2A((LPTSTR)lpszFind); -#endif // !(_RICHEDIT_VER >= 0x0200) - - if(ft.chrg.cpMin != ft.chrg.cpMax) // i.e. there is a selection - { - if(bFindDown) - { - ft.chrg.cpMin++; - } - else - { - // won't wraparound backwards - ft.chrg.cpMin = max(ft.chrg.cpMin, 0); - } - } - - DWORD dwFlags = bMatchCase ? FR_MATCHCASE : 0; - dwFlags |= bWholeWord ? FR_WHOLEWORD : 0; - - ft.chrg.cpMax = pT->GetTextLength() + m_nInitialSearchPos; - - if(bFindDown) - { - if(m_nInitialSearchPos >= 0) - ft.chrg.cpMax = pT->GetTextLength(); - - dwFlags |= FR_DOWN; - ATLASSERT(ft.chrg.cpMax >= ft.chrg.cpMin); - } - else - { - if(m_nInitialSearchPos >= 0) - ft.chrg.cpMax = 0; - - dwFlags &= ~FR_DOWN; - ATLASSERT(ft.chrg.cpMax <= ft.chrg.cpMin); - } - - BOOL bRet = FALSE; - - if(pT->FindAndSelect(dwFlags, ft) != -1) - { - bRet = TRUE; // we found the text - } - else if(m_nInitialSearchPos > 0) - { - // if the original starting point was not the beginning - // of the buffer and we haven't already been here - if(bFindDown) - { - ft.chrg.cpMin = 0; - ft.chrg.cpMax = m_nInitialSearchPos; - } - else - { - ft.chrg.cpMin = pT->GetTextLength(); - ft.chrg.cpMax = m_nInitialSearchPos; - } - m_nInitialSearchPos = m_nInitialSearchPos - pT->GetTextLength(); - - bRet = (pT->FindAndSelect(dwFlags, ft) != -1) ? TRUE : FALSE; - } - - return bRet; - } - - long FindAndSelect(DWORD dwFlags, FINDTEXTEX& ft) - { - T* pT = static_cast(this); - LONG index = pT->FindText(dwFlags, ft); - if(index != -1) // i.e. we found something - pT->SetSel(ft.chrgText); - - return index; - } -}; - -}; // namespace WTL - -#endif // __ATLFIND_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/atlframe.h b/prog/3rdPartyLibs/wtl-8.1/include/atlframe.h deleted file mode 100644 index 00358c37d..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/atlframe.h +++ /dev/null @@ -1,3465 +0,0 @@ -// Windows Template Library - WTL version 8.1 -// Copyright (C) Microsoft Corporation. All rights reserved. -// -// This file is a part of the Windows Template Library. -// The use and distribution terms for this software are covered by the -// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php) -// which can be found in the file CPL.TXT at the root of this distribution. -// By using this software in any fashion, you are agreeing to be bound by -// the terms of this license. You must not remove this notice, or -// any other, from this software. - -#ifndef __ATLFRAME_H__ -#define __ATLFRAME_H__ - -#pragma once - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#ifndef __ATLAPP_H__ - #error atlframe.h requires atlapp.h to be included first -#endif - -#ifndef __ATLWIN_H__ - #error atlframe.h requires atlwin.h to be included first -#endif - - -/////////////////////////////////////////////////////////////////////////////// -// Classes in this file: -// -// CFrameWindowImpl -// CMDIWindow -// CMDIFrameWindowImpl -// CMDIChildWindowImpl -// COwnerDraw -// CUpdateUIBase -// CUpdateUI -// CDynamicUpdateUI -// CDialogResize -// CDoubleBufferImpl -// CDoubleBufferWindowImpl -// -// Global functions: -// AtlCreateSimpleToolBar() - - -namespace WTL -{ - -/////////////////////////////////////////////////////////////////////////////// -// CFrameWndClassInfo - Manages frame window Windows class information - -class CFrameWndClassInfo -{ -public: -#ifndef _WIN32_WCE - enum { cchAutoName = 5 + sizeof(void*) * 2 }; // sizeof(void*) * 2 is the number of digits %p outputs - WNDCLASSEX m_wc; -#else // CE specific - enum { cchAutoName = MAX_PATH }; // MAX_PATH because this can be set in the wizard generated CMainFrame::ActivatePreviousInstance to a user defined string. - WNDCLASS m_wc; -#endif // !_WIN32_WCE - LPCTSTR m_lpszOrigName; - WNDPROC pWndProc; - LPCTSTR m_lpszCursorID; - BOOL m_bSystemCursor; - ATOM m_atom; - TCHAR m_szAutoName[cchAutoName]; - UINT m_uCommonResourceID; - -#ifndef _WIN32_WCE - ATOM Register(WNDPROC* pProc) - { - if (m_atom == 0) - { - CWindowCreateCriticalSectionLock lock; - if(FAILED(lock.Lock())) - { - ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CFrameWndClassInfo::Register.\n")); - ATLASSERT(FALSE); - return 0; - } - - if(m_atom == 0) - { - HINSTANCE hInst = ModuleHelper::GetModuleInstance(); - - if (m_lpszOrigName != NULL) - { - ATLASSERT(pProc != NULL); - LPCTSTR lpsz = m_wc.lpszClassName; - WNDPROC proc = m_wc.lpfnWndProc; - - WNDCLASSEX wc = { 0 }; - wc.cbSize = sizeof(WNDCLASSEX); - // try process local class first - if(!::GetClassInfoEx(ModuleHelper::GetModuleInstance(), m_lpszOrigName, &wc)) - { - // try global class - if(!::GetClassInfoEx(NULL, m_lpszOrigName, &wc)) - { - lock.Unlock(); - return 0; - } - } - m_wc = wc; - pWndProc = m_wc.lpfnWndProc; - m_wc.lpszClassName = lpsz; - m_wc.lpfnWndProc = proc; - } - else - { - m_wc.hCursor = ::LoadCursor(m_bSystemCursor ? NULL : hInst, m_lpszCursorID); - } - - m_wc.hInstance = hInst; - m_wc.style &= ~CS_GLOBALCLASS; // we don't register global classes - if (m_wc.lpszClassName == NULL) - { -#if (_WIN32_WINNT >= 0x0500) || defined(_WIN64) - SecureHelper::wsprintf_x(m_szAutoName, cchAutoName, _T("ATL:%p"), &m_wc); -#else // !((_WIN32_WINNT >= 0x0500) || defined(_WIN64)) - SecureHelper::wsprintf_x(m_szAutoName, cchAutoName, _T("ATL:%8.8X"), (DWORD_PTR)&m_wc); -#endif // !((_WIN32_WINNT >= 0x0500) || defined(_WIN64)) - m_wc.lpszClassName = m_szAutoName; - } - - WNDCLASSEX wcTemp = m_wc; - m_atom = (ATOM)::GetClassInfoEx(m_wc.hInstance, m_wc.lpszClassName, &wcTemp); - if (m_atom == 0) - { - if(m_uCommonResourceID != 0) // use it if not zero - { - m_wc.hIcon = (HICON)::LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR); - m_wc.hIconSm = (HICON)::LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); - } - m_atom = ::RegisterClassEx(&m_wc); - } - } - - lock.Unlock(); - } - - if (m_lpszOrigName != NULL) - { - ATLASSERT(pProc != NULL); - ATLASSERT(pWndProc != NULL); - *pProc = pWndProc; - } - - return m_atom; - } -#else // CE specific - ATOM Register(WNDPROC* pProc) - { - if (m_atom == 0) - { - CWindowCreateCriticalSectionLock lock; - if(FAILED(lock.Lock())) - { - ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CFrameWndClassInfo::Register.\n")); - ATLASSERT(FALSE); - return 0; - } - - if(m_atom == 0) - { - HINSTANCE hInst = ModuleHelper::GetModuleInstance(); - - if (m_lpszOrigName != NULL) - { - ATLASSERT(pProc != NULL); - LPCTSTR lpsz = m_wc.lpszClassName; - WNDPROC proc = m_wc.lpfnWndProc; - - WNDCLASS wc = { 0 }; - // try process local class first - if(!::GetClassInfo(ModuleHelper::GetModuleInstance(), m_lpszOrigName, &wc)) - { - // try global class - if(!::GetClassInfo(NULL, m_lpszOrigName, &wc)) - { - lock.Unlock(); - return 0; - } - } - m_wc = wc; - pWndProc = m_wc.lpfnWndProc; - m_wc.lpszClassName = lpsz; - m_wc.lpfnWndProc = proc; - } - else - { -#if defined(GWES_CURSOR) || defined(GWES_MCURSOR) - m_wc.hCursor = ::LoadCursor(m_bSystemCursor ? NULL : hInst, m_lpszCursorID); -#else // !(defined(GWES_CURSOR) || defined(GWES_MCURSOR)) - m_wc.hCursor = NULL; -#endif // !(defined(GWES_CURSOR) || defined(GWES_MCURSOR)) - } - - m_wc.hInstance = hInst; - m_wc.style &= ~CS_GLOBALCLASS; // we don't register global classes - if (m_wc.lpszClassName == NULL) - { - wsprintf(m_szAutoName, _T("ATL:%8.8X"), (DWORD_PTR)&m_wc); - m_wc.lpszClassName = m_szAutoName; - } - - WNDCLASS wcTemp = m_wc; - m_atom = (ATOM)::GetClassInfo(m_wc.hInstance, m_wc.lpszClassName, &wcTemp); - if (m_atom == 0) - { - if(m_uCommonResourceID != 0) // use it if not zero - m_wc.hIcon = (HICON)::LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR); - m_atom = ::RegisterClass(&m_wc); - } - } - - lock.Unlock(); - } - - if (m_lpszOrigName != NULL) - { - ATLASSERT(pProc != NULL); - ATLASSERT(pWndProc != NULL); - *pProc = pWndProc; - } - - return m_atom; - } -#endif // _WIN32_WCE -}; - - -/////////////////////////////////////////////////////////////////////////////// -// Macros for declaring frame window WNDCLASS - -#ifndef _WIN32_WCE - -#define DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \ -static WTL::CFrameWndClassInfo& GetWndClassInfo() \ -{ \ - static WTL::CFrameWndClassInfo wc = \ - { \ - { sizeof(WNDCLASSEX), 0, StartWindowProc, \ - 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName, NULL }, \ - NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \ - }; \ - return wc; \ -} - -#define DECLARE_FRAME_WND_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd) \ -static WTL::CFrameWndClassInfo& GetWndClassInfo() \ -{ \ - static WTL::CFrameWndClassInfo wc = \ - { \ - { sizeof(WNDCLASSEX), style, StartWindowProc, \ - 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName, NULL }, \ - NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \ - }; \ - return wc; \ -} - -#define DECLARE_FRAME_WND_SUPERCLASS(WndClassName, OrigWndClassName, uCommonResourceID) \ -static WTL::CFrameWndClassInfo& GetWndClassInfo() \ -{ \ - static WTL::CFrameWndClassInfo wc = \ - { \ - { sizeof(WNDCLASSEX), 0, StartWindowProc, \ - 0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName, NULL }, \ - OrigWndClassName, NULL, NULL, TRUE, 0, _T(""), uCommonResourceID \ - }; \ - return wc; \ -} - -#else // CE specific - -#define DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \ -static WTL::CFrameWndClassInfo& GetWndClassInfo() \ -{ \ - static WTL::CFrameWndClassInfo wc = \ - { \ - { 0, StartWindowProc, \ - 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName }, \ - NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \ - }; \ - return wc; \ -} - -#define DECLARE_FRAME_WND_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd) \ -static WTL::CFrameWndClassInfo& GetWndClassInfo() \ -{ \ - static WTL::CFrameWndClassInfo wc = \ - { \ - { style, StartWindowProc, \ - 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName }, \ - NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \ - }; \ - return wc; \ -} - -#define DECLARE_FRAME_WND_SUPERCLASS(WndClassName, OrigWndClassName, uCommonResourceID) \ -static WTL::CFrameWndClassInfo& GetWndClassInfo() \ -{ \ - static WTL::CFrameWndClassInfo wc = \ - { \ - { NULL, StartWindowProc, \ - 0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName }, \ - OrigWndClassName, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \ - }; \ - return wc; \ -} - -#endif // !_WIN32_WCE - - -/////////////////////////////////////////////////////////////////////////////// -// CFrameWindowImpl - -// Client window command chaining macro (only for frame windows) -#define CHAIN_CLIENT_COMMANDS() \ - if(uMsg == WM_COMMAND && m_hWndClient != NULL) \ - ::SendMessage(m_hWndClient, uMsg, wParam, lParam); - -// standard toolbar styles -#define ATL_SIMPLE_TOOLBAR_STYLE \ - (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | TBSTYLE_TOOLTIPS) -// toolbar in a rebar pane -#define ATL_SIMPLE_TOOLBAR_PANE_STYLE \ - (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NORESIZE | CCS_NOPARENTALIGN | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT) -// standard rebar styles -#if (_WIN32_IE >= 0x0400) - #define ATL_SIMPLE_REBAR_STYLE \ - (WS_CHILD | WS_VISIBLE | WS_BORDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS | RBS_AUTOSIZE) -#else - #define ATL_SIMPLE_REBAR_STYLE \ - (WS_CHILD | WS_VISIBLE | WS_BORDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS) -#endif // !(_WIN32_IE >= 0x0400) -// rebar without borders -#if (_WIN32_IE >= 0x0400) - #define ATL_SIMPLE_REBAR_NOBORDER_STYLE \ - (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS | RBS_AUTOSIZE | CCS_NODIVIDER) -#else - #define ATL_SIMPLE_REBAR_NOBORDER_STYLE \ - (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS | CCS_NODIVIDER) -#endif // !(_WIN32_IE >= 0x0400) - -// command bar support -#if !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE) - -#define CBRM_GETCMDBAR (WM_USER + 301) // returns command bar HWND -#define CBRM_GETMENU (WM_USER + 302) // returns loaded or attached menu -#define CBRM_TRACKPOPUPMENU (WM_USER + 303) // displays a popup menu - -struct _AtlFrameWnd_CmdBarPopupMenu -{ - int cbSize; - HMENU hMenu; - UINT uFlags; - int x; - int y; - LPTPMPARAMS lptpm; -}; - -#define CBRPOPUPMENU _AtlFrameWnd_CmdBarPopupMenu - -#endif // !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE) - - -template -class ATL_NO_VTABLE CFrameWindowImplBase : public ATL::CWindowImplBaseT< TBase, TWinTraits > -{ -public: - DECLARE_FRAME_WND_CLASS(NULL, 0) - -// Data members - HWND m_hWndToolBar; - HWND m_hWndStatusBar; - HWND m_hWndClient; - - HACCEL m_hAccel; - -#ifdef _WIN32_WCE - HWND m_hWndCECommandBar; -#endif // _WIN32_WCE - - struct _AtlToolBarData - { - WORD wVersion; - WORD wWidth; - WORD wHeight; - WORD wItemCount; - //WORD aItems[wItemCount] - - WORD* items() - { return (WORD*)(this+1); } - }; - -#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) - struct _ChevronMenuInfo - { - HMENU hMenu; - LPNMREBARCHEVRON lpnm; - bool bCmdBar; - }; -#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) - -// Constructor - CFrameWindowImplBase() : -#ifdef _WIN32_WCE - m_hWndCECommandBar(NULL), -#endif // _WIN32_WCE - m_hWndToolBar(NULL), - m_hWndStatusBar(NULL), - m_hWndClient(NULL), - m_hAccel(NULL) - { } - -// Methods - HWND Create(HWND hWndParent, ATL::_U_RECT rect, LPCTSTR szWindowName, DWORD dwStyle, DWORD dwExStyle, ATL::_U_MENUorID MenuOrID, ATOM atom, LPVOID lpCreateParam) - { - ATLASSERT(m_hWnd == NULL); - - if(atom == 0) - return NULL; - - ModuleHelper::AddCreateWndData(&m_thunk.cd, this); - - if(MenuOrID.m_hMenu == NULL && (dwStyle & WS_CHILD)) - MenuOrID.m_hMenu = (HMENU)(UINT_PTR)this; - if(rect.m_lpRect == NULL) - rect.m_lpRect = &TBase::rcDefault; - - HWND hWnd = ::CreateWindowEx(dwExStyle, MAKEINTATOM(atom), szWindowName, - dwStyle, rect.m_lpRect->left, rect.m_lpRect->top, rect.m_lpRect->right - rect.m_lpRect->left, - rect.m_lpRect->bottom - rect.m_lpRect->top, hWndParent, MenuOrID.m_hMenu, - ModuleHelper::GetModuleInstance(), lpCreateParam); - - ATLASSERT(hWnd == NULL || m_hWnd == hWnd); - - return hWnd; - } - - static HWND CreateSimpleToolBarCtrl(HWND hWndParent, UINT nResourceID, BOOL bInitialSeparator = FALSE, - DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR) - { - HINSTANCE hInst = ModuleHelper::GetResourceInstance(); - HRSRC hRsrc = ::FindResource(hInst, MAKEINTRESOURCE(nResourceID), RT_TOOLBAR); - if (hRsrc == NULL) - return NULL; - - HGLOBAL hGlobal = ::LoadResource(hInst, hRsrc); - if (hGlobal == NULL) - return NULL; - - _AtlToolBarData* pData = (_AtlToolBarData*)::LockResource(hGlobal); - if (pData == NULL) - return NULL; - ATLASSERT(pData->wVersion == 1); - - WORD* pItems = pData->items(); - int nItems = pData->wItemCount + (bInitialSeparator ? 1 : 0); - CTempBuffer buff; - TBBUTTON* pTBBtn = buff.Allocate(nItems); - ATLASSERT(pTBBtn != NULL); - if(pTBBtn == NULL) - return NULL; - - const int cxSeparator = 8; - - // set initial separator (half width) - if(bInitialSeparator) - { - pTBBtn[0].iBitmap = cxSeparator / 2; - pTBBtn[0].idCommand = 0; - pTBBtn[0].fsState = 0; - pTBBtn[0].fsStyle = TBSTYLE_SEP; - pTBBtn[0].dwData = 0; - pTBBtn[0].iString = 0; - } - - int nBmp = 0; - for(int i = 0, j = bInitialSeparator ? 1 : 0; i < pData->wItemCount; i++, j++) - { - if(pItems[i] != 0) - { - pTBBtn[j].iBitmap = nBmp++; - pTBBtn[j].idCommand = pItems[i]; - pTBBtn[j].fsState = TBSTATE_ENABLED; - pTBBtn[j].fsStyle = TBSTYLE_BUTTON; - pTBBtn[j].dwData = 0; - pTBBtn[j].iString = 0; - } - else - { - pTBBtn[j].iBitmap = cxSeparator; - pTBBtn[j].idCommand = 0; - pTBBtn[j].fsState = 0; - pTBBtn[j].fsStyle = TBSTYLE_SEP; - pTBBtn[j].dwData = 0; - pTBBtn[j].iString = 0; - } - } - -#ifndef _WIN32_WCE - HWND hWnd = ::CreateWindowEx(0, TOOLBARCLASSNAME, NULL, dwStyle, 0, 0, 100, 100, hWndParent, (HMENU)LongToHandle(nID), ModuleHelper::GetModuleInstance(), NULL); - if(hWnd == NULL) - { - ATLASSERT(FALSE); - return NULL; - } -#else // CE specific - dwStyle; - nID; - // The toolbar must go onto the existing CommandBar or MenuBar - HWND hWnd = hWndParent; -#endif // _WIN32_WCE - - ::SendMessage(hWnd, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0L); - - // check if font is taller than our bitmaps - CFontHandle font = (HFONT)::SendMessage(hWnd, WM_GETFONT, 0, 0L); - if(font.IsNull()) - font = AtlGetDefaultGuiFont(); - LOGFONT lf = { 0 }; - font.GetLogFont(lf); - WORD cyFontHeight = (WORD)abs(lf.lfHeight); - -#ifndef _WIN32_WCE - WORD bitsPerPixel = AtlGetBitmapResourceBitsPerPixel(nResourceID); - if(bitsPerPixel > 4) - { - COLORREF crMask = CLR_DEFAULT; - if(bitsPerPixel == 32) - { - // 32-bit color bitmap with alpha channel (valid for Windows XP and later) - crMask = CLR_NONE; - } - HIMAGELIST hImageList = ImageList_LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(nResourceID), pData->wWidth, 1, crMask, IMAGE_BITMAP, LR_CREATEDIBSECTION | LR_DEFAULTSIZE); - ATLASSERT(hImageList != NULL); - ::SendMessage(hWnd, TB_SETIMAGELIST, 0, (LPARAM)hImageList); - } - else -#endif // !_WIN32_WCE - { - TBADDBITMAP tbab = { 0 }; - tbab.hInst = hInst; - tbab.nID = nResourceID; - ::SendMessage(hWnd, TB_ADDBITMAP, nBmp, (LPARAM)&tbab); - } - - ::SendMessage(hWnd, TB_ADDBUTTONS, nItems, (LPARAM)pTBBtn); - ::SendMessage(hWnd, TB_SETBITMAPSIZE, 0, MAKELONG(pData->wWidth, max(pData->wHeight, cyFontHeight))); - const int cxyButtonMargin = 7; - ::SendMessage(hWnd, TB_SETBUTTONSIZE, 0, MAKELONG(pData->wWidth + cxyButtonMargin, max(pData->wHeight, cyFontHeight) + cxyButtonMargin)); - - return hWnd; - } - -#ifndef _WIN32_WCE - static HWND CreateSimpleReBarCtrl(HWND hWndParent, DWORD dwStyle = ATL_SIMPLE_REBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR) - { - // Ensure style combinations for proper rebar painting - if(dwStyle & CCS_NODIVIDER && dwStyle & WS_BORDER) - dwStyle &= ~WS_BORDER; - else if(!(dwStyle & WS_BORDER) && !(dwStyle & CCS_NODIVIDER)) - dwStyle |= CCS_NODIVIDER; - - // Create rebar window - HWND hWndReBar = ::CreateWindowEx(0, REBARCLASSNAME, NULL, dwStyle, 0, 0, 100, 100, hWndParent, (HMENU)LongToHandle(nID), ModuleHelper::GetModuleInstance(), NULL); - if(hWndReBar == NULL) - { - ATLTRACE2(atlTraceUI, 0, _T("Failed to create rebar.\n")); - return NULL; - } - - // Initialize and send the REBARINFO structure - REBARINFO rbi = { 0 }; - rbi.cbSize = sizeof(REBARINFO); - rbi.fMask = 0; - if(!::SendMessage(hWndReBar, RB_SETBARINFO, 0, (LPARAM)&rbi)) - { - ATLTRACE2(atlTraceUI, 0, _T("Failed to initialize rebar.\n")); - ::DestroyWindow(hWndReBar); - return NULL; - } - - return hWndReBar; - } - - BOOL CreateSimpleReBar(DWORD dwStyle = ATL_SIMPLE_REBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR) - { - ATLASSERT(!::IsWindow(m_hWndToolBar)); - m_hWndToolBar = CreateSimpleReBarCtrl(m_hWnd, dwStyle, nID); - return (m_hWndToolBar != NULL); - } - - static BOOL AddSimpleReBarBandCtrl(HWND hWndReBar, HWND hWndBand, int nID = 0, LPCTSTR lpstrTitle = NULL, BOOL bNewRow = FALSE, int cxWidth = 0, BOOL bFullWidthAlways = FALSE) - { - ATLASSERT(::IsWindow(hWndReBar)); // must be already created -#ifdef _DEBUG - // block - check if this is really a rebar - { - TCHAR lpszClassName[sizeof(REBARCLASSNAME)] = { 0 }; - ::GetClassName(hWndReBar, lpszClassName, sizeof(REBARCLASSNAME)); - ATLASSERT(lstrcmp(lpszClassName, REBARCLASSNAME) == 0); - } -#endif // _DEBUG - ATLASSERT(::IsWindow(hWndBand)); // must be already created - - // Get number of buttons on the toolbar - int nBtnCount = (int)::SendMessage(hWndBand, TB_BUTTONCOUNT, 0, 0L); - - // Set band info structure - REBARBANDINFO rbBand = { RunTimeHelper::SizeOf_REBARBANDINFO() }; -#if (_WIN32_IE >= 0x0400) - rbBand.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_ID | RBBIM_SIZE | RBBIM_IDEALSIZE; -#else - rbBand.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_ID | RBBIM_SIZE; -#endif // !(_WIN32_IE >= 0x0400) - if(lpstrTitle != NULL) - rbBand.fMask |= RBBIM_TEXT; - rbBand.fStyle = RBBS_CHILDEDGE; -#if (_WIN32_IE >= 0x0500) - if(nBtnCount > 0) // add chevron style for toolbar with buttons - rbBand.fStyle |= RBBS_USECHEVRON; -#endif // (_WIN32_IE >= 0x0500) - if(bNewRow) - rbBand.fStyle |= RBBS_BREAK; - - rbBand.lpText = (LPTSTR)lpstrTitle; - rbBand.hwndChild = hWndBand; - if(nID == 0) // calc band ID - nID = ATL_IDW_BAND_FIRST + (int)::SendMessage(hWndReBar, RB_GETBANDCOUNT, 0, 0L); - rbBand.wID = nID; - - // Calculate the size of the band - BOOL bRet = FALSE; - RECT rcTmp = { 0 }; - if(nBtnCount > 0) - { - bRet = (BOOL)::SendMessage(hWndBand, TB_GETITEMRECT, nBtnCount - 1, (LPARAM)&rcTmp); - ATLASSERT(bRet); - rbBand.cx = (cxWidth != 0) ? cxWidth : rcTmp.right; - rbBand.cyMinChild = rcTmp.bottom - rcTmp.top; - if(bFullWidthAlways) - { - rbBand.cxMinChild = rbBand.cx; - } - else if(lpstrTitle == NULL) - { - bRet = (BOOL)::SendMessage(hWndBand, TB_GETITEMRECT, 0, (LPARAM)&rcTmp); - ATLASSERT(bRet); - rbBand.cxMinChild = rcTmp.right; - } - else - { - rbBand.cxMinChild = 0; - } - } - else // no buttons, either not a toolbar or really has no buttons - { - bRet = ::GetWindowRect(hWndBand, &rcTmp); - ATLASSERT(bRet); - rbBand.cx = (cxWidth != 0) ? cxWidth : (rcTmp.right - rcTmp.left); - rbBand.cxMinChild = bFullWidthAlways ? rbBand.cx : 0; - rbBand.cyMinChild = rcTmp.bottom - rcTmp.top; - } - -#if (_WIN32_IE >= 0x0400) - rbBand.cxIdeal = rbBand.cx; -#endif // (_WIN32_IE >= 0x0400) - - // Add the band - LRESULT lRes = ::SendMessage(hWndReBar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand); - if(lRes == 0) - { - ATLTRACE2(atlTraceUI, 0, _T("Failed to add a band to the rebar.\n")); - return FALSE; - } - -#if (_WIN32_IE >= 0x0501) - DWORD dwExStyle = (DWORD)::SendMessage(hWndBand, TB_GETEXTENDEDSTYLE, 0, 0L); - ::SendMessage(hWndBand, TB_SETEXTENDEDSTYLE, 0, dwExStyle | TBSTYLE_EX_HIDECLIPPEDBUTTONS); -#endif // (_WIN32_IE >= 0x0501) - - return TRUE; - } - - BOOL AddSimpleReBarBand(HWND hWndBand, LPCTSTR lpstrTitle = NULL, BOOL bNewRow = FALSE, int cxWidth = 0, BOOL bFullWidthAlways = FALSE) - { - ATLASSERT(::IsWindow(m_hWndToolBar)); // must be an existing rebar - ATLASSERT(::IsWindow(hWndBand)); // must be created - return AddSimpleReBarBandCtrl(m_hWndToolBar, hWndBand, 0, lpstrTitle, bNewRow, cxWidth, bFullWidthAlways); - } - -#if (_WIN32_IE >= 0x0400) - void SizeSimpleReBarBands() - { - ATLASSERT(::IsWindow(m_hWndToolBar)); // must be an existing rebar - - int nCount = (int)::SendMessage(m_hWndToolBar, RB_GETBANDCOUNT, 0, 0L); - - for(int i = 0; i < nCount; i++) - { - REBARBANDINFO rbBand = { RunTimeHelper::SizeOf_REBARBANDINFO() }; - rbBand.fMask = RBBIM_SIZE; - BOOL bRet = (BOOL)::SendMessage(m_hWndToolBar, RB_GETBANDINFO, i, (LPARAM)&rbBand); - ATLASSERT(bRet); - RECT rect = { 0, 0, 0, 0 }; - ::SendMessage(m_hWndToolBar, RB_GETBANDBORDERS, i, (LPARAM)&rect); - rbBand.cx += rect.left + rect.right; - bRet = (BOOL)::SendMessage(m_hWndToolBar, RB_SETBANDINFO, i, (LPARAM)&rbBand); - ATLASSERT(bRet); - } - } -#endif // (_WIN32_IE >= 0x0400) -#endif // _WIN32_WCE - -#ifndef _WIN32_WCE - BOOL CreateSimpleStatusBar(LPCTSTR lpstrText, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL_IDW_STATUS_BAR) -#else // CE specific - BOOL CreateSimpleStatusBar(LPCTSTR lpstrText, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, UINT nID = ATL_IDW_STATUS_BAR) -#endif // _WIN32_WCE - { - ATLASSERT(!::IsWindow(m_hWndStatusBar)); - m_hWndStatusBar = ::CreateStatusWindow(dwStyle, lpstrText, m_hWnd, nID); - return (m_hWndStatusBar != NULL); - } - -#ifndef _WIN32_WCE - BOOL CreateSimpleStatusBar(UINT nTextID = ATL_IDS_IDLEMESSAGE, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL_IDW_STATUS_BAR) -#else // CE specific - BOOL CreateSimpleStatusBar(UINT nTextID = ATL_IDS_IDLEMESSAGE, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, UINT nID = ATL_IDW_STATUS_BAR) -#endif // _WIN32_WCE - { - const int cchMax = 128; // max text length is 127 for status bars (+1 for null) - TCHAR szText[cchMax]; - szText[0] = 0; - ::LoadString(ModuleHelper::GetResourceInstance(), nTextID, szText, cchMax); - return CreateSimpleStatusBar(szText, dwStyle, nID); - } - -#ifdef _WIN32_WCE - BOOL CreateSimpleCECommandBar(LPTSTR pszMenu = NULL, WORD iButton = 0, DWORD dwFlags = 0, int nCmdBarID = 1) - { - ATLASSERT(m_hWndCECommandBar == NULL); - ATLASSERT(m_hWndToolBar == NULL); - - m_hWndCECommandBar = ::CommandBar_Create(ModuleHelper::GetModuleInstance(), m_hWnd, nCmdBarID); - if(m_hWndCECommandBar == NULL) - return FALSE; - - m_hWndToolBar = m_hWndCECommandBar; - - BOOL bRet = TRUE; - - if(pszMenu != NULL) - bRet &= ::CommandBar_InsertMenubarEx(m_hWndCECommandBar, IS_INTRESOURCE(pszMenu) ? ModuleHelper::GetResourceInstance() : NULL, pszMenu, iButton); - - bRet &= ::CommandBar_AddAdornments(m_hWndCECommandBar, dwFlags, 0); - - return bRet; - } - -#if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) - BOOL CreateSimpleCEMenuBar(UINT nToolBarId = ATL_IDW_MENU_BAR, DWORD dwFlags = 0, int nBmpId = 0, int cBmpImages = 0) - { - ATLASSERT(m_hWndCECommandBar == NULL); - - SHMENUBARINFO mbi = { 0 }; - mbi.cbSize = sizeof(mbi); - mbi.hwndParent = m_hWnd; - mbi.dwFlags = dwFlags; - mbi.nToolBarId = nToolBarId; - mbi.hInstRes = ModuleHelper::GetResourceInstance(); - mbi.nBmpId = nBmpId; - mbi.cBmpImages = cBmpImages; - mbi.hwndMB = NULL; // This gets set by SHCreateMenuBar - - BOOL bRet = ::SHCreateMenuBar(&mbi); - if(bRet != FALSE) - { - m_hWndCECommandBar = mbi.hwndMB; - SizeToMenuBar(); - } - - return bRet; - } - - void SizeToMenuBar() // for menu bar only - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(::IsWindow(m_hWndCECommandBar)); - - RECT rect = { 0 }; - GetWindowRect(&rect); - RECT rectMB = { 0 }; - ::GetWindowRect(m_hWndCECommandBar, &rectMB); - int cy = ::IsWindowVisible(m_hWndCECommandBar) ? rectMB.top - rect.top : rectMB.bottom - rect.top; - SetWindowPos(NULL, 0, 0, rect.right - rect.left, cy, SWP_NOZORDER | SWP_NOMOVE); - } -#endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) -#endif // _WIN32_WCE - - void UpdateLayout(BOOL bResizeBars = TRUE) - { - RECT rect = { 0 }; - GetClientRect(&rect); - - // position bars and offset their dimensions - UpdateBarsPosition(rect, bResizeBars); - - // resize client window - if(m_hWndClient != NULL) - ::SetWindowPos(m_hWndClient, NULL, rect.left, rect.top, - rect.right - rect.left, rect.bottom - rect.top, - SWP_NOZORDER | SWP_NOACTIVATE); - } - - void UpdateBarsPosition(RECT& rect, BOOL bResizeBars = TRUE) - { - // resize toolbar - if(m_hWndToolBar != NULL && ((DWORD)::GetWindowLong(m_hWndToolBar, GWL_STYLE) & WS_VISIBLE)) - { - if(bResizeBars) - { - ::SendMessage(m_hWndToolBar, WM_SIZE, 0, 0); - ::InvalidateRect(m_hWndToolBar, NULL, FALSE); - } - RECT rectTB = { 0 }; - ::GetWindowRect(m_hWndToolBar, &rectTB); - rect.top += rectTB.bottom - rectTB.top; - } - - // resize status bar - if(m_hWndStatusBar != NULL && ((DWORD)::GetWindowLong(m_hWndStatusBar, GWL_STYLE) & WS_VISIBLE)) - { - if(bResizeBars) - ::SendMessage(m_hWndStatusBar, WM_SIZE, 0, 0); - RECT rectSB = { 0 }; - ::GetWindowRect(m_hWndStatusBar, &rectSB); - rect.bottom -= rectSB.bottom - rectSB.top; - } - } - - BOOL PreTranslateMessage(MSG* pMsg) - { - if(m_hAccel != NULL && ::TranslateAccelerator(m_hWnd, m_hAccel, pMsg)) - return TRUE; - return FALSE; - } - - BEGIN_MSG_MAP(CFrameWindowImplBase) - MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) -#ifndef _WIN32_WCE - MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect) -#endif // !_WIN32_WCE - MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) - MESSAGE_HANDLER(WM_DESTROY, OnDestroy) -#ifndef _WIN32_WCE - NOTIFY_CODE_HANDLER(TTN_GETDISPINFOA, OnToolTipTextA) - NOTIFY_CODE_HANDLER(TTN_GETDISPINFOW, OnToolTipTextW) -#endif // !_WIN32_WCE - END_MSG_MAP() - - LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - if(m_hWndClient != NULL) // view will paint itself instead - return 1; - - bHandled = FALSE; - return 0; - } - -#ifndef _WIN32_WCE - LRESULT OnMenuSelect(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - bHandled = FALSE; - - if(m_hWndStatusBar == NULL) - return 1; - - WORD wFlags = HIWORD(wParam); - if(wFlags == 0xFFFF && lParam == NULL) // menu closing - { - ::SendMessage(m_hWndStatusBar, SB_SIMPLE, FALSE, 0L); - } - else - { - const int cchBuff = 256; - TCHAR szBuff[cchBuff]; - szBuff[0] = 0; - if(!(wFlags & MF_POPUP)) - { - WORD wID = LOWORD(wParam); - // check for special cases - if(wID >= 0xF000 && wID < 0xF1F0) // system menu IDs - wID = (WORD)(((wID - 0xF000) >> 4) + ATL_IDS_SCFIRST); - else if(wID >= ID_FILE_MRU_FIRST && wID <= ID_FILE_MRU_LAST) // MRU items - wID = ATL_IDS_MRU_FILE; - else if(wID >= ATL_IDM_FIRST_MDICHILD && wID <= ATL_IDM_LAST_MDICHILD) // MDI child windows - wID = ATL_IDS_MDICHILD; - - int nRet = ::LoadString(ModuleHelper::GetResourceInstance(), wID, szBuff, cchBuff); - for(int i = 0; i < nRet; i++) - { - if(szBuff[i] == _T('\n')) - { - szBuff[i] = 0; - break; - } - } - } - ::SendMessage(m_hWndStatusBar, SB_SIMPLE, TRUE, 0L); - ::SendMessage(m_hWndStatusBar, SB_SETTEXT, (255 | SBT_NOBORDERS), (LPARAM)szBuff); - } - - return 1; - } -#endif // !_WIN32_WCE - - LRESULT OnSetFocus(UINT, WPARAM, LPARAM, BOOL& bHandled) - { - if(m_hWndClient != NULL) - ::SetFocus(m_hWndClient); - - bHandled = FALSE; - return 1; - } - - LRESULT OnDestroy(UINT, WPARAM, LPARAM, BOOL& bHandled) - { - if((GetStyle() & (WS_CHILD | WS_POPUP)) == 0) - ::PostQuitMessage(1); - - bHandled = FALSE; - return 1; - } - -#ifndef _WIN32_WCE - LRESULT OnToolTipTextA(int idCtrl, LPNMHDR pnmh, BOOL& /*bHandled*/) - { - LPNMTTDISPINFOA pDispInfo = (LPNMTTDISPINFOA)pnmh; - pDispInfo->szText[0] = 0; - - if((idCtrl != 0) && !(pDispInfo->uFlags & TTF_IDISHWND)) - { - const int cchBuff = 256; - char szBuff[cchBuff]; - szBuff[0] = 0; - int nRet = ::LoadStringA(ModuleHelper::GetResourceInstance(), idCtrl, szBuff, cchBuff); - for(int i = 0; i < nRet; i++) - { - if(szBuff[i] == '\n') - { - SecureHelper::strncpyA_x(pDispInfo->szText, _countof(pDispInfo->szText), &szBuff[i + 1], _TRUNCATE); - break; - } - } -#if (_WIN32_IE >= 0x0300) - if(nRet > 0) // string was loaded, save it - pDispInfo->uFlags |= TTF_DI_SETITEM; -#endif // (_WIN32_IE >= 0x0300) - } - - return 0; - } - - LRESULT OnToolTipTextW(int idCtrl, LPNMHDR pnmh, BOOL& /*bHandled*/) - { - LPNMTTDISPINFOW pDispInfo = (LPNMTTDISPINFOW)pnmh; - pDispInfo->szText[0] = 0; - - if((idCtrl != 0) && !(pDispInfo->uFlags & TTF_IDISHWND)) - { - const int cchBuff = 256; - wchar_t szBuff[cchBuff]; - szBuff[0] = 0; - int nRet = ::LoadStringW(ModuleHelper::GetResourceInstance(), idCtrl, szBuff, cchBuff); - for(int i = 0; i < nRet; i++) - { - if(szBuff[i] == L'\n') - { - SecureHelper::strncpyW_x(pDispInfo->szText, _countof(pDispInfo->szText), &szBuff[i + 1], _TRUNCATE); - break; - } - } -#if (_WIN32_IE >= 0x0300) - if(nRet > 0) // string was loaded, save it - pDispInfo->uFlags |= TTF_DI_SETITEM; -#endif // (_WIN32_IE >= 0x0300) - } - - return 0; - } -#endif // !_WIN32_WCE - -// Implementation - chevron menu support -#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) - bool PrepareChevronMenu(_ChevronMenuInfo& cmi) - { - // get rebar and toolbar - REBARBANDINFO rbbi = { RunTimeHelper::SizeOf_REBARBANDINFO() }; - rbbi.fMask = RBBIM_CHILD; - BOOL bRet = (BOOL)::SendMessage(cmi.lpnm->hdr.hwndFrom, RB_GETBANDINFO, cmi.lpnm->uBand, (LPARAM)&rbbi); - ATLASSERT(bRet); - - // assume the band is a toolbar - ATL::CWindow wnd = rbbi.hwndChild; - int nCount = (int)wnd.SendMessage(TB_BUTTONCOUNT); - if(nCount <= 0) // probably not a toolbar - return false; - - // check if it's a command bar - CMenuHandle menuCmdBar = (HMENU)wnd.SendMessage(CBRM_GETMENU); - cmi.bCmdBar = (menuCmdBar.m_hMenu != NULL); - - // build a menu from hidden items - CMenuHandle menu; - bRet = menu.CreatePopupMenu(); - ATLASSERT(bRet); - RECT rcClient = { 0 }; - bRet = wnd.GetClientRect(&rcClient); - ATLASSERT(bRet); - for(int i = 0; i < nCount; i++) - { - TBBUTTON tbb = { 0 }; - bRet = (BOOL)wnd.SendMessage(TB_GETBUTTON, i, (LPARAM)&tbb); - ATLASSERT(bRet); - // skip hidden buttons - if((tbb.fsState & TBSTATE_HIDDEN) != 0) - continue; - RECT rcButton = { 0 }; - bRet = (BOOL)wnd.SendMessage(TB_GETITEMRECT, i, (LPARAM)&rcButton); - ATLASSERT(bRet); - bool bEnabled = ((tbb.fsState & TBSTATE_ENABLED) != 0); - if(rcButton.right > rcClient.right) - { - if(tbb.fsStyle & BTNS_SEP) - { - if(menu.GetMenuItemCount() > 0) - menu.AppendMenu(MF_SEPARATOR); - } - else if(cmi.bCmdBar) - { - const int cchBuff = 200; - TCHAR szBuff[cchBuff] = { 0 }; - CMenuItemInfo mii; - mii.fMask = MIIM_TYPE | MIIM_SUBMENU; - mii.dwTypeData = szBuff; - mii.cch = cchBuff; - bRet = menuCmdBar.GetMenuItemInfo(i, TRUE, &mii); - ATLASSERT(bRet); - // Note: CmdBar currently supports only drop-down items - ATLASSERT(::IsMenu(mii.hSubMenu)); - bRet = menu.AppendMenu(MF_STRING | MF_POPUP | (bEnabled ? MF_ENABLED : MF_GRAYED), (UINT_PTR)mii.hSubMenu, mii.dwTypeData); - ATLASSERT(bRet); - } - else - { - // get button's text - const int cchBuff = 200; - TCHAR szBuff[cchBuff] = { 0 }; - LPTSTR lpstrText = szBuff; - TBBUTTONINFO tbbi = { 0 }; - tbbi.cbSize = sizeof(TBBUTTONINFO); - tbbi.dwMask = TBIF_TEXT; - tbbi.pszText = szBuff; - tbbi.cchText = cchBuff; - if(wnd.SendMessage(TB_GETBUTTONINFO, tbb.idCommand, (LPARAM)&tbbi) == -1 || lstrlen(szBuff) == 0) - { - // no text for this button, try a resource string - lpstrText = _T(""); - int nRet = ::LoadString(ModuleHelper::GetResourceInstance(), tbb.idCommand, szBuff, cchBuff); - for(int n = 0; n < nRet; n++) - { - if(szBuff[n] == _T('\n')) - { - lpstrText = &szBuff[n + 1]; - break; - } - } - } - bRet = menu.AppendMenu(MF_STRING | (bEnabled ? MF_ENABLED : MF_GRAYED), tbb.idCommand, lpstrText); - ATLASSERT(bRet); - } - } - } - - if(menu.GetMenuItemCount() == 0) // no hidden buttons after all - { - menu.DestroyMenu(); - ::MessageBeep((UINT)-1); - return false; - } - - cmi.hMenu = menu; - return true; - } - - void DisplayChevronMenu(_ChevronMenuInfo& cmi) - { -#ifndef TPM_VERPOSANIMATION - const UINT TPM_VERPOSANIMATION = 0x1000L; // Menu animation flag -#endif - // convert chevron rect to screen coordinates - ATL::CWindow wndFrom = cmi.lpnm->hdr.hwndFrom; - POINT pt = { cmi.lpnm->rc.left, cmi.lpnm->rc.bottom }; - wndFrom.MapWindowPoints(NULL, &pt, 1); - RECT rc = cmi.lpnm->rc; - wndFrom.MapWindowPoints(NULL, &rc); - // set up flags and rect - UINT uMenuFlags = TPM_LEFTBUTTON | TPM_VERTICAL | TPM_LEFTALIGN | TPM_TOPALIGN | (!AtlIsOldWindows() ? TPM_VERPOSANIMATION : 0); - TPMPARAMS TPMParams = { 0 }; - TPMParams.cbSize = sizeof(TPMPARAMS); - TPMParams.rcExclude = rc; - // check if this window has a command bar - HWND hWndCmdBar = (HWND)::SendMessage(m_hWnd, CBRM_GETCMDBAR, 0, 0L); - if(::IsWindow(hWndCmdBar)) - { - CBRPOPUPMENU CBRPopupMenu = { sizeof(CBRPOPUPMENU), cmi.hMenu, uMenuFlags, pt.x, pt.y, &TPMParams }; - ::SendMessage(hWndCmdBar, CBRM_TRACKPOPUPMENU, 0, (LPARAM)&CBRPopupMenu); - } - else - { - CMenuHandle menu = cmi.hMenu; - menu.TrackPopupMenuEx(uMenuFlags, pt.x, pt.y, m_hWnd, &TPMParams); - } - } - - void CleanupChevronMenu(_ChevronMenuInfo& cmi) - { - CMenuHandle menu = cmi.hMenu; - // if menu is from a command bar, detach submenus so they are not destroyed - if(cmi.bCmdBar) - { - for(int i = menu.GetMenuItemCount() - 1; i >=0; i--) - menu.RemoveMenu(i, MF_BYPOSITION); - } - // destroy menu - menu.DestroyMenu(); - // convert chevron rect to screen coordinates - ATL::CWindow wndFrom = cmi.lpnm->hdr.hwndFrom; - RECT rc = cmi.lpnm->rc; - wndFrom.MapWindowPoints(NULL, &rc); - // eat next message if click is on the same button - MSG msg = { 0 }; - if(::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_NOREMOVE) && ::PtInRect(&rc, msg.pt)) - ::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_REMOVE); - } -#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) -}; - - -template -class ATL_NO_VTABLE CFrameWindowImpl : public CFrameWindowImplBase< TBase, TWinTraits > -{ -public: - HWND Create(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - HMENU hMenu = NULL, LPVOID lpCreateParam = NULL) - { - ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc); - - dwStyle = T::GetWndStyle(dwStyle); - dwExStyle = T::GetWndExStyle(dwExStyle); - - if(rect.m_lpRect == NULL) - rect.m_lpRect = &TBase::rcDefault; - - return CFrameWindowImplBase< TBase, TWinTraits >::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, hMenu, atom, lpCreateParam); - } - - HWND CreateEx(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL) - { - const int cchName = 256; - TCHAR szWindowName[cchName]; - szWindowName[0] = 0; -#ifndef _WIN32_WCE - ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName); - HMENU hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID)); -#else // CE specific - ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName); - - // This always needs to be NULL for Windows CE. - // Frame Window menus have to go onto the CommandBar. - // Use CreateSimpleCECommandBar - HMENU hMenu = NULL; -#endif // _WIN32_WCE - - T* pT = static_cast(this); - HWND hWnd = pT->Create(hWndParent, rect, szWindowName, dwStyle, dwExStyle, hMenu, lpCreateParam); - - if(hWnd != NULL) - m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID)); - - return hWnd; - } - - BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR) - { - if(nResourceID == 0) - nResourceID = T::GetWndClassInfo().m_uCommonResourceID; -#ifndef _WIN32_WCE - ATLASSERT(!::IsWindow(m_hWndToolBar)); - m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd, nResourceID, TRUE, dwStyle, nID); - return (m_hWndToolBar != NULL); -#else // CE specific - HWND hWnd= T::CreateSimpleToolBarCtrl(m_hWndCECommandBar, nResourceID, TRUE, dwStyle, nID); - return (hWnd != NULL); -#endif // _WIN32_WCE - } - -#ifdef _WIN32_WCE - // CE specific variant that returns the handle of the toolbar - HWND CreateSimpleCEToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR) - { - if(nResourceID == 0) - nResourceID = T::GetWndClassInfo().m_uCommonResourceID; - - return T::CreateSimpleToolBarCtrl(m_hWndCECommandBar, nResourceID, TRUE, dwStyle, nID); - } -#endif // _WIN32_WCE - -// message map and handlers - typedef CFrameWindowImplBase< TBase, TWinTraits > _baseClass; - - BEGIN_MSG_MAP(CFrameWindowImpl) - MESSAGE_HANDLER(WM_SIZE, OnSize) -#ifndef _ATL_NO_REBAR_SUPPORT -#if (_WIN32_IE >= 0x0400) - NOTIFY_CODE_HANDLER(RBN_AUTOSIZE, OnReBarAutoSize) -#endif // (_WIN32_IE >= 0x0400) -#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) - NOTIFY_CODE_HANDLER(RBN_CHEVRONPUSHED, OnChevronPushed) -#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) -#endif // !_ATL_NO_REBAR_SUPPORT - CHAIN_MSG_MAP(_baseClass) - END_MSG_MAP() - - LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) - { - if(wParam != SIZE_MINIMIZED) - { - T* pT = static_cast(this); - pT->UpdateLayout(); - } - bHandled = FALSE; - return 1; - } - -#ifndef _ATL_NO_REBAR_SUPPORT -#if (_WIN32_IE >= 0x0400) - LRESULT OnReBarAutoSize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - pT->UpdateLayout(FALSE); - return 0; - } -#endif // (_WIN32_IE >= 0x0400) - -#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) - LRESULT OnChevronPushed(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled) - { - T* pT = static_cast(this); - _ChevronMenuInfo cmi = { NULL, (LPNMREBARCHEVRON)pnmh, false }; - if(!pT->PrepareChevronMenu(cmi)) - { - bHandled = FALSE; - return 1; - } - // display a popup menu with hidden items - pT->DisplayChevronMenu(cmi); - // cleanup - pT->CleanupChevronMenu(cmi); - return 0; - } -#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) -#endif // !_ATL_NO_REBAR_SUPPORT -}; - - -/////////////////////////////////////////////////////////////////////////////// -// AtlCreateSimpleToolBar - helper for creating simple toolbars - -#ifndef _WIN32_WCE - -inline HWND AtlCreateSimpleToolBar(HWND hWndParent, UINT nResourceID, BOOL bInitialSeparator = FALSE, - DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR) -{ - return CFrameWindowImplBase<>::CreateSimpleToolBarCtrl(hWndParent, nResourceID, bInitialSeparator, dwStyle, nID); -} - -#endif // !_WIN32_WCE - - -/////////////////////////////////////////////////////////////////////////////// -// CMDIWindow - -#ifndef _WIN32_WCE - -#ifndef _WTL_MDIWINDOWMENU_TEXT -#define _WTL_MDIWINDOWMENU_TEXT _T("&Window") -#endif - -class CMDIWindow : public ATL::CWindow -{ -public: -// Data members - HWND m_hWndMDIClient; - HMENU m_hMenu; - -// Constructors - CMDIWindow(HWND hWnd = NULL) : ATL::CWindow(hWnd), m_hWndMDIClient(NULL), m_hMenu(NULL) - { } - - CMDIWindow& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - -// Operations - HWND MDIGetActive(BOOL* lpbMaximized = NULL) - { - ATLASSERT(::IsWindow(m_hWndMDIClient)); - return (HWND)::SendMessage(m_hWndMDIClient, WM_MDIGETACTIVE, 0, (LPARAM)lpbMaximized); - } - - void MDIActivate(HWND hWndChildToActivate) - { - ATLASSERT(::IsWindow(m_hWndMDIClient)); - ATLASSERT(::IsWindow(hWndChildToActivate)); - ::SendMessage(m_hWndMDIClient, WM_MDIACTIVATE, (WPARAM)hWndChildToActivate, 0); - } - - void MDINext(HWND hWndChild, BOOL bPrevious = FALSE) - { - ATLASSERT(::IsWindow(m_hWndMDIClient)); - ATLASSERT(hWndChild == NULL || ::IsWindow(hWndChild)); - ::SendMessage(m_hWndMDIClient, WM_MDINEXT, (WPARAM)hWndChild, (LPARAM)bPrevious); - } - - void MDIMaximize(HWND hWndChildToMaximize) - { - ATLASSERT(::IsWindow(m_hWndMDIClient)); - ATLASSERT(::IsWindow(hWndChildToMaximize)); - ::SendMessage(m_hWndMDIClient, WM_MDIMAXIMIZE, (WPARAM)hWndChildToMaximize, 0); - } - - void MDIRestore(HWND hWndChildToRestore) - { - ATLASSERT(::IsWindow(m_hWndMDIClient)); - ATLASSERT(::IsWindow(hWndChildToRestore)); - ::SendMessage(m_hWndMDIClient, WM_MDIRESTORE, (WPARAM)hWndChildToRestore, 0); - } - - void MDIDestroy(HWND hWndChildToDestroy) - { - ATLASSERT(::IsWindow(m_hWndMDIClient)); - ATLASSERT(::IsWindow(hWndChildToDestroy)); - ::SendMessage(m_hWndMDIClient, WM_MDIDESTROY, (WPARAM)hWndChildToDestroy, 0); - } - - BOOL MDICascade(UINT uFlags = 0) - { - ATLASSERT(::IsWindow(m_hWndMDIClient)); - return (BOOL)::SendMessage(m_hWndMDIClient, WM_MDICASCADE, (WPARAM)uFlags, 0); - } - - BOOL MDITile(UINT uFlags = MDITILE_HORIZONTAL) - { - ATLASSERT(::IsWindow(m_hWndMDIClient)); - return (BOOL)::SendMessage(m_hWndMDIClient, WM_MDITILE, (WPARAM)uFlags, 0); - } - - void MDIIconArrange() - { - ATLASSERT(::IsWindow(m_hWndMDIClient)); - ::SendMessage(m_hWndMDIClient, WM_MDIICONARRANGE, 0, 0); - } - - HMENU MDISetMenu(HMENU hMenuFrame, HMENU hMenuWindow) - { - ATLASSERT(::IsWindow(m_hWndMDIClient)); - return (HMENU)::SendMessage(m_hWndMDIClient, WM_MDISETMENU, (WPARAM)hMenuFrame, (LPARAM)hMenuWindow); - } - - HMENU MDIRefreshMenu() - { - ATLASSERT(::IsWindow(m_hWndMDIClient)); - return (HMENU)::SendMessage(m_hWndMDIClient, WM_MDIREFRESHMENU, 0, 0); - } - -// Additional operations - static HMENU GetStandardWindowMenu(HMENU hMenu) - { - int nCount = ::GetMenuItemCount(hMenu); - if(nCount == -1) - return NULL; - int nLen = ::GetMenuString(hMenu, nCount - 2, NULL, 0, MF_BYPOSITION); - if(nLen == 0) - return NULL; - CTempBuffer buff; - LPTSTR lpszText = buff.Allocate(nLen + 1); - if(lpszText == NULL) - return NULL; - if(::GetMenuString(hMenu, nCount - 2, lpszText, nLen + 1, MF_BYPOSITION) != nLen) - return NULL; - if(lstrcmp(lpszText, _WTL_MDIWINDOWMENU_TEXT) != 0) - return NULL; - return ::GetSubMenu(hMenu, nCount - 2); - } - - void SetMDIFrameMenu() - { - HMENU hWindowMenu = GetStandardWindowMenu(m_hMenu); - MDISetMenu(m_hMenu, hWindowMenu); - MDIRefreshMenu(); - ::DrawMenuBar(GetMDIFrame()); - } - - HWND GetMDIFrame() const - { - return ::GetParent(m_hWndMDIClient); - } -}; - -#endif // !_WIN32_WCE - - -/////////////////////////////////////////////////////////////////////////////// -// CMDIFrameWindowImpl - -#ifndef _WIN32_WCE - -// MDI child command chaining macro (only for MDI frame windows) -#define CHAIN_MDI_CHILD_COMMANDS() \ - if(uMsg == WM_COMMAND) \ - { \ - HWND hWndChild = MDIGetActive(); \ - if(hWndChild != NULL) \ - ::SendMessage(hWndChild, uMsg, wParam, lParam); \ - } - -template -class ATL_NO_VTABLE CMDIFrameWindowImpl : public CFrameWindowImplBase -{ -public: - HWND Create(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - HMENU hMenu = NULL, LPVOID lpCreateParam = NULL) - { - m_hMenu = hMenu; - ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc); - - dwStyle = T::GetWndStyle(dwStyle); - dwExStyle = T::GetWndExStyle(dwExStyle); - - if(rect.m_lpRect == NULL) - rect.m_lpRect = &TBase::rcDefault; - - return CFrameWindowImplBase::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, hMenu, atom, lpCreateParam); - } - - HWND CreateEx(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL) - { - const int cchName = 256; - TCHAR szWindowName[cchName]; - szWindowName[0] = 0; - ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName); - HMENU hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID)); - - T* pT = static_cast(this); - HWND hWnd = pT->Create(hWndParent, rect, szWindowName, dwStyle, dwExStyle, hMenu, lpCreateParam); - - if(hWnd != NULL) - m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID)); - - return hWnd; - } - - BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR) - { - ATLASSERT(!::IsWindow(m_hWndToolBar)); - if(nResourceID == 0) - nResourceID = T::GetWndClassInfo().m_uCommonResourceID; - m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd, nResourceID, TRUE, dwStyle, nID); - return (m_hWndToolBar != NULL); - } - - virtual WNDPROC GetWindowProc() - { - return MDIFrameWindowProc; - } - - static LRESULT CALLBACK MDIFrameWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) - { - CMDIFrameWindowImpl< T, TBase, TWinTraits >* pThis = (CMDIFrameWindowImpl< T, TBase, TWinTraits >*)hWnd; - // set a ptr to this message and save the old value -#if (_ATL_VER >= 0x0700) - ATL::_ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam); - const ATL::_ATL_MSG* pOldMsg = pThis->m_pCurrentMsg; -#else // !(_ATL_VER >= 0x0700) - MSG msg = { pThis->m_hWnd, uMsg, wParam, lParam, 0, { 0, 0 } }; - const MSG* pOldMsg = pThis->m_pCurrentMsg; -#endif // !(_ATL_VER >= 0x0700) - pThis->m_pCurrentMsg = &msg; - // pass to the message map to process - LRESULT lRes = 0; - BOOL bRet = pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0); - // restore saved value for the current message - ATLASSERT(pThis->m_pCurrentMsg == &msg); - pThis->m_pCurrentMsg = pOldMsg; - // do the default processing if message was not handled - if(!bRet) - { - if(uMsg != WM_NCDESTROY) - lRes = pThis->DefWindowProc(uMsg, wParam, lParam); - else - { - // unsubclass, if needed - LONG_PTR pfnWndProc = ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC); - lRes = pThis->DefWindowProc(uMsg, wParam, lParam); - if(pThis->m_pfnSuperWindowProc != ::DefWindowProc && ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC) == pfnWndProc) - ::SetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC, (LONG_PTR)pThis->m_pfnSuperWindowProc); -#if (_ATL_VER >= 0x0700) - // mark window as destryed - pThis->m_dwState |= WINSTATE_DESTROYED; -#else // !(_ATL_VER >= 0x0700) - // clear out window handle - HWND hWnd = pThis->m_hWnd; - pThis->m_hWnd = NULL; - // clean up after window is destroyed - pThis->OnFinalMessage(hWnd); -#endif // !(_ATL_VER >= 0x0700) - } - } -#if (_ATL_VER >= 0x0700) - if(pThis->m_dwState & WINSTATE_DESTROYED && pThis->m_pCurrentMsg == NULL) - { - // clear out window handle - HWND hWnd = pThis->m_hWnd; - pThis->m_hWnd = NULL; - pThis->m_dwState &= ~WINSTATE_DESTROYED; - // clean up after window is destroyed - pThis->OnFinalMessage(hWnd); - } -#endif // (_ATL_VER >= 0x0700) - return lRes; - } - - // Overriden to call DefWindowProc which uses DefFrameProc - LRESULT DefWindowProc() - { - const MSG* pMsg = m_pCurrentMsg; - LRESULT lRes = 0; - if (pMsg != NULL) - lRes = DefWindowProc(pMsg->message, pMsg->wParam, pMsg->lParam); - return lRes; - } - - LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) - { - return ::DefFrameProc(m_hWnd, m_hWndMDIClient, uMsg, wParam, lParam); - } - - BOOL PreTranslateMessage(MSG* pMsg) - { - if(CFrameWindowImplBase::PreTranslateMessage(pMsg)) - return TRUE; - return ::TranslateMDISysAccel(m_hWndMDIClient, pMsg); - } - - HWND CreateMDIClient(HMENU hWindowMenu = NULL, UINT nID = ATL_IDW_CLIENT, UINT nFirstChildID = ATL_IDM_FIRST_MDICHILD) - { - DWORD dwStyle = WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | MDIS_ALLCHILDSTYLES; - DWORD dwExStyle = WS_EX_CLIENTEDGE; - - CLIENTCREATESTRUCT ccs = { 0 }; - ccs.hWindowMenu = hWindowMenu; - ccs.idFirstChild = nFirstChildID; - - if((GetStyle() & (WS_HSCROLL | WS_VSCROLL)) != 0) - { - // parent MDI frame's scroll styles move to the MDICLIENT - dwStyle |= (GetStyle() & (WS_HSCROLL | WS_VSCROLL)); - - // fast way to turn off the scrollbar bits (without a resize) - ModifyStyle(WS_HSCROLL | WS_VSCROLL, 0, SWP_NOREDRAW | SWP_FRAMECHANGED); - } - - // Create MDICLIENT window - m_hWndClient = ::CreateWindowEx(dwExStyle, _T("MDIClient"), NULL, - dwStyle, 0, 0, 1, 1, m_hWnd, (HMENU)LongToHandle(nID), - ModuleHelper::GetModuleInstance(), (LPVOID)&ccs); - if (m_hWndClient == NULL) - { - ATLTRACE2(atlTraceUI, 0, _T("MDI Frame failed to create MDICLIENT.\n")); - return NULL; - } - - // Move it to the top of z-order - ::BringWindowToTop(m_hWndClient); - - // set as MDI client window - m_hWndMDIClient = m_hWndClient; - - // update to proper size - T* pT = static_cast(this); - pT->UpdateLayout(); - - return m_hWndClient; - } - - typedef CFrameWindowImplBase _baseClass; - - BEGIN_MSG_MAP(CMDIFrameWindowImpl) - MESSAGE_HANDLER(WM_SIZE, OnSize) - MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) - MESSAGE_HANDLER(WM_MDISETMENU, OnMDISetMenu) -#ifndef _ATL_NO_REBAR_SUPPORT -#if (_WIN32_IE >= 0x0400) - NOTIFY_CODE_HANDLER(RBN_AUTOSIZE, OnReBarAutoSize) -#endif // (_WIN32_IE >= 0x0400) -#if (_WIN32_IE >= 0x0500) - NOTIFY_CODE_HANDLER(RBN_CHEVRONPUSHED, OnChevronPushed) -#endif // (_WIN32_IE >= 0x0500) -#endif // !_ATL_NO_REBAR_SUPPORT - CHAIN_MSG_MAP(_baseClass) - END_MSG_MAP() - - LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - if(wParam != SIZE_MINIMIZED) - { - T* pT = static_cast(this); - pT->UpdateLayout(); - } - // message must be handled, otherwise DefFrameProc would resize the client again - return 0; - } - - LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) - { - // don't allow CFrameWindowImplBase to handle this one - return DefWindowProc(uMsg, wParam, lParam); - } - - LRESULT OnMDISetMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - SetMDIFrameMenu(); - return 0; - } - -#ifndef _ATL_NO_REBAR_SUPPORT -#if (_WIN32_IE >= 0x0400) - LRESULT OnReBarAutoSize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - pT->UpdateLayout(FALSE); - return 0; - } -#endif // (_WIN32_IE >= 0x0400) - -#if (_WIN32_IE >= 0x0500) - LRESULT OnChevronPushed(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled) - { - T* pT = static_cast(this); - _ChevronMenuInfo cmi = { NULL, (LPNMREBARCHEVRON)pnmh, false }; - if(!pT->PrepareChevronMenu(cmi)) - { - bHandled = FALSE; - return 1; - } - // display a popup menu with hidden items - pT->DisplayChevronMenu(cmi); - // cleanup - pT->CleanupChevronMenu(cmi); - return 0; - } -#endif // (_WIN32_IE >= 0x0500) -#endif // !_ATL_NO_REBAR_SUPPORT -}; - -#endif // !_WIN32_WCE - - -/////////////////////////////////////////////////////////////////////////////// -// CMDIChildWindowImpl - -#ifndef _WIN32_WCE - -template -class ATL_NO_VTABLE CMDIChildWindowImpl : public CFrameWindowImplBase -{ -public: - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - UINT nMenuID = 0, LPVOID lpCreateParam = NULL) - { - ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc); - - if(nMenuID != 0) - m_hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(nMenuID)); - - dwStyle = T::GetWndStyle(dwStyle); - dwExStyle = T::GetWndExStyle(dwExStyle); - - dwExStyle |= WS_EX_MDICHILD; // force this one - m_pfnSuperWindowProc = ::DefMDIChildProc; - m_hWndMDIClient = hWndParent; - ATLASSERT(::IsWindow(m_hWndMDIClient)); - - if(rect.m_lpRect == NULL) - rect.m_lpRect = &TBase::rcDefault; - - // If the currently active MDI child is maximized, we want to create this one maximized too - ATL::CWindow wndParent = hWndParent; - BOOL bMaximized = FALSE; - wndParent.SendMessage(WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized); - if(bMaximized) - wndParent.SetRedraw(FALSE); - - HWND hWnd = CFrameWindowImplBase::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, (UINT)0U, atom, lpCreateParam); - - if(bMaximized) - { - // Maximize and redraw everything - if(hWnd != NULL) - MDIMaximize(hWnd); - wndParent.SetRedraw(TRUE); - wndParent.RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN); - ::SetFocus(GetMDIFrame()); // focus will be set back to this window - } - else if(hWnd != NULL && ::IsWindowVisible(m_hWnd) && !::IsChild(hWnd, ::GetFocus())) - { - ::SetFocus(hWnd); - } - - return hWnd; - } - - HWND CreateEx(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR lpcstrWindowName = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL) - { - const int cchName = 256; - TCHAR szWindowName[cchName]; - szWindowName[0] = 0; - if(lpcstrWindowName == NULL) - { - ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName); - lpcstrWindowName = szWindowName; - } - - T* pT = static_cast(this); - HWND hWnd = pT->Create(hWndParent, rect, lpcstrWindowName, dwStyle, dwExStyle, T::GetWndClassInfo().m_uCommonResourceID, lpCreateParam); - - if(hWnd != NULL) - m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID)); - - return hWnd; - } - - BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR) - { - ATLASSERT(!::IsWindow(m_hWndToolBar)); - if(nResourceID == 0) - nResourceID = T::GetWndClassInfo().m_uCommonResourceID; - m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd, nResourceID, TRUE, dwStyle, nID); - return (m_hWndToolBar != NULL); - } - - BOOL UpdateClientEdge(LPRECT lpRect = NULL) - { - // only adjust for active MDI child window - HWND hWndChild = MDIGetActive(); - if(hWndChild != NULL && hWndChild != m_hWnd) - return FALSE; - - // need to adjust the client edge style as max/restore happens - DWORD dwStyle = ::GetWindowLong(m_hWndMDIClient, GWL_EXSTYLE); - DWORD dwNewStyle = dwStyle; - if(hWndChild != NULL && ((GetExStyle() & WS_EX_CLIENTEDGE) == 0) && ((GetStyle() & WS_MAXIMIZE) != 0)) - dwNewStyle &= ~(WS_EX_CLIENTEDGE); - else - dwNewStyle |= WS_EX_CLIENTEDGE; - - if(dwStyle != dwNewStyle) - { - // SetWindowPos will not move invalid bits - ::RedrawWindow(m_hWndMDIClient, NULL, NULL, - RDW_INVALIDATE | RDW_ALLCHILDREN); - // remove/add WS_EX_CLIENTEDGE to MDI client area - ::SetWindowLong(m_hWndMDIClient, GWL_EXSTYLE, dwNewStyle); - ::SetWindowPos(m_hWndMDIClient, NULL, 0, 0, 0, 0, - SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | - SWP_NOZORDER | SWP_NOCOPYBITS); - - // return new client area - if (lpRect != NULL) - ::GetClientRect(m_hWndMDIClient, lpRect); - - return TRUE; - } - - return FALSE; - } - - typedef CFrameWindowImplBase _baseClass; - BEGIN_MSG_MAP(CMDIChildWindowImpl) - MESSAGE_HANDLER(WM_SIZE, OnSize) - MESSAGE_HANDLER(WM_WINDOWPOSCHANGED, OnWindowPosChanged) - MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActivate) - MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect) - MESSAGE_HANDLER(WM_MDIACTIVATE, OnMDIActivate) - MESSAGE_HANDLER(WM_DESTROY, OnDestroy) -#ifndef _ATL_NO_REBAR_SUPPORT -#if (_WIN32_IE >= 0x0400) - NOTIFY_CODE_HANDLER(RBN_AUTOSIZE, OnReBarAutoSize) -#endif // (_WIN32_IE >= 0x0400) -#if (_WIN32_IE >= 0x0500) - NOTIFY_CODE_HANDLER(RBN_CHEVRONPUSHED, OnChevronPushed) -#endif // (_WIN32_IE >= 0x0500) -#endif // !_ATL_NO_REBAR_SUPPORT - CHAIN_MSG_MAP(_baseClass) - END_MSG_MAP() - - LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) - { - DefWindowProc(uMsg, wParam, lParam); // needed for MDI children - if(wParam != SIZE_MINIMIZED) - { - T* pT = static_cast(this); - pT->UpdateLayout(); - } - return 0; - } - - LRESULT OnWindowPosChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) - { - // update MDI client edge and adjust MDI child rect - LPWINDOWPOS lpWndPos = (LPWINDOWPOS)lParam; - - if(!(lpWndPos->flags & SWP_NOSIZE)) - { - RECT rectClient; - if(UpdateClientEdge(&rectClient) && ((GetStyle() & WS_MAXIMIZE) != 0)) - { - ::AdjustWindowRectEx(&rectClient, GetStyle(), FALSE, GetExStyle()); - lpWndPos->x = rectClient.left; - lpWndPos->y = rectClient.top; - lpWndPos->cx = rectClient.right - rectClient.left; - lpWndPos->cy = rectClient.bottom - rectClient.top; - } - } - - bHandled = FALSE; - return 1; - } - - LRESULT OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) - { - LRESULT lRes = DefWindowProc(uMsg, wParam, lParam); - - // Activate this MDI window if needed - if(lRes == MA_ACTIVATE || lRes == MA_ACTIVATEANDEAT) - { - if(MDIGetActive() != m_hWnd) - MDIActivate(m_hWnd); - } - - return lRes; - } - - LRESULT OnMenuSelect(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) - { - return ::SendMessage(GetMDIFrame(), uMsg, wParam, lParam); - } - - LRESULT OnMDIActivate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) - { - if((HWND)lParam == m_hWnd && m_hMenu != NULL) - SetMDIFrameMenu(); - else if((HWND)lParam == NULL) - ::SendMessage(GetMDIFrame(), WM_MDISETMENU, 0, 0); - - bHandled = FALSE; - return 1; - } - - LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - if(m_hMenu != NULL) - { - ::DestroyMenu(m_hMenu); - m_hMenu = NULL; - } - UpdateClientEdge(); - bHandled = FALSE; - return 1; - } - -#ifndef _ATL_NO_REBAR_SUPPORT -#if (_WIN32_IE >= 0x0400) - LRESULT OnReBarAutoSize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - pT->UpdateLayout(FALSE); - return 0; - } -#endif // (_WIN32_IE >= 0x0400) - -#if (_WIN32_IE >= 0x0500) - LRESULT OnChevronPushed(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled) - { - T* pT = static_cast(this); - _ChevronMenuInfo cmi = { NULL, (LPNMREBARCHEVRON)pnmh, false }; - if(!pT->PrepareChevronMenu(cmi)) - { - bHandled = FALSE; - return 1; - } - // display a popup menu with hidden items - pT->DisplayChevronMenu(cmi); - // cleanup - pT->CleanupChevronMenu(cmi); - return 0; - } -#endif // (_WIN32_IE >= 0x0500) -#endif // !_ATL_NO_REBAR_SUPPORT -}; - -#endif // !_WIN32_WCE - - -/////////////////////////////////////////////////////////////////////////////// -// COwnerDraw - MI class for owner-draw support - -template -class COwnerDraw -{ -public: -#if (_ATL_VER < 0x0700) - BOOL m_bHandledOD; - - BOOL IsMsgHandled() const - { - return m_bHandledOD; - } - void SetMsgHandled(BOOL bHandled) - { - m_bHandledOD = bHandled; - } -#endif // (_ATL_VER < 0x0700) - -// Message map and handlers - BEGIN_MSG_MAP(COwnerDraw< T >) - MESSAGE_HANDLER(WM_DRAWITEM, OnDrawItem) - MESSAGE_HANDLER(WM_MEASUREITEM, OnMeasureItem) - MESSAGE_HANDLER(WM_COMPAREITEM, OnCompareItem) - MESSAGE_HANDLER(WM_DELETEITEM, OnDeleteItem) - ALT_MSG_MAP(1) - MESSAGE_HANDLER(OCM_DRAWITEM, OnDrawItem) - MESSAGE_HANDLER(OCM_MEASUREITEM, OnMeasureItem) - MESSAGE_HANDLER(OCM_COMPAREITEM, OnCompareItem) - MESSAGE_HANDLER(OCM_DELETEITEM, OnDeleteItem) - END_MSG_MAP() - - LRESULT OnDrawItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) - { - T* pT = static_cast(this); - pT->SetMsgHandled(TRUE); - pT->DrawItem((LPDRAWITEMSTRUCT)lParam); - bHandled = pT->IsMsgHandled(); - return (LRESULT)TRUE; - } - - LRESULT OnMeasureItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) - { - T* pT = static_cast(this); - pT->SetMsgHandled(TRUE); - pT->MeasureItem((LPMEASUREITEMSTRUCT)lParam); - bHandled = pT->IsMsgHandled(); - return (LRESULT)TRUE; - } - - LRESULT OnCompareItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) - { - T* pT = static_cast(this); - pT->SetMsgHandled(TRUE); - bHandled = pT->IsMsgHandled(); - return (LRESULT)pT->CompareItem((LPCOMPAREITEMSTRUCT)lParam); - } - - LRESULT OnDeleteItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) - { - T* pT = static_cast(this); - pT->SetMsgHandled(TRUE); - pT->DeleteItem((LPDELETEITEMSTRUCT)lParam); - bHandled = pT->IsMsgHandled(); - return (LRESULT)TRUE; - } - -// Overrideables - void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/) - { - // must be implemented - ATLASSERT(FALSE); - } - - void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) - { - if(lpMeasureItemStruct->CtlType != ODT_MENU) - { - // return default height for a system font - T* pT = static_cast(this); - HWND hWnd = pT->GetDlgItem(lpMeasureItemStruct->CtlID); - CClientDC dc(hWnd); - TEXTMETRIC tm = { 0 }; - dc.GetTextMetrics(&tm); - - lpMeasureItemStruct->itemHeight = tm.tmHeight; - } - else - lpMeasureItemStruct->itemHeight = ::GetSystemMetrics(SM_CYMENU); - } - - int CompareItem(LPCOMPAREITEMSTRUCT /*lpCompareItemStruct*/) - { - // all items are equal - return 0; - } - - void DeleteItem(LPDELETEITEMSTRUCT /*lpDeleteItemStruct*/) - { - // default - nothing - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// Update UI macros - -// these build the Update UI map inside a class definition -#define BEGIN_UPDATE_UI_MAP(thisClass) \ - static const CUpdateUIBase::_AtlUpdateUIMap* GetUpdateUIMap() \ - { \ - static const _AtlUpdateUIMap theMap[] = \ - { - -#define UPDATE_ELEMENT(nID, wType) \ - { nID, wType }, - -#define END_UPDATE_UI_MAP() \ - { (WORD)-1, 0 } \ - }; \ - return theMap; \ - } - -/////////////////////////////////////////////////////////////////////////////// -// CUpdateUI - manages UI elements updating - -class CUpdateUIBase -{ -public: - // constants - enum - { - // UI element type - UPDUI_MENUPOPUP = 0x0001, - UPDUI_MENUBAR = 0x0002, - UPDUI_CHILDWINDOW = 0x0004, - UPDUI_TOOLBAR = 0x0008, - UPDUI_STATUSBAR = 0x0010, - // state - UPDUI_ENABLED = 0x0000, - UPDUI_DISABLED = 0x0100, - UPDUI_CHECKED = 0x0200, - UPDUI_CHECKED2 = 0x0400, - UPDUI_RADIO = 0x0800, - UPDUI_DEFAULT = 0x1000, - UPDUI_TEXT = 0x2000, - // internal state - UPDUI_CLEARDEFAULT = 0x4000, - }; - - // element data - struct _AtlUpdateUIElement - { - HWND m_hWnd; - WORD m_wType; - - bool operator ==(const _AtlUpdateUIElement& e) const - { return (m_hWnd == e.m_hWnd && m_wType == e.m_wType); } - }; - - // map data - struct _AtlUpdateUIMap - { - WORD m_nID; - WORD m_wType; - - bool operator ==(const _AtlUpdateUIMap& e) const - { return (m_nID == e.m_nID && m_wType == e.m_wType); } - }; - - // instance data - struct _AtlUpdateUIData - { - WORD m_wState; - union - { - void* m_lpData; - LPTSTR m_lpstrText; - }; - - bool operator ==(const _AtlUpdateUIData& e) const - { return (m_wState == e.m_wState && m_lpData == e.m_lpData); } - }; - - ATL::CSimpleArray<_AtlUpdateUIElement> m_UIElements; // elements data - const _AtlUpdateUIMap* m_pUIMap; // static UI data - _AtlUpdateUIData* m_pUIData; // instance UI data - WORD m_wDirtyType; // global dirty flag - - bool m_bBlockAccelerators; - - -// Constructor, destructor - CUpdateUIBase() : m_pUIMap(NULL), m_pUIData(NULL), m_wDirtyType(0), m_bBlockAccelerators(false) - { } - - ~CUpdateUIBase() - { - if(m_pUIMap != NULL && m_pUIData != NULL) - { - const _AtlUpdateUIMap* pUIMap = m_pUIMap; - _AtlUpdateUIData* pUIData = m_pUIData; - while(pUIMap->m_nID != (WORD)-1) - { - if(pUIData->m_wState & UPDUI_TEXT) - delete [] pUIData->m_lpstrText; - pUIMap++; - pUIData++; - } - delete [] m_pUIData; - } - } - -// Check for disabled commands - bool UIGetBlockAccelerators() const - { - return m_bBlockAccelerators; - } - - bool UISetBlockAccelerators(bool bBlock) - { - bool bOld = m_bBlockAccelerators; - m_bBlockAccelerators = bBlock; - return bOld; - } - -// Add elements - BOOL UIAddMenuBar(HWND hWnd) // menu bar (main menu) - { - if(hWnd == NULL) - return FALSE; - _AtlUpdateUIElement e; - e.m_hWnd = hWnd; - e.m_wType = UPDUI_MENUBAR; - return m_UIElements.Add(e); - } - - BOOL UIAddToolBar(HWND hWnd) // toolbar - { - if(hWnd == NULL) - return FALSE; - _AtlUpdateUIElement e; - e.m_hWnd = hWnd; - e.m_wType = UPDUI_TOOLBAR; - return m_UIElements.Add(e); - } - - BOOL UIAddStatusBar(HWND hWnd) // status bar - { - if(hWnd == NULL) - return FALSE; - _AtlUpdateUIElement e; - e.m_hWnd = hWnd; - e.m_wType = UPDUI_STATUSBAR; - return m_UIElements.Add(e); - } - - BOOL UIAddChildWindowContainer(HWND hWnd) // child window - { - if(hWnd == NULL) - return FALSE; - _AtlUpdateUIElement e; - e.m_hWnd = hWnd; - e.m_wType = UPDUI_CHILDWINDOW; - return m_UIElements.Add(e); - } - -// Message map for popup menu updates and accelerator blocking - BEGIN_MSG_MAP(CUpdateUIBase) - MESSAGE_HANDLER(WM_INITMENUPOPUP, OnInitMenuPopup) - MESSAGE_HANDLER(WM_COMMAND, OnCommand) - END_MSG_MAP() - - LRESULT OnInitMenuPopup(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) - { - bHandled = FALSE; - HMENU hMenu = (HMENU)wParam; - if(hMenu == NULL) - return 1; - _AtlUpdateUIData* pUIData = m_pUIData; - if(pUIData == NULL) - return 1; - const _AtlUpdateUIMap* pMap = m_pUIMap; - while(pMap->m_nID != (WORD)-1) - { - if(pMap->m_wType & UPDUI_MENUPOPUP) - UIUpdateMenuBarElement(pMap->m_nID, pUIData, hMenu); - pMap++; - pUIData++; - } - return 0; - } - - LRESULT OnCommand(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) - { - bHandled = FALSE; - if(m_bBlockAccelerators && HIWORD(wParam) == 1) // accelerators only - { - int nID = LOWORD(wParam); - if((UIGetState(nID) & UPDUI_DISABLED) == UPDUI_DISABLED) - { - ATLTRACE2(atlTraceUI, 0, _T("CUpdateUIBase::OnCommand - blocked disabled command 0x%4.4X\n"), nID); - bHandled = TRUE; // eat the command, UI item is disabled - } - } - return 0; - } - -// methods for setting UI element state - BOOL UIEnable(int nID, BOOL bEnable, BOOL bForceUpdate = FALSE) - { - const _AtlUpdateUIMap* pMap = m_pUIMap; - _AtlUpdateUIData* pUIData = m_pUIData; - if(pUIData == NULL) - return FALSE; - - for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++) - { - if(nID == (int)pMap->m_nID) - { - if(bEnable) - { - if(pUIData->m_wState & UPDUI_DISABLED) - { - pUIData->m_wState |= pMap->m_wType; - pUIData->m_wState &= ~UPDUI_DISABLED; - } - } - else - { - if(!(pUIData->m_wState & UPDUI_DISABLED)) - { - pUIData->m_wState |= pMap->m_wType; - pUIData->m_wState |= UPDUI_DISABLED; - } - } - - if(bForceUpdate) - pUIData->m_wState |= pMap->m_wType; - if(pUIData->m_wState & pMap->m_wType) - m_wDirtyType |= pMap->m_wType; - - break; // found - } - } - - return TRUE; - } - - BOOL UISetCheck(int nID, int nCheck, BOOL bForceUpdate = FALSE) - { - const _AtlUpdateUIMap* pMap = m_pUIMap; - _AtlUpdateUIData* pUIData = m_pUIData; - if(pUIData == NULL) - return FALSE; - - for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++) - { - if(nID == (int)pMap->m_nID) - { - switch(nCheck) - { - case 0: - if((pUIData->m_wState & UPDUI_CHECKED) || (pUIData->m_wState & UPDUI_CHECKED2)) - { - pUIData->m_wState |= pMap->m_wType; - pUIData->m_wState &= ~(UPDUI_CHECKED | UPDUI_CHECKED2); - } - break; - case 1: - if(!(pUIData->m_wState & UPDUI_CHECKED)) - { - pUIData->m_wState |= pMap->m_wType; - pUIData->m_wState &= ~UPDUI_CHECKED2; - pUIData->m_wState |= UPDUI_CHECKED; - } - break; - case 2: - if(!(pUIData->m_wState & UPDUI_CHECKED2)) - { - pUIData->m_wState |= pMap->m_wType; - pUIData->m_wState &= ~UPDUI_CHECKED; - pUIData->m_wState |= UPDUI_CHECKED2; - } - break; - } - - if(bForceUpdate) - pUIData->m_wState |= pMap->m_wType; - if(pUIData->m_wState & pMap->m_wType) - m_wDirtyType |= pMap->m_wType; - - break; // found - } - } - - return TRUE; - } - - // variant that supports bool (checked/not-checked, no intermediate state) - BOOL UISetCheck(int nID, bool bCheck, BOOL bForceUpdate = FALSE) - { - return UISetCheck(nID, bCheck ? 1 : 0, bForceUpdate); - } - - BOOL UISetRadio(int nID, BOOL bRadio, BOOL bForceUpdate = FALSE) - { - const _AtlUpdateUIMap* pMap = m_pUIMap; - _AtlUpdateUIData* pUIData = m_pUIData; - if(pUIData == NULL) - return FALSE; - - for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++) - { - if(nID == (int)pMap->m_nID) - { - if(bRadio) - { - if(!(pUIData->m_wState & UPDUI_RADIO)) - { - pUIData->m_wState |= pMap->m_wType; - pUIData->m_wState |= UPDUI_RADIO; - } - } - else - { - if(pUIData->m_wState & UPDUI_RADIO) - { - pUIData->m_wState |= pMap->m_wType; - pUIData->m_wState &= ~UPDUI_RADIO; - } - } - - if(bForceUpdate) - pUIData->m_wState |= pMap->m_wType; - if(pUIData->m_wState & pMap->m_wType) - m_wDirtyType |= pMap->m_wType; - - break; // found - } - } - - return TRUE; - } - - BOOL UISetText(int nID, LPCTSTR lpstrText, BOOL bForceUpdate = FALSE) - { - const _AtlUpdateUIMap* pMap = m_pUIMap; - _AtlUpdateUIData* pUIData = m_pUIData; - if(pUIData == NULL) - return FALSE; - if(lpstrText == NULL) - lpstrText = _T(""); - - for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++) - { - if(nID == (int)pMap->m_nID) - { - if(pUIData->m_lpstrText == NULL || lstrcmp(pUIData->m_lpstrText, lpstrText)) - { - delete [] pUIData->m_lpstrText; - pUIData->m_lpstrText = NULL; - int nStrLen = lstrlen(lpstrText); - ATLTRY(pUIData->m_lpstrText = new TCHAR[nStrLen + 1]); - if(pUIData->m_lpstrText == NULL) - { - ATLTRACE2(atlTraceUI, 0, _T("UISetText - memory allocation failed\n")); - break; - } - SecureHelper::strcpy_x(pUIData->m_lpstrText, nStrLen + 1, lpstrText); - pUIData->m_wState |= (UPDUI_TEXT | pMap->m_wType); - } - - if(bForceUpdate) - pUIData->m_wState |= (UPDUI_TEXT | pMap->m_wType); - if(pUIData->m_wState & pMap->m_wType) - m_wDirtyType |= pMap->m_wType; - - break; // found - } - } - - return TRUE; - } - - BOOL UISetDefault(int nID, BOOL bDefault, BOOL bForceUpdate = FALSE) - { - const _AtlUpdateUIMap* pMap = m_pUIMap; - _AtlUpdateUIData* pUIData = m_pUIData; - if(pUIData == NULL) - return FALSE; - - for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++) - { - if(nID == (int)pMap->m_nID) - { - if(bDefault) - { - if((pUIData->m_wState & UPDUI_DEFAULT) == 0) - { - pUIData->m_wState |= pMap->m_wType; - pUIData->m_wState |= UPDUI_DEFAULT; - } - } - else - { - if((pUIData->m_wState & UPDUI_DEFAULT) != 0) - { - pUIData->m_wState |= pMap->m_wType; - pUIData->m_wState &= ~UPDUI_DEFAULT; - pUIData->m_wState |= UPDUI_CLEARDEFAULT; - } - } - - if(bForceUpdate) - pUIData->m_wState |= pMap->m_wType; - if(pUIData->m_wState & pMap->m_wType) - m_wDirtyType |= pMap->m_wType; - - break; // found - } - } - - return TRUE; - } - -// methods for complete state set/get - BOOL UISetState(int nID, DWORD dwState) - { - const _AtlUpdateUIMap* pMap = m_pUIMap; - _AtlUpdateUIData* pUIData = m_pUIData; - if(pUIData == NULL) - return FALSE; - for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++) - { - if(nID == (int)pMap->m_nID) - { - pUIData->m_wState = (WORD)(dwState | pMap->m_wType); - m_wDirtyType |= pMap->m_wType; - break; // found - } - } - return TRUE; - } - - DWORD UIGetState(int nID) - { - const _AtlUpdateUIMap* pMap = m_pUIMap; - _AtlUpdateUIData* pUIData = m_pUIData; - if(pUIData == NULL) - return 0; - for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++) - { - if(nID == (int)pMap->m_nID) - return pUIData->m_wState; - } - return 0; - } - -// methods for updating UI -#ifndef _WIN32_WCE - BOOL UIUpdateMenuBar(BOOL bForceUpdate = FALSE, BOOL bMainMenu = FALSE) - { - if(!(m_wDirtyType & UPDUI_MENUBAR) && !bForceUpdate) - return TRUE; - - const _AtlUpdateUIMap* pMap = m_pUIMap; - _AtlUpdateUIData* pUIData = m_pUIData; - if(pUIData == NULL) - return FALSE; - - while(pMap->m_nID != (WORD)-1) - { - for(int i = 0; i < m_UIElements.GetSize(); i++) - { - if(m_UIElements[i].m_wType == UPDUI_MENUBAR) - { - HMENU hMenu = ::GetMenu(m_UIElements[i].m_hWnd); - if(hMenu != NULL && (pUIData->m_wState & UPDUI_MENUBAR) && (pMap->m_wType & UPDUI_MENUBAR)) - UIUpdateMenuBarElement(pMap->m_nID, pUIData, hMenu); - } - if(bMainMenu) - ::DrawMenuBar(m_UIElements[i].m_hWnd); - } - pMap++; - pUIData->m_wState &= ~UPDUI_MENUBAR; - if(pUIData->m_wState & UPDUI_TEXT) - { - delete [] pUIData->m_lpstrText; - pUIData->m_lpstrText = NULL; - pUIData->m_wState &= ~UPDUI_TEXT; - } - pUIData++; - } - - m_wDirtyType &= ~UPDUI_MENUBAR; - return TRUE; - } -#endif // !_WIN32_WCE - - BOOL UIUpdateToolBar(BOOL bForceUpdate = FALSE) - { - if(!(m_wDirtyType & UPDUI_TOOLBAR) && !bForceUpdate) - return TRUE; - - const _AtlUpdateUIMap* pMap = m_pUIMap; - _AtlUpdateUIData* pUIData = m_pUIData; - if(pUIData == NULL) - return FALSE; - - while(pMap->m_nID != (WORD)-1) - { - for(int i = 0; i < m_UIElements.GetSize(); i++) - { - if(m_UIElements[i].m_wType == UPDUI_TOOLBAR) - { - if((pUIData->m_wState & UPDUI_TOOLBAR) && (pMap->m_wType & UPDUI_TOOLBAR)) - UIUpdateToolBarElement(pMap->m_nID, pUIData, m_UIElements[i].m_hWnd); - } - } - pMap++; - pUIData->m_wState &= ~UPDUI_TOOLBAR; - pUIData++; - } - - m_wDirtyType &= ~UPDUI_TOOLBAR; - return TRUE; - } - - BOOL UIUpdateStatusBar(BOOL bForceUpdate = FALSE) - { - if(!(m_wDirtyType & UPDUI_STATUSBAR) && !bForceUpdate) - return TRUE; - - const _AtlUpdateUIMap* pMap = m_pUIMap; - _AtlUpdateUIData* pUIData = m_pUIData; - if(pUIData == NULL) - return FALSE; - - while(pMap->m_nID != (WORD)-1) - { - for(int i = 0; i < m_UIElements.GetSize(); i++) - { - if(m_UIElements[i].m_wType == UPDUI_STATUSBAR) - { - if((pUIData->m_wState & UPDUI_STATUSBAR) && (pMap->m_wType & UPDUI_STATUSBAR)) - UIUpdateStatusBarElement(pMap->m_nID, pUIData, m_UIElements[i].m_hWnd); - } - } - pMap++; - pUIData->m_wState &= ~UPDUI_STATUSBAR; - if(pUIData->m_wState & UPDUI_TEXT) - { - delete [] pUIData->m_lpstrText; - pUIData->m_lpstrText = NULL; - pUIData->m_wState &= ~UPDUI_TEXT; - } - pUIData++; - } - - m_wDirtyType &= ~UPDUI_STATUSBAR; - return TRUE; - } - - BOOL UIUpdateChildWindows(BOOL bForceUpdate = FALSE) - { - if(!(m_wDirtyType & UPDUI_CHILDWINDOW) && !bForceUpdate) - return TRUE; - - const _AtlUpdateUIMap* pMap = m_pUIMap; - _AtlUpdateUIData* pUIData = m_pUIData; - if(pUIData == NULL) - return FALSE; - - while(pMap->m_nID != (WORD)-1) - { - for(int i = 0; i < m_UIElements.GetSize(); i++) - { - if(m_UIElements[i].m_wType == UPDUI_CHILDWINDOW) - { - if((pUIData->m_wState & UPDUI_CHILDWINDOW) && (pMap->m_wType & UPDUI_CHILDWINDOW)) - UIUpdateChildWindow(pMap->m_nID, pUIData, m_UIElements[i].m_hWnd); - } - } - pMap++; - pUIData->m_wState &= ~UPDUI_CHILDWINDOW; - if(pUIData->m_wState & UPDUI_TEXT) - { - delete [] pUIData->m_lpstrText; - pUIData->m_lpstrText = NULL; - pUIData->m_wState &= ~UPDUI_TEXT; - } - pUIData++; - } - - m_wDirtyType &= ~UPDUI_CHILDWINDOW; - return TRUE; - } - -// internal element specific methods - static void UIUpdateMenuBarElement(int nID, _AtlUpdateUIData* pUIData, HMENU hMenu) - { -#ifndef _WIN32_WCE - if((pUIData->m_wState & UPDUI_CLEARDEFAULT) != 0) - { - ::SetMenuDefaultItem(hMenu, (UINT)-1, 0); - pUIData->m_wState &= ~UPDUI_CLEARDEFAULT; - } -#endif // !_WIN32_WCE - - CMenuItemInfo mii; - mii.fMask = MIIM_STATE; - mii.wID = nID; - -#ifndef _WIN32_WCE - if((pUIData->m_wState & UPDUI_DISABLED) != 0) - mii.fState |= MFS_DISABLED | MFS_GRAYED; - else - mii.fState |= MFS_ENABLED; - - if((pUIData->m_wState & UPDUI_CHECKED) != 0) - mii.fState |= MFS_CHECKED; - else - mii.fState |= MFS_UNCHECKED; - - if((pUIData->m_wState & UPDUI_DEFAULT) != 0) - mii.fState |= MFS_DEFAULT; -#else // CE specific - // ::SetMenuItemInfo() can't disable or check menu items - // on Windows CE, so we have to do that directly - UINT uEnable = MF_BYCOMMAND; - if((pUIData->m_wState & UPDUI_DISABLED) != 0) - uEnable |= MF_GRAYED; - else - uEnable |= MF_ENABLED; - ::EnableMenuItem(hMenu, nID, uEnable); - - UINT uCheck = MF_BYCOMMAND; - if((pUIData->m_wState & UPDUI_CHECKED) != 0) - uCheck |= MF_CHECKED; - else - uCheck |= MF_UNCHECKED; - ::CheckMenuItem(hMenu, nID, uCheck); -#endif // _WIN32_WCE - - if((pUIData->m_wState & UPDUI_TEXT) != 0) - { - CMenuItemInfo miiNow; - miiNow.fMask = MIIM_TYPE; - miiNow.wID = nID; - if(::GetMenuItemInfo(hMenu, nID, FALSE, &miiNow)) - { - mii.fMask |= MIIM_TYPE; - // MFT_BITMAP and MFT_SEPARATOR don't go together with MFT_STRING -#ifndef _WIN32_WCE - mii.fType |= (miiNow.fType & ~(MFT_BITMAP | MFT_SEPARATOR)) | MFT_STRING; -#else // CE specific - mii.fType |= (miiNow.fType & ~(MFT_SEPARATOR)) | MFT_STRING; -#endif // _WIN32_WCE - mii.dwTypeData = pUIData->m_lpstrText; - } - } - - ::SetMenuItemInfo(hMenu, nID, FALSE, &mii); - } - - static void UIUpdateToolBarElement(int nID, _AtlUpdateUIData* pUIData, HWND hWndToolBar) - { - // Note: only handles enabled/disabled, checked state, and radio (press) - ::SendMessage(hWndToolBar, TB_ENABLEBUTTON, nID, (LPARAM)(pUIData->m_wState & UPDUI_DISABLED) ? FALSE : TRUE); - ::SendMessage(hWndToolBar, TB_CHECKBUTTON, nID, (LPARAM)(pUIData->m_wState & UPDUI_CHECKED) ? TRUE : FALSE); - ::SendMessage(hWndToolBar, TB_INDETERMINATE, nID, (LPARAM)(pUIData->m_wState & UPDUI_CHECKED2) ? TRUE : FALSE); - ::SendMessage(hWndToolBar, TB_PRESSBUTTON, nID, (LPARAM)(pUIData->m_wState & UPDUI_RADIO) ? TRUE : FALSE); - } - - static void UIUpdateStatusBarElement(int nID, _AtlUpdateUIData* pUIData, HWND hWndStatusBar) - { - // Note: only handles text - if(pUIData->m_wState & UPDUI_TEXT) - ::SendMessage(hWndStatusBar, SB_SETTEXT, nID, (LPARAM)pUIData->m_lpstrText); - } - - static void UIUpdateChildWindow(int nID, _AtlUpdateUIData* pUIData, HWND hWnd) - { - HWND hChild = ::GetDlgItem(hWnd, nID); - - ::EnableWindow(hChild, (pUIData->m_wState & UPDUI_DISABLED) ? FALSE : TRUE); - // for check and radio, assume that window is a button - int nCheck = BST_UNCHECKED; - if(pUIData->m_wState & UPDUI_CHECKED || pUIData->m_wState & UPDUI_RADIO) - nCheck = BST_CHECKED; - else if(pUIData->m_wState & UPDUI_CHECKED2) - nCheck = BST_INDETERMINATE; - ::SendMessage(hChild, BM_SETCHECK, nCheck, 0L); - if(pUIData->m_wState & UPDUI_DEFAULT) - { - DWORD dwRet = (DWORD)::SendMessage(hWnd, DM_GETDEFID, 0, 0L); - if(HIWORD(dwRet) == DC_HASDEFID) - { - HWND hOldDef = ::GetDlgItem(hWnd, (int)(short)LOWORD(dwRet)); - // remove BS_DEFPUSHBUTTON - ::SendMessage(hOldDef, BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0)); - } - ::SendMessage(hWnd, DM_SETDEFID, nID, 0L); - } - if(pUIData->m_wState & UPDUI_TEXT) - ::SetWindowText(hChild, pUIData->m_lpstrText); - } -}; - -template -class CUpdateUI : public CUpdateUIBase -{ -public: - CUpdateUI() - { - T* pT = static_cast(this); - pT; - const _AtlUpdateUIMap* pMap = pT->GetUpdateUIMap(); - m_pUIMap = pMap; - ATLASSERT(m_pUIMap != NULL); - int nCount; - for(nCount = 1; pMap->m_nID != (WORD)-1; nCount++) - pMap++; - - // check for duplicates (debug only) -#ifdef _DEBUG - for(int i = 0; i < nCount; i++) - { - for(int j = 0; j < nCount; j++) - { - // shouldn't have duplicates in the update UI map - if(i != j) - ATLASSERT(m_pUIMap[j].m_nID != m_pUIMap[i].m_nID); - } - } -#endif // _DEBUG - - ATLTRY(m_pUIData = new _AtlUpdateUIData[nCount]); - ATLASSERT(m_pUIData != NULL); - - if(m_pUIData != NULL) - memset(m_pUIData, 0, sizeof(_AtlUpdateUIData) * nCount); - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CDynamicUpdateUI - allows update elements to dynamically added and removed -// in addition to a static update UI map - -template -class CDynamicUpdateUI : public CUpdateUIBase -{ -public: -// Data members - ATL::CSimpleArray<_AtlUpdateUIMap> m_arrUIMap; // copy of the static UI data - ATL::CSimpleArray<_AtlUpdateUIData> m_arrUIData; // instance UI data - -// Constructor/destructor - CDynamicUpdateUI() - { - T* pT = static_cast(this); - pT; - const _AtlUpdateUIMap* pMap = pT->GetUpdateUIMap(); - ATLASSERT(pMap != NULL); - - for(;;) - { - BOOL bRet = m_arrUIMap.Add(*(_AtlUpdateUIMap*)pMap); - ATLASSERT(bRet); - - if(bRet != FALSE) - { - _AtlUpdateUIData data = { 0, NULL }; - bRet = m_arrUIData.Add(data); - ATLASSERT(bRet); - } - - if(pMap->m_nID == (WORD)-1) - break; - - pMap++; - } - - ATLASSERT(m_arrUIMap.GetSize() == m_arrUIData.GetSize()); - -#ifdef _DEBUG - // check for duplicates (debug only) - for(int i = 0; i < m_arrUIMap.GetSize(); i++) - { - for(int j = 0; j < m_arrUIMap.GetSize(); j++) - { - // shouldn't have duplicates in the update UI map - if(i != j) - ATLASSERT(m_arrUIMap[j].m_nID != m_arrUIMap[i].m_nID); - } - } -#endif // _DEBUG - - // Set internal data pointers to point to the new data arrays - m_pUIMap = m_arrUIMap.m_aT; - m_pUIData = m_arrUIData.m_aT; - } - - ~CDynamicUpdateUI() - { - for(int i = 0; i < m_arrUIData.GetSize(); i++) - { - if((m_arrUIData[i].m_wState & UPDUI_TEXT) != 0) - delete [] m_arrUIData[i].m_lpstrText; - } - - // Reset internal data pointers (memory will be released by CSimpleArray d-tor) - m_pUIMap = NULL; - m_pUIData = NULL; - } - -// Methods for dynamically adding and removing update elements - bool UIAddUpdateElement(WORD nID, WORD wType) - { - // check for duplicates - for(int i = 0; i < m_arrUIMap.GetSize(); i++) - { - // shouldn't have duplicates in the update UI map - ATLASSERT(m_arrUIMap[i].m_nID != nID); - if(m_arrUIMap[i].m_nID == nID) - return false; - } - - bool bRetVal = false; - - // Add new end element - _AtlUpdateUIMap uumEnd = { (WORD)-1, 0 }; - BOOL bRet = m_arrUIMap.Add(uumEnd); - ATLASSERT(bRet); - - if(bRet != FALSE) - { - _AtlUpdateUIData uud = { 0, NULL }; - bRet = m_arrUIData.Add(uud); - ATLASSERT(bRet); - - // Set new data to the previous end element - if(bRet != FALSE) - { - int nSize = m_arrUIMap.GetSize(); - _AtlUpdateUIMap uum = { nID, wType }; - m_arrUIMap.SetAtIndex(nSize - 2, uum); - m_arrUIData.SetAtIndex(nSize - 2, uud); - - // Set internal data pointers again, just in case that memory moved - m_pUIMap = m_arrUIMap.m_aT; - m_pUIData = m_arrUIData.m_aT; - - bRetVal = true; - } - } - - return bRetVal; - } - - bool UIRemoveUpdateElement(WORD nID) - { - bool bRetVal = false; - - for(int i = 0; i < m_arrUIMap.GetSize(); i++) - { - if(m_arrUIMap[i].m_nID == nID) - { - BOOL bRet = m_arrUIMap.RemoveAt(i); - ATLASSERT(bRet); - bRet = m_arrUIData.RemoveAt(i); - ATLASSERT(bRet); - - bRetVal = true; - break; - } - } - - return bRetVal; - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CDialogResize - provides support for resizing dialog controls -// (works for any window that has child controls) - -// Put CDialogResize in the list of base classes for a dialog (or even plain window), -// then implement DLGRESIZE map by specifying controls and groups of control -// and using DLSZ_* values to specify how are they supposed to be resized. -// -// Notes: -// - Resizeable border (WS_THICKFRAME style) should be set in the dialog template -// for top level dialogs (popup or overlapped), so that users can resize the dialog. -// - Some flags cannot be combined; for instance DLSZ_CENTER_X overrides DLSZ_SIZE_X, -// DLSZ_SIZE_X overrides DLSZ_MOVE_X. X and Y flags can be combined. -// - Order of controls is important - group controls are resized and moved based -// on the position of the previous control in a group. - -// dialog resize map macros -#define BEGIN_DLGRESIZE_MAP(thisClass) \ - static const _AtlDlgResizeMap* GetDlgResizeMap() \ - { \ - static const _AtlDlgResizeMap theMap[] = \ - { - -#define END_DLGRESIZE_MAP() \ - { -1, 0 }, \ - }; \ - return theMap; \ - } - -#define DLGRESIZE_CONTROL(id, flags) \ - { id, flags }, - -#define BEGIN_DLGRESIZE_GROUP() \ - { -1, _DLSZ_BEGIN_GROUP }, - -#define END_DLGRESIZE_GROUP() \ - { -1, _DLSZ_END_GROUP }, - - -template -class CDialogResize -{ -public: -// Data declarations and members - enum - { - DLSZ_SIZE_X = 0x00000001, - DLSZ_SIZE_Y = 0x00000002, - DLSZ_MOVE_X = 0x00000004, - DLSZ_MOVE_Y = 0x00000008, - DLSZ_REPAINT = 0x00000010, - DLSZ_CENTER_X = 0x00000020, - DLSZ_CENTER_Y = 0x00000040, - - // internal use only - _DLSZ_BEGIN_GROUP = 0x00001000, - _DLSZ_END_GROUP = 0x00002000, - _DLSZ_GRIPPER = 0x00004000 - }; - - struct _AtlDlgResizeMap - { - int m_nCtlID; - DWORD m_dwResizeFlags; - }; - - struct _AtlDlgResizeData - { - int m_nCtlID; - DWORD m_dwResizeFlags; - RECT m_rect; - - int GetGroupCount() const - { - return (int)LOBYTE(HIWORD(m_dwResizeFlags)); - } - - void SetGroupCount(int nCount) - { - ATLASSERT(nCount > 0 && nCount < 256); - DWORD dwCount = (DWORD)MAKELONG(0, MAKEWORD(nCount, 0)); - m_dwResizeFlags &= 0xFF00FFFF; - m_dwResizeFlags |= dwCount; - } - - bool operator ==(const _AtlDlgResizeData& r) const - { return (m_nCtlID == r.m_nCtlID && m_dwResizeFlags == r.m_dwResizeFlags); } - }; - - ATL::CSimpleArray<_AtlDlgResizeData> m_arrData; - SIZE m_sizeDialog; - POINT m_ptMinTrackSize; - bool m_bGripper; - - -// Constructor - CDialogResize() : m_bGripper(false) - { - m_sizeDialog.cx = 0; - m_sizeDialog.cy = 0; - m_ptMinTrackSize.x = -1; - m_ptMinTrackSize.y = -1; - } - -// Operations - void DlgResize_Init(bool bAddGripper = true, bool bUseMinTrackSize = true, DWORD dwForceStyle = WS_CLIPCHILDREN) - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - - DWORD dwStyle = pT->GetStyle(); - -#ifdef _DEBUG - // Debug only: Check if top level dialogs have a resizeable border. - if(((dwStyle & WS_CHILD) == 0) && ((dwStyle & WS_THICKFRAME) == 0)) - ATLTRACE2(atlTraceUI, 0, _T("DlgResize_Init - warning: top level dialog without the WS_THICKFRAME style - user cannot resize it\n")); -#endif // _DEBUG - - // Force specified styles (default WS_CLIPCHILDREN reduces flicker) - if((dwStyle & dwForceStyle) != dwForceStyle) - pT->ModifyStyle(0, dwForceStyle); - - // Adding this style removes an empty icon that dialogs with WS_THICKFRAME have. - // Setting icon to NULL is required when XP themes are active. - // Note: This will not prevent adding an icon for the dialog using SetIcon() - if((dwStyle & WS_CHILD) == 0) - { - pT->ModifyStyleEx(0, WS_EX_DLGMODALFRAME); - if(pT->GetIcon(FALSE) == NULL) - pT->SetIcon(NULL, FALSE); - } - - // Cleanup in case of multiple initialization - // block: first check for the gripper control, destroy it if needed - { - ATL::CWindow wndGripper = pT->GetDlgItem(ATL_IDW_STATUS_BAR); - if(wndGripper.IsWindow() && m_arrData.GetSize() > 0 && (m_arrData[0].m_dwResizeFlags & _DLSZ_GRIPPER) != 0) - wndGripper.DestroyWindow(); - } - // clear out everything else - m_arrData.RemoveAll(); - m_sizeDialog.cx = 0; - m_sizeDialog.cy = 0; - m_ptMinTrackSize.x = -1; - m_ptMinTrackSize.y = -1; - - // Get initial dialog client size - RECT rectDlg = { 0 }; - pT->GetClientRect(&rectDlg); - m_sizeDialog.cx = rectDlg.right; - m_sizeDialog.cy = rectDlg.bottom; - -#ifndef _WIN32_WCE - // Create gripper if requested - m_bGripper = false; - if(bAddGripper) - { - // shouldn't exist already - ATLASSERT(!::IsWindow(pT->GetDlgItem(ATL_IDW_STATUS_BAR))); - if(!::IsWindow(pT->GetDlgItem(ATL_IDW_STATUS_BAR))) - { - ATL::CWindow wndGripper; - wndGripper.Create(_T("SCROLLBAR"), pT->m_hWnd, rectDlg, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SBS_SIZEBOX | SBS_SIZEGRIP | SBS_SIZEBOXBOTTOMRIGHTALIGN, 0, ATL_IDW_STATUS_BAR); - ATLASSERT(wndGripper.IsWindow()); - if(wndGripper.IsWindow()) - { - m_bGripper = true; - RECT rectCtl = { 0 }; - wndGripper.GetWindowRect(&rectCtl); - ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rectCtl, 2); - _AtlDlgResizeData data = { ATL_IDW_STATUS_BAR, DLSZ_MOVE_X | DLSZ_MOVE_Y | DLSZ_REPAINT | _DLSZ_GRIPPER, { rectCtl.left, rectCtl.top, rectCtl.right, rectCtl.bottom } }; - m_arrData.Add(data); - } - } - } -#else // CE specific - bAddGripper; // avoid level 4 warning -#endif // _WIN32_WCE - - // Get min track position if requested - if(bUseMinTrackSize) - { - if((dwStyle & WS_CHILD) != 0) - { - RECT rect = { 0 }; - pT->GetClientRect(&rect); - m_ptMinTrackSize.x = rect.right - rect.left; - m_ptMinTrackSize.y = rect.bottom - rect.top; - } - else - { - RECT rect = { 0 }; - pT->GetWindowRect(&rect); - m_ptMinTrackSize.x = rect.right - rect.left; - m_ptMinTrackSize.y = rect.bottom - rect.top; - } - } - - // Walk the map and initialize data - const _AtlDlgResizeMap* pMap = pT->GetDlgResizeMap(); - ATLASSERT(pMap != NULL); - int nGroupStart = -1; - for(int nCount = 1; !(pMap->m_nCtlID == -1 && pMap->m_dwResizeFlags == 0); nCount++, pMap++) - { - if(pMap->m_nCtlID == -1) - { - switch(pMap->m_dwResizeFlags) - { - case _DLSZ_BEGIN_GROUP: - ATLASSERT(nGroupStart == -1); - nGroupStart = m_arrData.GetSize(); - break; - case _DLSZ_END_GROUP: - { - ATLASSERT(nGroupStart != -1); - int nGroupCount = m_arrData.GetSize() - nGroupStart; - m_arrData[nGroupStart].SetGroupCount(nGroupCount); - nGroupStart = -1; - } - break; - default: - ATLASSERT(FALSE && _T("Invalid DLGRESIZE Map Entry")); - break; - } - } - else - { - // this ID conflicts with the default gripper one - ATLASSERT(m_bGripper ? (pMap->m_nCtlID != ATL_IDW_STATUS_BAR) : TRUE); - - ATL::CWindow ctl = pT->GetDlgItem(pMap->m_nCtlID); - ATLASSERT(ctl.IsWindow()); - RECT rectCtl = { 0 }; - ctl.GetWindowRect(&rectCtl); - ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rectCtl, 2); - - DWORD dwGroupFlag = (nGroupStart != -1 && m_arrData.GetSize() == nGroupStart) ? _DLSZ_BEGIN_GROUP : 0; - _AtlDlgResizeData data = { pMap->m_nCtlID, pMap->m_dwResizeFlags | dwGroupFlag, { rectCtl.left, rectCtl.top, rectCtl.right, rectCtl.bottom } }; - m_arrData.Add(data); - } - } - ATLASSERT((nGroupStart == -1) && _T("No End Group Entry in the DLGRESIZE Map")); - } - - void DlgResize_UpdateLayout(int cxWidth, int cyHeight) - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - - // Restrict minimum size if requested - if(((pT->GetStyle() & WS_CHILD) != 0) && m_ptMinTrackSize.x != -1 && m_ptMinTrackSize.y != -1) - { - if(cxWidth < m_ptMinTrackSize.x) - cxWidth = m_ptMinTrackSize.x; - if(cyHeight < m_ptMinTrackSize.y) - cyHeight = m_ptMinTrackSize.y; - } - - BOOL bVisible = pT->IsWindowVisible(); - if(bVisible) - pT->SetRedraw(FALSE); - - for(int i = 0; i < m_arrData.GetSize(); i++) - { - if((m_arrData[i].m_dwResizeFlags & _DLSZ_BEGIN_GROUP) != 0) // start of a group - { - int nGroupCount = m_arrData[i].GetGroupCount(); - ATLASSERT(nGroupCount > 0 && i + nGroupCount - 1 < m_arrData.GetSize()); - RECT rectGroup = m_arrData[i].m_rect; - - int j = 1; - for(j = 1; j < nGroupCount; j++) - { - rectGroup.left = min(rectGroup.left, m_arrData[i + j].m_rect.left); - rectGroup.top = min(rectGroup.top, m_arrData[i + j].m_rect.top); - rectGroup.right = max(rectGroup.right, m_arrData[i + j].m_rect.right); - rectGroup.bottom = max(rectGroup.bottom, m_arrData[i + j].m_rect.bottom); - } - - for(j = 0; j < nGroupCount; j++) - { - _AtlDlgResizeData* pDataPrev = NULL; - if(j > 0) - pDataPrev = &(m_arrData[i + j - 1]); - pT->DlgResize_PositionControl(cxWidth, cyHeight, rectGroup, m_arrData[i + j], true, pDataPrev); - } - - i += nGroupCount - 1; // increment to skip all group controls - } - else // one control entry - { - RECT rectGroup = { 0, 0, 0, 0 }; - pT->DlgResize_PositionControl(cxWidth, cyHeight, rectGroup, m_arrData[i], false); - } - } - - if(bVisible) - pT->SetRedraw(TRUE); - - pT->RedrawWindow(NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN); - } - -// Message map and handlers - BEGIN_MSG_MAP(CDialogResize) - MESSAGE_HANDLER(WM_SIZE, OnSize) -#ifndef _WIN32_WCE - MESSAGE_HANDLER(WM_GETMINMAXINFO, OnGetMinMaxInfo) -#endif // _WIN32_WCE - END_MSG_MAP() - - LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); -#ifndef _WIN32_WCE - if(m_bGripper) - { - ATL::CWindow wndGripper = pT->GetDlgItem(ATL_IDW_STATUS_BAR); - if(wParam == SIZE_MAXIMIZED) - wndGripper.ShowWindow(SW_HIDE); - else if(wParam == SIZE_RESTORED) - wndGripper.ShowWindow(SW_SHOW); - } -#endif // _WIN32_WCE - if(wParam != SIZE_MINIMIZED) - { - ATLASSERT(::IsWindow(pT->m_hWnd)); - pT->DlgResize_UpdateLayout(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); - } - return 0; - } - -#ifndef _WIN32_WCE - LRESULT OnGetMinMaxInfo(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) - { - if(m_ptMinTrackSize.x != -1 && m_ptMinTrackSize.y != -1) - { - LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam; - lpMMI->ptMinTrackSize = m_ptMinTrackSize; - } - return 0; - } -#endif // _WIN32_WCE - -// Implementation - bool DlgResize_PositionControl(int cxWidth, int cyHeight, RECT& rectGroup, _AtlDlgResizeData& data, bool bGroup, - _AtlDlgResizeData* pDataPrev = NULL) - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - ATL::CWindow ctl; - RECT rectCtl = { 0 }; - - ctl = pT->GetDlgItem(data.m_nCtlID); - if(!ctl.GetWindowRect(&rectCtl)) - return false; - ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rectCtl, 2); - - if(bGroup) - { - if((data.m_dwResizeFlags & DLSZ_CENTER_X) != 0) - { - int cxRight = rectGroup.right + cxWidth - m_sizeDialog.cx; - int cxCtl = data.m_rect.right - data.m_rect.left; - rectCtl.left = rectGroup.left + (cxRight - rectGroup.left - cxCtl) / 2; - rectCtl.right = rectCtl.left + cxCtl; - } - else if((data.m_dwResizeFlags & (DLSZ_SIZE_X | DLSZ_MOVE_X)) != 0) - { - rectCtl.left = rectGroup.left + ::MulDiv(data.m_rect.left - rectGroup.left, rectGroup.right - rectGroup.left + (cxWidth - m_sizeDialog.cx), rectGroup.right - rectGroup.left); - - if((data.m_dwResizeFlags & DLSZ_SIZE_X) != 0) - { - rectCtl.right = rectGroup.left + ::MulDiv(data.m_rect.right - rectGroup.left, rectGroup.right - rectGroup.left + (cxWidth - m_sizeDialog.cx), rectGroup.right - rectGroup.left); - - if(pDataPrev != NULL) - { - ATL::CWindow ctlPrev = pT->GetDlgItem(pDataPrev->m_nCtlID); - RECT rcPrev = { 0 }; - ctlPrev.GetWindowRect(&rcPrev); - ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rcPrev, 2); - int dxAdjust = (rectCtl.left - rcPrev.right) - (data.m_rect.left - pDataPrev->m_rect.right); - rcPrev.right += dxAdjust; - ctlPrev.SetWindowPos(NULL, &rcPrev, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE); - } - } - else - { - rectCtl.right = rectCtl.left + (data.m_rect.right - data.m_rect.left); - } - } - - if((data.m_dwResizeFlags & DLSZ_CENTER_Y) != 0) - { - int cyBottom = rectGroup.bottom + cyHeight - m_sizeDialog.cy; - int cyCtl = data.m_rect.bottom - data.m_rect.top; - rectCtl.top = rectGroup.top + (cyBottom - rectGroup.top - cyCtl) / 2; - rectCtl.bottom = rectCtl.top + cyCtl; - } - else if((data.m_dwResizeFlags & (DLSZ_SIZE_Y | DLSZ_MOVE_Y)) != 0) - { - rectCtl.top = rectGroup.top + ::MulDiv(data.m_rect.top - rectGroup.top, rectGroup.bottom - rectGroup.top + (cyHeight - m_sizeDialog.cy), rectGroup.bottom - rectGroup.top); - - if((data.m_dwResizeFlags & DLSZ_SIZE_Y) != 0) - { - rectCtl.bottom = rectGroup.top + ::MulDiv(data.m_rect.bottom - rectGroup.top, rectGroup.bottom - rectGroup.top + (cyHeight - m_sizeDialog.cy), rectGroup.bottom - rectGroup.top); - - if(pDataPrev != NULL) - { - ATL::CWindow ctlPrev = pT->GetDlgItem(pDataPrev->m_nCtlID); - RECT rcPrev = { 0 }; - ctlPrev.GetWindowRect(&rcPrev); - ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rcPrev, 2); - int dxAdjust = (rectCtl.top - rcPrev.bottom) - (data.m_rect.top - pDataPrev->m_rect.bottom); - rcPrev.bottom += dxAdjust; - ctlPrev.SetWindowPos(NULL, &rcPrev, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE); - } - } - else - { - rectCtl.bottom = rectCtl.top + (data.m_rect.bottom - data.m_rect.top); - } - } - } - else // no group - { - if((data.m_dwResizeFlags & DLSZ_CENTER_X) != 0) - { - int cxCtl = data.m_rect.right - data.m_rect.left; - rectCtl.left = (cxWidth - cxCtl) / 2; - rectCtl.right = rectCtl.left + cxCtl; - } - else if((data.m_dwResizeFlags & (DLSZ_SIZE_X | DLSZ_MOVE_X)) != 0) - { - rectCtl.right = data.m_rect.right + (cxWidth - m_sizeDialog.cx); - - if((data.m_dwResizeFlags & DLSZ_MOVE_X) != 0) - rectCtl.left = rectCtl.right - (data.m_rect.right - data.m_rect.left); - } - - if((data.m_dwResizeFlags & DLSZ_CENTER_Y) != 0) - { - int cyCtl = data.m_rect.bottom - data.m_rect.top; - rectCtl.top = (cyHeight - cyCtl) / 2; - rectCtl.bottom = rectCtl.top + cyCtl; - } - else if((data.m_dwResizeFlags & (DLSZ_SIZE_Y | DLSZ_MOVE_Y)) != 0) - { - rectCtl.bottom = data.m_rect.bottom + (cyHeight - m_sizeDialog.cy); - - if((data.m_dwResizeFlags & DLSZ_MOVE_Y) != 0) - rectCtl.top = rectCtl.bottom - (data.m_rect.bottom - data.m_rect.top); - } - } - - if((data.m_dwResizeFlags & DLSZ_REPAINT) != 0) - ctl.Invalidate(); - - if((data.m_dwResizeFlags & (DLSZ_SIZE_X | DLSZ_SIZE_Y | DLSZ_MOVE_X | DLSZ_MOVE_Y | DLSZ_REPAINT | DLSZ_CENTER_X | DLSZ_CENTER_Y)) != 0) - ctl.SetWindowPos(NULL, &rectCtl, SWP_NOZORDER | SWP_NOACTIVATE); - - return true; - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CDoubleBufferImpl - Provides double-buffer painting support to any window - -template -class CDoubleBufferImpl -{ -public: -// Overrideables - void DoPaint(CDCHandle /*dc*/) - { - // must be implemented in a derived class - ATLASSERT(FALSE); - } - -// Message map and handlers - BEGIN_MSG_MAP(CDoubleBufferImpl) - MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) - MESSAGE_HANDLER(WM_PAINT, OnPaint) -#ifndef _WIN32_WCE - MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) -#endif // !_WIN32_WCE - END_MSG_MAP() - - LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - return 1; // no background painting needed - } - - LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - - if(wParam != NULL) - { - RECT rect = { 0 }; - pT->GetClientRect(&rect); - CMemoryDC dcMem((HDC)wParam, rect); - pT->DoPaint(dcMem.m_hDC); - } - else - { - CPaintDC dc(pT->m_hWnd); - CMemoryDC dcMem(dc.m_hDC, dc.m_ps.rcPaint); - pT->DoPaint(dcMem.m_hDC); - } - - return 0; - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CDoubleBufferWindowImpl - Implements a double-buffer painting window - -template -class ATL_NO_VTABLE CDoubleBufferWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CDoubleBufferImpl< T > -{ -public: - BEGIN_MSG_MAP(CDoubleBufferWindowImpl) - CHAIN_MSG_MAP(CDoubleBufferImpl< T >) - END_MSG_MAP() -}; - - -// command bar support -#if !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE) - #undef CBRM_GETMENU - #undef CBRM_TRACKPOPUPMENU - #undef CBRM_GETCMDBAR - #undef CBRPOPUPMENU -#endif // !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE) - -}; // namespace WTL - -#endif // __ATLFRAME_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/atlgdi.h b/prog/3rdPartyLibs/wtl-8.1/include/atlgdi.h deleted file mode 100644 index c6f801938..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/atlgdi.h +++ /dev/null @@ -1,3850 +0,0 @@ -// Windows Template Library - WTL version 8.1 -// Copyright (C) Microsoft Corporation. All rights reserved. -// -// This file is a part of the Windows Template Library. -// The use and distribution terms for this software are covered by the -// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php) -// which can be found in the file CPL.TXT at the root of this distribution. -// By using this software in any fashion, you are agreeing to be bound by -// the terms of this license. You must not remove this notice, or -// any other, from this software. - -#ifndef __ATLGDI_H__ -#define __ATLGDI_H__ - -#pragma once - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#ifndef __ATLAPP_H__ - #error atlgdi.h requires atlapp.h to be included first -#endif - - -// protect template members from windowsx.h macros -#ifdef _INC_WINDOWSX - #undef CopyRgn - #undef CreateBrush - #undef CreatePen - #undef SelectBrush - #undef SelectPen - #undef SelectFont - #undef SelectBitmap -#endif // _INC_WINDOWSX - -// required libraries -#if !defined(_ATL_NO_MSIMG) && !defined(_WIN32_WCE) - #pragma comment(lib, "msimg32.lib") -#endif // !defined(_ATL_NO_MSIMG) && !defined(_WIN32_WCE) -#if !defined(_ATL_NO_OPENGL) && !defined(_WIN32_WCE) - #pragma comment(lib, "opengl32.lib") -#endif // !defined(_ATL_NO_OPENGL) && !defined(_WIN32_WCE) - - -/////////////////////////////////////////////////////////////////////////////// -// Classes in this file: -// -// CPenT -// CBrushT -// CLogFont -// CFontT -// CBitmapT -// CPaletteT -// CRgnT -// CDCT -// CPaintDC -// CClientDC -// CWindowDC -// CMemoryDC -// CEnhMetaFileInfo -// CEnhMetaFileT -// CEnhMetaFileDC -// -// Global functions: -// AtlGetBitmapResourceInfo() -// AtlGetBitmapResourceBitsPerPixel() -// AtlIsAlphaBitmapResource() -// AtlIsDib16() -// AtlGetDibColorTableSize() -// AtlGetDibNumColors(), -// AtlGetDibBitmap() -// AtlCopyBitmap() -// AtlCreatePackedDib16() -// AtlSetClipboardDib16() -// AtlGetClipboardDib() - - -namespace WTL -{ - -/////////////////////////////////////////////////////////////////////////////// -// Bitmap resource helpers to extract bitmap information for a bitmap resource - -inline LPBITMAPINFOHEADER AtlGetBitmapResourceInfo(HMODULE hModule, ATL::_U_STRINGorID image) -{ - HRSRC hResource = ::FindResource(hModule, image.m_lpstr, RT_BITMAP); - ATLASSERT(hResource != NULL); - HGLOBAL hGlobal = ::LoadResource(hModule, hResource); - ATLASSERT(hGlobal != NULL); - LPBITMAPINFOHEADER pBitmapInfoHeader = (LPBITMAPINFOHEADER)::LockResource(hGlobal); - ATLASSERT(pBitmapInfoHeader != NULL); - return pBitmapInfoHeader; -} - -inline WORD AtlGetBitmapResourceBitsPerPixel(HMODULE hModule, ATL::_U_STRINGorID image) -{ - LPBITMAPINFOHEADER pBitmapInfoHeader = AtlGetBitmapResourceInfo(hModule, image); - ATLASSERT(pBitmapInfoHeader != NULL); - return pBitmapInfoHeader->biBitCount; -} - -inline WORD AtlGetBitmapResourceBitsPerPixel(ATL::_U_STRINGorID image) -{ - return AtlGetBitmapResourceBitsPerPixel(ModuleHelper::GetResourceInstance(), image); -} - -/////////////////////////////////////////////////////////////////////////////// -// 32-bit (alpha channel) bitmap resource helper - -// Note: 32-bit (alpha channel) images work only on Windows XP with Common Controls version 6. -// If you want your app to work on older version of Windows, load non-alpha images if Common -// Controls version is less than 6. - -inline bool AtlIsAlphaBitmapResource(ATL::_U_STRINGorID image) -{ - return (AtlGetBitmapResourceBitsPerPixel(image) == 32); -} - - -/////////////////////////////////////////////////////////////////////////////// -// CPen - -template -class CPenT -{ -public: -// Data members - HPEN m_hPen; - -// Constructor/destructor/operators - CPenT(HPEN hPen = NULL) : m_hPen(hPen) - { } - - ~CPenT() - { - if(t_bManaged && m_hPen != NULL) - DeleteObject(); - } - - CPenT& operator =(HPEN hPen) - { - Attach(hPen); - return *this; - } - - void Attach(HPEN hPen) - { - if(t_bManaged && m_hPen != NULL && m_hPen != hPen) - ::DeleteObject(m_hPen); - m_hPen = hPen; - } - - HPEN Detach() - { - HPEN hPen = m_hPen; - m_hPen = NULL; - return hPen; - } - - operator HPEN() const { return m_hPen; } - - bool IsNull() const { return (m_hPen == NULL); } - -// Create methods - HPEN CreatePen(int nPenStyle, int nWidth, COLORREF crColor) - { - ATLASSERT(m_hPen == NULL); - m_hPen = ::CreatePen(nPenStyle, nWidth, crColor); - return m_hPen; - } - -#ifndef _WIN32_WCE - HPEN CreatePen(int nPenStyle, int nWidth, const LOGBRUSH* pLogBrush, int nStyleCount = 0, const DWORD* lpStyle = NULL) - { - ATLASSERT(m_hPen == NULL); - m_hPen = ::ExtCreatePen(nPenStyle, nWidth, pLogBrush, nStyleCount, lpStyle); - return m_hPen; - } -#endif // !_WIN32_WCE - - HPEN CreatePenIndirect(LPLOGPEN lpLogPen) - { - ATLASSERT(m_hPen == NULL); - m_hPen = ::CreatePenIndirect(lpLogPen); - return m_hPen; - } - - BOOL DeleteObject() - { - ATLASSERT(m_hPen != NULL); - BOOL bRet = ::DeleteObject(m_hPen); - if(bRet) - m_hPen = NULL; - return bRet; - } - -// Attributes - int GetLogPen(LOGPEN* pLogPen) const - { - ATLASSERT(m_hPen != NULL); - return ::GetObject(m_hPen, sizeof(LOGPEN), pLogPen); - } - - bool GetLogPen(LOGPEN& LogPen) const - { - ATLASSERT(m_hPen != NULL); - return (::GetObject(m_hPen, sizeof(LOGPEN), &LogPen) == sizeof(LOGPEN)); - } - -#ifndef _WIN32_WCE - int GetExtLogPen(EXTLOGPEN* pLogPen) const - { - ATLASSERT(m_hPen != NULL); - return ::GetObject(m_hPen, sizeof(EXTLOGPEN), pLogPen); - } - - bool GetExtLogPen(EXTLOGPEN& ExtLogPen) const - { - ATLASSERT(m_hPen != NULL); - return (::GetObject(m_hPen, sizeof(EXTLOGPEN), &ExtLogPen) == sizeof(EXTLOGPEN)); - } -#endif // !_WIN32_WCE -}; - -typedef CPenT CPenHandle; -typedef CPenT CPen; - - -/////////////////////////////////////////////////////////////////////////////// -// CBrush - -template -class CBrushT -{ -public: -// Data members - HBRUSH m_hBrush; - -// Constructor/destructor/operators - CBrushT(HBRUSH hBrush = NULL) : m_hBrush(hBrush) - { } - - ~CBrushT() - { - if(t_bManaged && m_hBrush != NULL) - DeleteObject(); - } - - CBrushT& operator =(HBRUSH hBrush) - { - Attach(hBrush); - return *this; - } - - void Attach(HBRUSH hBrush) - { - if(t_bManaged && m_hBrush != NULL && m_hBrush != hBrush) - ::DeleteObject(m_hBrush); - m_hBrush = hBrush; - } - - HBRUSH Detach() - { - HBRUSH hBrush = m_hBrush; - m_hBrush = NULL; - return hBrush; - } - - operator HBRUSH() const { return m_hBrush; } - - bool IsNull() const { return (m_hBrush == NULL); } - -// Create methods - HBRUSH CreateSolidBrush(COLORREF crColor) - { - ATLASSERT(m_hBrush == NULL); - m_hBrush = ::CreateSolidBrush(crColor); - return m_hBrush; - } - -#ifndef _WIN32_WCE - HBRUSH CreateHatchBrush(int nIndex, COLORREF crColor) - { - ATLASSERT(m_hBrush == NULL); - m_hBrush = ::CreateHatchBrush(nIndex, crColor); - return m_hBrush; - } -#endif // !_WIN32_WCE - -#if !defined(_WIN32_WCE) || (_ATL_VER >= 0x0800) - HBRUSH CreateBrushIndirect(const LOGBRUSH* lpLogBrush) - { - ATLASSERT(m_hBrush == NULL); -#ifndef _WIN32_WCE - m_hBrush = ::CreateBrushIndirect(lpLogBrush); -#else // CE specific - m_hBrush = ATL::CreateBrushIndirect(lpLogBrush); -#endif // _WIN32_WCE - return m_hBrush; - } -#endif // !defined(_WIN32_WCE) || (_ATL_VER >= 0x0800) - - HBRUSH CreatePatternBrush(HBITMAP hBitmap) - { - ATLASSERT(m_hBrush == NULL); - m_hBrush = ::CreatePatternBrush(hBitmap); - return m_hBrush; - } - - HBRUSH CreateDIBPatternBrush(HGLOBAL hPackedDIB, UINT nUsage) - { - ATLASSERT(hPackedDIB != NULL); - const void* lpPackedDIB = GlobalLock(hPackedDIB); - ATLASSERT(lpPackedDIB != NULL); - m_hBrush = ::CreateDIBPatternBrushPt(lpPackedDIB, nUsage); - GlobalUnlock(hPackedDIB); - return m_hBrush; - } - - HBRUSH CreateDIBPatternBrush(const void* lpPackedDIB, UINT nUsage) - { - ATLASSERT(m_hBrush == NULL); - m_hBrush = ::CreateDIBPatternBrushPt(lpPackedDIB, nUsage); - return m_hBrush; - } - - HBRUSH CreateSysColorBrush(int nIndex) - { - ATLASSERT(m_hBrush == NULL); - m_hBrush = ::GetSysColorBrush(nIndex); - return m_hBrush; - } - - BOOL DeleteObject() - { - ATLASSERT(m_hBrush != NULL); - BOOL bRet = ::DeleteObject(m_hBrush); - if(bRet) - m_hBrush = NULL; - return bRet; - } - -// Attributes - int GetLogBrush(LOGBRUSH* pLogBrush) const - { - ATLASSERT(m_hBrush != NULL); - return ::GetObject(m_hBrush, sizeof(LOGBRUSH), pLogBrush); - } - - bool GetLogBrush(LOGBRUSH& LogBrush) const - { - ATLASSERT(m_hBrush != NULL); - return (::GetObject(m_hBrush, sizeof(LOGBRUSH), &LogBrush) == sizeof(LOGBRUSH)); - } -}; - -typedef CBrushT CBrushHandle; -typedef CBrushT CBrush; - - -/////////////////////////////////////////////////////////////////////////////// -// CFont - -class CLogFont : public LOGFONT -{ -public: - CLogFont() - { - memset(this, 0, sizeof(LOGFONT)); - } - - CLogFont(const LOGFONT& lf) - { - Copy(&lf); - } - - CLogFont(HFONT hFont) - { - ATLASSERT(::GetObjectType(hFont) == OBJ_FONT); - ::GetObject(hFont, sizeof(LOGFONT), (LOGFONT*)this); - } - - HFONT CreateFontIndirect() - { - return ::CreateFontIndirect(this); - } - - void SetBold() - { - lfWeight = FW_BOLD; - } - - bool IsBold() const - { - return (lfWeight >= FW_BOLD); - } - - void MakeBolder(int iScale = 1) - { - lfWeight += FW_BOLD * iScale; - } - - void MakeLarger(int iScale) - { - if(lfHeight > 0) - lfHeight += iScale; - else - lfHeight -= iScale; - } - - void SetHeight(LONG nPointSize, HDC hDC = NULL) - { - // For MM_TEXT mapping mode - lfHeight = -::MulDiv(nPointSize, ::GetDeviceCaps(hDC, LOGPIXELSY), 72); - } - - LONG GetHeight(HDC hDC = NULL) const - { - // For MM_TEXT mapping mode - return ::MulDiv(-lfHeight, 72, ::GetDeviceCaps(hDC, LOGPIXELSY)); - } - - LONG GetDeciPointHeight(HDC hDC = NULL) const - { -#ifndef _WIN32_WCE - POINT ptOrg = { 0, 0 }; - ::DPtoLP(hDC, &ptOrg, 1); - POINT pt = { 0, 0 }; - pt.y = abs(lfHeight) + ptOrg.y; - ::LPtoDP(hDC,&pt,1); - return ::MulDiv(pt.y, 720, ::GetDeviceCaps(hDC, LOGPIXELSY)); // 72 points/inch, 10 decipoints/point -#else // CE specific - // DP and LP are always the same on CE - return ::MulDiv(abs(lfHeight), 720, ::GetDeviceCaps(hDC, LOGPIXELSY)); // 72 points/inch, 10 decipoints/point -#endif // _WIN32_WCE - } - - void SetHeightFromDeciPoint(LONG nDeciPtHeight, HDC hDC = NULL) - { -#ifndef _WIN32_WCE - POINT pt = { 0, 0 }; - pt.y = ::MulDiv(::GetDeviceCaps(hDC, LOGPIXELSY), nDeciPtHeight, 720); // 72 points/inch, 10 decipoints/point - ::DPtoLP(hDC, &pt, 1); - POINT ptOrg = { 0, 0 }; - ::DPtoLP(hDC, &ptOrg, 1); - lfHeight = -abs(pt.y - ptOrg.y); -#else // CE specific - // DP and LP are always the same on CE - lfHeight = -abs(::MulDiv(::GetDeviceCaps(hDC, LOGPIXELSY), nDeciPtHeight, 720)); // 72 points/inch, 10 decipoints/point -#endif // _WIN32_WCE - } - -#ifndef _WIN32_WCE - void SetCaptionFont() - { - NONCLIENTMETRICS ncm = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() }; - ATLVERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0)); - Copy(&ncm.lfCaptionFont); - } - - void SetMenuFont() - { - NONCLIENTMETRICS ncm = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() }; - ATLVERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0)); - Copy(&ncm.lfMenuFont); - } - - void SetStatusFont() - { - NONCLIENTMETRICS ncm = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() }; - ATLVERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0)); - Copy(&ncm.lfStatusFont); - } - - void SetMessageBoxFont() - { - NONCLIENTMETRICS ncm = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() }; - ATLVERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0)); - Copy(&ncm.lfMessageFont); - } -#endif // !_WIN32_WCE - - void Copy(const LOGFONT* pLogFont) - { - ATLASSERT(pLogFont != NULL); - *(LOGFONT*)this = *pLogFont; - } - - CLogFont& operator =(const CLogFont& src) - { - Copy(&src); - return *this; - } - - CLogFont& operator =(const LOGFONT& src) - { - Copy(&src); - return *this; - } - - CLogFont& operator =(HFONT hFont) - { - ATLASSERT(::GetObjectType(hFont) == OBJ_FONT); - ::GetObject(hFont, sizeof(LOGFONT), (LOGFONT*)this); - return *this; - } - - bool operator ==(const LOGFONT& logfont) const - { - return(logfont.lfHeight == lfHeight && - logfont.lfWidth == lfWidth && - logfont.lfEscapement == lfEscapement && - logfont.lfOrientation == lfOrientation && - logfont.lfWeight == lfWeight && - logfont.lfItalic == lfItalic && - logfont.lfUnderline == lfUnderline && - logfont.lfStrikeOut == lfStrikeOut && - logfont.lfCharSet == lfCharSet && - logfont.lfOutPrecision == lfOutPrecision && - logfont.lfClipPrecision == lfClipPrecision && - logfont.lfQuality == lfQuality && - logfont.lfPitchAndFamily == lfPitchAndFamily && - lstrcmp(logfont.lfFaceName, lfFaceName) == 0); - } -}; - - -template -class CFontT -{ -public: -// Data members - HFONT m_hFont; - -// Constructor/destructor/operators - CFontT(HFONT hFont = NULL) : m_hFont(hFont) - { } - - ~CFontT() - { - if(t_bManaged && m_hFont != NULL) - DeleteObject(); - } - - CFontT& operator =(HFONT hFont) - { - Attach(hFont); - return *this; - } - - void Attach(HFONT hFont) - { - if(t_bManaged && m_hFont != NULL && m_hFont != hFont) - ::DeleteObject(m_hFont); - m_hFont = hFont; - } - - HFONT Detach() - { - HFONT hFont = m_hFont; - m_hFont = NULL; - return hFont; - } - - operator HFONT() const { return m_hFont; } - - bool IsNull() const { return (m_hFont == NULL); } - -// Create methods - HFONT CreateFontIndirect(const LOGFONT* lpLogFont) - { - ATLASSERT(m_hFont == NULL); - m_hFont = ::CreateFontIndirect(lpLogFont); - return m_hFont; - } - -#if !defined(_WIN32_WCE) && (_WIN32_WINNT >= 0x0500) - HFONT CreateFontIndirectEx(CONST ENUMLOGFONTEXDV* penumlfex) - { - ATLASSERT(m_hFont == NULL); - m_hFont = ::CreateFontIndirectEx(penumlfex); - return m_hFont; - } -#endif // !defined(_WIN32_WCE) && (_WIN32_WINNT >= 0x0500) - -#if !defined(_WIN32_WCE) || (_ATL_VER >= 0x0800) - HFONT CreateFont(int nHeight, int nWidth, int nEscapement, - int nOrientation, int nWeight, BYTE bItalic, BYTE bUnderline, - BYTE cStrikeOut, BYTE nCharSet, BYTE nOutPrecision, - BYTE nClipPrecision, BYTE nQuality, BYTE nPitchAndFamily, - LPCTSTR lpszFacename) - { - ATLASSERT(m_hFont == NULL); -#ifndef _WIN32_WCE - m_hFont = ::CreateFont(nHeight, nWidth, nEscapement, - nOrientation, nWeight, bItalic, bUnderline, cStrikeOut, - nCharSet, nOutPrecision, nClipPrecision, nQuality, - nPitchAndFamily, lpszFacename); -#else // CE specific - m_hFont = ATL::CreateFont(nHeight, nWidth, nEscapement, - nOrientation, nWeight, bItalic, bUnderline, cStrikeOut, - nCharSet, nOutPrecision, nClipPrecision, nQuality, - nPitchAndFamily, lpszFacename); -#endif // _WIN32_WCE - return m_hFont; - } -#endif // !defined(_WIN32_WCE) || (_ATL_VER >= 0x0800) - - HFONT CreatePointFont(int nPointSize, LPCTSTR lpszFaceName, HDC hDC = NULL, bool bBold = false, bool bItalic = false) - { - LOGFONT logFont = { 0 }; - logFont.lfCharSet = DEFAULT_CHARSET; - logFont.lfHeight = nPointSize; - SecureHelper::strncpy_x(logFont.lfFaceName, _countof(logFont.lfFaceName), lpszFaceName, _TRUNCATE); - - if(bBold) - logFont.lfWeight = FW_BOLD; - if(bItalic) - logFont.lfItalic = (BYTE)TRUE; - - return CreatePointFontIndirect(&logFont, hDC); - } - - HFONT CreatePointFontIndirect(const LOGFONT* lpLogFont, HDC hDC = NULL) - { - HDC hDC1 = (hDC != NULL) ? hDC : ::GetDC(NULL); - - // convert nPointSize to logical units based on hDC - LOGFONT logFont = *lpLogFont; -#ifndef _WIN32_WCE - POINT pt = { 0, 0 }; - pt.y = ::MulDiv(::GetDeviceCaps(hDC1, LOGPIXELSY), logFont.lfHeight, 720); // 72 points/inch, 10 decipoints/point - ::DPtoLP(hDC1, &pt, 1); - POINT ptOrg = { 0, 0 }; - ::DPtoLP(hDC1, &ptOrg, 1); - logFont.lfHeight = -abs(pt.y - ptOrg.y); -#else // CE specific - // DP and LP are always the same on CE - logFont.lfHeight = -abs(::MulDiv(::GetDeviceCaps(hDC1, LOGPIXELSY), logFont.lfHeight, 720)); // 72 points/inch, 10 decipoints/point -#endif // _WIN32_WCE - - if(hDC == NULL) - ::ReleaseDC(NULL, hDC1); - - return CreateFontIndirect(&logFont); - } - - BOOL DeleteObject() - { - ATLASSERT(m_hFont != NULL); - BOOL bRet = ::DeleteObject(m_hFont); - if(bRet) - m_hFont = NULL; - return bRet; - } - -// Attributes - int GetLogFont(LOGFONT* pLogFont) const - { - ATLASSERT(m_hFont != NULL); - return ::GetObject(m_hFont, sizeof(LOGFONT), pLogFont); - } - - bool GetLogFont(LOGFONT& LogFont) const - { - ATLASSERT(m_hFont != NULL); - return (::GetObject(m_hFont, sizeof(LOGFONT), &LogFont) == sizeof(LOGFONT)); - } -}; - -typedef CFontT CFontHandle; -typedef CFontT CFont; - - -/////////////////////////////////////////////////////////////////////////////// -// CBitmap - -template -class CBitmapT -{ -public: -// Data members - HBITMAP m_hBitmap; - -// Constructor/destructor/operators - CBitmapT(HBITMAP hBitmap = NULL) : m_hBitmap(hBitmap) - { } - - ~CBitmapT() - { - if(t_bManaged && m_hBitmap != NULL) - DeleteObject(); - } - - CBitmapT& operator =(HBITMAP hBitmap) - { - Attach(hBitmap); - return *this; - } - - void Attach(HBITMAP hBitmap) - { - if(t_bManaged && m_hBitmap != NULL&& m_hBitmap != hBitmap) - ::DeleteObject(m_hBitmap); - m_hBitmap = hBitmap; - } - - HBITMAP Detach() - { - HBITMAP hBitmap = m_hBitmap; - m_hBitmap = NULL; - return hBitmap; - } - - operator HBITMAP() const { return m_hBitmap; } - - bool IsNull() const { return (m_hBitmap == NULL); } - -// Create and load methods - HBITMAP LoadBitmap(ATL::_U_STRINGorID bitmap) - { - ATLASSERT(m_hBitmap == NULL); - m_hBitmap = ::LoadBitmap(ModuleHelper::GetResourceInstance(), bitmap.m_lpstr); - return m_hBitmap; - } - - HBITMAP LoadOEMBitmap(UINT nIDBitmap) // for OBM_/OCR_/OIC_ - { - ATLASSERT(m_hBitmap == NULL); - m_hBitmap = ::LoadBitmap(NULL, MAKEINTRESOURCE(nIDBitmap)); - return m_hBitmap; - } - -#ifndef _WIN32_WCE - HBITMAP LoadMappedBitmap(UINT nIDBitmap, UINT nFlags = 0, LPCOLORMAP lpColorMap = NULL, int nMapSize = 0) - { - ATLASSERT(m_hBitmap == NULL); - m_hBitmap = ::CreateMappedBitmap(ModuleHelper::GetResourceInstance(), nIDBitmap, (WORD)nFlags, lpColorMap, nMapSize); - return m_hBitmap; - } -#endif // !_WIN32_WCE - - HBITMAP CreateBitmap(int nWidth, int nHeight, UINT nPlanes, UINT nBitsPerPixel, const void* lpBits) - { - ATLASSERT(m_hBitmap == NULL); - m_hBitmap = ::CreateBitmap(nWidth, nHeight, nPlanes, nBitsPerPixel, lpBits); - return m_hBitmap; - } - -#ifndef _WIN32_WCE - HBITMAP CreateBitmapIndirect(LPBITMAP lpBitmap) - { - ATLASSERT(m_hBitmap == NULL); - m_hBitmap = ::CreateBitmapIndirect(lpBitmap); - return m_hBitmap; - } -#endif // !_WIN32_WCE - - HBITMAP CreateCompatibleBitmap(HDC hDC, int nWidth, int nHeight) - { - ATLASSERT(m_hBitmap == NULL); - m_hBitmap = ::CreateCompatibleBitmap(hDC, nWidth, nHeight); - return m_hBitmap; - } - -#ifndef _WIN32_WCE - HBITMAP CreateDiscardableBitmap(HDC hDC, int nWidth, int nHeight) - { - ATLASSERT(m_hBitmap == NULL); - m_hBitmap = ::CreateDiscardableBitmap(hDC, nWidth, nHeight); - return m_hBitmap; - } -#endif // !_WIN32_WCE - - BOOL DeleteObject() - { - ATLASSERT(m_hBitmap != NULL); - BOOL bRet = ::DeleteObject(m_hBitmap); - if(bRet) - m_hBitmap = NULL; - return bRet; - } - -// Attributes - int GetBitmap(BITMAP* pBitMap) const - { - ATLASSERT(m_hBitmap != NULL); - return ::GetObject(m_hBitmap, sizeof(BITMAP), pBitMap); - } - - bool GetBitmap(BITMAP& bm) const - { - ATLASSERT(m_hBitmap != NULL); - return (::GetObject(m_hBitmap, sizeof(BITMAP), &bm) == sizeof(BITMAP)); - } - - bool GetSize(SIZE& size) const - { - ATLASSERT(m_hBitmap != NULL); - BITMAP bm = { 0 }; - if(!GetBitmap(&bm)) - return false; - size.cx = bm.bmWidth; - size.cy = bm.bmHeight; - return true; - } - -#ifndef _WIN32_WCE - DWORD GetBitmapBits(DWORD dwCount, LPVOID lpBits) const - { - ATLASSERT(m_hBitmap != NULL); - return ::GetBitmapBits(m_hBitmap, dwCount, lpBits); - } -#endif // !_WIN32_WCE - -#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 410) - DWORD SetBitmapBits(DWORD dwCount, const void* lpBits) - { - ATLASSERT(m_hBitmap != NULL); - return ::SetBitmapBits(m_hBitmap, dwCount, lpBits); - } -#endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 410) - -#ifndef _WIN32_WCE - BOOL GetBitmapDimension(LPSIZE lpSize) const - { - ATLASSERT(m_hBitmap != NULL); - return ::GetBitmapDimensionEx(m_hBitmap, lpSize); - } - - BOOL SetBitmapDimension(int nWidth, int nHeight, LPSIZE lpSize = NULL) - { - ATLASSERT(m_hBitmap != NULL); - return ::SetBitmapDimensionEx(m_hBitmap, nWidth, nHeight, lpSize); - } - -// DIB support - HBITMAP CreateDIBitmap(HDC hDC, CONST BITMAPINFOHEADER* lpbmih, DWORD dwInit, CONST VOID* lpbInit, CONST BITMAPINFO* lpbmi, UINT uColorUse) - { - ATLASSERT(m_hBitmap == NULL); - m_hBitmap = ::CreateDIBitmap(hDC, lpbmih, dwInit, lpbInit, lpbmi, uColorUse); - return m_hBitmap; - } -#endif // !_WIN32_WCE - - HBITMAP CreateDIBSection(HDC hDC, CONST BITMAPINFO* lpbmi, UINT uColorUse, VOID** ppvBits, HANDLE hSection, DWORD dwOffset) - { - ATLASSERT(m_hBitmap == NULL); - m_hBitmap = ::CreateDIBSection(hDC, lpbmi, uColorUse, ppvBits, hSection, dwOffset); - return m_hBitmap; - } - -#ifndef _WIN32_WCE - int GetDIBits(HDC hDC, UINT uStartScan, UINT cScanLines, LPVOID lpvBits, LPBITMAPINFO lpbmi, UINT uColorUse) const - { - ATLASSERT(m_hBitmap != NULL); - return ::GetDIBits(hDC, m_hBitmap, uStartScan, cScanLines, lpvBits, lpbmi, uColorUse); - } - - int SetDIBits(HDC hDC, UINT uStartScan, UINT cScanLines, CONST VOID* lpvBits, CONST BITMAPINFO* lpbmi, UINT uColorUse) - { - ATLASSERT(m_hBitmap != NULL); - return ::SetDIBits(hDC, m_hBitmap, uStartScan, cScanLines, lpvBits, lpbmi, uColorUse); - } -#endif // !_WIN32_WCE -}; - -typedef CBitmapT CBitmapHandle; -typedef CBitmapT CBitmap; - - -/////////////////////////////////////////////////////////////////////////////// -// CPalette - -template -class CPaletteT -{ -public: -// Data members - HPALETTE m_hPalette; - -// Constructor/destructor/operators - CPaletteT(HPALETTE hPalette = NULL) : m_hPalette(hPalette) - { } - - ~CPaletteT() - { - if(t_bManaged && m_hPalette != NULL) - DeleteObject(); - } - - CPaletteT& operator =(HPALETTE hPalette) - { - Attach(hPalette); - return *this; - } - - void Attach(HPALETTE hPalette) - { - if(t_bManaged && m_hPalette != NULL && m_hPalette != hPalette) - ::DeleteObject(m_hPalette); - m_hPalette = hPalette; - } - - HPALETTE Detach() - { - HPALETTE hPalette = m_hPalette; - m_hPalette = NULL; - return hPalette; - } - - operator HPALETTE() const { return m_hPalette; } - - bool IsNull() const { return (m_hPalette == NULL); } - -// Create methods - HPALETTE CreatePalette(LPLOGPALETTE lpLogPalette) - { - ATLASSERT(m_hPalette == NULL); - m_hPalette = ::CreatePalette(lpLogPalette); - return m_hPalette; - } - -#ifndef _WIN32_WCE - HPALETTE CreateHalftonePalette(HDC hDC) - { - ATLASSERT(m_hPalette == NULL); - ATLASSERT(hDC != NULL); - m_hPalette = ::CreateHalftonePalette(hDC); - return m_hPalette; - } -#endif // !_WIN32_WCE - - BOOL DeleteObject() - { - ATLASSERT(m_hPalette != NULL); - BOOL bRet = ::DeleteObject(m_hPalette); - if(bRet) - m_hPalette = NULL; - return bRet; - } - -// Attributes - int GetEntryCount() const - { - ATLASSERT(m_hPalette != NULL); - WORD nEntries = 0; - ::GetObject(m_hPalette, sizeof(WORD), &nEntries); - return (int)nEntries; - } - - UINT GetPaletteEntries(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors) const - { - ATLASSERT(m_hPalette != NULL); - return ::GetPaletteEntries(m_hPalette, nStartIndex, nNumEntries, lpPaletteColors); - } - - UINT SetPaletteEntries(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors) - { - ATLASSERT(m_hPalette != NULL); - return ::SetPaletteEntries(m_hPalette, nStartIndex, nNumEntries, lpPaletteColors); - } - -// Operations -#ifndef _WIN32_WCE - void AnimatePalette(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors) - { - ATLASSERT(m_hPalette != NULL); - ::AnimatePalette(m_hPalette, nStartIndex, nNumEntries, lpPaletteColors); - } - - BOOL ResizePalette(UINT nNumEntries) - { - ATLASSERT(m_hPalette != NULL); - return ::ResizePalette(m_hPalette, nNumEntries); - } -#endif // !_WIN32_WCE - - UINT GetNearestPaletteIndex(COLORREF crColor) const - { - ATLASSERT(m_hPalette != NULL); - return ::GetNearestPaletteIndex(m_hPalette, crColor); - } -}; - -typedef CPaletteT CPaletteHandle; -typedef CPaletteT CPalette; - - -/////////////////////////////////////////////////////////////////////////////// -// CRgn - -template -class CRgnT -{ -public: -// Data members - HRGN m_hRgn; - -// Constructor/destructor/operators - CRgnT(HRGN hRgn = NULL) : m_hRgn(hRgn) - { } - - ~CRgnT() - { - if(t_bManaged && m_hRgn != NULL) - DeleteObject(); - } - - CRgnT& operator =(HRGN hRgn) - { - Attach(hRgn); - return *this; - } - - void Attach(HRGN hRgn) - { - if(t_bManaged && m_hRgn != NULL && m_hRgn != hRgn) - ::DeleteObject(m_hRgn); - m_hRgn = hRgn; - } - - HRGN Detach() - { - HRGN hRgn = m_hRgn; - m_hRgn = NULL; - return hRgn; - } - - operator HRGN() const { return m_hRgn; } - - bool IsNull() const { return (m_hRgn == NULL); } - -// Create methods - HRGN CreateRectRgn(int x1, int y1, int x2, int y2) - { - ATLASSERT(m_hRgn == NULL); - m_hRgn = ::CreateRectRgn(x1, y1, x2, y2); - return m_hRgn; - } - - HRGN CreateRectRgnIndirect(LPCRECT lpRect) - { - ATLASSERT(m_hRgn == NULL); - m_hRgn = ::CreateRectRgnIndirect(lpRect); - return m_hRgn; - } - -#ifndef _WIN32_WCE - HRGN CreateEllipticRgn(int x1, int y1, int x2, int y2) - { - ATLASSERT(m_hRgn == NULL); - m_hRgn = ::CreateEllipticRgn(x1, y1, x2, y2); - return m_hRgn; - } - - HRGN CreateEllipticRgnIndirect(LPCRECT lpRect) - { - ATLASSERT(m_hRgn == NULL); - m_hRgn = ::CreateEllipticRgnIndirect(lpRect); - return m_hRgn; - } - - HRGN CreatePolygonRgn(LPPOINT lpPoints, int nCount, int nMode) - { - ATLASSERT(m_hRgn == NULL); - m_hRgn = ::CreatePolygonRgn(lpPoints, nCount, nMode); - return m_hRgn; - } - - HRGN CreatePolyPolygonRgn(LPPOINT lpPoints, LPINT lpPolyCounts, int nCount, int nPolyFillMode) - { - ATLASSERT(m_hRgn == NULL); - m_hRgn = ::CreatePolyPolygonRgn(lpPoints, lpPolyCounts, nCount, nPolyFillMode); - return m_hRgn; - } - - HRGN CreateRoundRectRgn(int x1, int y1, int x2, int y2, int x3, int y3) - { - ATLASSERT(m_hRgn == NULL); - m_hRgn = ::CreateRoundRectRgn(x1, y1, x2, y2, x3, y3); - return m_hRgn; - } - - HRGN CreateFromPath(HDC hDC) - { - ATLASSERT(m_hRgn == NULL); - ATLASSERT(hDC != NULL); - m_hRgn = ::PathToRegion(hDC); - return m_hRgn; - } - - HRGN CreateFromData(const XFORM* lpXForm, int nCount, const RGNDATA* pRgnData) - { - ATLASSERT(m_hRgn == NULL); - m_hRgn = ::ExtCreateRegion(lpXForm, nCount, pRgnData); - return m_hRgn; - } -#endif // !_WIN32_WCE - - BOOL DeleteObject() - { - ATLASSERT(m_hRgn != NULL); - BOOL bRet = ::DeleteObject(m_hRgn); - if(bRet) - m_hRgn = NULL; - return bRet; - } - -// Operations - void SetRectRgn(int x1, int y1, int x2, int y2) - { - ATLASSERT(m_hRgn != NULL); - ::SetRectRgn(m_hRgn, x1, y1, x2, y2); - } - - void SetRectRgn(LPCRECT lpRect) - { - ATLASSERT(m_hRgn != NULL); - ::SetRectRgn(m_hRgn, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); - } - - int CombineRgn(HRGN hRgnSrc1, HRGN hRgnSrc2, int nCombineMode) - { - ATLASSERT(m_hRgn != NULL); - return ::CombineRgn(m_hRgn, hRgnSrc1, hRgnSrc2, nCombineMode); - } - - int CombineRgn(HRGN hRgnSrc, int nCombineMode) - { - ATLASSERT(m_hRgn != NULL); - return ::CombineRgn(m_hRgn, m_hRgn, hRgnSrc, nCombineMode); - } - - int CopyRgn(HRGN hRgnSrc) - { - ATLASSERT(m_hRgn != NULL); - return ::CombineRgn(m_hRgn, hRgnSrc, NULL, RGN_COPY); - } - - BOOL EqualRgn(HRGN hRgn) const - { - ATLASSERT(m_hRgn != NULL); - return ::EqualRgn(m_hRgn, hRgn); - } - - int OffsetRgn(int x, int y) - { - ATLASSERT(m_hRgn != NULL); - return ::OffsetRgn(m_hRgn, x, y); - } - - int OffsetRgn(POINT point) - { - ATLASSERT(m_hRgn != NULL); - return ::OffsetRgn(m_hRgn, point.x, point.y); - } - - int GetRgnBox(LPRECT lpRect) const - { - ATLASSERT(m_hRgn != NULL); - return ::GetRgnBox(m_hRgn, lpRect); - } - - BOOL PtInRegion(int x, int y) const - { - ATLASSERT(m_hRgn != NULL); - return ::PtInRegion(m_hRgn, x, y); - } - - BOOL PtInRegion(POINT point) const - { - ATLASSERT(m_hRgn != NULL); - return ::PtInRegion(m_hRgn, point.x, point.y); - } - - BOOL RectInRegion(LPCRECT lpRect) const - { - ATLASSERT(m_hRgn != NULL); - return ::RectInRegion(m_hRgn, lpRect); - } - - int GetRegionData(LPRGNDATA lpRgnData, int nDataSize) const - { - ATLASSERT(m_hRgn != NULL); - return (int)::GetRegionData(m_hRgn, nDataSize, lpRgnData); - } -}; - -typedef CRgnT CRgnHandle; -typedef CRgnT CRgn; - - -/////////////////////////////////////////////////////////////////////////////// -// CDC - The device context class - -template -class CDCT -{ -public: -// Data members - HDC m_hDC; - -// Constructor/destructor/operators - CDCT(HDC hDC = NULL) : m_hDC(hDC) - { - } - - ~CDCT() - { - if(t_bManaged && m_hDC != NULL) - ::DeleteDC(Detach()); - } - - CDCT& operator =(HDC hDC) - { - Attach(hDC); - return *this; - } - - void Attach(HDC hDC) - { - if(t_bManaged && m_hDC != NULL && m_hDC != hDC) - ::DeleteDC(m_hDC); - m_hDC = hDC; - } - - HDC Detach() - { - HDC hDC = m_hDC; - m_hDC = NULL; - return hDC; - } - - operator HDC() const { return m_hDC; } - - bool IsNull() const { return (m_hDC == NULL); } - -// Operations -#ifndef _WIN32_WCE - HWND WindowFromDC() const - { - ATLASSERT(m_hDC != NULL); - return ::WindowFromDC(m_hDC); - } -#endif // !_WIN32_WCE - - CPenHandle GetCurrentPen() const - { - ATLASSERT(m_hDC != NULL); - return CPenHandle((HPEN)::GetCurrentObject(m_hDC, OBJ_PEN)); - } - - CBrushHandle GetCurrentBrush() const - { - ATLASSERT(m_hDC != NULL); - return CBrushHandle((HBRUSH)::GetCurrentObject(m_hDC, OBJ_BRUSH)); - } - - CPaletteHandle GetCurrentPalette() const - { - ATLASSERT(m_hDC != NULL); - return CPaletteHandle((HPALETTE)::GetCurrentObject(m_hDC, OBJ_PAL)); - } - - CFontHandle GetCurrentFont() const - { - ATLASSERT(m_hDC != NULL); - return CFontHandle((HFONT)::GetCurrentObject(m_hDC, OBJ_FONT)); - } - - CBitmapHandle GetCurrentBitmap() const - { - ATLASSERT(m_hDC != NULL); - return CBitmapHandle((HBITMAP)::GetCurrentObject(m_hDC, OBJ_BITMAP)); - } - - HDC CreateDC(LPCTSTR lpszDriverName, LPCTSTR lpszDeviceName, LPCTSTR lpszOutput, const DEVMODE* lpInitData) - { - ATLASSERT(m_hDC == NULL); - m_hDC = ::CreateDC(lpszDriverName, lpszDeviceName, lpszOutput, lpInitData); - return m_hDC; - } - - HDC CreateCompatibleDC(HDC hDC = NULL) - { - ATLASSERT(m_hDC == NULL); - m_hDC = ::CreateCompatibleDC(hDC); - return m_hDC; - } - - BOOL DeleteDC() - { - if(m_hDC == NULL) - return FALSE; - BOOL bRet = ::DeleteDC(m_hDC); - if(bRet) - m_hDC = NULL; - return bRet; - } - -// Device-Context Functions - int SaveDC() - { - ATLASSERT(m_hDC != NULL); - return ::SaveDC(m_hDC); - } - - BOOL RestoreDC(int nSavedDC) - { - ATLASSERT(m_hDC != NULL); - return ::RestoreDC(m_hDC, nSavedDC); - } - - int GetDeviceCaps(int nIndex) const - { - ATLASSERT(m_hDC != NULL); - return ::GetDeviceCaps(m_hDC, nIndex); - } - -#ifndef _WIN32_WCE - UINT SetBoundsRect(LPCRECT lpRectBounds, UINT flags) - { - ATLASSERT(m_hDC != NULL); - return ::SetBoundsRect(m_hDC, lpRectBounds, flags); - } - - UINT GetBoundsRect(LPRECT lpRectBounds, UINT flags) const - { - ATLASSERT(m_hDC != NULL); - return ::GetBoundsRect(m_hDC, lpRectBounds, flags); - } - - BOOL ResetDC(const DEVMODE* lpDevMode) - { - ATLASSERT(m_hDC != NULL); - return ::ResetDC(m_hDC, lpDevMode) != NULL; - } - -// Drawing-Tool Functions - BOOL GetBrushOrg(LPPOINT lpPoint) const - { - ATLASSERT(m_hDC != NULL); - return ::GetBrushOrgEx(m_hDC, lpPoint); - } -#endif // !_WIN32_WCE - - BOOL SetBrushOrg(int x, int y, LPPOINT lpPoint = NULL) - { - ATLASSERT(m_hDC != NULL); - return ::SetBrushOrgEx(m_hDC, x, y, lpPoint); - } - - BOOL SetBrushOrg(POINT point, LPPOINT lpPointRet = NULL) - { - ATLASSERT(m_hDC != NULL); - return ::SetBrushOrgEx(m_hDC, point.x, point.y, lpPointRet); - } - -#ifndef _WIN32_WCE - int EnumObjects(int nObjectType, int (CALLBACK* lpfn)(LPVOID, LPARAM), LPARAM lpData) - { - ATLASSERT(m_hDC != NULL); -#ifdef STRICT - return ::EnumObjects(m_hDC, nObjectType, (GOBJENUMPROC)lpfn, lpData); -#else - return ::EnumObjects(m_hDC, nObjectType, (GOBJENUMPROC)lpfn, (LPVOID)lpData); -#endif - } -#endif // !_WIN32_WCE - -// Type-safe selection helpers - HPEN SelectPen(HPEN hPen) - { - ATLASSERT(m_hDC != NULL); -#ifndef _WIN32_WCE - ATLASSERT(hPen == NULL || ::GetObjectType(hPen) == OBJ_PEN || ::GetObjectType(hPen) == OBJ_EXTPEN); -#else // CE specific - ATLASSERT(hPen == NULL || ::GetObjectType(hPen) == OBJ_PEN); -#endif // _WIN32_WCE - return (HPEN)::SelectObject(m_hDC, hPen); - } - - HBRUSH SelectBrush(HBRUSH hBrush) - { - ATLASSERT(m_hDC != NULL); - ATLASSERT(hBrush == NULL || ::GetObjectType(hBrush) == OBJ_BRUSH); - return (HBRUSH)::SelectObject(m_hDC, hBrush); - } - - HFONT SelectFont(HFONT hFont) - { - ATLASSERT(m_hDC != NULL); - ATLASSERT(hFont == NULL || ::GetObjectType(hFont) == OBJ_FONT); - return (HFONT)::SelectObject(m_hDC, hFont); - } - - HBITMAP SelectBitmap(HBITMAP hBitmap) - { - ATLASSERT(m_hDC != NULL); - ATLASSERT(hBitmap == NULL || ::GetObjectType(hBitmap) == OBJ_BITMAP); - return (HBITMAP)::SelectObject(m_hDC, hBitmap); - } - - int SelectRgn(HRGN hRgn) // special return for regions - { - ATLASSERT(m_hDC != NULL); - ATLASSERT(hRgn == NULL || ::GetObjectType(hRgn) == OBJ_REGION); - return PtrToInt(::SelectObject(m_hDC, hRgn)); - } - -// Type-safe selection helpers for stock objects - HPEN SelectStockPen(int nPen) - { - ATLASSERT(m_hDC != NULL); -#if (_WIN32_WINNT >= 0x0500) - ATLASSERT(nPen == WHITE_PEN || nPen == BLACK_PEN || nPen == NULL_PEN || nPen == DC_PEN); -#else - ATLASSERT(nPen == WHITE_PEN || nPen == BLACK_PEN || nPen == NULL_PEN); -#endif // !(_WIN32_WINNT >= 0x0500) - return SelectPen((HPEN)::GetStockObject(nPen)); - } - - HBRUSH SelectStockBrush(int nBrush) - { -#if (_WIN32_WINNT >= 0x0500) - ATLASSERT((nBrush >= WHITE_BRUSH && nBrush <= HOLLOW_BRUSH) || nBrush == DC_BRUSH); -#else - ATLASSERT(nBrush >= WHITE_BRUSH && nBrush <= HOLLOW_BRUSH); -#endif // !(_WIN32_WINNT >= 0x0500) - return SelectBrush((HBRUSH)::GetStockObject(nBrush)); - } - - HFONT SelectStockFont(int nFont) - { -#ifndef _WIN32_WCE - ATLASSERT((nFont >= OEM_FIXED_FONT && nFont <= SYSTEM_FIXED_FONT) || nFont == DEFAULT_GUI_FONT); -#else // CE specific - ATLASSERT(nFont == SYSTEM_FONT); -#endif // _WIN32_WCE - return SelectFont((HFONT)::GetStockObject(nFont)); - } - - HPALETTE SelectStockPalette(int nPalette, BOOL bForceBackground) - { - ATLASSERT(nPalette == DEFAULT_PALETTE); // the only one supported - return SelectPalette((HPALETTE)::GetStockObject(nPalette), bForceBackground); - } - -// Color and Color Palette Functions - COLORREF GetNearestColor(COLORREF crColor) const - { - ATLASSERT(m_hDC != NULL); - return ::GetNearestColor(m_hDC, crColor); - } - - HPALETTE SelectPalette(HPALETTE hPalette, BOOL bForceBackground) - { - ATLASSERT(m_hDC != NULL); - - return ::SelectPalette(m_hDC, hPalette, bForceBackground); - } - - UINT RealizePalette() - { - ATLASSERT(m_hDC != NULL); - return ::RealizePalette(m_hDC); - } - -#ifndef _WIN32_WCE - void UpdateColors() - { - ATLASSERT(m_hDC != NULL); - ::UpdateColors(m_hDC); - } -#endif // !_WIN32_WCE - -// Drawing-Attribute Functions - COLORREF GetBkColor() const - { - ATLASSERT(m_hDC != NULL); - return ::GetBkColor(m_hDC); - } - - int GetBkMode() const - { - ATLASSERT(m_hDC != NULL); - return ::GetBkMode(m_hDC); - } - -#ifndef _WIN32_WCE - int GetPolyFillMode() const - { - ATLASSERT(m_hDC != NULL); - return ::GetPolyFillMode(m_hDC); - } - - int GetROP2() const - { - ATLASSERT(m_hDC != NULL); - return ::GetROP2(m_hDC); - } - - int GetStretchBltMode() const - { - ATLASSERT(m_hDC != NULL); - return ::GetStretchBltMode(m_hDC); - } -#endif // !_WIN32_WCE - - COLORREF GetTextColor() const - { - ATLASSERT(m_hDC != NULL); - return ::GetTextColor(m_hDC); - } - - COLORREF SetBkColor(COLORREF crColor) - { - ATLASSERT(m_hDC != NULL); - return ::SetBkColor(m_hDC, crColor); - } - - int SetBkMode(int nBkMode) - { - ATLASSERT(m_hDC != NULL); - return ::SetBkMode(m_hDC, nBkMode); - } - -#ifndef _WIN32_WCE - int SetPolyFillMode(int nPolyFillMode) - { - ATLASSERT(m_hDC != NULL); - return ::SetPolyFillMode(m_hDC, nPolyFillMode); - } -#endif // !_WIN32_WCE - - int SetROP2(int nDrawMode) - { - ATLASSERT(m_hDC != NULL); - return ::SetROP2(m_hDC, nDrawMode); - } - -#ifndef _WIN32_WCE - int SetStretchBltMode(int nStretchMode) - { - ATLASSERT(m_hDC != NULL); - return ::SetStretchBltMode(m_hDC, nStretchMode); - } -#endif // !_WIN32_WCE - - COLORREF SetTextColor(COLORREF crColor) - { - ATLASSERT(m_hDC != NULL); - return ::SetTextColor(m_hDC, crColor); - } - -#ifndef _WIN32_WCE - BOOL GetColorAdjustment(LPCOLORADJUSTMENT lpColorAdjust) const - { - ATLASSERT(m_hDC != NULL); - return ::GetColorAdjustment(m_hDC, lpColorAdjust); - } - - BOOL SetColorAdjustment(const COLORADJUSTMENT* lpColorAdjust) - { - ATLASSERT(m_hDC != NULL); - return ::SetColorAdjustment(m_hDC, lpColorAdjust); - } - -// Mapping Functions - int GetMapMode() const - { - ATLASSERT(m_hDC != NULL); - return ::GetMapMode(m_hDC); - } - - BOOL GetViewportOrg(LPPOINT lpPoint) const - { - ATLASSERT(m_hDC != NULL); - return ::GetViewportOrgEx(m_hDC, lpPoint); - } - - int SetMapMode(int nMapMode) - { - ATLASSERT(m_hDC != NULL); - return ::SetMapMode(m_hDC, nMapMode); - } -#endif // !_WIN32_WCE - - // Viewport Origin - BOOL SetViewportOrg(int x, int y, LPPOINT lpPoint = NULL) - { - ATLASSERT(m_hDC != NULL); - return ::SetViewportOrgEx(m_hDC, x, y, lpPoint); - } - - BOOL SetViewportOrg(POINT point, LPPOINT lpPointRet = NULL) - { - ATLASSERT(m_hDC != NULL); - return SetViewportOrg(point.x, point.y, lpPointRet); - } - -#ifndef _WIN32_WCE - BOOL OffsetViewportOrg(int nWidth, int nHeight, LPPOINT lpPoint = NULL) - { - ATLASSERT(m_hDC != NULL); - return ::OffsetViewportOrgEx(m_hDC, nWidth, nHeight, lpPoint); - } - - // Viewport Extent - BOOL GetViewportExt(LPSIZE lpSize) const - { - ATLASSERT(m_hDC != NULL); - return ::GetViewportExtEx(m_hDC, lpSize); - } - - BOOL SetViewportExt(int x, int y, LPSIZE lpSize = NULL) - { - ATLASSERT(m_hDC != NULL); - return ::SetViewportExtEx(m_hDC, x, y, lpSize); - } - - BOOL SetViewportExt(SIZE size, LPSIZE lpSizeRet = NULL) - { - ATLASSERT(m_hDC != NULL); - return SetViewportExt(size.cx, size.cy, lpSizeRet); - } - - BOOL ScaleViewportExt(int xNum, int xDenom, int yNum, int yDenom, LPSIZE lpSize = NULL) - { - ATLASSERT(m_hDC != NULL); - return ::ScaleViewportExtEx(m_hDC, xNum, xDenom, yNum, yDenom, lpSize); - } -#endif // !_WIN32_WCE - - // Window Origin -#ifndef _WIN32_WCE - BOOL GetWindowOrg(LPPOINT lpPoint) const - { - ATLASSERT(m_hDC != NULL); - return ::GetWindowOrgEx(m_hDC, lpPoint); - } - - BOOL SetWindowOrg(int x, int y, LPPOINT lpPoint = NULL) - { - ATLASSERT(m_hDC != NULL); - return ::SetWindowOrgEx(m_hDC, x, y, lpPoint); - } - - BOOL SetWindowOrg(POINT point, LPPOINT lpPointRet = NULL) - { - ATLASSERT(m_hDC != NULL); - return SetWindowOrg(point.x, point.y, lpPointRet); - } - - BOOL OffsetWindowOrg(int nWidth, int nHeight, LPPOINT lpPoint = NULL) - { - ATLASSERT(m_hDC != NULL); - return ::OffsetWindowOrgEx(m_hDC, nWidth, nHeight, lpPoint); - } - - // Window extent - BOOL GetWindowExt(LPSIZE lpSize) const - { - ATLASSERT(m_hDC != NULL); - return ::GetWindowExtEx(m_hDC, lpSize); - } - - BOOL SetWindowExt(int x, int y, LPSIZE lpSize = NULL) - { - ATLASSERT(m_hDC != NULL); - return ::SetWindowExtEx(m_hDC, x, y, lpSize); - } - - BOOL SetWindowExt(SIZE size, LPSIZE lpSizeRet = NULL) - { - ATLASSERT(m_hDC != NULL); - return SetWindowExt(size.cx, size.cy, lpSizeRet); - } - - BOOL ScaleWindowExt(int xNum, int xDenom, int yNum, int yDenom, LPSIZE lpSize = NULL) - { - ATLASSERT(m_hDC != NULL); - return ::ScaleWindowExtEx(m_hDC, xNum, xDenom, yNum, yDenom, lpSize); - } - -// Coordinate Functions - BOOL DPtoLP(LPPOINT lpPoints, int nCount = 1) const - { - ATLASSERT(m_hDC != NULL); - return ::DPtoLP(m_hDC, lpPoints, nCount); - } - - BOOL DPtoLP(LPRECT lpRect) const - { - ATLASSERT(m_hDC != NULL); - return ::DPtoLP(m_hDC, (LPPOINT)lpRect, 2); - } - - BOOL DPtoLP(LPSIZE lpSize) const - { - SIZE sizeWinExt = { 0, 0 }; - if(!GetWindowExt(&sizeWinExt)) - return FALSE; - SIZE sizeVpExt = { 0, 0 }; - if(!GetViewportExt(&sizeVpExt)) - return FALSE; - lpSize->cx = ::MulDiv(lpSize->cx, abs(sizeWinExt.cx), abs(sizeVpExt.cx)); - lpSize->cy = ::MulDiv(lpSize->cy, abs(sizeWinExt.cy), abs(sizeVpExt.cy)); - return TRUE; - } - - BOOL LPtoDP(LPPOINT lpPoints, int nCount = 1) const - { - ATLASSERT(m_hDC != NULL); - return ::LPtoDP(m_hDC, lpPoints, nCount); - } - - BOOL LPtoDP(LPRECT lpRect) const - { - ATLASSERT(m_hDC != NULL); - return ::LPtoDP(m_hDC, (LPPOINT)lpRect, 2); - } - - BOOL LPtoDP(LPSIZE lpSize) const - { - SIZE sizeWinExt = { 0, 0 }; - if(!GetWindowExt(&sizeWinExt)) - return FALSE; - SIZE sizeVpExt = { 0, 0 }; - if(!GetViewportExt(&sizeVpExt)) - return FALSE; - lpSize->cx = ::MulDiv(lpSize->cx, abs(sizeVpExt.cx), abs(sizeWinExt.cx)); - lpSize->cy = ::MulDiv(lpSize->cy, abs(sizeVpExt.cy), abs(sizeWinExt.cy)); - return TRUE; - } - -// Special Coordinate Functions (useful for dealing with metafiles and OLE) - #define HIMETRIC_INCH 2540 // HIMETRIC units per inch - - void DPtoHIMETRIC(LPSIZE lpSize) const - { - ATLASSERT(m_hDC != NULL); - int nMapMode; - if((nMapMode = GetMapMode()) < MM_ISOTROPIC && nMapMode != MM_TEXT) - { - // when using a constrained map mode, map against physical inch - ((CDCHandle*)this)->SetMapMode(MM_HIMETRIC); - DPtoLP(lpSize); - ((CDCHandle*)this)->SetMapMode(nMapMode); - } - else - { - // map against logical inch for non-constrained mapping modes - int cxPerInch = GetDeviceCaps(LOGPIXELSX); - int cyPerInch = GetDeviceCaps(LOGPIXELSY); - ATLASSERT(cxPerInch != 0 && cyPerInch != 0); - lpSize->cx = ::MulDiv(lpSize->cx, HIMETRIC_INCH, cxPerInch); - lpSize->cy = ::MulDiv(lpSize->cy, HIMETRIC_INCH, cyPerInch); - } - } - - void HIMETRICtoDP(LPSIZE lpSize) const - { - ATLASSERT(m_hDC != NULL); - int nMapMode; - if((nMapMode = GetMapMode()) < MM_ISOTROPIC && nMapMode != MM_TEXT) - { - // when using a constrained map mode, map against physical inch - ((CDCHandle*)this)->SetMapMode(MM_HIMETRIC); - LPtoDP(lpSize); - ((CDCHandle*)this)->SetMapMode(nMapMode); - } - else - { - // map against logical inch for non-constrained mapping modes - int cxPerInch = GetDeviceCaps(LOGPIXELSX); - int cyPerInch = GetDeviceCaps(LOGPIXELSY); - ATLASSERT(cxPerInch != 0 && cyPerInch != 0); - lpSize->cx = ::MulDiv(lpSize->cx, cxPerInch, HIMETRIC_INCH); - lpSize->cy = ::MulDiv(lpSize->cy, cyPerInch, HIMETRIC_INCH); - } - } - - void LPtoHIMETRIC(LPSIZE lpSize) const - { - LPtoDP(lpSize); - DPtoHIMETRIC(lpSize); - } - - void HIMETRICtoLP(LPSIZE lpSize) const - { - HIMETRICtoDP(lpSize); - DPtoLP(lpSize); - } -#endif // !_WIN32_WCE - -// Region Functions - BOOL FillRgn(HRGN hRgn, HBRUSH hBrush) - { - ATLASSERT(m_hDC != NULL); - return ::FillRgn(m_hDC, hRgn, hBrush); - } - -#ifndef _WIN32_WCE - BOOL FrameRgn(HRGN hRgn, HBRUSH hBrush, int nWidth, int nHeight) - { - ATLASSERT(m_hDC != NULL); - return ::FrameRgn(m_hDC, hRgn, hBrush, nWidth, nHeight); - } - - BOOL InvertRgn(HRGN hRgn) - { - ATLASSERT(m_hDC != NULL); - return ::InvertRgn(m_hDC, hRgn); - } - - BOOL PaintRgn(HRGN hRgn) - { - ATLASSERT(m_hDC != NULL); - return ::PaintRgn(m_hDC, hRgn); - } -#endif // !_WIN32_WCE - -// Clipping Functions - int GetClipBox(LPRECT lpRect) const - { - ATLASSERT(m_hDC != NULL); - return ::GetClipBox(m_hDC, lpRect); - } - - int GetClipRgn(CRgn& region) const - { - ATLASSERT(m_hDC != NULL); - if(region.IsNull()) - region.CreateRectRgn(0, 0, 0, 0); - - int nRet = ::GetClipRgn(m_hDC, region); - if(nRet != 1) - region.DeleteObject(); - - return nRet; - } - -#ifndef _WIN32_WCE - BOOL PtVisible(int x, int y) const - { - ATLASSERT(m_hDC != NULL); - return ::PtVisible(m_hDC, x, y); - } - - BOOL PtVisible(POINT point) const - { - ATLASSERT(m_hDC != NULL); - return ::PtVisible(m_hDC, point.x, point.y); - } -#endif // !_WIN32_WCE - - BOOL RectVisible(LPCRECT lpRect) const - { - ATLASSERT(m_hDC != NULL); - return ::RectVisible(m_hDC, lpRect); - } - - int SelectClipRgn(HRGN hRgn) - { - ATLASSERT(m_hDC != NULL); - return ::SelectClipRgn(m_hDC, (HRGN)hRgn); - } - - int ExcludeClipRect(int x1, int y1, int x2, int y2) - { - ATLASSERT(m_hDC != NULL); - return ::ExcludeClipRect(m_hDC, x1, y1, x2, y2); - } - - int ExcludeClipRect(LPCRECT lpRect) - { - ATLASSERT(m_hDC != NULL); - return ::ExcludeClipRect(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); - } - -#ifndef _WIN32_WCE - int ExcludeUpdateRgn(HWND hWnd) - { - ATLASSERT(m_hDC != NULL); - return ::ExcludeUpdateRgn(m_hDC, hWnd); - } -#endif // !_WIN32_WCE - - int IntersectClipRect(int x1, int y1, int x2, int y2) - { - ATLASSERT(m_hDC != NULL); - return ::IntersectClipRect(m_hDC, x1, y1, x2, y2); - } - - int IntersectClipRect(LPCRECT lpRect) - { - ATLASSERT(m_hDC != NULL); - return ::IntersectClipRect(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); - } - -#ifndef _WIN32_WCE - int OffsetClipRgn(int x, int y) - { - ATLASSERT(m_hDC != NULL); - return ::OffsetClipRgn(m_hDC, x, y); - } - - int OffsetClipRgn(SIZE size) - { - ATLASSERT(m_hDC != NULL); - return ::OffsetClipRgn(m_hDC, size.cx, size.cy); - } - - int SelectClipRgn(HRGN hRgn, int nMode) - { - ATLASSERT(m_hDC != NULL); - return ::ExtSelectClipRgn(m_hDC, hRgn, nMode); - } -#endif // !_WIN32_WCE - -// Line-Output Functions -#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) - BOOL GetCurrentPosition(LPPOINT lpPoint) const - { - ATLASSERT(m_hDC != NULL); - return ::GetCurrentPositionEx(m_hDC, lpPoint); - } - - BOOL MoveTo(int x, int y, LPPOINT lpPoint = NULL) - { - ATLASSERT(m_hDC != NULL); - return ::MoveToEx(m_hDC, x, y, lpPoint); - } - - BOOL MoveTo(POINT point, LPPOINT lpPointRet = NULL) - { - ATLASSERT(m_hDC != NULL); - return MoveTo(point.x, point.y, lpPointRet); - } - - BOOL LineTo(int x, int y) - { - ATLASSERT(m_hDC != NULL); - return ::LineTo(m_hDC, x, y); - } - - BOOL LineTo(POINT point) - { - ATLASSERT(m_hDC != NULL); - return LineTo(point.x, point.y); - } -#endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) - -#ifndef _WIN32_WCE - BOOL Arc(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) - { - ATLASSERT(m_hDC != NULL); - return ::Arc(m_hDC, x1, y1, x2, y2, x3, y3, x4, y4); - } - - BOOL Arc(LPCRECT lpRect, POINT ptStart, POINT ptEnd) - { - ATLASSERT(m_hDC != NULL); - return ::Arc(m_hDC, lpRect->left, lpRect->top, - lpRect->right, lpRect->bottom, ptStart.x, ptStart.y, - ptEnd.x, ptEnd.y); - } -#endif // !_WIN32_WCE - - BOOL Polyline(LPPOINT lpPoints, int nCount) - { - ATLASSERT(m_hDC != NULL); - return ::Polyline(m_hDC, lpPoints, nCount); - } - -#ifndef _WIN32_WCE - BOOL AngleArc(int x, int y, int nRadius, float fStartAngle, float fSweepAngle) - { - ATLASSERT(m_hDC != NULL); - return ::AngleArc(m_hDC, x, y, nRadius, fStartAngle, fSweepAngle); - } - - BOOL ArcTo(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) - { - ATLASSERT(m_hDC != NULL); - return ::ArcTo(m_hDC, x1, y1, x2, y2, x3, y3, x4, y4); - } - - BOOL ArcTo(LPCRECT lpRect, POINT ptStart, POINT ptEnd) - { - ATLASSERT(m_hDC != NULL); - return ArcTo(lpRect->left, lpRect->top, lpRect->right, - lpRect->bottom, ptStart.x, ptStart.y, ptEnd.x, ptEnd.y); - } - - int GetArcDirection() const - { - ATLASSERT(m_hDC != NULL); - return ::GetArcDirection(m_hDC); - } - - int SetArcDirection(int nArcDirection) - { - ATLASSERT(m_hDC != NULL); - return ::SetArcDirection(m_hDC, nArcDirection); - } - - BOOL PolyDraw(const POINT* lpPoints, const BYTE* lpTypes, int nCount) - { - ATLASSERT(m_hDC != NULL); - return ::PolyDraw(m_hDC, lpPoints, lpTypes, nCount); - } - - BOOL PolylineTo(const POINT* lpPoints, int nCount) - { - ATLASSERT(m_hDC != NULL); - return ::PolylineTo(m_hDC, lpPoints, nCount); - } - - BOOL PolyPolyline(const POINT* lpPoints, - const DWORD* lpPolyPoints, int nCount) - { - ATLASSERT(m_hDC != NULL); - return ::PolyPolyline(m_hDC, lpPoints, lpPolyPoints, nCount); - } - - BOOL PolyBezier(const POINT* lpPoints, int nCount) - { - ATLASSERT(m_hDC != NULL); - return ::PolyBezier(m_hDC, lpPoints, nCount); - } - - BOOL PolyBezierTo(const POINT* lpPoints, int nCount) - { - ATLASSERT(m_hDC != NULL); - return ::PolyBezierTo(m_hDC, lpPoints, nCount); - } -#endif // !_WIN32_WCE - -// Simple Drawing Functions - BOOL FillRect(LPCRECT lpRect, HBRUSH hBrush) - { - ATLASSERT(m_hDC != NULL); - return ::FillRect(m_hDC, lpRect, hBrush); - } - - BOOL FillRect(LPCRECT lpRect, int nColorIndex) - { - ATLASSERT(m_hDC != NULL); -#ifndef _WIN32_WCE - return ::FillRect(m_hDC, lpRect, (HBRUSH)LongToPtr(nColorIndex + 1)); -#else // CE specific - return ::FillRect(m_hDC, lpRect, ::GetSysColorBrush(nColorIndex)); -#endif // _WIN32_WCE - } - -#ifndef _WIN32_WCE - BOOL FrameRect(LPCRECT lpRect, HBRUSH hBrush) - { - ATLASSERT(m_hDC != NULL); - return ::FrameRect(m_hDC, lpRect, hBrush); - } -#endif // !_WIN32_WCE - -#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 420) - BOOL InvertRect(LPCRECT lpRect) - { - ATLASSERT(m_hDC != NULL); - return ::InvertRect(m_hDC, lpRect); - } -#endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 420) - - BOOL DrawIcon(int x, int y, HICON hIcon) - { - ATLASSERT(m_hDC != NULL); -#ifndef _WIN32_WCE - return ::DrawIcon(m_hDC, x, y, hIcon); -#else // CE specific - return ::DrawIconEx(m_hDC, x, y, hIcon, 0, 0, 0, NULL, DI_NORMAL); -#endif // _WIN32_WCE - } - - BOOL DrawIcon(POINT point, HICON hIcon) - { - ATLASSERT(m_hDC != NULL); -#ifndef _WIN32_WCE - return ::DrawIcon(m_hDC, point.x, point.y, hIcon); -#else // CE specific - return ::DrawIconEx(m_hDC, point.x, point.y, hIcon, 0, 0, 0, NULL, DI_NORMAL); -#endif // _WIN32_WCE - } - - BOOL DrawIconEx(int x, int y, HICON hIcon, int cxWidth, int cyWidth, UINT uStepIfAniCur = 0, HBRUSH hbrFlickerFreeDraw = NULL, UINT uFlags = DI_NORMAL) - { - ATLASSERT(m_hDC != NULL); - return ::DrawIconEx(m_hDC, x, y, hIcon, cxWidth, cyWidth, uStepIfAniCur, hbrFlickerFreeDraw, uFlags); - } - - BOOL DrawIconEx(POINT point, HICON hIcon, SIZE size, UINT uStepIfAniCur = 0, HBRUSH hbrFlickerFreeDraw = NULL, UINT uFlags = DI_NORMAL) - { - ATLASSERT(m_hDC != NULL); - return ::DrawIconEx(m_hDC, point.x, point.y, hIcon, size.cx, size.cy, uStepIfAniCur, hbrFlickerFreeDraw, uFlags); - } - -#ifndef _WIN32_WCE - BOOL DrawState(POINT pt, SIZE size, HBITMAP hBitmap, UINT nFlags, HBRUSH hBrush = NULL) - { - ATLASSERT(m_hDC != NULL); - return ::DrawState(m_hDC, hBrush, NULL, (LPARAM)hBitmap, 0, pt.x, pt.y, size.cx, size.cy, nFlags | DST_BITMAP); - } - - BOOL DrawState(POINT pt, SIZE size, HICON hIcon, UINT nFlags, HBRUSH hBrush = NULL) - { - ATLASSERT(m_hDC != NULL); - return ::DrawState(m_hDC, hBrush, NULL, (LPARAM)hIcon, 0, pt.x, pt.y, size.cx, size.cy, nFlags | DST_ICON); - } - - BOOL DrawState(POINT pt, SIZE size, LPCTSTR lpszText, UINT nFlags, BOOL bPrefixText = TRUE, int nTextLen = 0, HBRUSH hBrush = NULL) - { - ATLASSERT(m_hDC != NULL); - return ::DrawState(m_hDC, hBrush, NULL, (LPARAM)lpszText, (WPARAM)nTextLen, pt.x, pt.y, size.cx, size.cy, nFlags | (bPrefixText ? DST_PREFIXTEXT : DST_TEXT)); - } - - BOOL DrawState(POINT pt, SIZE size, DRAWSTATEPROC lpDrawProc, LPARAM lData, UINT nFlags, HBRUSH hBrush = NULL) - { - ATLASSERT(m_hDC != NULL); - return ::DrawState(m_hDC, hBrush, lpDrawProc, lData, 0, pt.x, pt.y, size.cx, size.cy, nFlags | DST_COMPLEX); - } -#endif // !_WIN32_WCE - -// Ellipse and Polygon Functions -#ifndef _WIN32_WCE - BOOL Chord(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) - { - ATLASSERT(m_hDC != NULL); - return ::Chord(m_hDC, x1, y1, x2, y2, x3, y3, x4, y4); - } - - BOOL Chord(LPCRECT lpRect, POINT ptStart, POINT ptEnd) - { - ATLASSERT(m_hDC != NULL); - return ::Chord(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, ptStart.x, ptStart.y, ptEnd.x, ptEnd.y); - } -#endif // !_WIN32_WCE - - void DrawFocusRect(LPCRECT lpRect) - { - ATLASSERT(m_hDC != NULL); - ::DrawFocusRect(m_hDC, lpRect); - } - - BOOL Ellipse(int x1, int y1, int x2, int y2) - { - ATLASSERT(m_hDC != NULL); - return ::Ellipse(m_hDC, x1, y1, x2, y2); - } - - BOOL Ellipse(LPCRECT lpRect) - { - ATLASSERT(m_hDC != NULL); - return ::Ellipse(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); - } - -#ifndef _WIN32_WCE - BOOL Pie(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) - { - ATLASSERT(m_hDC != NULL); - return ::Pie(m_hDC, x1, y1, x2, y2, x3, y3, x4, y4); - } - - BOOL Pie(LPCRECT lpRect, POINT ptStart, POINT ptEnd) - { - ATLASSERT(m_hDC != NULL); - return ::Pie(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, ptStart.x, ptStart.y, ptEnd.x, ptEnd.y); - } -#endif // !_WIN32_WCE - - BOOL Polygon(LPPOINT lpPoints, int nCount) - { - ATLASSERT(m_hDC != NULL); - return ::Polygon(m_hDC, lpPoints, nCount); - } - -#ifndef _WIN32_WCE - BOOL PolyPolygon(LPPOINT lpPoints, LPINT lpPolyCounts, int nCount) - { - ATLASSERT(m_hDC != NULL); - return ::PolyPolygon(m_hDC, lpPoints, lpPolyCounts, nCount); - } -#endif // !_WIN32_WCE - - BOOL Rectangle(int x1, int y1, int x2, int y2) - { - ATLASSERT(m_hDC != NULL); - return ::Rectangle(m_hDC, x1, y1, x2, y2); - } - - BOOL Rectangle(LPCRECT lpRect) - { - ATLASSERT(m_hDC != NULL); - return ::Rectangle(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); - } - - BOOL RoundRect(int x1, int y1, int x2, int y2, int x3, int y3) - { - ATLASSERT(m_hDC != NULL); - return ::RoundRect(m_hDC, x1, y1, x2, y2, x3, y3); - } - - BOOL RoundRect(LPCRECT lpRect, POINT point) - { - ATLASSERT(m_hDC != NULL); - return ::RoundRect(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, point.x, point.y); - } - -// Bitmap Functions - BOOL PatBlt(int x, int y, int nWidth, int nHeight, DWORD dwRop) - { - ATLASSERT(m_hDC != NULL); - return ::PatBlt(m_hDC, x, y, nWidth, nHeight, dwRop); - } - - BOOL BitBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC, - int xSrc, int ySrc, DWORD dwRop) - { - ATLASSERT(m_hDC != NULL); - return ::BitBlt(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, dwRop); - } - - BOOL StretchBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop) - { - ATLASSERT(m_hDC != NULL); - return ::StretchBlt(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, nSrcWidth, nSrcHeight, dwRop); - } - - COLORREF GetPixel(int x, int y) const - { - ATLASSERT(m_hDC != NULL); - return ::GetPixel(m_hDC, x, y); - } - - COLORREF GetPixel(POINT point) const - { - ATLASSERT(m_hDC != NULL); - return ::GetPixel(m_hDC, point.x, point.y); - } - - COLORREF SetPixel(int x, int y, COLORREF crColor) - { - ATLASSERT(m_hDC != NULL); - return ::SetPixel(m_hDC, x, y, crColor); - } - - COLORREF SetPixel(POINT point, COLORREF crColor) - { - ATLASSERT(m_hDC != NULL); - return ::SetPixel(m_hDC, point.x, point.y, crColor); - } - -#ifndef _WIN32_WCE - BOOL FloodFill(int x, int y, COLORREF crColor) - { - ATLASSERT(m_hDC != NULL); - return ::FloodFill(m_hDC, x, y, crColor); - } - - BOOL ExtFloodFill(int x, int y, COLORREF crColor, UINT nFillType) - { - ATLASSERT(m_hDC != NULL); - return ::ExtFloodFill(m_hDC, x, y, crColor, nFillType); - } -#endif // !_WIN32_WCE - - BOOL MaskBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, HBITMAP hMaskBitmap, int xMask, int yMask, DWORD dwRop) - { - ATLASSERT(m_hDC != NULL); - return ::MaskBlt(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, hMaskBitmap, xMask, yMask, dwRop); - } - -#ifndef _WIN32_WCE - BOOL PlgBlt(LPPOINT lpPoint, HDC hSrcDC, int xSrc, int ySrc, int nWidth, int nHeight, HBITMAP hMaskBitmap, int xMask, int yMask) - { - ATLASSERT(m_hDC != NULL); - return ::PlgBlt(m_hDC, lpPoint, hSrcDC, xSrc, ySrc, nWidth, nHeight, hMaskBitmap, xMask, yMask); - } - - BOOL SetPixelV(int x, int y, COLORREF crColor) - { - ATLASSERT(m_hDC != NULL); - return ::SetPixelV(m_hDC, x, y, crColor); - } - - BOOL SetPixelV(POINT point, COLORREF crColor) - { - ATLASSERT(m_hDC != NULL); - return ::SetPixelV(m_hDC, point.x, point.y, crColor); - } -#endif // !_WIN32_WCE - -#if !defined(_ATL_NO_MSIMG) || defined(_WIN32_WCE) -#ifndef _WIN32_WCE - BOOL TransparentBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, UINT crTransparent) - { - ATLASSERT(m_hDC != NULL); - return ::TransparentBlt(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, nSrcWidth, nSrcHeight, crTransparent); - } -#else // CE specific - BOOL TransparentImage(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, UINT crTransparent) - { - ATLASSERT(m_hDC != NULL); - return ::TransparentImage(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, nSrcWidth, nSrcHeight, crTransparent); - } -#endif // _WIN32_WCE - -#if (!defined(_WIN32_WCE) || (_WIN32_WCE >= 420)) - BOOL GradientFill(const PTRIVERTEX pVertices, DWORD nVertices, void* pMeshElements, DWORD nMeshElements, DWORD dwMode) - { - ATLASSERT(m_hDC != NULL); - return ::GradientFill(m_hDC, pVertices, nVertices, pMeshElements, nMeshElements, dwMode); - } -#endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 420) - -#if !defined(_WIN32_WCE) || (_WIN32_WCE > 0x500) - BOOL AlphaBlend(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, BLENDFUNCTION bf) - { - ATLASSERT(m_hDC != NULL); - return ::AlphaBlend(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, nSrcWidth, nSrcHeight, bf); - } -#endif // !defined(_WIN32_WCE) || (_WIN32_WCE > 0x500) -#endif // !defined(_ATL_NO_MSIMG) || defined(_WIN32_WCE) - -// Extra bitmap functions - // Helper function for painting a disabled toolbar or menu bitmap - // This function can take either an HBITMAP (for SS) or a DC with - // the bitmap already painted (for cmdbar) - BOOL DitherBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC, HBITMAP hBitmap, int xSrc, int ySrc, - HBRUSH hBrushBackground = ::GetSysColorBrush(COLOR_3DFACE), - HBRUSH hBrush3DEffect = ::GetSysColorBrush(COLOR_3DHILIGHT), - HBRUSH hBrushDisabledImage = ::GetSysColorBrush(COLOR_3DSHADOW)) - { - ATLASSERT(m_hDC != NULL || hBitmap != NULL); - ATLASSERT(nWidth > 0 && nHeight > 0); - - // Create a generic DC for all BitBlts - CDCHandle dc = (hSrcDC != NULL) ? hSrcDC : ::CreateCompatibleDC(m_hDC); - ATLASSERT(dc.m_hDC != NULL); - if(dc.m_hDC == NULL) - return FALSE; - - // Create a DC for the monochrome DIB section - CDC dcBW = ::CreateCompatibleDC(m_hDC); - ATLASSERT(dcBW.m_hDC != NULL); - if(dcBW.m_hDC == NULL) - { - if(hSrcDC == NULL) - dc.DeleteDC(); - return FALSE; - } - - // Create the monochrome DIB section with a black and white palette - struct RGBBWBITMAPINFO - { - BITMAPINFOHEADER bmiHeader; - RGBQUAD bmiColors[2]; - }; - - RGBBWBITMAPINFO rgbBWBitmapInfo = - { - { sizeof(BITMAPINFOHEADER), nWidth, nHeight, 1, 1, BI_RGB, 0, 0, 0, 0, 0 }, - { { 0x00, 0x00, 0x00, 0x00 }, { 0xFF, 0xFF, 0xFF, 0x00 } } - }; - - VOID* pbitsBW; - CBitmap bmpBW = ::CreateDIBSection(dcBW, (LPBITMAPINFO)&rgbBWBitmapInfo, DIB_RGB_COLORS, &pbitsBW, NULL, 0); - ATLASSERT(bmpBW.m_hBitmap != NULL); - if(bmpBW.m_hBitmap == NULL) - { - if(hSrcDC == NULL) - dc.DeleteDC(); - return FALSE; - } - - // Attach the monochrome DIB section and the bitmap to the DCs - HBITMAP hbmOldBW = dcBW.SelectBitmap(bmpBW); - HBITMAP hbmOldDC = NULL; - if(hBitmap != NULL) - hbmOldDC = dc.SelectBitmap(hBitmap); - - // Block: Dark gray removal: we want (128, 128, 128) pixels to become black and not white - { - CDC dcTemp1 = ::CreateCompatibleDC(m_hDC); - CDC dcTemp2 = ::CreateCompatibleDC(m_hDC); - CBitmap bmpTemp1; - bmpTemp1.CreateCompatibleBitmap(dc, nWidth, nHeight); - CBitmap bmpTemp2; - bmpTemp2.CreateBitmap(nWidth, nHeight, 1, 1, NULL); - HBITMAP hOldBmp1 = dcTemp1.SelectBitmap(bmpTemp1); - HBITMAP hOldBmp2 = dcTemp2.SelectBitmap(bmpTemp2); - // Let's copy our image, it will be altered - dcTemp1.BitBlt(0, 0, nWidth, nHeight, dc, xSrc, ySrc, SRCCOPY); - - // All dark gray pixels will become white, the others black - dcTemp1.SetBkColor(RGB(128, 128, 128)); - dcTemp2.BitBlt(0, 0, nWidth, nHeight, dcTemp1, 0, 0, SRCCOPY); - // Do an XOR to set to black these white pixels - dcTemp1.BitBlt(0, 0, nWidth, nHeight, dcTemp2, 0, 0, SRCINVERT); - - // BitBlt the bitmap into the monochrome DIB section - // The DIB section will do a true monochrome conversion - // The magenta background being closer to white will become white - dcBW.BitBlt(0, 0, nWidth, nHeight, dcTemp1, 0, 0, SRCCOPY); - - // Cleanup - dcTemp1.SelectBitmap(hOldBmp1); - dcTemp2.SelectBitmap(hOldBmp2); - } - - // Paint the destination rectangle using hBrushBackground - if(hBrushBackground != NULL) - { - RECT rc = { x, y, x + nWidth, y + nHeight }; - FillRect(&rc, hBrushBackground); - } - - // BitBlt the black bits in the monochrome bitmap into hBrush3DEffect color in the destination DC - // The magic ROP comes from the Charles Petzold's book - HBRUSH hOldBrush = SelectBrush(hBrush3DEffect); - BitBlt(x + 1, y + 1, nWidth, nHeight, dcBW, 0, 0, 0xB8074A); - - // BitBlt the black bits in the monochrome bitmap into hBrushDisabledImage color in the destination DC - SelectBrush(hBrushDisabledImage); - BitBlt(x, y, nWidth, nHeight, dcBW, 0, 0, 0xB8074A); - - SelectBrush(hOldBrush); - dcBW.SelectBitmap(hbmOldBW); - dc.SelectBitmap(hbmOldDC); - - if(hSrcDC == NULL) - dc.DeleteDC(); - - return TRUE; - } - -// Text Functions -#ifndef _WIN32_WCE - BOOL TextOut(int x, int y, LPCTSTR lpszString, int nCount = -1) - { - ATLASSERT(m_hDC != NULL); - if(nCount == -1) - nCount = lstrlen(lpszString); - return ::TextOut(m_hDC, x, y, lpszString, nCount); - } -#endif // !_WIN32_WCE - - BOOL ExtTextOut(int x, int y, UINT nOptions, LPCRECT lpRect, LPCTSTR lpszString, UINT nCount = -1, LPINT lpDxWidths = NULL) - { - ATLASSERT(m_hDC != NULL); - if(nCount == -1) - nCount = lstrlen(lpszString); - return ::ExtTextOut(m_hDC, x, y, nOptions, lpRect, lpszString, nCount, lpDxWidths); - } - -#ifndef _WIN32_WCE - SIZE TabbedTextOut(int x, int y, LPCTSTR lpszString, int nCount = -1, int nTabPositions = 0, LPINT lpnTabStopPositions = NULL, int nTabOrigin = 0) - { - ATLASSERT(m_hDC != NULL); - if(nCount == -1) - nCount = lstrlen(lpszString); - LONG lRes = ::TabbedTextOut(m_hDC, x, y, lpszString, nCount, nTabPositions, lpnTabStopPositions, nTabOrigin); - SIZE size = { GET_X_LPARAM(lRes), GET_Y_LPARAM(lRes) }; - return size; - } -#endif // !_WIN32_WCE - - int DrawText(LPCTSTR lpstrText, int cchText, LPRECT lpRect, UINT uFormat) - { - ATLASSERT(m_hDC != NULL); -#ifndef _WIN32_WCE - ATLASSERT((uFormat & DT_MODIFYSTRING) == 0); -#endif // !_WIN32_WCE - return ::DrawText(m_hDC, lpstrText, cchText, lpRect, uFormat); - } - - int DrawText(LPTSTR lpstrText, int cchText, LPRECT lpRect, UINT uFormat) - { - ATLASSERT(m_hDC != NULL); - return ::DrawText(m_hDC, lpstrText, cchText, lpRect, uFormat); - } - -#ifndef _WIN32_WCE - int DrawTextEx(LPTSTR lpstrText, int cchText, LPRECT lpRect, UINT uFormat, LPDRAWTEXTPARAMS lpDTParams = NULL) - { - ATLASSERT(m_hDC != NULL); - return ::DrawTextEx(m_hDC, lpstrText, cchText, lpRect, uFormat, lpDTParams); - } -#endif // !_WIN32_WCE - -#if (_WIN32_WINNT >= 0x0501) - int DrawShadowText(LPCWSTR lpstrText, int cchText, LPRECT lpRect, DWORD dwFlags, COLORREF clrText, COLORREF clrShadow, int xOffset, int yOffset) - { - ATLASSERT(m_hDC != NULL); - // This function is present only if comctl32.dll version 6 is loaded; - // we use LoadLibrary/GetProcAddress to allow apps compiled with - // _WIN32_WINNT >= 0x0501 to run on older Windows/CommCtrl - int nRet = 0; - HMODULE hCommCtrlDLL = ::LoadLibrary(_T("comctl32.dll")); - ATLASSERT(hCommCtrlDLL != NULL); - if(hCommCtrlDLL != NULL) - { - typedef int (WINAPI *PFN_DrawShadowText)(HDC hDC, LPCWSTR lpstrText, UINT cchText, LPRECT lpRect, DWORD dwFlags, COLORREF clrText, COLORREF clrShadow, int xOffset, int yOffset); - PFN_DrawShadowText pfnDrawShadowText = (PFN_DrawShadowText)::GetProcAddress(hCommCtrlDLL, "DrawShadowText"); - ATLASSERT(pfnDrawShadowText != NULL); // this function requires CommCtrl6 - if(pfnDrawShadowText != NULL) - nRet = pfnDrawShadowText(m_hDC, lpstrText, cchText, lpRect, dwFlags, clrText, clrShadow, xOffset, yOffset); - ::FreeLibrary(hCommCtrlDLL); - } - return nRet; - } -#endif // (_WIN32_WINNT >= 0x0501) - - BOOL GetTextExtent(LPCTSTR lpszString, int nCount, LPSIZE lpSize) const - { - ATLASSERT(m_hDC != NULL); - if(nCount == -1) - nCount = lstrlen(lpszString); - return ::GetTextExtentPoint32(m_hDC, lpszString, nCount, lpSize); - } - - BOOL GetTextExtentExPoint(LPCTSTR lpszString, int cchString, LPSIZE lpSize, int nMaxExtent, LPINT lpnFit = NULL, LPINT alpDx = NULL) - { - ATLASSERT(m_hDC != NULL); - return ::GetTextExtentExPoint(m_hDC, lpszString, cchString, nMaxExtent, lpnFit, alpDx, lpSize); - } - -#ifndef _WIN32_WCE - DWORD GetTabbedTextExtent(LPCTSTR lpszString, int nCount = -1, int nTabPositions = 0, LPINT lpnTabStopPositions = NULL) const - { - ATLASSERT(m_hDC != NULL); - if(nCount == -1) - nCount = lstrlen(lpszString); - return ::GetTabbedTextExtent(m_hDC, lpszString, nCount, nTabPositions, lpnTabStopPositions); - } - - BOOL GrayString(HBRUSH hBrush, BOOL (CALLBACK* lpfnOutput)(HDC, LPARAM, int), LPARAM lpData, int nCount, int x, int y, int nWidth, int nHeight) - { - ATLASSERT(m_hDC != NULL); - return ::GrayString(m_hDC, hBrush, (GRAYSTRINGPROC)lpfnOutput, lpData, nCount, x, y, nWidth, nHeight); - } -#endif // !_WIN32_WCE - -#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) - UINT GetTextAlign() const - { - ATLASSERT(m_hDC != NULL); - return ::GetTextAlign(m_hDC); - } - - UINT SetTextAlign(UINT nFlags) - { - ATLASSERT(m_hDC != NULL); - return ::SetTextAlign(m_hDC, nFlags); - } -#endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) - - int GetTextFace(LPTSTR lpszFacename, int nCount) const - { - ATLASSERT(m_hDC != NULL); - return ::GetTextFace(m_hDC, nCount, lpszFacename); - } - - int GetTextFaceLen() const - { - ATLASSERT(m_hDC != NULL); - return ::GetTextFace(m_hDC, 0, NULL); - } - -#ifndef _ATL_NO_COM -#ifdef _OLEAUTO_H_ - BOOL GetTextFace(BSTR& bstrFace) const - { - USES_CONVERSION; - ATLASSERT(m_hDC != NULL); - ATLASSERT(bstrFace == NULL); - - int nLen = GetTextFaceLen(); - if(nLen == 0) - return FALSE; - - CTempBuffer buff; - LPTSTR lpszText = buff.Allocate(nLen); - if(lpszText == NULL) - return FALSE; - - if(!GetTextFace(lpszText, nLen)) - return FALSE; - - bstrFace = ::SysAllocString(T2OLE(lpszText)); - return (bstrFace != NULL) ? TRUE : FALSE; - } -#endif -#endif // !_ATL_NO_COM - -#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - int GetTextFace(_CSTRING_NS::CString& strFace) const - { - ATLASSERT(m_hDC != NULL); - - int nLen = GetTextFaceLen(); - if(nLen == 0) - return 0; - - LPTSTR lpstr = strFace.GetBufferSetLength(nLen); - if(lpstr == NULL) - return 0; - int nRet = GetTextFace(lpstr, nLen); - strFace.ReleaseBuffer(); - return nRet; - } -#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - - BOOL GetTextMetrics(LPTEXTMETRIC lpMetrics) const - { - ATLASSERT(m_hDC != NULL); - return ::GetTextMetrics(m_hDC, lpMetrics); - } - -#ifndef _WIN32_WCE - int SetTextJustification(int nBreakExtra, int nBreakCount) - { - ATLASSERT(m_hDC != NULL); - return ::SetTextJustification(m_hDC, nBreakExtra, nBreakCount); - } - - int GetTextCharacterExtra() const - { - ATLASSERT(m_hDC != NULL); - return ::GetTextCharacterExtra(m_hDC); - } - - int SetTextCharacterExtra(int nCharExtra) - { - ATLASSERT(m_hDC != NULL); - return ::SetTextCharacterExtra(m_hDC, nCharExtra); - } -#endif // !_WIN32_WCE - -// Advanced Drawing - BOOL DrawEdge(LPRECT lpRect, UINT nEdge, UINT nFlags) - { - ATLASSERT(m_hDC != NULL); - return ::DrawEdge(m_hDC, lpRect, nEdge, nFlags); - } - - BOOL DrawFrameControl(LPRECT lpRect, UINT nType, UINT nState) - { - ATLASSERT(m_hDC != NULL); - return ::DrawFrameControl(m_hDC, lpRect, nType, nState); - } - -// Scrolling Functions - BOOL ScrollDC(int dx, int dy, LPCRECT lpRectScroll, LPCRECT lpRectClip, HRGN hRgnUpdate, LPRECT lpRectUpdate) - { - ATLASSERT(m_hDC != NULL); - return ::ScrollDC(m_hDC, dx, dy, lpRectScroll, lpRectClip, hRgnUpdate, lpRectUpdate); - } - -// Font Functions -#ifndef _WIN32_WCE - BOOL GetCharWidth(UINT nFirstChar, UINT nLastChar, LPINT lpBuffer) const - { - ATLASSERT(m_hDC != NULL); - return ::GetCharWidth(m_hDC, nFirstChar, nLastChar, lpBuffer); - } - - // GetCharWidth32 is not supported under Win9x - BOOL GetCharWidth32(UINT nFirstChar, UINT nLastChar, LPINT lpBuffer) const - { - ATLASSERT(m_hDC != NULL); - return ::GetCharWidth32(m_hDC, nFirstChar, nLastChar, lpBuffer); - } - - DWORD SetMapperFlags(DWORD dwFlag) - { - ATLASSERT(m_hDC != NULL); - return ::SetMapperFlags(m_hDC, dwFlag); - } - - BOOL GetAspectRatioFilter(LPSIZE lpSize) const - { - ATLASSERT(m_hDC != NULL); - return ::GetAspectRatioFilterEx(m_hDC, lpSize); - } - - BOOL GetCharABCWidths(UINT nFirstChar, UINT nLastChar, LPABC lpabc) const - { - ATLASSERT(m_hDC != NULL); - return ::GetCharABCWidths(m_hDC, nFirstChar, nLastChar, lpabc); - } - - DWORD GetFontData(DWORD dwTable, DWORD dwOffset, LPVOID lpData, DWORD cbData) const - { - ATLASSERT(m_hDC != NULL); - return ::GetFontData(m_hDC, dwTable, dwOffset, lpData, cbData); - } - - int GetKerningPairs(int nPairs, LPKERNINGPAIR lpkrnpair) const - { - ATLASSERT(m_hDC != NULL); - return ::GetKerningPairs(m_hDC, nPairs, lpkrnpair); - } - - UINT GetOutlineTextMetrics(UINT cbData, LPOUTLINETEXTMETRIC lpotm) const - { - ATLASSERT(m_hDC != NULL); - return ::GetOutlineTextMetrics(m_hDC, cbData, lpotm); - } - - DWORD GetGlyphOutline(UINT nChar, UINT nFormat, LPGLYPHMETRICS lpgm, DWORD cbBuffer, LPVOID lpBuffer, const MAT2* lpmat2) const - { - ATLASSERT(m_hDC != NULL); - return ::GetGlyphOutline(m_hDC, nChar, nFormat, lpgm, cbBuffer, lpBuffer, lpmat2); - } - - BOOL GetCharABCWidths(UINT nFirstChar, UINT nLastChar, LPABCFLOAT lpABCF) const - { - ATLASSERT(m_hDC != NULL); - return ::GetCharABCWidthsFloat(m_hDC, nFirstChar, nLastChar, lpABCF); - } - - BOOL GetCharWidth(UINT nFirstChar, UINT nLastChar, float* lpFloatBuffer) const - { - ATLASSERT(m_hDC != NULL); - return ::GetCharWidthFloat(m_hDC, nFirstChar, nLastChar, lpFloatBuffer); - } -#endif // !_WIN32_WCE - -// Printer/Device Escape Functions -#ifndef _WIN32_WCE - int Escape(int nEscape, int nCount, LPCSTR lpszInData, LPVOID lpOutData) - { - ATLASSERT(m_hDC != NULL); - return ::Escape(m_hDC, nEscape, nCount, lpszInData, lpOutData); - } -#endif // !_WIN32_WCE - - int Escape(int nEscape, int nInputSize, LPCSTR lpszInputData, - int nOutputSize, LPSTR lpszOutputData) - { - ATLASSERT(m_hDC != NULL); - return ::ExtEscape(m_hDC, nEscape, nInputSize, lpszInputData, nOutputSize, lpszOutputData); - } - -#ifndef _WIN32_WCE - int DrawEscape(int nEscape, int nInputSize, LPCSTR lpszInputData) - { - ATLASSERT(m_hDC != NULL); - return ::DrawEscape(m_hDC, nEscape, nInputSize, lpszInputData); - } -#endif // !_WIN32_WCE - - // Escape helpers -#if !defined(_WIN32_WCE) || ((_WIN32_WCE >= 200) && defined(StartDoc)) - int StartDoc(LPCTSTR lpszDocName) // old Win3.0 version - { - DOCINFO di = { 0 }; - di.cbSize = sizeof(DOCINFO); - di.lpszDocName = lpszDocName; - return StartDoc(&di); - } - - int StartDoc(LPDOCINFO lpDocInfo) - { - ATLASSERT(m_hDC != NULL); - return ::StartDoc(m_hDC, lpDocInfo); - } - - int StartPage() - { - ATLASSERT(m_hDC != NULL); - return ::StartPage(m_hDC); - } - - int EndPage() - { - ATLASSERT(m_hDC != NULL); - return ::EndPage(m_hDC); - } - - int SetAbortProc(BOOL (CALLBACK* lpfn)(HDC, int)) - { - ATLASSERT(m_hDC != NULL); - return ::SetAbortProc(m_hDC, (ABORTPROC)lpfn); - } - - int AbortDoc() - { - ATLASSERT(m_hDC != NULL); - return ::AbortDoc(m_hDC); - } - - int EndDoc() - { - ATLASSERT(m_hDC != NULL); - return ::EndDoc(m_hDC); - } -#endif // !defined(_WIN32_WCE) || ((_WIN32_WCE >= 200) && defined(StartDoc)) - -// MetaFile Functions -#ifndef _WIN32_WCE - BOOL PlayMetaFile(HMETAFILE hMF) - { - ATLASSERT(m_hDC != NULL); - if(::GetDeviceCaps(m_hDC, TECHNOLOGY) == DT_METAFILE) - { - // playing metafile in metafile, just use core windows API - return ::PlayMetaFile(m_hDC, hMF); - } - - // for special playback, lParam == pDC - return ::EnumMetaFile(m_hDC, hMF, EnumMetaFileProc, (LPARAM)this); - } - - BOOL PlayMetaFile(HENHMETAFILE hEnhMetaFile, LPCRECT lpBounds) - { - ATLASSERT(m_hDC != NULL); - return ::PlayEnhMetaFile(m_hDC, hEnhMetaFile, lpBounds); - } - - BOOL AddMetaFileComment(UINT nDataSize, const BYTE* pCommentData) // can be used for enhanced metafiles only - { - ATLASSERT(m_hDC != NULL); - return ::GdiComment(m_hDC, nDataSize, pCommentData); - } - - // Special handling for metafile playback - static int CALLBACK EnumMetaFileProc(HDC hDC, HANDLETABLE* pHandleTable, METARECORD* pMetaRec, int nHandles, LPARAM lParam) - { - CDCHandle* pDC = (CDCHandle*)lParam; - - switch (pMetaRec->rdFunction) - { - case META_SETMAPMODE: - pDC->SetMapMode((int)(short)pMetaRec->rdParm[0]); - break; - case META_SETWINDOWEXT: - pDC->SetWindowExt((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]); - break; - case META_SETWINDOWORG: - pDC->SetWindowOrg((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]); - break; - case META_SETVIEWPORTEXT: - pDC->SetViewportExt((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]); - break; - case META_SETVIEWPORTORG: - pDC->SetViewportOrg((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]); - break; - case META_SCALEWINDOWEXT: - pDC->ScaleWindowExt((int)(short)pMetaRec->rdParm[3], (int)(short)pMetaRec->rdParm[2], - (int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]); - break; - case META_SCALEVIEWPORTEXT: - pDC->ScaleViewportExt((int)(short)pMetaRec->rdParm[3], (int)(short)pMetaRec->rdParm[2], - (int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]); - break; - case META_OFFSETVIEWPORTORG: - pDC->OffsetViewportOrg((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]); - break; - case META_SAVEDC: - pDC->SaveDC(); - break; - case META_RESTOREDC: - pDC->RestoreDC((int)(short)pMetaRec->rdParm[0]); - break; - case META_SETBKCOLOR: - pDC->SetBkColor(*(UNALIGNED COLORREF*)&pMetaRec->rdParm[0]); - break; - case META_SETTEXTCOLOR: - pDC->SetTextColor(*(UNALIGNED COLORREF*)&pMetaRec->rdParm[0]); - break; - - // need to watch out for SelectObject(HFONT), for custom font mapping - case META_SELECTOBJECT: - { - HGDIOBJ hObject = pHandleTable->objectHandle[pMetaRec->rdParm[0]]; - UINT nObjType = ::GetObjectType(hObject); - if(nObjType == 0) - { - // object type is unknown, determine if it is a font - HFONT hStockFont = (HFONT)::GetStockObject(SYSTEM_FONT); - HFONT hFontOld = (HFONT)::SelectObject(pDC->m_hDC, hStockFont); - HGDIOBJ hObjOld = ::SelectObject(pDC->m_hDC, hObject); - if(hObjOld == hStockFont) - { - // got the stock object back, so must be selecting a font - pDC->SelectFont((HFONT)hObject); - break; // don't play the default record - } - else - { - // didn't get the stock object back, so restore everything - ::SelectObject(pDC->m_hDC, hFontOld); - ::SelectObject(pDC->m_hDC, hObjOld); - } - // and fall through to PlayMetaFileRecord... - } - else if(nObjType == OBJ_FONT) - { - // play back as CDCHandle::SelectFont(HFONT) - pDC->SelectFont((HFONT)hObject); - break; // don't play the default record - } - } - // fall through... - - default: - ::PlayMetaFileRecord(hDC, pHandleTable, pMetaRec, nHandles); - break; - } - - return 1; - } -#endif // !_WIN32_WCE - -// Path Functions -#ifndef _WIN32_WCE - BOOL AbortPath() - { - ATLASSERT(m_hDC != NULL); - return ::AbortPath(m_hDC); - } - - BOOL BeginPath() - { - ATLASSERT(m_hDC != NULL); - return ::BeginPath(m_hDC); - } - - BOOL CloseFigure() - { - ATLASSERT(m_hDC != NULL); - return ::CloseFigure(m_hDC); - } - - BOOL EndPath() - { - ATLASSERT(m_hDC != NULL); - return ::EndPath(m_hDC); - } - - BOOL FillPath() - { - ATLASSERT(m_hDC != NULL); - return ::FillPath(m_hDC); - } - - BOOL FlattenPath() - { - ATLASSERT(m_hDC != NULL); - return ::FlattenPath(m_hDC); - } - - BOOL StrokeAndFillPath() - { - ATLASSERT(m_hDC != NULL); - return ::StrokeAndFillPath(m_hDC); - } - - BOOL StrokePath() - { - ATLASSERT(m_hDC != NULL); - return ::StrokePath(m_hDC); - } - - BOOL WidenPath() - { - ATLASSERT(m_hDC != NULL); - return ::WidenPath(m_hDC); - } - - BOOL GetMiterLimit(PFLOAT pfMiterLimit) const - { - ATLASSERT(m_hDC != NULL); - return ::GetMiterLimit(m_hDC, pfMiterLimit); - } - - BOOL SetMiterLimit(float fMiterLimit) - { - ATLASSERT(m_hDC != NULL); - return ::SetMiterLimit(m_hDC, fMiterLimit, NULL); - } - - int GetPath(LPPOINT lpPoints, LPBYTE lpTypes, int nCount) const - { - ATLASSERT(m_hDC != NULL); - return ::GetPath(m_hDC, lpPoints, lpTypes, nCount); - } - - BOOL SelectClipPath(int nMode) - { - ATLASSERT(m_hDC != NULL); - return ::SelectClipPath(m_hDC, nMode); - } -#endif // !_WIN32_WCE - -// Misc Helper Functions - static CBrushHandle PASCAL GetHalftoneBrush() - { - HBRUSH halftoneBrush = NULL; - WORD grayPattern[8]; - for(int i = 0; i < 8; i++) - grayPattern[i] = (WORD)(0x5555 << (i & 1)); - HBITMAP grayBitmap = CreateBitmap(8, 8, 1, 1, &grayPattern); - if(grayBitmap != NULL) - { - halftoneBrush = ::CreatePatternBrush(grayBitmap); - DeleteObject(grayBitmap); - } - return CBrushHandle(halftoneBrush); - } - - void DrawDragRect(LPCRECT lpRect, SIZE size, LPCRECT lpRectLast, SIZE sizeLast, HBRUSH hBrush = NULL, HBRUSH hBrushLast = NULL) - { - // first, determine the update region and select it - CRgn rgnOutside; - rgnOutside.CreateRectRgnIndirect(lpRect); - RECT rect = *lpRect; - ::InflateRect(&rect, -size.cx, -size.cy); - ::IntersectRect(&rect, &rect, lpRect); - CRgn rgnInside; - rgnInside.CreateRectRgnIndirect(&rect); - CRgn rgnNew; - rgnNew.CreateRectRgn(0, 0, 0, 0); - rgnNew.CombineRgn(rgnOutside, rgnInside, RGN_XOR); - - HBRUSH hBrushOld = NULL; - CBrush brushHalftone; - if(hBrush == NULL) - brushHalftone = hBrush = CDCHandle::GetHalftoneBrush(); - if(hBrushLast == NULL) - hBrushLast = hBrush; - - CRgn rgnLast; - CRgn rgnUpdate; - if(lpRectLast != NULL) - { - // find difference between new region and old region - rgnLast.CreateRectRgn(0, 0, 0, 0); - rgnOutside.SetRectRgn(lpRectLast->left, lpRectLast->top, lpRectLast->right, lpRectLast->bottom); - rect = *lpRectLast; - ::InflateRect(&rect, -sizeLast.cx, -sizeLast.cy); - ::IntersectRect(&rect, &rect, lpRectLast); - rgnInside.SetRectRgn(rect.left, rect.top, rect.right, rect.bottom); - rgnLast.CombineRgn(rgnOutside, rgnInside, RGN_XOR); - - // only diff them if brushes are the same - if(hBrush == hBrushLast) - { - rgnUpdate.CreateRectRgn(0, 0, 0, 0); - rgnUpdate.CombineRgn(rgnLast, rgnNew, RGN_XOR); - } - } - if(hBrush != hBrushLast && lpRectLast != NULL) - { - // brushes are different -- erase old region first - SelectClipRgn(rgnLast); - GetClipBox(&rect); - hBrushOld = SelectBrush(hBrushLast); - PatBlt(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, PATINVERT); - SelectBrush(hBrushOld); - hBrushOld = NULL; - } - - // draw into the update/new region - SelectClipRgn(rgnUpdate.IsNull() ? rgnNew : rgnUpdate); - GetClipBox(&rect); - hBrushOld = SelectBrush(hBrush); - PatBlt(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, PATINVERT); - - // cleanup DC - if(hBrushOld != NULL) - SelectBrush(hBrushOld); - SelectClipRgn(NULL); - } - - void FillSolidRect(LPCRECT lpRect, COLORREF clr) - { - ATLASSERT(m_hDC != NULL); - - COLORREF clrOld = ::SetBkColor(m_hDC, clr); - ATLASSERT(clrOld != CLR_INVALID); - if(clrOld != CLR_INVALID) - { - ::ExtTextOut(m_hDC, 0, 0, ETO_OPAQUE, lpRect, NULL, 0, NULL); - ::SetBkColor(m_hDC, clrOld); - } - } - - void FillSolidRect(int x, int y, int cx, int cy, COLORREF clr) - { - ATLASSERT(m_hDC != NULL); - - RECT rect = { x, y, x + cx, y + cy }; - FillSolidRect(&rect, clr); - } - - void Draw3dRect(LPCRECT lpRect, COLORREF clrTopLeft, COLORREF clrBottomRight) - { - Draw3dRect(lpRect->left, lpRect->top, lpRect->right - lpRect->left, - lpRect->bottom - lpRect->top, clrTopLeft, clrBottomRight); - } - - void Draw3dRect(int x, int y, int cx, int cy, COLORREF clrTopLeft, COLORREF clrBottomRight) - { - FillSolidRect(x, y, cx - 1, 1, clrTopLeft); - FillSolidRect(x, y, 1, cy - 1, clrTopLeft); - FillSolidRect(x + cx, y, -1, cy, clrBottomRight); - FillSolidRect(x, y + cy, cx, -1, clrBottomRight); - } - -// DIB support -#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 410) - int SetDIBitsToDevice(int x, int y, DWORD dwWidth, DWORD dwHeight, int xSrc, int ySrc, UINT uStartScan, UINT cScanLines, CONST VOID* lpvBits, CONST BITMAPINFO* lpbmi, UINT uColorUse) - { - ATLASSERT(m_hDC != NULL); - return ::SetDIBitsToDevice(m_hDC, x, y, dwWidth, dwHeight, xSrc, ySrc, uStartScan, cScanLines, lpvBits, lpbmi, uColorUse); - } -#endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 410) - -#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) - int StretchDIBits(int x, int y, int nWidth, int nHeight, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, CONST VOID* lpvBits, CONST BITMAPINFO* lpbmi, UINT uColorUse, DWORD dwRop) - { - ATLASSERT(m_hDC != NULL); - return ::StretchDIBits(m_hDC, x, y, nWidth, nHeight, xSrc, ySrc, nSrcWidth, nSrcHeight, lpvBits, lpbmi, uColorUse, dwRop); - } - - UINT GetDIBColorTable(UINT uStartIndex, UINT cEntries, RGBQUAD* pColors) const - { - ATLASSERT(m_hDC != NULL); - return ::GetDIBColorTable(m_hDC, uStartIndex, cEntries, pColors); - } - - UINT SetDIBColorTable(UINT uStartIndex, UINT cEntries, CONST RGBQUAD* pColors) - { - ATLASSERT(m_hDC != NULL); - return ::SetDIBColorTable(m_hDC, uStartIndex, cEntries, pColors); - } -#endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) - -// OpenGL support -#if !defined(_ATL_NO_OPENGL) && !defined(_WIN32_WCE) - int ChoosePixelFormat(CONST PIXELFORMATDESCRIPTOR* ppfd) - { - ATLASSERT(m_hDC != NULL); - return ::ChoosePixelFormat(m_hDC, ppfd); - } - - int DescribePixelFormat(int iPixelFormat, UINT nBytes, LPPIXELFORMATDESCRIPTOR ppfd) - { - ATLASSERT(m_hDC != NULL); - return ::DescribePixelFormat(m_hDC, iPixelFormat, nBytes, ppfd); - } - - int GetPixelFormat() const - { - ATLASSERT(m_hDC != NULL); - return ::GetPixelFormat(m_hDC); - } - - BOOL SetPixelFormat(int iPixelFormat, CONST PIXELFORMATDESCRIPTOR* ppfd) - { - ATLASSERT(m_hDC != NULL); - return ::SetPixelFormat(m_hDC, iPixelFormat, ppfd); - } - - BOOL SwapBuffers() - { - ATLASSERT(m_hDC != NULL); - return ::SwapBuffers(m_hDC); - } - - HGLRC wglCreateContext() - { - ATLASSERT(m_hDC != NULL); - return ::wglCreateContext(m_hDC); - } - - HGLRC wglCreateLayerContext(int iLayerPlane) - { - ATLASSERT(m_hDC != NULL); - return ::wglCreateLayerContext(m_hDC, iLayerPlane); - } - - BOOL wglMakeCurrent(HGLRC hglrc) - { - ATLASSERT(m_hDC != NULL); - return ::wglMakeCurrent(m_hDC, hglrc); - } - - BOOL wglUseFontBitmaps(DWORD dwFirst, DWORD dwCount, DWORD listBase) - { - ATLASSERT(m_hDC != NULL); - return ::wglUseFontBitmaps(m_hDC, dwFirst, dwCount, listBase); - } - - BOOL wglUseFontOutlines(DWORD dwFirst, DWORD dwCount, DWORD listBase, FLOAT deviation, FLOAT extrusion, int format, LPGLYPHMETRICSFLOAT lpgmf) - { - ATLASSERT(m_hDC != NULL); - return ::wglUseFontOutlines(m_hDC, dwFirst, dwCount, listBase, deviation, extrusion, format, lpgmf); - } - - BOOL wglDescribeLayerPlane(int iPixelFormat, int iLayerPlane, UINT nBytes, LPLAYERPLANEDESCRIPTOR plpd) - { - ATLASSERT(m_hDC != NULL); - return ::wglDescribeLayerPlane(m_hDC, iPixelFormat, iLayerPlane, nBytes, plpd); - } - - int wglSetLayerPaletteEntries(int iLayerPlane, int iStart, int cEntries, CONST COLORREF* pclr) - { - ATLASSERT(m_hDC != NULL); - return ::wglSetLayerPaletteEntries(m_hDC, iLayerPlane, iStart, cEntries, pclr); - } - - int wglGetLayerPaletteEntries(int iLayerPlane, int iStart, int cEntries, COLORREF* pclr) - { - ATLASSERT(m_hDC != NULL); - return ::wglGetLayerPaletteEntries(m_hDC, iLayerPlane, iStart, cEntries, pclr); - } - - BOOL wglRealizeLayerPalette(int iLayerPlane, BOOL bRealize) - { - ATLASSERT(m_hDC != NULL); - return ::wglRealizeLayerPalette(m_hDC, iLayerPlane, bRealize); - } - - BOOL wglSwapLayerBuffers(UINT uPlanes) - { - ATLASSERT(m_hDC != NULL); - return ::wglSwapLayerBuffers(m_hDC, uPlanes); - } -#endif // !defined(_ATL_NO_OPENGL) && !defined(_WIN32_WCE) - -// New for Windows 2000 only -#if (_WIN32_WINNT >= 0x0500) - COLORREF GetDCPenColor() const - { - ATLASSERT(m_hDC != NULL); - return ::GetDCPenColor(m_hDC); - } - - COLORREF SetDCPenColor(COLORREF clr) - { - ATLASSERT(m_hDC != NULL); - return ::SetDCPenColor(m_hDC, clr); - } - - COLORREF GetDCBrushColor() const - { - ATLASSERT(m_hDC != NULL); - return ::GetDCBrushColor(m_hDC); - } - - COLORREF SetDCBrushColor(COLORREF clr) - { - ATLASSERT(m_hDC != NULL); - return ::SetDCBrushColor(m_hDC, clr); - } - -#ifndef _WIN32_WCE - DWORD GetFontUnicodeRanges(LPGLYPHSET lpgs) const - { - ATLASSERT(m_hDC != NULL); - return ::GetFontUnicodeRanges(m_hDC, lpgs); - } -#endif // !_WIN32_WCE - - DWORD GetGlyphIndices(LPCTSTR lpstr, int cch, LPWORD pgi, DWORD dwFlags) const - { - ATLASSERT(m_hDC != NULL); - return ::GetGlyphIndices(m_hDC, lpstr, cch, pgi, dwFlags); - } - - BOOL GetTextExtentPointI(LPWORD pgiIn, int cgi, LPSIZE lpSize) const - { - ATLASSERT(m_hDC != NULL); - return ::GetTextExtentPointI(m_hDC, pgiIn, cgi, lpSize); - } - - BOOL GetTextExtentExPointI(LPWORD pgiIn, int cgi, int nMaxExtent, LPINT lpnFit, LPINT alpDx, LPSIZE lpSize) const - { - ATLASSERT(m_hDC != NULL); - return ::GetTextExtentExPointI(m_hDC, pgiIn, cgi, nMaxExtent, lpnFit, alpDx, lpSize); - } - - BOOL GetCharWidthI(UINT giFirst, UINT cgi, LPWORD pgi, LPINT lpBuffer) const - { - ATLASSERT(m_hDC != NULL); - return ::GetCharWidthI(m_hDC, giFirst, cgi, pgi, lpBuffer); - } - - BOOL GetCharABCWidthsI(UINT giFirst, UINT cgi, LPWORD pgi, LPABC lpabc) const - { - ATLASSERT(m_hDC != NULL); - return ::GetCharABCWidthsI(m_hDC, giFirst, cgi, pgi, lpabc); - } -#endif // (_WIN32_WINNT >= 0x0500) - -// New for Windows 2000 and Windows 98 -#if (WINVER >= 0x0500) && !defined(_WIN32_WCE) - BOOL ColorCorrectPalette(HPALETTE hPalette, DWORD dwFirstEntry, DWORD dwNumOfEntries) - { - ATLASSERT(m_hDC != NULL); - return ::ColorCorrectPalette(m_hDC, hPalette, dwFirstEntry, dwNumOfEntries); - } -#endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE) -}; - -typedef CDCT CDCHandle; -typedef CDCT CDC; - - -/////////////////////////////////////////////////////////////////////////////// -// CDC Helpers - -class CPaintDC : public CDC -{ -public: -// Data members - HWND m_hWnd; - PAINTSTRUCT m_ps; - -// Constructor/destructor - CPaintDC(HWND hWnd) - { - ATLASSERT(::IsWindow(hWnd)); - m_hWnd = hWnd; - m_hDC = ::BeginPaint(hWnd, &m_ps); - } - - ~CPaintDC() - { - ATLASSERT(m_hDC != NULL); - ATLASSERT(::IsWindow(m_hWnd)); - ::EndPaint(m_hWnd, &m_ps); - Detach(); - } -}; - -class CClientDC : public CDC -{ -public: -// Data members - HWND m_hWnd; - -// Constructor/destructor - CClientDC(HWND hWnd) - { - ATLASSERT(hWnd == NULL || ::IsWindow(hWnd)); - m_hWnd = hWnd; - m_hDC = ::GetDC(hWnd); - } - - ~CClientDC() - { - ATLASSERT(m_hDC != NULL); - ::ReleaseDC(m_hWnd, Detach()); - } -}; - -class CWindowDC : public CDC -{ -public: -// Data members - HWND m_hWnd; - -// Constructor/destructor - CWindowDC(HWND hWnd) - { - ATLASSERT(hWnd == NULL || ::IsWindow(hWnd)); - m_hWnd = hWnd; - m_hDC = ::GetWindowDC(hWnd); - } - - ~CWindowDC() - { - ATLASSERT(m_hDC != NULL); - ::ReleaseDC(m_hWnd, Detach()); - } -}; - -class CMemoryDC : public CDC -{ -public: -// Data members - HDC m_hDCOriginal; - RECT m_rcPaint; - CBitmap m_bmp; - HBITMAP m_hBmpOld; - -// Constructor/destructor - CMemoryDC(HDC hDC, RECT& rcPaint) : m_hDCOriginal(hDC), m_hBmpOld(NULL) - { - m_rcPaint = rcPaint; - CreateCompatibleDC(m_hDCOriginal); - ATLASSERT(m_hDC != NULL); - m_bmp.CreateCompatibleBitmap(m_hDCOriginal, m_rcPaint.right - m_rcPaint.left, m_rcPaint.bottom - m_rcPaint.top); - ATLASSERT(m_bmp.m_hBitmap != NULL); - m_hBmpOld = SelectBitmap(m_bmp); - SetViewportOrg(-m_rcPaint.left, -m_rcPaint.top); - } - - ~CMemoryDC() - { - ::BitBlt(m_hDCOriginal, m_rcPaint.left, m_rcPaint.top, m_rcPaint.right - m_rcPaint.left, m_rcPaint.bottom - m_rcPaint.top, m_hDC, m_rcPaint.left, m_rcPaint.top, SRCCOPY); - SelectBitmap(m_hBmpOld); - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// Enhanced metafile support - -#ifndef _WIN32_WCE - -class CEnhMetaFileInfo -{ -public: -// Data members - HENHMETAFILE m_hEMF; - BYTE* m_pBits; - TCHAR* m_pDesc; - ENHMETAHEADER m_header; - PIXELFORMATDESCRIPTOR m_pfd; - -// Constructor/destructor - CEnhMetaFileInfo(HENHMETAFILE hEMF) : m_pBits(NULL), m_pDesc(NULL), m_hEMF(hEMF) - { } - - ~CEnhMetaFileInfo() - { - delete [] m_pBits; - delete [] m_pDesc; - } - -// Operations - BYTE* GetEnhMetaFileBits() - { - ATLASSERT(m_hEMF != NULL); - UINT nBytes = ::GetEnhMetaFileBits(m_hEMF, 0, NULL); - delete [] m_pBits; - m_pBits = NULL; - ATLTRY(m_pBits = new BYTE[nBytes]); - if (m_pBits != NULL) - ::GetEnhMetaFileBits(m_hEMF, nBytes, m_pBits); - return m_pBits; - } - - LPTSTR GetEnhMetaFileDescription() - { - ATLASSERT(m_hEMF != NULL); - UINT nLen = ::GetEnhMetaFileDescription(m_hEMF, 0, NULL); - delete [] m_pDesc; - m_pDesc = NULL; - ATLTRY(m_pDesc = new TCHAR[nLen]); - if (m_pDesc != NULL) - nLen = ::GetEnhMetaFileDescription(m_hEMF, nLen, m_pDesc); - return m_pDesc; - } - - ENHMETAHEADER* GetEnhMetaFileHeader() - { - ATLASSERT(m_hEMF != NULL); - memset(&m_header, 0, sizeof(m_header)); - m_header.iType = EMR_HEADER; - m_header.nSize = sizeof(ENHMETAHEADER); - UINT n = ::GetEnhMetaFileHeader(m_hEMF, sizeof(ENHMETAHEADER), &m_header); - return (n != 0) ? &m_header : NULL; - } - - PIXELFORMATDESCRIPTOR* GetEnhMetaFilePixelFormat() - { - ATLASSERT(m_hEMF != NULL); - memset(&m_pfd, 0, sizeof(m_pfd)); - UINT n = ::GetEnhMetaFilePixelFormat(m_hEMF, sizeof(m_pfd), &m_pfd); - return (n != 0) ? &m_pfd : NULL; - } -}; - - -template -class CEnhMetaFileT -{ -public: -// Data members - HENHMETAFILE m_hEMF; - -// Constructor/destructor - CEnhMetaFileT(HENHMETAFILE hEMF = NULL) : m_hEMF(hEMF) - { - } - - ~CEnhMetaFileT() - { - if(t_bManaged && m_hEMF != NULL) - DeleteObject(); - } - -// Operations - CEnhMetaFileT& operator =(HENHMETAFILE hEMF) - { - Attach(hEMF); - return *this; - } - - void Attach(HENHMETAFILE hEMF) - { - if(t_bManaged && m_hEMF != NULL && m_hEMF != hEMF) - DeleteObject(); - m_hEMF = hEMF; - } - - HENHMETAFILE Detach() - { - HENHMETAFILE hEMF = m_hEMF; - m_hEMF = NULL; - return hEMF; - } - - operator HENHMETAFILE() const { return m_hEMF; } - - bool IsNull() const { return (m_hEMF == NULL); } - - BOOL DeleteObject() - { - ATLASSERT(m_hEMF != NULL); - BOOL bRet = ::DeleteEnhMetaFile(m_hEMF); - m_hEMF = NULL; - return bRet; - } - - UINT GetEnhMetaFileBits(UINT cbBuffer, LPBYTE lpbBuffer) const - { - ATLASSERT(m_hEMF != NULL); - return ::GetEnhMetaFileBits(m_hEMF, cbBuffer, lpbBuffer); - } - - UINT GetEnhMetaFileDescription(UINT cchBuffer, LPTSTR lpszDescription) const - { - ATLASSERT(m_hEMF != NULL); - return ::GetEnhMetaFileDescription(m_hEMF, cchBuffer, lpszDescription); - } - - UINT GetEnhMetaFileHeader(LPENHMETAHEADER lpemh) const - { - ATLASSERT(m_hEMF != NULL); - lpemh->iType = EMR_HEADER; - lpemh->nSize = sizeof(ENHMETAHEADER); - return ::GetEnhMetaFileHeader(m_hEMF, sizeof(ENHMETAHEADER), lpemh); - } - - UINT GetEnhMetaFilePaletteEntries(UINT cEntries, LPPALETTEENTRY lppe) const - { - ATLASSERT(m_hEMF != NULL); - return ::GetEnhMetaFilePaletteEntries(m_hEMF, cEntries, lppe); - } - - UINT GetEnhMetaFilePixelFormat(DWORD cbBuffer, PIXELFORMATDESCRIPTOR* ppfd) const - { - ATLASSERT(m_hEMF != NULL); - return ::GetEnhMetaFilePixelFormat(m_hEMF, cbBuffer, ppfd); - } -}; - -typedef CEnhMetaFileT CEnhMetaFileHandle; -typedef CEnhMetaFileT CEnhMetaFile; - - -class CEnhMetaFileDC : public CDC -{ -public: -// Constructor/destructor - CEnhMetaFileDC() - { - } - - CEnhMetaFileDC(HDC hdc, LPCRECT lpRect) - { - Create(hdc, NULL, lpRect, NULL); - ATLASSERT(m_hDC != NULL); - } - - CEnhMetaFileDC(HDC hdcRef, LPCTSTR lpFilename, LPCRECT lpRect, LPCTSTR lpDescription) - { - Create(hdcRef, lpFilename, lpRect, lpDescription); - ATLASSERT(m_hDC != NULL); - } - - ~CEnhMetaFileDC() - { - HENHMETAFILE hEMF = Close(); - if (hEMF != NULL) - ::DeleteEnhMetaFile(hEMF); - } - -// Operations - void Create(HDC hdcRef, LPCTSTR lpFilename, LPCRECT lpRect, LPCTSTR lpDescription) - { - ATLASSERT(m_hDC == NULL); - m_hDC = ::CreateEnhMetaFile(hdcRef, lpFilename, lpRect, lpDescription); - } - - HENHMETAFILE Close() - { - HENHMETAFILE hEMF = NULL; - if (m_hDC != NULL) - { - hEMF = ::CloseEnhMetaFile(m_hDC); - m_hDC = NULL; - } - return hEMF; - } -}; - -#endif // !_WIN32_WCE - - -/////////////////////////////////////////////////////////////////////////////// -// WinCE compatible clipboard CF_DIB format support functions - -#ifndef _WTL_NO_DIB16 - -#define DIBINFO16_BITFIELDS { 31744, 992, 31 } - -// DIBINFO16 - To avoid color table problems in WinCE we only create this type of Dib -struct DIBINFO16 // a BITMAPINFO with 2 additional color bitfields -{ - BITMAPINFOHEADER bmiHeader; - RGBQUAD bmiColors[3]; - - DIBINFO16(SIZE size) - { - BITMAPINFOHEADER bmih = { sizeof(BITMAPINFOHEADER), size.cx, size.cy, - 1, 16, BI_BITFIELDS, 2 * size.cx * size.cy , 0, 0, 3 }; - DWORD dw[3] = DIBINFO16_BITFIELDS ; - - bmiHeader = bmih; - memcpy(bmiColors, dw, 3 * sizeof(DWORD)); - } -}; - - -// AtlxxxDibxxx minimal packed DIB implementation and helpers to copy and paste CF_DIB - -inline bool AtlIsDib16(LPBITMAPINFOHEADER pbmih) -{ - return (pbmih->biBitCount == 16) && (pbmih->biCompression == BI_BITFIELDS); -} - -inline int AtlGetDibColorTableSize(LPBITMAPINFOHEADER pbmih) -{ - switch (pbmih->biBitCount) - { - case 2: - case 4: - case 8: - return pbmih->biClrUsed ? pbmih->biClrUsed : 1 << pbmih->biBitCount; - case 24: - break; - case 16: - case 32: - return pbmih->biCompression == BI_BITFIELDS ? 3 : 0; - default: - ATLASSERT(FALSE); // should never come here - } - - return 0; -} - -inline int AtlGetDibNumColors(LPBITMAPINFOHEADER pbmih) -{ - switch (pbmih->biBitCount) - { - case 2: - case 4: - case 8: - if (pbmih->biClrUsed) - return pbmih->biClrUsed; - else - break; - case 16: - if (pbmih->biCompression == BI_BITFIELDS ) - return 1 << 15; - else - break; - case 24: - break; - case 32: - if (pbmih->biCompression == BI_BITFIELDS ) - return 1 << 24; - else - break; - default: - ATLASSERT(FALSE); - } - - return 1 << pbmih->biBitCount; -} - -inline HBITMAP AtlGetDibBitmap(LPBITMAPINFO pbmi) -{ - HBITMAP hbm = NULL; - CDC dc(NULL); - void * pBits = NULL; - - LPBYTE pDibBits = (LPBYTE)pbmi + sizeof(BITMAPINFOHEADER) + AtlGetDibColorTableSize(&pbmi->bmiHeader) * sizeof(RGBQUAD); - if (hbm = CreateDIBSection(dc, pbmi, DIB_RGB_COLORS, &pBits, NULL, NULL)) - memcpy(pBits, pDibBits, pbmi->bmiHeader.biSizeImage); - - return hbm; -} - -inline HBITMAP AtlCopyBitmap(HBITMAP hbm , SIZE sizeDst, bool bAsBitmap = false) -{ - CDC hdcSrc = CreateCompatibleDC(NULL); - CDC hdcDst = CreateCompatibleDC(NULL); - - CBitmapHandle hbmOld = NULL, hbmOld2 = NULL, bmSrc = hbm; - - CBitmap bmNew = NULL; - - SIZE sizeSrc = { 0 }; - bmSrc.GetSize(sizeSrc); - - hbmOld = hdcSrc.SelectBitmap(bmSrc); - - if (bAsBitmap) - { - bmNew.CreateCompatibleBitmap(hdcSrc, sizeDst.cx, sizeDst.cy); - } - else - { - DIBINFO16 dib16(sizeDst); - LPVOID pBits = NULL; - bmNew = CreateDIBSection(hdcDst, (const BITMAPINFO*)&dib16, DIB_RGB_COLORS, &pBits, NULL, NULL); - } - - ATLASSERT(!bmNew.IsNull()); - - hbmOld2 = hdcDst.SelectBitmap(bmNew); - BOOL bOK = FALSE; - - if ((sizeDst.cx == sizeSrc.cx) && (sizeDst.cy == sizeSrc.cy)) - bOK = hdcDst.BitBlt(0, 0, sizeDst.cx, sizeDst.cy, hdcSrc, 0, 0, SRCCOPY); - else - bOK = hdcDst.StretchBlt(0, 0, sizeDst.cx, sizeDst.cy, hdcSrc, 0, 0, sizeSrc.cx, sizeSrc.cy, SRCCOPY); - - hdcSrc.SelectBitmap(hbmOld); - hdcDst.SelectBitmap(hbmOld2); - - if (bOK == FALSE) - bmNew.DeleteObject(); - - return bmNew.Detach(); -} - -inline HLOCAL AtlCreatePackedDib16(HBITMAP hbm, SIZE size) -{ - DIBSECTION ds = { 0 }; - LPBYTE pDib = NULL; - bool bCopied = false; - - bool bOK = GetObject(hbm, sizeof(ds), &ds) == sizeof(ds); - if ((bOK == FALSE) || (ds.dsBm.bmBits == NULL) || (AtlIsDib16(&ds.dsBmih) == FALSE) || - (ds.dsBmih.biWidth != size.cx ) || (ds.dsBmih.biHeight != size.cy )) - { - if ((hbm = AtlCopyBitmap(hbm, size)) != NULL) - { - bCopied = true; - bOK = GetObject(hbm, sizeof(ds), &ds) == sizeof(ds); - } - else - { - bOK = FALSE; - } - } - - if((bOK == TRUE) && (AtlIsDib16(&ds.dsBmih) == TRUE) && (ds.dsBm.bmBits != NULL)) - { - pDib = (LPBYTE)LocalAlloc(LMEM_ZEROINIT, sizeof(DIBINFO16) + ds.dsBmih.biSizeImage); - if (pDib != NULL) - { - memcpy(pDib , &ds.dsBmih, sizeof(DIBINFO16)); - memcpy(pDib + sizeof(DIBINFO16), ds.dsBm.bmBits, ds.dsBmih.biSizeImage); - } - } - - if (bCopied == true) - DeleteObject(hbm); - - return (HLOCAL)pDib; -} - -inline bool AtlSetClipboardDib16(HBITMAP hbm, SIZE size, HWND hWnd) -{ - ATLASSERT(::IsWindow(hWnd)); - BOOL bOK = OpenClipboard(hWnd); - if (bOK == TRUE) - { - if ((bOK = EmptyClipboard()) == TRUE) - { - HLOCAL hDib = AtlCreatePackedDib16(hbm, size); - if (hDib != NULL) - { - bOK = SetClipboardData(CF_DIB, hDib) != NULL; - if (bOK == FALSE) - LocalFree(hDib); - } - else - { - bOK = FALSE; - } - } - CloseClipboard(); - } - - return bOK == TRUE; -} - -inline HBITMAP AtlGetClipboardDib(HWND hWnd) -{ - ATLASSERT(::IsWindow(hWnd) == TRUE); - HBITMAP hbm = NULL; - if (OpenClipboard(hWnd) == TRUE) - { - LPBITMAPINFO pbmi = (LPBITMAPINFO)GetClipboardData(CF_DIB); - if (pbmi != NULL) - hbm = AtlGetDibBitmap(pbmi); - CloseClipboard(); - } - - return hbm; -} - -#endif // _WTL_NO_DIB16 - -}; // namespace WTL - -#endif // __ATLGDI_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/atlmisc.h b/prog/3rdPartyLibs/wtl-8.1/include/atlmisc.h deleted file mode 100644 index ff5e7ee7a..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/atlmisc.h +++ /dev/null @@ -1,4021 +0,0 @@ -// Windows Template Library - WTL version 8.1 -// Copyright (C) Microsoft Corporation. All rights reserved. -// -// This file is a part of the Windows Template Library. -// The use and distribution terms for this software are covered by the -// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php) -// which can be found in the file CPL.TXT at the root of this distribution. -// By using this software in any fashion, you are agreeing to be bound by -// the terms of this license. You must not remove this notice, or -// any other, from this software. - -#ifndef __ATLMISC_H__ -#define __ATLMISC_H__ - -#pragma once - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#ifndef __ATLAPP_H__ - #error atlmisc.h requires atlapp.h to be included first -#endif - - -#ifdef _ATL_TMP_NO_CSTRING - #define _WTL_NO_CSTRING -#endif - -#if defined(_WTL_USE_CSTRING) && defined(_WTL_NO_CSTRING) - #error Conflicting options - both _WTL_USE_CSTRING and _WTL_NO_CSTRING are defined -#endif // defined(_WTL_USE_CSTRING) && defined(_WTL_NO_CSTRING) - -#if !defined(_WTL_USE_CSTRING) && !defined(_WTL_NO_CSTRING) - #define _WTL_USE_CSTRING -#endif // !defined(_WTL_USE_CSTRING) && !defined(_WTL_NO_CSTRING) - -#ifndef _WTL_NO_CSTRING - #if defined(_ATL_USE_CSTRING_FLOAT) && defined(_ATL_MIN_CRT) - #error Cannot use CString floating point formatting with _ATL_MIN_CRT defined - #endif // defined(_ATL_USE_CSTRING_FLOAT) && defined(_ATL_MIN_CRT) -#endif // !_WTL_NO_CSTRING - - -/////////////////////////////////////////////////////////////////////////////// -// Classes in this file: -// -// CSize -// CPoint -// CRect -// CString -// -// CRecentDocumentListBase -// CRecentDocumentList -// CFindFile -// -// Global functions: -// AtlLoadAccelerators() -// AtlLoadMenu() -// AtlLoadBitmap() -// AtlLoadSysBitmap() -// AtlLoadCursor() -// AtlLoadSysCursor() -// AtlLoadIcon() -// AtlLoadSysIcon() -// AtlLoadBitmapImage() -// AtlLoadCursorImage() -// AtlLoadIconImage() -// AtlLoadSysBitmapImage() -// AtlLoadSysCursorImage() -// AtlLoadSysIconImage() -// AtlLoadString() -// -// AtlGetStockPen() -// AtlGetStockBrush() -// AtlGetStockFont() -// AtlGetStockPalette() -// -// AtlCompactPath() - - -namespace WTL -{ - -#ifndef _WTL_NO_WTYPES - -// forward declarations -class CSize; -class CPoint; -class CRect; - -/////////////////////////////////////////////////////////////////////////////// -// CSize - Wrapper for Windows SIZE structure. - -class CSize : public SIZE -{ -public: -// Constructors - CSize() - { - cx = 0; - cy = 0; - } - - CSize(int initCX, int initCY) - { - cx = initCX; - cy = initCY; - } - - CSize(SIZE initSize) - { - *(SIZE*)this = initSize; - } - - CSize(POINT initPt) - { - *(POINT*)this = initPt; - } - - CSize(DWORD dwSize) - { - cx = (short)LOWORD(dwSize); - cy = (short)HIWORD(dwSize); - } - -// Operations - BOOL operator ==(SIZE size) const - { - return (cx == size.cx && cy == size.cy); - } - - BOOL operator !=(SIZE size) const - { - return (cx != size.cx || cy != size.cy); - } - - void operator +=(SIZE size) - { - cx += size.cx; - cy += size.cy; - } - - void operator -=(SIZE size) - { - cx -= size.cx; - cy -= size.cy; - } - - void SetSize(int CX, int CY) - { - cx = CX; - cy = CY; - } - -// Operators returning CSize values - CSize operator +(SIZE size) const - { - return CSize(cx + size.cx, cy + size.cy); - } - - CSize operator -(SIZE size) const - { - return CSize(cx - size.cx, cy - size.cy); - } - - CSize operator -() const - { - return CSize(-cx, -cy); - } - -// Operators returning CPoint values - CPoint operator +(POINT point) const; - CPoint operator -(POINT point) const; - -// Operators returning CRect values - CRect operator +(const RECT* lpRect) const; - CRect operator -(const RECT* lpRect) const; -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CPoint - Wrapper for Windows POINT structure. - -class CPoint : public POINT -{ -public: -// Constructors - CPoint() - { - x = 0; - y = 0; - } - - CPoint(int initX, int initY) - { - x = initX; - y = initY; - } - - CPoint(POINT initPt) - { - *(POINT*)this = initPt; - } - - CPoint(SIZE initSize) - { - *(SIZE*)this = initSize; - } - - CPoint(DWORD dwPoint) - { - x = (short)LOWORD(dwPoint); - y = (short)HIWORD(dwPoint); - } - -// Operations - void Offset(int xOffset, int yOffset) - { - x += xOffset; - y += yOffset; - } - - void Offset(POINT point) - { - x += point.x; - y += point.y; - } - - void Offset(SIZE size) - { - x += size.cx; - y += size.cy; - } - - BOOL operator ==(POINT point) const - { - return (x == point.x && y == point.y); - } - - BOOL operator !=(POINT point) const - { - return (x != point.x || y != point.y); - } - - void operator +=(SIZE size) - { - x += size.cx; - y += size.cy; - } - - void operator -=(SIZE size) - { - x -= size.cx; - y -= size.cy; - } - - void operator +=(POINT point) - { - x += point.x; - y += point.y; - } - - void operator -=(POINT point) - { - x -= point.x; - y -= point.y; - } - - void SetPoint(int X, int Y) - { - x = X; - y = Y; - } - -// Operators returning CPoint values - CPoint operator +(SIZE size) const - { - return CPoint(x + size.cx, y + size.cy); - } - - CPoint operator -(SIZE size) const - { - return CPoint(x - size.cx, y - size.cy); - } - - CPoint operator -() const - { - return CPoint(-x, -y); - } - - CPoint operator +(POINT point) const - { - return CPoint(x + point.x, y + point.y); - } - -// Operators returning CSize values - CSize operator -(POINT point) const - { - return CSize(x - point.x, y - point.y); - } - -// Operators returning CRect values - CRect operator +(const RECT* lpRect) const; - CRect operator -(const RECT* lpRect) const; -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CRect - Wrapper for Windows RECT structure. - -class CRect : public RECT -{ -public: -// Constructors - CRect() - { - left = 0; - top = 0; - right = 0; - bottom = 0; - } - - CRect(int l, int t, int r, int b) - { - left = l; - top = t; - right = r; - bottom = b; - } - - CRect(const RECT& srcRect) - { - ::CopyRect(this, &srcRect); - } - - CRect(LPCRECT lpSrcRect) - { - ::CopyRect(this, lpSrcRect); - } - - CRect(POINT point, SIZE size) - { - right = (left = point.x) + size.cx; - bottom = (top = point.y) + size.cy; - } - - CRect(POINT topLeft, POINT bottomRight) - { - left = topLeft.x; - top = topLeft.y; - right = bottomRight.x; - bottom = bottomRight.y; - } - -// Attributes (in addition to RECT members) - int Width() const - { - return right - left; - } - - int Height() const - { - return bottom - top; - } - - CSize Size() const - { - return CSize(right - left, bottom - top); - } - - CPoint& TopLeft() - { - return *((CPoint*)this); - } - - CPoint& BottomRight() - { - return *((CPoint*)this + 1); - } - - const CPoint& TopLeft() const - { - return *((CPoint*)this); - } - - const CPoint& BottomRight() const - { - return *((CPoint*)this + 1); - } - - CPoint CenterPoint() const - { - return CPoint((left + right) / 2, (top + bottom) / 2); - } - - // convert between CRect and LPRECT/LPCRECT (no need for &) - operator LPRECT() - { - return this; - } - - operator LPCRECT() const - { - return this; - } - - BOOL IsRectEmpty() const - { - return ::IsRectEmpty(this); - } - - BOOL IsRectNull() const - { - return (left == 0 && right == 0 && top == 0 && bottom == 0); - } - - BOOL PtInRect(POINT point) const - { - return ::PtInRect(this, point); - } - -// Operations - void SetRect(int x1, int y1, int x2, int y2) - { - ::SetRect(this, x1, y1, x2, y2); - } - - void SetRect(POINT topLeft, POINT bottomRight) - { - ::SetRect(this, topLeft.x, topLeft.y, bottomRight.x, bottomRight.y); - } - - void SetRectEmpty() - { - ::SetRectEmpty(this); - } - - void CopyRect(LPCRECT lpSrcRect) - { - ::CopyRect(this, lpSrcRect); - } - - BOOL EqualRect(LPCRECT lpRect) const - { - return ::EqualRect(this, lpRect); - } - - void InflateRect(int x, int y) - { - ::InflateRect(this, x, y); - } - - void InflateRect(SIZE size) - { - ::InflateRect(this, size.cx, size.cy); - } - - void InflateRect(LPCRECT lpRect) - { - left -= lpRect->left; - top -= lpRect->top; - right += lpRect->right; - bottom += lpRect->bottom; - } - - void InflateRect(int l, int t, int r, int b) - { - left -= l; - top -= t; - right += r; - bottom += b; - } - - void DeflateRect(int x, int y) - { - ::InflateRect(this, -x, -y); - } - - void DeflateRect(SIZE size) - { - ::InflateRect(this, -size.cx, -size.cy); - } - - void DeflateRect(LPCRECT lpRect) - { - left += lpRect->left; - top += lpRect->top; - right -= lpRect->right; - bottom -= lpRect->bottom; - } - - void DeflateRect(int l, int t, int r, int b) - { - left += l; - top += t; - right -= r; - bottom -= b; - } - - void OffsetRect(int x, int y) - { - ::OffsetRect(this, x, y); - } - void OffsetRect(SIZE size) - { - ::OffsetRect(this, size.cx, size.cy); - } - - void OffsetRect(POINT point) - { - ::OffsetRect(this, point.x, point.y); - } - - void NormalizeRect() - { - int nTemp; - if (left > right) - { - nTemp = left; - left = right; - right = nTemp; - } - if (top > bottom) - { - nTemp = top; - top = bottom; - bottom = nTemp; - } - } - - // absolute position of rectangle - void MoveToY(int y) - { - bottom = Height() + y; - top = y; - } - - void MoveToX(int x) - { - right = Width() + x; - left = x; - } - - void MoveToXY(int x, int y) - { - MoveToX(x); - MoveToY(y); - } - - void MoveToXY(POINT pt) - { - MoveToX(pt.x); - MoveToY(pt.y); - } - - // operations that fill '*this' with result - BOOL IntersectRect(LPCRECT lpRect1, LPCRECT lpRect2) - { - return ::IntersectRect(this, lpRect1, lpRect2); - } - - BOOL UnionRect(LPCRECT lpRect1, LPCRECT lpRect2) - { - return ::UnionRect(this, lpRect1, lpRect2); - } - - BOOL SubtractRect(LPCRECT lpRectSrc1, LPCRECT lpRectSrc2) - { - return ::SubtractRect(this, lpRectSrc1, lpRectSrc2); - } - -// Additional Operations - void operator =(const RECT& srcRect) - { - ::CopyRect(this, &srcRect); - } - - BOOL operator ==(const RECT& rect) const - { - return ::EqualRect(this, &rect); - } - - BOOL operator !=(const RECT& rect) const - { - return !::EqualRect(this, &rect); - } - - void operator +=(POINT point) - { - ::OffsetRect(this, point.x, point.y); - } - - void operator +=(SIZE size) - { - ::OffsetRect(this, size.cx, size.cy); - } - - void operator +=(LPCRECT lpRect) - { - InflateRect(lpRect); - } - - void operator -=(POINT point) - { - ::OffsetRect(this, -point.x, -point.y); - } - - void operator -=(SIZE size) - { - ::OffsetRect(this, -size.cx, -size.cy); - } - - void operator -=(LPCRECT lpRect) - { - DeflateRect(lpRect); - } - - void operator &=(const RECT& rect) - { - ::IntersectRect(this, this, &rect); - } - - void operator |=(const RECT& rect) - { - ::UnionRect(this, this, &rect); - } - -// Operators returning CRect values - CRect operator +(POINT pt) const - { - CRect rect(*this); - ::OffsetRect(&rect, pt.x, pt.y); - return rect; - } - - CRect operator -(POINT pt) const - { - CRect rect(*this); - ::OffsetRect(&rect, -pt.x, -pt.y); - return rect; - } - - CRect operator +(LPCRECT lpRect) const - { - CRect rect(this); - rect.InflateRect(lpRect); - return rect; - } - - CRect operator +(SIZE size) const - { - CRect rect(*this); - ::OffsetRect(&rect, size.cx, size.cy); - return rect; - } - - CRect operator -(SIZE size) const - { - CRect rect(*this); - ::OffsetRect(&rect, -size.cx, -size.cy); - return rect; - } - - CRect operator -(LPCRECT lpRect) const - { - CRect rect(this); - rect.DeflateRect(lpRect); - return rect; - } - - CRect operator &(const RECT& rect2) const - { - CRect rect; - ::IntersectRect(&rect, this, &rect2); - return rect; - } - - CRect operator |(const RECT& rect2) const - { - CRect rect; - ::UnionRect(&rect, this, &rect2); - return rect; - } - - CRect MulDiv(int nMultiplier, int nDivisor) const - { - return CRect( - ::MulDiv(left, nMultiplier, nDivisor), - ::MulDiv(top, nMultiplier, nDivisor), - ::MulDiv(right, nMultiplier, nDivisor), - ::MulDiv(bottom, nMultiplier, nDivisor)); - } -}; - - -// CSize implementation - -inline CPoint CSize::operator +(POINT point) const -{ return CPoint(cx + point.x, cy + point.y); } - -inline CPoint CSize::operator -(POINT point) const -{ return CPoint(cx - point.x, cy - point.y); } - -inline CRect CSize::operator +(const RECT* lpRect) const -{ return CRect(lpRect) + *this; } - -inline CRect CSize::operator -(const RECT* lpRect) const -{ return CRect(lpRect) - *this; } - - -// CPoint implementation - -inline CRect CPoint::operator +(const RECT* lpRect) const -{ return CRect(lpRect) + *this; } - -inline CRect CPoint::operator -(const RECT* lpRect) const -{ return CRect(lpRect) - *this; } - -#endif // !_WTL_NO_WTYPES - - -// WTL::CSize or ATL::CSize scalar operators - -#if !defined(_WTL_NO_SIZE_SCALAR) && (!defined(_WTL_NO_WTYPES) || defined(__ATLTYPES_H__)) - -template -inline CSize operator *(SIZE s, Num n) -{ - return CSize((int)(s.cx * n), (int)(s.cy * n)); -}; - -template -inline void operator *=(SIZE & s, Num n) -{ - s = s * n; -}; - -template -inline CSize operator /(SIZE s, Num n) -{ - return CSize((int)(s.cx / n), (int)(s.cy / n)); -}; - -template -inline void operator /=(SIZE & s, Num n) -{ - s = s / n; -}; - -#endif // !defined(_WTL_NO_SIZE_SCALAR) && (!defined(_WTL_NO_WTYPES) || defined(__ATLTYPES_H__)) - - -/////////////////////////////////////////////////////////////////////////////// -// CString - String class - -#ifndef _WTL_NO_CSTRING - -struct CStringData -{ - long nRefs; // reference count - int nDataLength; - int nAllocLength; - // TCHAR data[nAllocLength] - - TCHAR* data() - { return (TCHAR*)(this + 1); } -}; - -// Globals - -// For an empty string, m_pchData will point here -// (note: avoids special case of checking for NULL m_pchData) -// empty string data (and locked) -_declspec(selectany) int rgInitData[] = { -1, 0, 0, 0 }; -_declspec(selectany) CStringData* _atltmpDataNil = (CStringData*)&rgInitData; -_declspec(selectany) LPCTSTR _atltmpPchNil = (LPCTSTR)(((BYTE*)&rgInitData) + sizeof(CStringData)); - - -class CString -{ -public: -// Constructors - CString() - { - Init(); - } - - CString(const CString& stringSrc) - { - ATLASSERT(stringSrc.GetData()->nRefs != 0); - if (stringSrc.GetData()->nRefs >= 0) - { - ATLASSERT(stringSrc.GetData() != _atltmpDataNil); - m_pchData = stringSrc.m_pchData; - InterlockedIncrement(&GetData()->nRefs); - } - else - { - Init(); - *this = stringSrc.m_pchData; - } - } - - CString(TCHAR ch, int nRepeat = 1) - { - ATLASSERT(!_istlead(ch)); // can't create a lead byte string - Init(); - if (nRepeat >= 1) - { - if(AllocBuffer(nRepeat)) - { -#ifdef _UNICODE - for (int i = 0; i < nRepeat; i++) - m_pchData[i] = ch; -#else - memset(m_pchData, ch, nRepeat); -#endif - } - } - } - - CString(LPCTSTR lpsz) - { - Init(); - if (lpsz != NULL && HIWORD(lpsz) == NULL) - { - UINT nID = LOWORD((DWORD_PTR)lpsz); - if (!LoadString(nID)) - ATLTRACE2(atlTraceUI, 0, _T("Warning: implicit LoadString(%u) in CString failed\n"), nID); - } - else - { - int nLen = SafeStrlen(lpsz); - if (nLen != 0) - { - if(AllocBuffer(nLen)) - SecureHelper::memcpy_x(m_pchData, (nLen + 1) * sizeof(TCHAR), lpsz, nLen * sizeof(TCHAR)); - } - } - } - -#ifdef _UNICODE - CString(LPCSTR lpsz) - { - Init(); -#if defined(_WIN32_WCE) && (_ATL_VER >= 0x0800) - int nSrcLen = (lpsz != NULL) ? ATL::lstrlenA(lpsz) : 0; -#else - int nSrcLen = (lpsz != NULL) ? lstrlenA(lpsz) : 0; -#endif - if (nSrcLen != 0) - { - if(AllocBuffer(nSrcLen)) - { - _mbstowcsz(m_pchData, lpsz, nSrcLen + 1); - ReleaseBuffer(); - } - } - } -#else // !_UNICODE - CString(LPCWSTR lpsz) - { - Init(); - int nSrcLen = (lpsz != NULL) ? (int)wcslen(lpsz) : 0; - if (nSrcLen != 0) - { - if(AllocBuffer(nSrcLen * 2)) - { - _wcstombsz(m_pchData, lpsz, (nSrcLen * 2) + 1); - ReleaseBuffer(); - } - } - } -#endif // !_UNICODE - - CString(LPCTSTR lpch, int nLength) - { - Init(); - if (nLength != 0) - { - if(AllocBuffer(nLength)) - SecureHelper::memcpy_x(m_pchData, (nLength + 1) * sizeof(TCHAR), lpch, nLength * sizeof(TCHAR)); - } - } - -#ifdef _UNICODE - CString(LPCSTR lpsz, int nLength) - { - Init(); - if (nLength != 0) - { - if(AllocBuffer(nLength)) - { - int n = ::MultiByteToWideChar(CP_ACP, 0, lpsz, nLength, m_pchData, nLength + 1); - ReleaseBuffer((n >= 0) ? n : -1); - } - } - } -#else // !_UNICODE - CString(LPCWSTR lpsz, int nLength) - { - Init(); - if (nLength != 0) - { - if(((nLength * 2) > nLength) && AllocBuffer(nLength * 2)) - { - int n = ::WideCharToMultiByte(CP_ACP, 0, lpsz, nLength, m_pchData, (nLength * 2) + 1, NULL, NULL); - ReleaseBuffer((n >= 0) ? n : -1); - } - } - } -#endif // !_UNICODE - - CString(const unsigned char* lpsz) - { - Init(); - *this = (LPCSTR)lpsz; - } - -// Attributes & Operations - int GetLength() const // as an array of characters - { - return GetData()->nDataLength; - } - - BOOL IsEmpty() const - { - return GetData()->nDataLength == 0; - } - - void Empty() // free up the data - { - if (GetData()->nDataLength == 0) - return; - - if (GetData()->nRefs >= 0) - Release(); - else - *this = _T(""); - - ATLASSERT(GetData()->nDataLength == 0); - ATLASSERT(GetData()->nRefs < 0 || GetData()->nAllocLength == 0); - } - - TCHAR GetAt(int nIndex) const // 0 based - { - ATLASSERT(nIndex >= 0); - ATLASSERT(nIndex < GetData()->nDataLength); - return m_pchData[nIndex]; - } - - TCHAR operator [](int nIndex) const // same as GetAt - { - // same as GetAt - ATLASSERT(nIndex >= 0); - ATLASSERT(nIndex < GetData()->nDataLength); - return m_pchData[nIndex]; - } - - void SetAt(int nIndex, TCHAR ch) - { - ATLASSERT(nIndex >= 0); - ATLASSERT(nIndex < GetData()->nDataLength); - - CopyBeforeWrite(); - m_pchData[nIndex] = ch; - } - - operator LPCTSTR() const // as a C string - { - return m_pchData; - } - - // overloaded assignment - CString& operator =(const CString& stringSrc) - { - if (m_pchData != stringSrc.m_pchData) - { - if ((GetData()->nRefs < 0 && GetData() != _atltmpDataNil) || stringSrc.GetData()->nRefs < 0) - { - // actual copy necessary since one of the strings is locked - AssignCopy(stringSrc.GetData()->nDataLength, stringSrc.m_pchData); - } - else - { - // can just copy references around - Release(); - ATLASSERT(stringSrc.GetData() != _atltmpDataNil); - m_pchData = stringSrc.m_pchData; - InterlockedIncrement(&GetData()->nRefs); - } - } - return *this; - } - - CString& operator =(TCHAR ch) - { - ATLASSERT(!_istlead(ch)); // can't set single lead byte - AssignCopy(1, &ch); - return *this; - } - -#ifdef _UNICODE - CString& operator =(char ch) - { - *this = (TCHAR)ch; - return *this; - } -#endif - - CString& operator =(LPCTSTR lpsz) - { - ATLASSERT(lpsz == NULL || _IsValidString(lpsz)); - AssignCopy(SafeStrlen(lpsz), lpsz); - return *this; - } - -#ifdef _UNICODE - CString& operator =(LPCSTR lpsz) - { -#if defined(_WIN32_WCE) && (_ATL_VER >= 0x0800) - int nSrcLen = (lpsz != NULL) ? ATL::lstrlenA(lpsz) : 0; -#else - int nSrcLen = (lpsz != NULL) ? lstrlenA(lpsz) : 0; -#endif - if(AllocBeforeWrite(nSrcLen)) - { - _mbstowcsz(m_pchData, lpsz, nSrcLen + 1); - ReleaseBuffer(); - } - return *this; - } -#else // !_UNICODE - CString& operator =(LPCWSTR lpsz) - { - int nSrcLen = (lpsz != NULL) ? (int)wcslen(lpsz) : 0; - if(AllocBeforeWrite(nSrcLen * 2)) - { - _wcstombsz(m_pchData, lpsz, (nSrcLen * 2) + 1); - ReleaseBuffer(); - } - return *this; - } -#endif // !_UNICODE - - CString& operator =(const unsigned char* lpsz) - { - *this = (LPCSTR)lpsz; - return *this; - } - - // string concatenation - CString& operator +=(const CString& string) - { - ConcatInPlace(string.GetData()->nDataLength, string.m_pchData); - return *this; - } - - CString& operator +=(TCHAR ch) - { - ConcatInPlace(1, &ch); - return *this; - } - -#ifdef _UNICODE - CString& operator +=(char ch) - { - *this += (TCHAR)ch; - return *this; - } -#endif - - CString& operator +=(LPCTSTR lpsz) - { - ATLASSERT(lpsz == NULL || _IsValidString(lpsz)); - ConcatInPlace(SafeStrlen(lpsz), lpsz); - return *this; - } - - friend CString __stdcall operator +(const CString& string1, const CString& string2); - friend CString __stdcall operator +(const CString& string, TCHAR ch); - friend CString __stdcall operator +(TCHAR ch, const CString& string); -#ifdef _UNICODE - friend CString __stdcall operator +(const CString& string, char ch); - friend CString __stdcall operator +(char ch, const CString& string); -#endif - friend CString __stdcall operator +(const CString& string, LPCTSTR lpsz); - friend CString __stdcall operator +(LPCTSTR lpsz, const CString& string); - - // string comparison - int Compare(LPCTSTR lpsz) const // straight character (MBCS/Unicode aware) - { - return _cstrcmp(m_pchData, lpsz); - } - - int CompareNoCase(LPCTSTR lpsz) const // ignore case (MBCS/Unicode aware) - { - return _cstrcmpi(m_pchData, lpsz); - } - -#ifndef _WIN32_WCE - // CString::Collate is often slower than Compare but is MBSC/Unicode - // aware as well as locale-sensitive with respect to sort order. - int Collate(LPCTSTR lpsz) const // NLS aware - { - return _cstrcoll(m_pchData, lpsz); - } - - int CollateNoCase(LPCTSTR lpsz) const // ignore case - { - return _cstrcolli(m_pchData, lpsz); - } -#endif // !_WIN32_WCE - - // simple sub-string extraction - CString Mid(int nFirst, int nCount) const - { - // out-of-bounds requests return sensible things - if (nFirst < 0) - nFirst = 0; - if (nCount < 0) - nCount = 0; - - if (nFirst + nCount > GetData()->nDataLength) - nCount = GetData()->nDataLength - nFirst; - if (nFirst > GetData()->nDataLength) - nCount = 0; - - CString dest; - AllocCopy(dest, nCount, nFirst, 0); - return dest; - } - - CString Mid(int nFirst) const - { - return Mid(nFirst, GetData()->nDataLength - nFirst); - } - - CString Left(int nCount) const - { - if (nCount < 0) - nCount = 0; - else if (nCount > GetData()->nDataLength) - nCount = GetData()->nDataLength; - - CString dest; - AllocCopy(dest, nCount, 0, 0); - return dest; - } - - CString Right(int nCount) const - { - if (nCount < 0) - nCount = 0; - else if (nCount > GetData()->nDataLength) - nCount = GetData()->nDataLength; - - CString dest; - AllocCopy(dest, nCount, GetData()->nDataLength-nCount, 0); - return dest; - } - - CString SpanIncluding(LPCTSTR lpszCharSet) const // strspn equivalent - { - ATLASSERT(_IsValidString(lpszCharSet)); - return Left(_cstrspn(m_pchData, lpszCharSet)); - } - - CString SpanExcluding(LPCTSTR lpszCharSet) const // strcspn equivalent - { - ATLASSERT(_IsValidString(lpszCharSet)); - return Left(_cstrcspn(m_pchData, lpszCharSet)); - } - - // upper/lower/reverse conversion - void MakeUpper() - { - CopyBeforeWrite(); - CharUpper(m_pchData); - } - - void MakeLower() - { - CopyBeforeWrite(); - CharLower(m_pchData); - } - - void MakeReverse() - { - CopyBeforeWrite(); - _cstrrev(m_pchData); - } - - // trimming whitespace (either side) - void TrimRight() - { - CopyBeforeWrite(); - - // find beginning of trailing spaces by starting at beginning (DBCS aware) - LPTSTR lpsz = m_pchData; - LPTSTR lpszLast = NULL; - while (*lpsz != _T('\0')) - { - if (_cstrisspace(*lpsz)) - { - if (lpszLast == NULL) - lpszLast = lpsz; - } - else - { - lpszLast = NULL; - } - lpsz = ::CharNext(lpsz); - } - - if (lpszLast != NULL) - { - // truncate at trailing space start - *lpszLast = _T('\0'); - GetData()->nDataLength = (int)(DWORD_PTR)(lpszLast - m_pchData); - } - } - - void TrimLeft() - { - CopyBeforeWrite(); - - // find first non-space character - LPCTSTR lpsz = m_pchData; - while (_cstrisspace(*lpsz)) - lpsz = ::CharNext(lpsz); - - // fix up data and length - int nDataLength = GetData()->nDataLength - (int)(DWORD_PTR)(lpsz - m_pchData); - SecureHelper::memmove_x(m_pchData, (GetData()->nAllocLength + 1) * sizeof(TCHAR), lpsz, (nDataLength + 1) * sizeof(TCHAR)); - GetData()->nDataLength = nDataLength; - } - - // remove continuous occurrences of chTarget starting from right - void TrimRight(TCHAR chTarget) - { - // find beginning of trailing matches - // by starting at beginning (DBCS aware) - - CopyBeforeWrite(); - LPTSTR lpsz = m_pchData; - LPTSTR lpszLast = NULL; - - while (*lpsz != _T('\0')) - { - if (*lpsz == chTarget) - { - if (lpszLast == NULL) - lpszLast = lpsz; - } - else - lpszLast = NULL; - lpsz = ::CharNext(lpsz); - } - - if (lpszLast != NULL) - { - // truncate at left-most matching character - *lpszLast = _T('\0'); - GetData()->nDataLength = (int)(DWORD_PTR)(lpszLast - m_pchData); - } - } - - // remove continuous occcurrences of characters in passed string, starting from right - void TrimRight(LPCTSTR lpszTargetList) - { - // find beginning of trailing matches by starting at beginning (DBCS aware) - - CopyBeforeWrite(); - LPTSTR lpsz = m_pchData; - LPTSTR lpszLast = NULL; - - while (*lpsz != _T('\0')) - { - TCHAR* pNext = ::CharNext(lpsz); - if(pNext > lpsz + 1) - { - if (_cstrchr_db(lpszTargetList, *lpsz, *(lpsz + 1)) != NULL) - { - if (lpszLast == NULL) - lpszLast = lpsz; - } - else - { - lpszLast = NULL; - } - } - else - { - if (_cstrchr(lpszTargetList, *lpsz) != NULL) - { - if (lpszLast == NULL) - lpszLast = lpsz; - } - else - { - lpszLast = NULL; - } - } - - lpsz = pNext; - } - - if (lpszLast != NULL) - { - // truncate at left-most matching character - *lpszLast = _T('\0'); - GetData()->nDataLength = (int)(DWORD_PTR)(lpszLast - m_pchData); - } - } - - // remove continuous occurrences of chTarget starting from left - void TrimLeft(TCHAR chTarget) - { - // find first non-matching character - - CopyBeforeWrite(); - LPCTSTR lpsz = m_pchData; - - while (chTarget == *lpsz) - lpsz = ::CharNext(lpsz); - - if (lpsz != m_pchData) - { - // fix up data and length - int nDataLength = GetData()->nDataLength - (int)(DWORD_PTR)(lpsz - m_pchData); - SecureHelper::memmove_x(m_pchData, (GetData()->nAllocLength + 1) * sizeof(TCHAR), lpsz, (nDataLength + 1) * sizeof(TCHAR)); - GetData()->nDataLength = nDataLength; - } - } - - // remove continuous occcurrences of characters in passed string, starting from left - void TrimLeft(LPCTSTR lpszTargets) - { - // if we're not trimming anything, we're not doing any work - if (SafeStrlen(lpszTargets) == 0) - return; - - CopyBeforeWrite(); - LPCTSTR lpsz = m_pchData; - - while (*lpsz != _T('\0')) - { - TCHAR* pNext = ::CharNext(lpsz); - if(pNext > lpsz + 1) - { - if (_cstrchr_db(lpszTargets, *lpsz, *(lpsz + 1)) == NULL) - break; - } - else - { - if (_cstrchr(lpszTargets, *lpsz) == NULL) - break; - } - lpsz = pNext; - } - - if (lpsz != m_pchData) - { - // fix up data and length - int nDataLength = GetData()->nDataLength - (int)(DWORD_PTR)(lpsz - m_pchData); - SecureHelper::memmove_x(m_pchData, (GetData()->nAllocLength + 1) * sizeof(TCHAR), lpsz, (nDataLength + 1) * sizeof(TCHAR)); - GetData()->nDataLength = nDataLength; - } - } - - // advanced manipulation - // replace occurrences of chOld with chNew - int Replace(TCHAR chOld, TCHAR chNew) - { - int nCount = 0; - - // short-circuit the nop case - if (chOld != chNew) - { - // otherwise modify each character that matches in the string - CopyBeforeWrite(); - LPTSTR psz = m_pchData; - LPTSTR pszEnd = psz + GetData()->nDataLength; - while (psz < pszEnd) - { - // replace instances of the specified character only - if (*psz == chOld) - { - *psz = chNew; - nCount++; - } - psz = ::CharNext(psz); - } - } - return nCount; - } - - // replace occurrences of substring lpszOld with lpszNew; - // empty lpszNew removes instances of lpszOld - int Replace(LPCTSTR lpszOld, LPCTSTR lpszNew) - { - // can't have empty or NULL lpszOld - - int nSourceLen = SafeStrlen(lpszOld); - if (nSourceLen == 0) - return 0; - int nReplacementLen = SafeStrlen(lpszNew); - - // loop once to figure out the size of the result string - int nCount = 0; - LPTSTR lpszStart = m_pchData; - LPTSTR lpszEnd = m_pchData + GetData()->nDataLength; - LPTSTR lpszTarget = NULL; - while (lpszStart < lpszEnd) - { - while ((lpszTarget = (TCHAR*)_cstrstr(lpszStart, lpszOld)) != NULL) - { - nCount++; - lpszStart = lpszTarget + nSourceLen; - } - lpszStart += lstrlen(lpszStart) + 1; - } - - // if any changes were made, make them - if (nCount > 0) - { - CopyBeforeWrite(); - - // if the buffer is too small, just allocate a new buffer (slow but sure) - int nOldLength = GetData()->nDataLength; - int nNewLength = nOldLength + (nReplacementLen - nSourceLen) * nCount; - if (GetData()->nAllocLength < nNewLength || GetData()->nRefs > 1) - { - CStringData* pOldData = GetData(); - LPTSTR pstr = m_pchData; - if(!AllocBuffer(nNewLength)) - return -1; - SecureHelper::memcpy_x(m_pchData, (nNewLength + 1) * sizeof(TCHAR), pstr, pOldData->nDataLength * sizeof(TCHAR)); - CString::Release(pOldData); - } - // else, we just do it in-place - lpszStart = m_pchData; - lpszEnd = m_pchData + GetData()->nDataLength; - - // loop again to actually do the work - while (lpszStart < lpszEnd) - { - while ((lpszTarget = (TCHAR*)_cstrstr(lpszStart, lpszOld)) != NULL) - { - int nBalance = nOldLength - ((int)(DWORD_PTR)(lpszTarget - m_pchData) + nSourceLen); - int cchBuffLen = GetData()->nAllocLength - (int)(DWORD_PTR)(lpszTarget - m_pchData); - SecureHelper::memmove_x(lpszTarget + nReplacementLen, (cchBuffLen - nReplacementLen + 1) * sizeof(TCHAR), lpszTarget + nSourceLen, nBalance * sizeof(TCHAR)); - SecureHelper::memcpy_x(lpszTarget, (cchBuffLen + 1) * sizeof(TCHAR), lpszNew, nReplacementLen * sizeof(TCHAR)); - lpszStart = lpszTarget + nReplacementLen; - lpszStart[nBalance] = _T('\0'); - nOldLength += (nReplacementLen - nSourceLen); - } - lpszStart += lstrlen(lpszStart) + 1; - } - ATLASSERT(m_pchData[nNewLength] == _T('\0')); - GetData()->nDataLength = nNewLength; - } - - return nCount; - } - - // remove occurrences of chRemove - int Remove(TCHAR chRemove) - { - CopyBeforeWrite(); - - LPTSTR pstrSource = m_pchData; - LPTSTR pstrDest = m_pchData; - LPTSTR pstrEnd = m_pchData + GetData()->nDataLength; - - while (pstrSource < pstrEnd) - { - if (*pstrSource != chRemove) - { - *pstrDest = *pstrSource; - pstrDest = ::CharNext(pstrDest); - } - pstrSource = ::CharNext(pstrSource); - } - *pstrDest = _T('\0'); - int nCount = (int)(DWORD_PTR)(pstrSource - pstrDest); - GetData()->nDataLength -= nCount; - - return nCount; - } - - // insert character at zero-based index; concatenates if index is past end of string - int Insert(int nIndex, TCHAR ch) - { - CopyBeforeWrite(); - - if (nIndex < 0) - nIndex = 0; - - int nNewLength = GetData()->nDataLength; - if (nIndex > nNewLength) - nIndex = nNewLength; - nNewLength++; - - if (GetData()->nAllocLength < nNewLength) - { - CStringData* pOldData = GetData(); - LPTSTR pstr = m_pchData; - if(!AllocBuffer(nNewLength)) - return -1; - SecureHelper::memcpy_x(m_pchData, (nNewLength + 1) * sizeof(TCHAR), pstr, (pOldData->nDataLength + 1) * sizeof(TCHAR)); - CString::Release(pOldData); - } - - // move existing bytes down - SecureHelper::memmove_x(m_pchData + nIndex + 1, (GetData()->nAllocLength - nIndex) * sizeof(TCHAR), m_pchData + nIndex, (nNewLength - nIndex) * sizeof(TCHAR)); - m_pchData[nIndex] = ch; - GetData()->nDataLength = nNewLength; - - return nNewLength; - } - - // insert substring at zero-based index; concatenates if index is past end of string - int Insert(int nIndex, LPCTSTR pstr) - { - if (nIndex < 0) - nIndex = 0; - - int nInsertLength = SafeStrlen(pstr); - int nNewLength = GetData()->nDataLength; - if (nInsertLength > 0) - { - CopyBeforeWrite(); - if (nIndex > nNewLength) - nIndex = nNewLength; - nNewLength += nInsertLength; - - if (GetData()->nAllocLength < nNewLength) - { - CStringData* pOldData = GetData(); - LPTSTR pstr = m_pchData; - if(!AllocBuffer(nNewLength)) - return -1; - SecureHelper::memcpy_x(m_pchData, (nNewLength + 1) * sizeof(TCHAR), pstr, (pOldData->nDataLength + 1) * sizeof(TCHAR)); - CString::Release(pOldData); - } - - // move existing bytes down - SecureHelper::memmove_x(m_pchData + nIndex + nInsertLength, (GetData()->nAllocLength + 1 - nIndex - nInsertLength) * sizeof(TCHAR), m_pchData + nIndex, (nNewLength - nIndex - nInsertLength + 1) * sizeof(TCHAR)); - SecureHelper::memcpy_x(m_pchData + nIndex, (GetData()->nAllocLength + 1 - nIndex) * sizeof(TCHAR), pstr, nInsertLength * sizeof(TCHAR)); - GetData()->nDataLength = nNewLength; - } - - return nNewLength; - } - - // delete nCount characters starting at zero-based index - int Delete(int nIndex, int nCount = 1) - { - if (nIndex < 0) - nIndex = 0; - int nLength = GetData()->nDataLength; - if (nCount > 0 && nIndex < nLength) - { - if((nIndex + nCount) > nLength) - nCount = nLength - nIndex; - CopyBeforeWrite(); - int nBytesToCopy = nLength - (nIndex + nCount) + 1; - - SecureHelper::memmove_x(m_pchData + nIndex, (GetData()->nAllocLength + 1 - nIndex) * sizeof(TCHAR), m_pchData + nIndex + nCount, nBytesToCopy * sizeof(TCHAR)); - nLength -= nCount; - GetData()->nDataLength = nLength; - } - - return nLength; - } - - // searching (return starting index, or -1 if not found) - // look for a single character match - int Find(TCHAR ch) const // like "C" strchr - { - return Find(ch, 0); - } - - int ReverseFind(TCHAR ch) const - { - // find last single character - LPCTSTR lpsz = _cstrrchr(m_pchData, (_TUCHAR)ch); - - // return -1 if not found, distance from beginning otherwise - return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData); - } - - int Find(TCHAR ch, int nStart) const // starting at index - { - int nLength = GetData()->nDataLength; - if (nStart < 0 || nStart >= nLength) - return -1; - - // find first single character - LPCTSTR lpsz = _cstrchr(m_pchData + nStart, (_TUCHAR)ch); - - // return -1 if not found and index otherwise - return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData); - } - - int FindOneOf(LPCTSTR lpszCharSet) const - { - ATLASSERT(_IsValidString(lpszCharSet)); - LPCTSTR lpsz = _cstrpbrk(m_pchData, lpszCharSet); - return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData); - } - - // look for a specific sub-string - // find a sub-string (like strstr) - int Find(LPCTSTR lpszSub) const // like "C" strstr - { - return Find(lpszSub, 0); - } - - int Find(LPCTSTR lpszSub, int nStart) const // starting at index - { - ATLASSERT(_IsValidString(lpszSub)); - - int nLength = GetData()->nDataLength; - if (nStart < 0 || nStart > nLength) - return -1; - - // find first matching substring - LPCTSTR lpsz = _cstrstr(m_pchData + nStart, lpszSub); - - // return -1 for not found, distance from beginning otherwise - return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData); - } - - // Concatentation for non strings - CString& Append(int n) - { - const int cchBuff = 12; - TCHAR szBuffer[cchBuff] = { 0 }; - SecureHelper::wsprintf_x(szBuffer, cchBuff, _T("%d"), n); - ConcatInPlace(SafeStrlen(szBuffer), szBuffer); - return *this; - } - - // simple formatting - // formatting (using wsprintf style formatting) - BOOL __cdecl Format(LPCTSTR lpszFormat, ...) - { - ATLASSERT(_IsValidString(lpszFormat)); - - va_list argList; - va_start(argList, lpszFormat); - BOOL bRet = FormatV(lpszFormat, argList); - va_end(argList); - return bRet; - } - - BOOL __cdecl Format(UINT nFormatID, ...) - { - CString strFormat; - BOOL bRet = strFormat.LoadString(nFormatID); - ATLASSERT(bRet != 0); - - va_list argList; - va_start(argList, nFormatID); - bRet = FormatV(strFormat, argList); - va_end(argList); - return bRet; - } - - BOOL FormatV(LPCTSTR lpszFormat, va_list argList) - { - ATLASSERT(_IsValidString(lpszFormat)); - - enum _FormatModifiers - { - FORCE_ANSI = 0x10000, - FORCE_UNICODE = 0x20000, - FORCE_INT64 = 0x40000 - }; - - va_list argListSave = argList; - - // make a guess at the maximum length of the resulting string - int nMaxLen = 0; - for (LPCTSTR lpsz = lpszFormat; *lpsz != _T('\0'); lpsz = ::CharNext(lpsz)) - { - // handle '%' character, but watch out for '%%' - if (*lpsz != _T('%') || *(lpsz = ::CharNext(lpsz)) == _T('%')) - { - nMaxLen += (int)(::CharNext(lpsz) - lpsz); - continue; - } - - int nItemLen = 0; - - // handle '%' character with format - int nWidth = 0; - for (; *lpsz != _T('\0'); lpsz = ::CharNext(lpsz)) - { - // check for valid flags - if (*lpsz == _T('#')) - nMaxLen += 2; // for '0x' - else if (*lpsz == _T('*')) - nWidth = va_arg(argList, int); - else if (*lpsz == _T('-') || *lpsz == _T('+') || *lpsz == _T('0') || *lpsz == _T(' ')) - ; - else // hit non-flag character - break; - } - // get width and skip it - if (nWidth == 0) - { - // width indicated by - nWidth = _cstrtoi(lpsz); - for (; *lpsz != _T('\0') && _cstrisdigit(*lpsz); lpsz = ::CharNext(lpsz)) - ; - } - ATLASSERT(nWidth >= 0); - - int nPrecision = 0; - if (*lpsz == _T('.')) - { - // skip past '.' separator (width.precision) - lpsz = ::CharNext(lpsz); - - // get precision and skip it - if (*lpsz == _T('*')) - { - nPrecision = va_arg(argList, int); - lpsz = ::CharNext(lpsz); - } - else - { - nPrecision = _cstrtoi(lpsz); - for (; *lpsz != _T('\0') && _cstrisdigit(*lpsz); lpsz = ::CharNext(lpsz)) - ; - } - ATLASSERT(nPrecision >= 0); - } - - // should be on type modifier or specifier - int nModifier = 0; - if(lpsz[0] == _T('I') && lpsz[1] == _T('6') && lpsz[2] == _T('4')) - { - lpsz += 3; - nModifier = FORCE_INT64; - } - else - { - switch (*lpsz) - { - // modifiers that affect size - case _T('h'): - nModifier = FORCE_ANSI; - lpsz = ::CharNext(lpsz); - break; - case _T('l'): - nModifier = FORCE_UNICODE; - lpsz = ::CharNext(lpsz); - break; - - // modifiers that do not affect size - case _T('F'): - case _T('N'): - case _T('L'): - lpsz = ::CharNext(lpsz); - break; - } - } - - // now should be on specifier - switch (*lpsz | nModifier) - { - // single characters - case _T('c'): - case _T('C'): - nItemLen = 2; - va_arg(argList, TCHAR); - break; - case _T('c') | FORCE_ANSI: - case _T('C') | FORCE_ANSI: - nItemLen = 2; - va_arg(argList, char); - break; - case _T('c') | FORCE_UNICODE: - case _T('C') | FORCE_UNICODE: - nItemLen = 2; - va_arg(argList, WCHAR); - break; - - // strings - case _T('s'): - { - LPCTSTR pstrNextArg = va_arg(argList, LPCTSTR); - if (pstrNextArg == NULL) - { - nItemLen = 6; // "(null)" - } - else - { - nItemLen = lstrlen(pstrNextArg); - nItemLen = max(1, nItemLen); - } - break; - } - - case _T('S'): - { -#ifndef _UNICODE - LPWSTR pstrNextArg = va_arg(argList, LPWSTR); - if (pstrNextArg == NULL) - { - nItemLen = 6; // "(null)" - } - else - { - nItemLen = (int)wcslen(pstrNextArg); - nItemLen = max(1, nItemLen); - } -#else // _UNICODE - LPCSTR pstrNextArg = va_arg(argList, LPCSTR); - if (pstrNextArg == NULL) - { - nItemLen = 6; // "(null)" - } - else - { -#if defined(_WIN32_WCE) && (_ATL_VER >= 0x0800) - nItemLen = ATL::lstrlenA(pstrNextArg); -#else - nItemLen = lstrlenA(pstrNextArg); -#endif - nItemLen = max(1, nItemLen); - } -#endif // _UNICODE - break; - } - - case _T('s') | FORCE_ANSI: - case _T('S') | FORCE_ANSI: - { - LPCSTR pstrNextArg = va_arg(argList, LPCSTR); - if (pstrNextArg == NULL) - { - nItemLen = 6; // "(null)" - } - else - { -#if defined(_WIN32_WCE) && (_ATL_VER >= 0x0800) - nItemLen = ATL::lstrlenA(pstrNextArg); -#else - nItemLen = lstrlenA(pstrNextArg); -#endif - nItemLen = max(1, nItemLen); - } - break; - } - - case _T('s') | FORCE_UNICODE: - case _T('S') | FORCE_UNICODE: - { - LPWSTR pstrNextArg = va_arg(argList, LPWSTR); - if (pstrNextArg == NULL) - { - nItemLen = 6; // "(null)" - } - else - { - nItemLen = (int)wcslen(pstrNextArg); - nItemLen = max(1, nItemLen); - } - break; - } - } - - // adjust nItemLen for strings - if (nItemLen != 0) - { - nItemLen = max(nItemLen, nWidth); - if (nPrecision != 0) - nItemLen = min(nItemLen, nPrecision); - } - else - { - switch (*lpsz) - { - // integers - case _T('d'): - case _T('i'): - case _T('u'): - case _T('x'): - case _T('X'): - case _T('o'): - if (nModifier & FORCE_INT64) - va_arg(argList, __int64); - else - va_arg(argList, int); - nItemLen = 32; - nItemLen = max(nItemLen, nWidth + nPrecision); - break; - -#ifndef _ATL_USE_CSTRING_FLOAT - case _T('e'): - case _T('E'): - case _T('f'): - case _T('g'): - case _T('G'): - ATLASSERT(!"Floating point (%%e, %%E, %%f, %%g, and %%G) is not supported by the WTL::CString class."); -#ifndef _DEBUG - ::OutputDebugString(_T("Floating point (%%e, %%f, %%g, and %%G) is not supported by the WTL::CString class.")); -#ifndef _WIN32_WCE - ::DebugBreak(); -#else // CE specific - DebugBreak(); -#endif // _WIN32_WCE -#endif // !_DEBUG - break; -#else // _ATL_USE_CSTRING_FLOAT - case _T('e'): - case _T('E'): - case _T('g'): - case _T('G'): - va_arg(argList, double); - nItemLen = 128; - nItemLen = max(nItemLen, nWidth + nPrecision); - break; - case _T('f'): - { - double f = va_arg(argList, double); - // 312 == strlen("-1+(309 zeroes).") - // 309 zeroes == max precision of a double - // 6 == adjustment in case precision is not specified, - // which means that the precision defaults to 6 - int cchLen = max(nWidth, 312 + nPrecision + 6); - CTempBuffer buff; - LPTSTR pszTemp = buff.Allocate(cchLen); - if(pszTemp != NULL) - { - SecureHelper::sprintf_x(pszTemp, cchLen, _T("%*.*f"), nWidth, nPrecision + 6, f); - nItemLen = (int)_tcslen(pszTemp); - } - else - { - nItemLen = cchLen; - } - } - break; -#endif // _ATL_USE_CSTRING_FLOAT - - case _T('p'): - va_arg(argList, void*); - nItemLen = 32; - nItemLen = max(nItemLen, nWidth + nPrecision); - break; - - // no output - case _T('n'): - va_arg(argList, int*); - break; - - default: - ATLASSERT(FALSE); // unknown formatting option - } - } - - // adjust nMaxLen for output nItemLen - nMaxLen += nItemLen; - } - - if(GetBuffer(nMaxLen) == NULL) - return FALSE; -#ifndef _ATL_USE_CSTRING_FLOAT - int nRet = SecureHelper::wvsprintf_x(m_pchData, GetAllocLength() + 1, lpszFormat, argListSave); -#else // _ATL_USE_CSTRING_FLOAT - int nRet = SecureHelper::vsprintf_x(m_pchData, GetAllocLength() + 1, lpszFormat, argListSave); -#endif // _ATL_USE_CSTRING_FLOAT - nRet; // ref - ATLASSERT(nRet <= GetAllocLength()); - ReleaseBuffer(); - - va_end(argListSave); - return TRUE; - } - - // formatting for localization (uses FormatMessage API) - // formatting (using FormatMessage style formatting) - BOOL __cdecl FormatMessage(LPCTSTR lpszFormat, ...) - { - // format message into temporary buffer lpszTemp - va_list argList; - va_start(argList, lpszFormat); - LPTSTR lpszTemp; - BOOL bRet = TRUE; - - if (::FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER, - lpszFormat, 0, 0, (LPTSTR)&lpszTemp, 0, &argList) == 0 || lpszTemp == NULL) - bRet = FALSE; - - // assign lpszTemp into the resulting string and free the temporary - *this = lpszTemp; - LocalFree(lpszTemp); - va_end(argList); - return bRet; - } - - BOOL __cdecl FormatMessage(UINT nFormatID, ...) - { - // get format string from string table - CString strFormat; - BOOL bRetTmp = strFormat.LoadString(nFormatID); - bRetTmp; // ref - ATLASSERT(bRetTmp != 0); - - // format message into temporary buffer lpszTemp - va_list argList; - va_start(argList, nFormatID); - LPTSTR lpszTemp; - BOOL bRet = TRUE; - - if (::FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER, - strFormat, 0, 0, (LPTSTR)&lpszTemp, 0, &argList) == 0 || lpszTemp == NULL) - bRet = FALSE; - - // assign lpszTemp into the resulting string and free lpszTemp - *this = lpszTemp; - LocalFree(lpszTemp); - va_end(argList); - return bRet; - } - - // Windows support - BOOL LoadString(UINT nID) // load from string resource (255 chars max.) - { -#ifdef _UNICODE - const int CHAR_FUDGE = 1; // one TCHAR unused is good enough -#else - const int CHAR_FUDGE = 2; // two BYTES unused for case of DBC last char -#endif - - // try fixed buffer first (to avoid wasting space in the heap) - TCHAR szTemp[256]; - int nCount = sizeof(szTemp) / sizeof(szTemp[0]); - int nLen = _LoadString(nID, szTemp, nCount); - if (nCount - nLen > CHAR_FUDGE) - { - *this = szTemp; - return (nLen > 0); - } - - // try buffer size of 512, then larger size until entire string is retrieved - int nSize = 256; - do - { - nSize += 256; - LPTSTR lpstr = GetBuffer(nSize - 1); - if(lpstr == NULL) - { - nLen = 0; - break; - } - nLen = _LoadString(nID, lpstr, nSize); - } while (nSize - nLen <= CHAR_FUDGE); - ReleaseBuffer(); - - return (nLen > 0); - } - -#ifndef _UNICODE - // ANSI <-> OEM support (convert string in place) - void AnsiToOem() - { - CopyBeforeWrite(); - ::AnsiToOem(m_pchData, m_pchData); - } - - void OemToAnsi() - { - CopyBeforeWrite(); - ::OemToAnsi(m_pchData, m_pchData); - } -#endif - -#ifndef _ATL_NO_COM - // OLE BSTR support (use for OLE automation) - BSTR AllocSysString() const - { -#if defined(_UNICODE) || defined(OLE2ANSI) - BSTR bstr = ::SysAllocStringLen(m_pchData, GetData()->nDataLength); -#else - int nLen = MultiByteToWideChar(CP_ACP, 0, m_pchData, - GetData()->nDataLength, NULL, NULL); - BSTR bstr = ::SysAllocStringLen(NULL, nLen); - if(bstr != NULL) - MultiByteToWideChar(CP_ACP, 0, m_pchData, GetData()->nDataLength, bstr, nLen); -#endif - return bstr; - } - - BSTR SetSysString(BSTR* pbstr) const - { -#if defined(_UNICODE) || defined(OLE2ANSI) - ::SysReAllocStringLen(pbstr, m_pchData, GetData()->nDataLength); -#else - int nLen = MultiByteToWideChar(CP_ACP, 0, m_pchData, - GetData()->nDataLength, NULL, NULL); - if(::SysReAllocStringLen(pbstr, NULL, nLen)) - MultiByteToWideChar(CP_ACP, 0, m_pchData, GetData()->nDataLength, *pbstr, nLen); -#endif - ATLASSERT(*pbstr != NULL); - return *pbstr; - } -#endif // !_ATL_NO_COM - - // Access to string implementation buffer as "C" character array - LPTSTR GetBuffer(int nMinBufLength) - { - ATLASSERT(nMinBufLength >= 0); - - if (GetData()->nRefs > 1 || nMinBufLength > GetData()->nAllocLength) - { - // we have to grow the buffer - CStringData* pOldData = GetData(); - int nOldLen = GetData()->nDataLength; // AllocBuffer will tromp it - if (nMinBufLength < nOldLen) - nMinBufLength = nOldLen; - - if(!AllocBuffer(nMinBufLength)) - return NULL; - - SecureHelper::memcpy_x(m_pchData, (nMinBufLength + 1) * sizeof(TCHAR), pOldData->data(), (nOldLen + 1) * sizeof(TCHAR)); - GetData()->nDataLength = nOldLen; - CString::Release(pOldData); - } - ATLASSERT(GetData()->nRefs <= 1); - - // return a pointer to the character storage for this string - ATLASSERT(m_pchData != NULL); - return m_pchData; - } - - void ReleaseBuffer(int nNewLength = -1) - { - CopyBeforeWrite(); // just in case GetBuffer was not called - - if (nNewLength == -1) - nNewLength = lstrlen(m_pchData); // zero terminated - - ATLASSERT(nNewLength <= GetData()->nAllocLength); - GetData()->nDataLength = nNewLength; - m_pchData[nNewLength] = _T('\0'); - } - - LPTSTR GetBufferSetLength(int nNewLength) - { - ATLASSERT(nNewLength >= 0); - - if(GetBuffer(nNewLength) == NULL) - return NULL; - - GetData()->nDataLength = nNewLength; - m_pchData[nNewLength] = _T('\0'); - return m_pchData; - } - - void FreeExtra() - { - ATLASSERT(GetData()->nDataLength <= GetData()->nAllocLength); - if (GetData()->nDataLength != GetData()->nAllocLength) - { - CStringData* pOldData = GetData(); - if(AllocBuffer(GetData()->nDataLength)) - { - SecureHelper::memcpy_x(m_pchData, (GetData()->nAllocLength + 1) * sizeof(TCHAR), pOldData->data(), pOldData->nDataLength * sizeof(TCHAR)); - ATLASSERT(m_pchData[GetData()->nDataLength] == _T('\0')); - CString::Release(pOldData); - } - } - ATLASSERT(GetData() != NULL); - } - - // Use LockBuffer/UnlockBuffer to turn refcounting off - LPTSTR LockBuffer() - { - LPTSTR lpsz = GetBuffer(0); - if(lpsz != NULL) - GetData()->nRefs = -1; - return lpsz; - } - - void UnlockBuffer() - { - ATLASSERT(GetData()->nRefs == -1); - if (GetData() != _atltmpDataNil) - GetData()->nRefs = 1; - } - -// Implementation -public: - ~CString() // free any attached data - { - if (GetData() != _atltmpDataNil) - { - if (InterlockedDecrement(&GetData()->nRefs) <= 0) - delete[] (BYTE*)GetData(); - } - } - - int GetAllocLength() const - { - return GetData()->nAllocLength; - } - - static BOOL __stdcall _IsValidString(LPCTSTR lpsz, int /*nLength*/ = -1) - { - return (lpsz != NULL) ? TRUE : FALSE; - } - -protected: - LPTSTR m_pchData; // pointer to ref counted string data - - // implementation helpers - CStringData* GetData() const - { - ATLASSERT(m_pchData != NULL); - return ((CStringData*)m_pchData) - 1; - } - - void Init() - { - m_pchData = _GetEmptyString().m_pchData; - } - - BOOL AllocCopy(CString& dest, int nCopyLen, int nCopyIndex, int nExtraLen) const - { - // will clone the data attached to this string - // allocating 'nExtraLen' characters - // Places results in uninitialized string 'dest' - // Will copy the part or all of original data to start of new string - - BOOL bRet = FALSE; - int nNewLen = nCopyLen + nExtraLen; - if (nNewLen == 0) - { - dest.Init(); - bRet = TRUE; - } - else if(nNewLen >= nCopyLen) - { - if(dest.AllocBuffer(nNewLen)) - { - SecureHelper::memcpy_x(dest.m_pchData, (nNewLen + 1) * sizeof(TCHAR), m_pchData + nCopyIndex, nCopyLen * sizeof(TCHAR)); - bRet = TRUE; - } - } - - return bRet; - } - - // always allocate one extra character for '\0' termination - // assumes [optimistically] that data length will equal allocation length - BOOL AllocBuffer(int nLen) - { - ATLASSERT(nLen >= 0); - ATLASSERT(nLen <= INT_MAX - 1); // max size (enough room for 1 extra) - - if (nLen == 0) - { - Init(); - } - else - { - CStringData* pData = NULL; - ATLTRY(pData = (CStringData*)new BYTE[sizeof(CStringData) + (nLen + 1) * sizeof(TCHAR)]); - if(pData == NULL) - return FALSE; - - pData->nRefs = 1; - pData->data()[nLen] = _T('\0'); - pData->nDataLength = nLen; - pData->nAllocLength = nLen; - m_pchData = pData->data(); - } - - return TRUE; - } - - // Assignment operators - // All assign a new value to the string - // (a) first see if the buffer is big enough - // (b) if enough room, copy on top of old buffer, set size and type - // (c) otherwise free old string data, and create a new one - // - // All routines return the new string (but as a 'const CString&' so that - // assigning it again will cause a copy, eg: s1 = s2 = "hi there". - // - void AssignCopy(int nSrcLen, LPCTSTR lpszSrcData) - { - if(AllocBeforeWrite(nSrcLen)) - { - SecureHelper::memcpy_x(m_pchData, (nSrcLen + 1) * sizeof(TCHAR), lpszSrcData, nSrcLen * sizeof(TCHAR)); - GetData()->nDataLength = nSrcLen; - m_pchData[nSrcLen] = _T('\0'); - } - } - - // Concatenation - // NOTE: "operator +" is done as friend functions for simplicity - // There are three variants: - // CString + CString - // and for ? = TCHAR, LPCTSTR - // CString + ? - // ? + CString - BOOL ConcatCopy(int nSrc1Len, LPCTSTR lpszSrc1Data, int nSrc2Len, LPCTSTR lpszSrc2Data) - { - // -- master concatenation routine - // Concatenate two sources - // -- assume that 'this' is a new CString object - - BOOL bRet = TRUE; - int nNewLen = nSrc1Len + nSrc2Len; - if(nNewLen < nSrc1Len || nNewLen < nSrc2Len) - { - bRet = FALSE; - } - else if(nNewLen != 0) - { - bRet = AllocBuffer(nNewLen); - if (bRet) - { - SecureHelper::memcpy_x(m_pchData, (nNewLen + 1) * sizeof(TCHAR), lpszSrc1Data, nSrc1Len * sizeof(TCHAR)); - SecureHelper::memcpy_x(m_pchData + nSrc1Len, (nNewLen + 1 - nSrc1Len) * sizeof(TCHAR), lpszSrc2Data, nSrc2Len * sizeof(TCHAR)); - } - } - return bRet; - } - - void ConcatInPlace(int nSrcLen, LPCTSTR lpszSrcData) - { - // -- the main routine for += operators - - // concatenating an empty string is a no-op! - if (nSrcLen == 0) - return; - - // if the buffer is too small, or we have a width mis-match, just - // allocate a new buffer (slow but sure) - if (GetData()->nRefs > 1 || GetData()->nDataLength + nSrcLen > GetData()->nAllocLength) - { - // we have to grow the buffer, use the ConcatCopy routine - CStringData* pOldData = GetData(); - if (ConcatCopy(GetData()->nDataLength, m_pchData, nSrcLen, lpszSrcData)) - { - ATLASSERT(pOldData != NULL); - CString::Release(pOldData); - } - } - else - { - // fast concatenation when buffer big enough - SecureHelper::memcpy_x(m_pchData + GetData()->nDataLength, (GetData()->nAllocLength + 1) * sizeof(TCHAR), lpszSrcData, nSrcLen * sizeof(TCHAR)); - GetData()->nDataLength += nSrcLen; - ATLASSERT(GetData()->nDataLength <= GetData()->nAllocLength); - m_pchData[GetData()->nDataLength] = _T('\0'); - } - } - - void CopyBeforeWrite() - { - if (GetData()->nRefs > 1) - { - CStringData* pData = GetData(); - Release(); - if(AllocBuffer(pData->nDataLength)) - SecureHelper::memcpy_x(m_pchData, (GetData()->nAllocLength + 1) * sizeof(TCHAR), pData->data(), (pData->nDataLength + 1) * sizeof(TCHAR)); - } - ATLASSERT(GetData()->nRefs <= 1); - } - - BOOL AllocBeforeWrite(int nLen) - { - BOOL bRet = TRUE; - if (GetData()->nRefs > 1 || nLen > GetData()->nAllocLength) - { - Release(); - bRet = AllocBuffer(nLen); - } - ATLASSERT(GetData()->nRefs <= 1); - return bRet; - } - - void Release() - { - if (GetData() != _atltmpDataNil) - { - ATLASSERT(GetData()->nRefs != 0); - if (InterlockedDecrement(&GetData()->nRefs) <= 0) - delete[] (BYTE*)GetData(); - Init(); - } - } - - static void PASCAL Release(CStringData* pData) - { - if (pData != _atltmpDataNil) - { - ATLASSERT(pData->nRefs != 0); - if (InterlockedDecrement(&pData->nRefs) <= 0) - delete[] (BYTE*)pData; - } - } - - static int PASCAL SafeStrlen(LPCTSTR lpsz) - { - return (lpsz == NULL) ? 0 : lstrlen(lpsz); - } - - static int __stdcall _LoadString(UINT nID, LPTSTR lpszBuf, UINT nMaxBuf) - { -#ifdef _DEBUG - // LoadString without annoying warning from the Debug kernel if the - // segment containing the string is not present - if (::FindResource(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE((nID >> 4) + 1), RT_STRING) == NULL) - { - lpszBuf[0] = _T('\0'); - return 0; // not found - } -#endif // _DEBUG - - int nLen = ::LoadString(ModuleHelper::GetResourceInstance(), nID, lpszBuf, nMaxBuf); - if (nLen == 0) - lpszBuf[0] = _T('\0'); - - return nLen; - } - - static const CString& __stdcall _GetEmptyString() - { - return *(CString*)&_atltmpPchNil; - } - -// CString conversion helpers - static int __cdecl _wcstombsz(char* mbstr, const wchar_t* wcstr, size_t count) - { - if (count == 0 && mbstr != NULL) - return 0; - - int result = ::WideCharToMultiByte(CP_ACP, 0, wcstr, -1, mbstr, (int)count, NULL, NULL); - ATLASSERT(mbstr == NULL || result <= (int)count); - if (result > 0) - mbstr[result - 1] = 0; - return result; - } - - static int __cdecl _mbstowcsz(wchar_t* wcstr, const char* mbstr, size_t count) - { - if (count == 0 && wcstr != NULL) - return 0; - - int result = ::MultiByteToWideChar(CP_ACP, 0, mbstr, -1, wcstr, (int)count); - ATLASSERT(wcstr == NULL || result <= (int)count); - if (result > 0) - wcstr[result - 1] = 0; - return result; - } - -// Helpers to avoid CRT startup code -#ifdef _ATL_MIN_CRT - static const TCHAR* _cstrchr(const TCHAR* p, TCHAR ch) - { - // strchr for '\0' should succeed - while (*p != 0) - { - if (*p == ch) - break; - p = ::CharNext(p); - } - return (*p == ch) ? p : NULL; - } - - static const TCHAR* _cstrrchr(const TCHAR* p, TCHAR ch) - { - const TCHAR* lpsz = NULL; - while (*p != 0) - { - if (*p == ch) - lpsz = p; - p = ::CharNext(p); - } - return lpsz; - } - - static TCHAR* _cstrrev(TCHAR* pStr) - { - // optimize NULL, zero-length, and single-char case - if ((pStr == NULL) || (pStr[0] == _T('\0')) || (pStr[1] == _T('\0'))) - return pStr; - - TCHAR* p = pStr; - - while (*p != 0) - { - TCHAR* pNext = ::CharNext(p); - if(pNext > p + 1) - { - char p1 = *(char*)p; - *(char*)p = *(char*)(p + 1); - *(char*)(p + 1) = p1; - } - p = pNext; - } - - p--; - TCHAR* q = pStr; - - while (q < p) - { - TCHAR t = *q; - *q = *p; - *p = t; - q++; - p--; - } - return pStr; - } - - static const TCHAR* _cstrstr(const TCHAR* pStr, const TCHAR* pCharSet) - { - int nLen = lstrlen(pCharSet); - if (nLen == 0) - return (TCHAR*)pStr; - - const TCHAR* pRet = NULL; - const TCHAR* pCur = pStr; - while((pCur = _cstrchr(pCur, *pCharSet)) != NULL) - { - if(memcmp(pCur, pCharSet, nLen * sizeof(TCHAR)) == 0) - { - pRet = pCur; - break; - } - pCur = ::CharNext(pCur); - } - return pRet; - } - - static int _cstrspn(const TCHAR* pStr, const TCHAR* pCharSet) - { - int nRet = 0; - const TCHAR* p = pStr; - while (*p != 0) - { - const TCHAR* pNext = ::CharNext(p); - if(pNext > p + 1) - { - if(_cstrchr_db(pCharSet, *p, *(p + 1)) == NULL) - break; - nRet += 2; - } - else - { - if(_cstrchr(pCharSet, *p) == NULL) - break; - nRet++; - } - p = pNext; - } - return nRet; - } - - static int _cstrcspn(const TCHAR* pStr, const TCHAR* pCharSet) - { - int nRet = 0; - TCHAR* p = (TCHAR*)pStr; - while (*p != 0) - { - TCHAR* pNext = ::CharNext(p); - if(pNext > p + 1) - { - if(_cstrchr_db(pCharSet, *p, *(p + 1)) != NULL) - break; - nRet += 2; - } - else - { - if(_cstrchr(pCharSet, *p) != NULL) - break; - nRet++; - } - p = pNext; - } - return nRet; - } - - static const TCHAR* _cstrpbrk(const TCHAR* p, const TCHAR* lpszCharSet) - { - int n = _cstrcspn(p, lpszCharSet); - return (p[n] != 0) ? &p[n] : NULL; - } - - static int _cstrisdigit(TCHAR ch) - { - WORD type; - GetStringTypeEx(GetThreadLocale(), CT_CTYPE1, &ch, 1, &type); - return (type & C1_DIGIT) == C1_DIGIT; - } - - static int _cstrisspace(TCHAR ch) - { - WORD type; - GetStringTypeEx(GetThreadLocale(), CT_CTYPE1, &ch, 1, &type); - return (type & C1_SPACE) == C1_SPACE; - } - - static int _cstrcmp(const TCHAR* pstrOne, const TCHAR* pstrOther) - { - return lstrcmp(pstrOne, pstrOther); - } - - static int _cstrcmpi(const TCHAR* pstrOne, const TCHAR* pstrOther) - { - return lstrcmpi(pstrOne, pstrOther); - } - - static int _cstrcoll(const TCHAR* pstrOne, const TCHAR* pstrOther) - { - int nRet = CompareString(GetThreadLocale(), 0, pstrOne, -1, pstrOther, -1); - ATLASSERT(nRet != 0); - return nRet - 2; // convert to strcmp convention - } - - static int _cstrcolli(const TCHAR* pstrOne, const TCHAR* pstrOther) - { - int nRet = CompareString(GetThreadLocale(), NORM_IGNORECASE, pstrOne, -1, pstrOther, -1); - ATLASSERT(nRet != 0); - return nRet - 2; // convert to strcmp convention - } - - static int _cstrtoi(const TCHAR* nptr) - { - int c; // current char - int total; // current total - int sign; // if '-', then negative, otherwise positive - - while (_cstrisspace(*nptr)) - ++nptr; - - c = (int)(_TUCHAR)*nptr++; - sign = c; // save sign indication - if (c == _T('-') || c == _T('+')) - c = (int)(_TUCHAR)*nptr++; // skip sign - - total = 0; - - while (_cstrisdigit((TCHAR)c)) - { - total = 10 * total + (c - '0'); // accumulate digit - c = (int)(_TUCHAR)*nptr++; // get next char - } - - if (sign == '-') - return -total; - else - return total; // return result, negated if necessary - } -#else // !_ATL_MIN_CRT - static const TCHAR* _cstrchr(const TCHAR* p, TCHAR ch) - { - return _tcschr(p, ch); - } - - static const TCHAR* _cstrrchr(const TCHAR* p, TCHAR ch) - { - return _tcsrchr(p, ch); - } - - static TCHAR* _cstrrev(TCHAR* pStr) - { - return _tcsrev(pStr); - } - - static const TCHAR* _cstrstr(const TCHAR* pStr, const TCHAR* pCharSet) - { - return _tcsstr(pStr, pCharSet); - } - - static int _cstrspn(const TCHAR* pStr, const TCHAR* pCharSet) - { - return (int)_tcsspn(pStr, pCharSet); - } - - static int _cstrcspn(const TCHAR* pStr, const TCHAR* pCharSet) - { - return (int)_tcscspn(pStr, pCharSet); - } - - static const TCHAR* _cstrpbrk(const TCHAR* p, const TCHAR* lpszCharSet) - { - return _tcspbrk(p, lpszCharSet); - } - - static int _cstrisdigit(TCHAR ch) - { - return _istdigit(ch); - } - - static int _cstrisspace(TCHAR ch) - { - return _istspace((_TUCHAR)ch); - } - - static int _cstrcmp(const TCHAR* pstrOne, const TCHAR* pstrOther) - { - return _tcscmp(pstrOne, pstrOther); - } - - static int _cstrcmpi(const TCHAR* pstrOne, const TCHAR* pstrOther) - { - return _tcsicmp(pstrOne, pstrOther); - } - -#ifndef _WIN32_WCE - static int _cstrcoll(const TCHAR* pstrOne, const TCHAR* pstrOther) - { - return _tcscoll(pstrOne, pstrOther); - } - - static int _cstrcolli(const TCHAR* pstrOne, const TCHAR* pstrOther) - { - return _tcsicoll(pstrOne, pstrOther); - } -#endif // !_WIN32_WCE - - static int _cstrtoi(const TCHAR* nptr) - { - return _ttoi(nptr); - } -#endif // !_ATL_MIN_CRT - - static const TCHAR* _cstrchr_db(const TCHAR* p, TCHAR ch1, TCHAR ch2) - { - const TCHAR* lpsz = NULL; - while (*p != 0) - { - if (*p == ch1 && *(p + 1) == ch2) - { - lpsz = p; - break; - } - p = ::CharNext(p); - } - return lpsz; - } -}; - - -// Compare helpers - -inline bool __stdcall operator ==(const CString& s1, const CString& s2) -{ return s1.Compare(s2) == 0; } - -inline bool __stdcall operator ==(const CString& s1, LPCTSTR s2) -{ return s1.Compare(s2) == 0; } - -inline bool __stdcall operator ==(LPCTSTR s1, const CString& s2) -{ return s2.Compare(s1) == 0; } - -inline bool __stdcall operator !=(const CString& s1, const CString& s2) -{ return s1.Compare(s2) != 0; } - -inline bool __stdcall operator !=(const CString& s1, LPCTSTR s2) -{ return s1.Compare(s2) != 0; } - -inline bool __stdcall operator !=(LPCTSTR s1, const CString& s2) -{ return s2.Compare(s1) != 0; } - -inline bool __stdcall operator <(const CString& s1, const CString& s2) -{ return s1.Compare(s2) < 0; } - -inline bool __stdcall operator <(const CString& s1, LPCTSTR s2) -{ return s1.Compare(s2) < 0; } - -inline bool __stdcall operator <(LPCTSTR s1, const CString& s2) -{ return s2.Compare(s1) > 0; } - -inline bool __stdcall operator >(const CString& s1, const CString& s2) -{ return s1.Compare(s2) > 0; } - -inline bool __stdcall operator >(const CString& s1, LPCTSTR s2) -{ return s1.Compare(s2) > 0; } - -inline bool __stdcall operator >(LPCTSTR s1, const CString& s2) -{ return s2.Compare(s1) < 0; } - -inline bool __stdcall operator <=(const CString& s1, const CString& s2) -{ return s1.Compare(s2) <= 0; } - -inline bool __stdcall operator <=(const CString& s1, LPCTSTR s2) -{ return s1.Compare(s2) <= 0; } - -inline bool __stdcall operator <=(LPCTSTR s1, const CString& s2) -{ return s2.Compare(s1) >= 0; } - -inline bool __stdcall operator >=(const CString& s1, const CString& s2) -{ return s1.Compare(s2) >= 0; } - -inline bool __stdcall operator >=(const CString& s1, LPCTSTR s2) -{ return s1.Compare(s2) >= 0; } - -inline bool __stdcall operator >=(LPCTSTR s1, const CString& s2) -{ return s2.Compare(s1) <= 0; } - - -// CString "operator +" functions - -inline CString __stdcall operator +(const CString& string1, const CString& string2) -{ - CString s; - s.ConcatCopy(string1.GetData()->nDataLength, string1.m_pchData, string2.GetData()->nDataLength, string2.m_pchData); - return s; -} - -inline CString __stdcall operator +(const CString& string, TCHAR ch) -{ - CString s; - s.ConcatCopy(string.GetData()->nDataLength, string.m_pchData, 1, &ch); - return s; -} - -inline CString __stdcall operator +(TCHAR ch, const CString& string) -{ - CString s; - s.ConcatCopy(1, &ch, string.GetData()->nDataLength, string.m_pchData); - return s; -} - -#ifdef _UNICODE -inline CString __stdcall operator +(const CString& string, char ch) -{ - return string + (TCHAR)ch; -} - -inline CString __stdcall operator +(char ch, const CString& string) -{ - return (TCHAR)ch + string; -} -#endif // _UNICODE - -inline CString __stdcall operator +(const CString& string, LPCTSTR lpsz) -{ - ATLASSERT(lpsz == NULL || CString::_IsValidString(lpsz)); - CString s; - s.ConcatCopy(string.GetData()->nDataLength, string.m_pchData, CString::SafeStrlen(lpsz), lpsz); - return s; -} - -inline CString __stdcall operator +(LPCTSTR lpsz, const CString& string) -{ - ATLASSERT(lpsz == NULL || CString::_IsValidString(lpsz)); - CString s; - s.ConcatCopy(CString::SafeStrlen(lpsz), lpsz, string.GetData()->nDataLength, string.m_pchData); - return s; -} - -#endif // !_WTL_NO_CSTRING - - -/////////////////////////////////////////////////////////////////////////////// -// CRecentDocumentList - MRU List Support - -#ifndef _WIN32_WCE - -#ifndef _WTL_MRUEMPTY_TEXT - #define _WTL_MRUEMPTY_TEXT _T("(empty)") -#endif - -// forward declaration -inline bool AtlCompactPath(LPTSTR lpstrOut, LPCTSTR lpstrIn, int cchLen); - -template -class CRecentDocumentListBase -{ -public: -// Declarations - struct _DocEntry - { - TCHAR szDocName[t_cchItemLen]; - bool operator ==(const _DocEntry& de) const - { return (lstrcmpi(szDocName, de.szDocName) == 0); } - }; - - enum - { - m_nMaxEntries_Min = 2, - m_nMaxEntries_Max = t_nLastID - t_nFirstID + 1, - m_cchMaxItemLen_Min = 6, - m_cchMaxItemLen_Max = t_cchItemLen, - m_cchItemNameLen = 11 - }; - -// Data members - ATL::CSimpleArray<_DocEntry> m_arrDocs; - int m_nMaxEntries; // default is 4 - HMENU m_hMenu; - - TCHAR m_szNoEntries[t_cchItemLen]; - - int m_cchMaxItemLen; - -// Constructor - CRecentDocumentListBase() : m_hMenu(NULL), m_nMaxEntries(4), m_cchMaxItemLen(-1) - { - // These ASSERTs verify values of the template arguments - ATLASSERT(t_cchItemLen > m_cchMaxItemLen_Min); - ATLASSERT(m_nMaxEntries_Max > m_nMaxEntries_Min); - } - -// Attributes - HMENU GetMenuHandle() const - { - return m_hMenu; - } - - void SetMenuHandle(HMENU hMenu) - { - ATLASSERT(hMenu == NULL || ::IsMenu(hMenu)); - m_hMenu = hMenu; - if(m_hMenu == NULL || (::GetMenuString(m_hMenu, t_nFirstID, m_szNoEntries, t_cchItemLen, MF_BYCOMMAND) == 0)) - { - T* pT = static_cast(this); - pT; // avoid level 4 warning - SecureHelper::strncpy_x(m_szNoEntries, _countof(m_szNoEntries), pT->GetMRUEmptyText(), _TRUNCATE); - } - } - - int GetMaxEntries() const - { - return m_nMaxEntries; - } - - void SetMaxEntries(int nMaxEntries) - { - ATLASSERT(nMaxEntries >= m_nMaxEntries_Min && nMaxEntries <= m_nMaxEntries_Max); - if(nMaxEntries < m_nMaxEntries_Min) - nMaxEntries = m_nMaxEntries_Min; - else if(nMaxEntries > m_nMaxEntries_Max) - nMaxEntries = m_nMaxEntries_Max; - m_nMaxEntries = nMaxEntries; - } - - int GetMaxItemLength() const - { - return m_cchMaxItemLen; - } - - void SetMaxItemLength(int cchMaxLen) - { - ATLASSERT((cchMaxLen >= m_cchMaxItemLen_Min && cchMaxLen <= m_cchMaxItemLen_Max) || cchMaxLen == -1); - if(cchMaxLen != -1) - { - if(cchMaxLen < m_cchMaxItemLen_Min) - cchMaxLen = m_cchMaxItemLen_Min; - else if(cchMaxLen > m_cchMaxItemLen_Max) - cchMaxLen = m_cchMaxItemLen_Max; - } - m_cchMaxItemLen = cchMaxLen; - T* pT = static_cast(this); - pT->UpdateMenu(); - } - -// Operations - BOOL AddToList(LPCTSTR lpstrDocName) - { - _DocEntry de; - errno_t nRet = SecureHelper::strncpy_x(de.szDocName, _countof(de.szDocName), lpstrDocName, _TRUNCATE); - if(nRet != 0 && nRet != STRUNCATE) - return FALSE; - - for(int i = 0; i < m_arrDocs.GetSize(); i++) - { - if(lstrcmpi(m_arrDocs[i].szDocName, lpstrDocName) == 0) - { - m_arrDocs.RemoveAt(i); - break; - } - } - - if(m_arrDocs.GetSize() == m_nMaxEntries) - m_arrDocs.RemoveAt(0); - - BOOL bRet = m_arrDocs.Add(de); - if(bRet) - { - T* pT = static_cast(this); - bRet = pT->UpdateMenu(); - } - return bRet; - } - - // This function is deprecated because it is not safe. - // Use the version below that accepts the buffer length. -#if (_MSC_VER >= 1300) - __declspec(deprecated) -#endif - BOOL GetFromList(int /*nItemID*/, LPTSTR /*lpstrDocName*/) - { - ATLASSERT(FALSE); - return FALSE; - } - - BOOL GetFromList(int nItemID, LPTSTR lpstrDocName, int cchLength) - { - int nIndex = m_arrDocs.GetSize() - (nItemID - t_nFirstID) - 1; - if(nIndex < 0 || nIndex >= m_arrDocs.GetSize()) - return FALSE; - if(lstrlen(m_arrDocs[nIndex].szDocName) >= cchLength) - return FALSE; - SecureHelper::strcpy_x(lpstrDocName, cchLength, m_arrDocs[nIndex].szDocName); - - return TRUE; - } - -#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - BOOL GetFromList(int nItemID, _CSTRING_NS::CString& strDocName) - { - int nIndex = m_arrDocs.GetSize() - (nItemID - t_nFirstID) - 1; - if(nIndex < 0 || nIndex >= m_arrDocs.GetSize()) - return FALSE; - strDocName = m_arrDocs[nIndex].szDocName; - return TRUE; - } -#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - - BOOL RemoveFromList(int nItemID) - { - int nIndex = m_arrDocs.GetSize() - (nItemID - t_nFirstID) - 1; - BOOL bRet = m_arrDocs.RemoveAt(nIndex); - if(bRet) - { - T* pT = static_cast(this); - bRet = pT->UpdateMenu(); - } - return bRet; - } - - BOOL MoveToTop(int nItemID) - { - int nIndex = m_arrDocs.GetSize() - (nItemID - t_nFirstID) - 1; - if(nIndex < 0 || nIndex >= m_arrDocs.GetSize()) - return FALSE; - _DocEntry de; - de = m_arrDocs[nIndex]; - m_arrDocs.RemoveAt(nIndex); - BOOL bRet = m_arrDocs.Add(de); - if(bRet) - { - T* pT = static_cast(this); - bRet = pT->UpdateMenu(); - } - return bRet; - } - - BOOL ReadFromRegistry(LPCTSTR lpstrRegKey) - { - T* pT = static_cast(this); - ATL::CRegKey rkParent; - ATL::CRegKey rk; - - LONG lRet = rkParent.Open(HKEY_CURRENT_USER, lpstrRegKey); - if(lRet != ERROR_SUCCESS) - return FALSE; - lRet = rk.Open(rkParent, pT->GetRegKeyName()); - if(lRet != ERROR_SUCCESS) - return FALSE; - - DWORD dwRet = 0; -#if (_ATL_VER >= 0x0700) - lRet = rk.QueryDWORDValue(pT->GetRegCountName(), dwRet); -#else - lRet = rk.QueryValue(dwRet, pT->GetRegCountName()); -#endif - if(lRet != ERROR_SUCCESS) - return FALSE; - SetMaxEntries(dwRet); - - m_arrDocs.RemoveAll(); - - TCHAR szRetString[t_cchItemLen] = { 0 }; - _DocEntry de; - - for(int nItem = m_nMaxEntries; nItem > 0; nItem--) - { - TCHAR szBuff[m_cchItemNameLen] = { 0 }; - SecureHelper::wsprintf_x(szBuff, m_cchItemNameLen, pT->GetRegItemName(), nItem); -#if (_ATL_VER >= 0x0700) - ULONG ulCount = t_cchItemLen; - lRet = rk.QueryStringValue(szBuff, szRetString, &ulCount); -#else - DWORD dwCount = t_cchItemLen * sizeof(TCHAR); - lRet = rk.QueryValue(szRetString, szBuff, &dwCount); -#endif - if(lRet == ERROR_SUCCESS) - { - SecureHelper::strcpy_x(de.szDocName, _countof(de.szDocName), szRetString); - m_arrDocs.Add(de); - } - } - - rk.Close(); - rkParent.Close(); - - return pT->UpdateMenu(); - } - - BOOL WriteToRegistry(LPCTSTR lpstrRegKey) - { - T* pT = static_cast(this); - pT; // avoid level 4 warning - ATL::CRegKey rkParent; - ATL::CRegKey rk; - - LONG lRet = rkParent.Create(HKEY_CURRENT_USER, lpstrRegKey); - if(lRet != ERROR_SUCCESS) - return FALSE; - lRet = rk.Create(rkParent, pT->GetRegKeyName()); - if(lRet != ERROR_SUCCESS) - return FALSE; - -#if (_ATL_VER >= 0x0700) - lRet = rk.SetDWORDValue(pT->GetRegCountName(), m_nMaxEntries); -#else - lRet = rk.SetValue(m_nMaxEntries, pT->GetRegCountName()); -#endif - ATLASSERT(lRet == ERROR_SUCCESS); - - // set new values - int nItem; - for(nItem = m_arrDocs.GetSize(); nItem > 0; nItem--) - { - TCHAR szBuff[m_cchItemNameLen] = { 0 }; - SecureHelper::wsprintf_x(szBuff, m_cchItemNameLen, pT->GetRegItemName(), nItem); - TCHAR szDocName[t_cchItemLen] = { 0 }; - GetFromList(t_nFirstID + nItem - 1, szDocName, t_cchItemLen); -#if (_ATL_VER >= 0x0700) - lRet = rk.SetStringValue(szBuff, szDocName); -#else - lRet = rk.SetValue(szDocName, szBuff); -#endif - ATLASSERT(lRet == ERROR_SUCCESS); - } - - // delete unused keys - for(nItem = m_arrDocs.GetSize() + 1; nItem < m_nMaxEntries_Max; nItem++) - { - TCHAR szBuff[m_cchItemNameLen] = { 0 }; - SecureHelper::wsprintf_x(szBuff, m_cchItemNameLen, pT->GetRegItemName(), nItem); - rk.DeleteValue(szBuff); - } - - rk.Close(); - rkParent.Close(); - - return TRUE; - } - -// Implementation - BOOL UpdateMenu() - { - if(m_hMenu == NULL) - return FALSE; - ATLASSERT(::IsMenu(m_hMenu)); - - int nItems = ::GetMenuItemCount(m_hMenu); - int nInsertPoint; - for(nInsertPoint = 0; nInsertPoint < nItems; nInsertPoint++) - { - CMenuItemInfo mi; - mi.fMask = MIIM_ID; - ::GetMenuItemInfo(m_hMenu, nInsertPoint, TRUE, &mi); - if (mi.wID == t_nFirstID) - break; - } - ATLASSERT(nInsertPoint < nItems && "You need a menu item with an ID = t_nFirstID"); - - int nItem; - for(nItem = t_nFirstID; nItem < t_nFirstID + m_nMaxEntries; nItem++) - { - // keep the first one as an insertion point - if (nItem != t_nFirstID) - ::DeleteMenu(m_hMenu, nItem, MF_BYCOMMAND); - } - - TCHAR szItemText[t_cchItemLen + 6] = { 0 }; // add space for &, 2 digits, and a space - int nSize = m_arrDocs.GetSize(); - nItem = 0; - if(nSize > 0) - { - for(nItem = 0; nItem < nSize; nItem++) - { - if(m_cchMaxItemLen == -1) - { - SecureHelper::wsprintf_x(szItemText, t_cchItemLen + 6, _T("&%i %s"), nItem + 1, m_arrDocs[nSize - 1 - nItem].szDocName); - } - else - { - TCHAR szBuff[t_cchItemLen] = { 0 }; - T* pT = static_cast(this); - pT; // avoid level 4 warning - bool bRet = pT->CompactDocumentName(szBuff, m_arrDocs[nSize - 1 - nItem].szDocName, m_cchMaxItemLen); - bRet; // avoid level 4 warning - ATLASSERT(bRet); - SecureHelper::wsprintf_x(szItemText, t_cchItemLen + 6, _T("&%i %s"), nItem + 1, szBuff); - } - ::InsertMenu(m_hMenu, nInsertPoint + nItem, MF_BYPOSITION | MF_STRING, t_nFirstID + nItem, szItemText); - } - } - else // empty - { - ::InsertMenu(m_hMenu, nInsertPoint, MF_BYPOSITION | MF_STRING, t_nFirstID, m_szNoEntries); - ::EnableMenuItem(m_hMenu, t_nFirstID, MF_GRAYED); - nItem++; - } - ::DeleteMenu(m_hMenu, nInsertPoint + nItem, MF_BYPOSITION); - - return TRUE; - } - -// Overrideables - // override to provide a different method of compacting document names - static bool CompactDocumentName(LPTSTR lpstrOut, LPCTSTR lpstrIn, int cchLen) - { - return AtlCompactPath(lpstrOut, lpstrIn, cchLen); - } - - static LPCTSTR GetRegKeyName() - { - return _T("Recent Document List"); - } - - static LPCTSTR GetRegCountName() - { - return _T("DocumentCount"); - } - - static LPCTSTR GetRegItemName() - { - // Note: This string is a format string used with wsprintf(). - // Resulting formatted string must be m_cchItemNameLen or less - // characters long, including the terminating null character. - return _T("Document%i"); - } - - static LPCTSTR GetMRUEmptyText() - { - return _WTL_MRUEMPTY_TEXT; - } -}; - -class CRecentDocumentList : public CRecentDocumentListBase -{ -public: -// nothing here -}; - -#endif // _WIN32_WCE - - -/////////////////////////////////////////////////////////////////////////////// -// CFindFile - file search helper class - -class CFindFile -{ -public: -// Data members - WIN32_FIND_DATA m_fd; - TCHAR m_lpszRoot[MAX_PATH]; - TCHAR m_chDirSeparator; - HANDLE m_hFind; - BOOL m_bFound; - -// Constructor/destructor - CFindFile() : m_hFind(NULL), m_chDirSeparator(_T('\\')), m_bFound(FALSE) - { } - - ~CFindFile() - { - Close(); - } - -// Attributes - ULONGLONG GetFileSize() const - { - ATLASSERT(m_hFind != NULL); - - ULARGE_INTEGER nFileSize = { 0 }; - - if(m_bFound) - { - nFileSize.LowPart = m_fd.nFileSizeLow; - nFileSize.HighPart = m_fd.nFileSizeHigh; - } - else - { - nFileSize.QuadPart = 0; - } - - return nFileSize.QuadPart; - } - - BOOL GetFileName(LPTSTR lpstrFileName, int cchLength) const - { - ATLASSERT(m_hFind != NULL); - if(lstrlen(m_fd.cFileName) >= cchLength) - return FALSE; - - if(m_bFound) - SecureHelper::strcpy_x(lpstrFileName, cchLength, m_fd.cFileName); - - return m_bFound; - } - - BOOL GetFilePath(LPTSTR lpstrFilePath, int cchLength) const - { - ATLASSERT(m_hFind != NULL); - - int nLen = lstrlen(m_lpszRoot); -#ifndef _WIN32_WCE - ATLASSERT(nLen > 0); - if(nLen == 0) - return FALSE; - - bool bAddSep = (m_lpszRoot[nLen - 1] != _T('\\') && m_lpszRoot[nLen - 1] !=_T('/')); -#else // CE specific - // allow diskless devices (nLen == 0) - bool bAddSep = ((nLen == 0) || (m_lpszRoot[nLen - 1] != _T('\\') && m_lpszRoot[nLen - 1] !=_T('/'))); -#endif // _WIN32_WCE - - if((lstrlen(m_lpszRoot) + (bAddSep ? 1 : 0)) >= cchLength) - return FALSE; - - SecureHelper::strcpy_x(lpstrFilePath, cchLength, m_lpszRoot); - - if(bAddSep) - { - TCHAR szSeparator[2] = { m_chDirSeparator, 0 }; - SecureHelper::strcat_x(lpstrFilePath, cchLength, szSeparator); - } - - SecureHelper::strcat_x(lpstrFilePath, cchLength, m_fd.cFileName); - - return TRUE; - } - -#ifndef _WIN32_WCE - BOOL GetFileTitle(LPTSTR lpstrFileTitle, int cchLength) const - { - ATLASSERT(m_hFind != NULL); - - TCHAR szBuff[MAX_PATH] = { 0 }; - if(!GetFileName(szBuff, MAX_PATH)) - return FALSE; - - if(lstrlen(szBuff) >= cchLength || cchLength < 1) - return FALSE; - - // find the last dot - LPTSTR pstrDot = (LPTSTR)_cstrrchr(szBuff, _T('.')); - if(pstrDot != NULL) - *pstrDot = 0; - - SecureHelper::strcpy_x(lpstrFileTitle, cchLength, szBuff); - - return TRUE; - } -#endif // !_WIN32_WCE - - BOOL GetFileURL(LPTSTR lpstrFileURL, int cchLength) const - { - ATLASSERT(m_hFind != NULL); - - TCHAR szBuff[MAX_PATH] = { 0 }; - if(!GetFilePath(szBuff, MAX_PATH)) - return FALSE; - LPCTSTR lpstrFileURLPrefix = _T("file://"); - if(lstrlen(szBuff) + lstrlen(lpstrFileURLPrefix) >= cchLength) - return FALSE; - SecureHelper::strcpy_x(lpstrFileURL, cchLength, lpstrFileURLPrefix); - SecureHelper::strcat_x(lpstrFileURL, cchLength, szBuff); - - return TRUE; - } - - BOOL GetRoot(LPTSTR lpstrRoot, int cchLength) const - { - ATLASSERT(m_hFind != NULL); - if(lstrlen(m_lpszRoot) >= cchLength) - return FALSE; - - SecureHelper::strcpy_x(lpstrRoot, cchLength, m_lpszRoot); - - return TRUE; - } - -#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - _CSTRING_NS::CString GetFileName() const - { - ATLASSERT(m_hFind != NULL); - - _CSTRING_NS::CString ret; - - if(m_bFound) - ret = m_fd.cFileName; - return ret; - } - - _CSTRING_NS::CString GetFilePath() const - { - ATLASSERT(m_hFind != NULL); - - _CSTRING_NS::CString strResult = m_lpszRoot; - int nLen = strResult.GetLength(); -#ifndef _WIN32_WCE - ATLASSERT(nLen > 0); - if(nLen == 0) - return strResult; - - if((strResult[nLen - 1] != _T('\\')) && (strResult[nLen - 1] != _T('/'))) -#else // CE specific - // allow diskless devices (nLen == 0) - if((nLen == 0) || ((strResult[nLen - 1] != _T('\\')) && (strResult[nLen - 1] != _T('/')))) -#endif // _WIN32_WCE - strResult += m_chDirSeparator; - strResult += GetFileName(); - return strResult; - } - -#ifndef _WIN32_WCE - _CSTRING_NS::CString GetFileTitle() const - { - ATLASSERT(m_hFind != NULL); - - _CSTRING_NS::CString strResult; - GetFileTitle(strResult.GetBuffer(MAX_PATH), MAX_PATH); - strResult.ReleaseBuffer(); - - return strResult; - } -#endif // !_WIN32_WCE - - _CSTRING_NS::CString GetFileURL() const - { - ATLASSERT(m_hFind != NULL); - - _CSTRING_NS::CString strResult("file://"); - strResult += GetFilePath(); - return strResult; - } - - _CSTRING_NS::CString GetRoot() const - { - ATLASSERT(m_hFind != NULL); - - _CSTRING_NS::CString str = m_lpszRoot; - return str; - } -#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - - BOOL GetLastWriteTime(FILETIME* pTimeStamp) const - { - ATLASSERT(m_hFind != NULL); - ATLASSERT(pTimeStamp != NULL); - - if(m_bFound && pTimeStamp != NULL) - { - *pTimeStamp = m_fd.ftLastWriteTime; - return TRUE; - } - - return FALSE; - } - - BOOL GetLastAccessTime(FILETIME* pTimeStamp) const - { - ATLASSERT(m_hFind != NULL); - ATLASSERT(pTimeStamp != NULL); - - if(m_bFound && pTimeStamp != NULL) - { - *pTimeStamp = m_fd.ftLastAccessTime; - return TRUE; - } - - return FALSE; - } - - BOOL GetCreationTime(FILETIME* pTimeStamp) const - { - ATLASSERT(m_hFind != NULL); - - if(m_bFound && pTimeStamp != NULL) - { - *pTimeStamp = m_fd.ftCreationTime; - return TRUE; - } - - return FALSE; - } - - BOOL MatchesMask(DWORD dwMask) const - { - ATLASSERT(m_hFind != NULL); - - if(m_bFound) - return ((m_fd.dwFileAttributes & dwMask) != 0); - - return FALSE; - } - - BOOL IsDots() const - { - ATLASSERT(m_hFind != NULL); - - // return TRUE if the file name is "." or ".." and - // the file is a directory - - BOOL bResult = FALSE; - if(m_bFound && IsDirectory()) - { - if(m_fd.cFileName[0] == _T('.') && (m_fd.cFileName[1] == _T('\0') || (m_fd.cFileName[1] == _T('.') && m_fd.cFileName[2] == _T('\0')))) - bResult = TRUE; - } - - return bResult; - } - - BOOL IsReadOnly() const - { - return MatchesMask(FILE_ATTRIBUTE_READONLY); - } - - BOOL IsDirectory() const - { - return MatchesMask(FILE_ATTRIBUTE_DIRECTORY); - } - - BOOL IsCompressed() const - { - return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); - } - - BOOL IsSystem() const - { - return MatchesMask(FILE_ATTRIBUTE_SYSTEM); - } - - BOOL IsHidden() const - { - return MatchesMask(FILE_ATTRIBUTE_HIDDEN); - } - - BOOL IsTemporary() const - { - return MatchesMask(FILE_ATTRIBUTE_TEMPORARY); - } - - BOOL IsNormal() const - { - return MatchesMask(FILE_ATTRIBUTE_NORMAL); - } - - BOOL IsArchived() const - { - return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); - } - -// Operations - BOOL FindFile(LPCTSTR pstrName = NULL) - { - Close(); - - if(pstrName == NULL) - { - pstrName = _T("*.*"); - } - else if(lstrlen(pstrName) >= MAX_PATH) - { - ATLASSERT(FALSE); - return FALSE; - } - - SecureHelper::strcpy_x(m_fd.cFileName, _countof(m_fd.cFileName), pstrName); - - m_hFind = ::FindFirstFile(pstrName, &m_fd); - - if(m_hFind == INVALID_HANDLE_VALUE) - return FALSE; - -#ifndef _WIN32_WCE - bool bFullPath = (::GetFullPathName(pstrName, MAX_PATH, m_lpszRoot, NULL) != 0); -#else // CE specific - errno_t nRet = SecureHelper::strncpy_x(m_lpszRoot, _countof(m_lpszRoot), pstrName, _TRUNCATE); - bool bFullPath = (nRet == 0 || nRet == STRUNCATE); -#endif // _WIN32_WCE - - // passed name isn't a valid path but was found by the API - ATLASSERT(bFullPath); - if(!bFullPath) - { - Close(); - ::SetLastError(ERROR_INVALID_NAME); - return FALSE; - } - else - { - // find the last forward or backward whack - LPTSTR pstrBack = (LPTSTR)_cstrrchr(m_lpszRoot, _T('\\')); - LPTSTR pstrFront = (LPTSTR)_cstrrchr(m_lpszRoot, _T('/')); - - if(pstrFront != NULL || pstrBack != NULL) - { - if(pstrFront == NULL) - pstrFront = m_lpszRoot; - if(pstrBack == NULL) - pstrBack = m_lpszRoot; - - // from the start to the last whack is the root - - if(pstrFront >= pstrBack) - *pstrFront = _T('\0'); - else - *pstrBack = _T('\0'); - } - } - - m_bFound = TRUE; - - return TRUE; - } - - BOOL FindNextFile() - { - ATLASSERT(m_hFind != NULL); - - if(m_hFind == NULL) - return FALSE; - - if(!m_bFound) - return FALSE; - - m_bFound = ::FindNextFile(m_hFind, &m_fd); - - return m_bFound; - } - - void Close() - { - m_bFound = FALSE; - - if(m_hFind != NULL && m_hFind != INVALID_HANDLE_VALUE) - { - ::FindClose(m_hFind); - m_hFind = NULL; - } - } - -// Helper - static const TCHAR* _cstrrchr(const TCHAR* p, TCHAR ch) - { -#ifdef _ATL_MIN_CRT - const TCHAR* lpsz = NULL; - while (*p != 0) - { - if (*p == ch) - lpsz = p; - p = ::CharNext(p); - } - return lpsz; -#else // !_ATL_MIN_CRT - return _tcsrchr(p, ch); -#endif // !_ATL_MIN_CRT - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// Global functions for loading resources - -inline HACCEL AtlLoadAccelerators(ATL::_U_STRINGorID table) -{ - return ::LoadAccelerators(ModuleHelper::GetResourceInstance(), table.m_lpstr); -} - -inline HMENU AtlLoadMenu(ATL::_U_STRINGorID menu) -{ - return ::LoadMenu(ModuleHelper::GetResourceInstance(), menu.m_lpstr); -} - -inline HBITMAP AtlLoadBitmap(ATL::_U_STRINGorID bitmap) -{ - return ::LoadBitmap(ModuleHelper::GetResourceInstance(), bitmap.m_lpstr); -} - -#ifdef OEMRESOURCE -inline HBITMAP AtlLoadSysBitmap(ATL::_U_STRINGorID bitmap) -{ -#ifdef _DEBUG - WORD wID = (WORD)bitmap.m_lpstr; - ATLASSERT(wID >= 32734 && wID <= 32767); -#endif // _DEBUG - return ::LoadBitmap(NULL, bitmap.m_lpstr); -} -#endif // OEMRESOURCE - -inline HCURSOR AtlLoadCursor(ATL::_U_STRINGorID cursor) -{ - return ::LoadCursor(ModuleHelper::GetResourceInstance(), cursor.m_lpstr); -} - -inline HCURSOR AtlLoadSysCursor(LPCTSTR lpCursorName) -{ -#if (WINVER >= 0x0500) - ATLASSERT(lpCursorName == IDC_ARROW || lpCursorName == IDC_IBEAM || lpCursorName == IDC_WAIT || - lpCursorName == IDC_CROSS || lpCursorName == IDC_UPARROW || lpCursorName == IDC_SIZE || - lpCursorName == IDC_ICON || lpCursorName == IDC_SIZENWSE || lpCursorName == IDC_SIZENESW || - lpCursorName == IDC_SIZEWE || lpCursorName == IDC_SIZENS || lpCursorName == IDC_SIZEALL || - lpCursorName == IDC_NO || lpCursorName == IDC_APPSTARTING || lpCursorName == IDC_HELP || - lpCursorName == IDC_HAND); -#else // !(WINVER >= 0x0500) - ATLASSERT(lpCursorName == IDC_ARROW || lpCursorName == IDC_IBEAM || lpCursorName == IDC_WAIT || - lpCursorName == IDC_CROSS || lpCursorName == IDC_UPARROW || lpCursorName == IDC_SIZE || - lpCursorName == IDC_ICON || lpCursorName == IDC_SIZENWSE || lpCursorName == IDC_SIZENESW || - lpCursorName == IDC_SIZEWE || lpCursorName == IDC_SIZENS || lpCursorName == IDC_SIZEALL || - lpCursorName == IDC_NO || lpCursorName == IDC_APPSTARTING || lpCursorName == IDC_HELP); -#endif // !(WINVER >= 0x0500) - return ::LoadCursor(NULL, lpCursorName); -} - -inline HICON AtlLoadIcon(ATL::_U_STRINGorID icon) -{ - return ::LoadIcon(ModuleHelper::GetResourceInstance(), icon.m_lpstr); -} - -#ifndef _WIN32_WCE -inline HICON AtlLoadSysIcon(LPCTSTR lpIconName) -{ -#if (WINVER >= 0x0600) - ATLASSERT(lpIconName == IDI_APPLICATION || lpIconName == IDI_ASTERISK || lpIconName == IDI_EXCLAMATION || - lpIconName == IDI_HAND || lpIconName == IDI_QUESTION || lpIconName == IDI_WINLOGO || - lpIconName == IDI_SHIELD); -#else // !(WINVER >= 0x0600) - ATLASSERT(lpIconName == IDI_APPLICATION || lpIconName == IDI_ASTERISK || lpIconName == IDI_EXCLAMATION || - lpIconName == IDI_HAND || lpIconName == IDI_QUESTION || lpIconName == IDI_WINLOGO); -#endif // !(WINVER >= 0x0600) - return ::LoadIcon(NULL, lpIconName); -} -#endif // !_WIN32_WCE - -inline HBITMAP AtlLoadBitmapImage(ATL::_U_STRINGorID bitmap, UINT fuLoad = LR_DEFAULTCOLOR) -{ - return (HBITMAP)::LoadImage(ModuleHelper::GetResourceInstance(), bitmap.m_lpstr, IMAGE_BITMAP, 0, 0, fuLoad); -} - -inline HCURSOR AtlLoadCursorImage(ATL::_U_STRINGorID cursor, UINT fuLoad = LR_DEFAULTCOLOR | LR_DEFAULTSIZE, int cxDesired = 0, int cyDesired = 0) -{ - return (HCURSOR)::LoadImage(ModuleHelper::GetResourceInstance(), cursor.m_lpstr, IMAGE_CURSOR, cxDesired, cyDesired, fuLoad); -} - -inline HICON AtlLoadIconImage(ATL::_U_STRINGorID icon, UINT fuLoad = LR_DEFAULTCOLOR | LR_DEFAULTSIZE, int cxDesired = 0, int cyDesired = 0) -{ - return (HICON)::LoadImage(ModuleHelper::GetResourceInstance(), icon.m_lpstr, IMAGE_ICON, cxDesired, cyDesired, fuLoad); -} - -#ifdef OEMRESOURCE -inline HBITMAP AtlLoadSysBitmapImage(WORD wBitmapID, UINT fuLoad = LR_DEFAULTCOLOR) -{ - ATLASSERT(wBitmapID >= 32734 && wBitmapID <= 32767); - ATLASSERT((fuLoad & LR_LOADFROMFILE) == 0); // this one doesn't load from a file - return (HBITMAP)::LoadImage(NULL, MAKEINTRESOURCE(wBitmapID), IMAGE_BITMAP, 0, 0, fuLoad); -} -#endif // OEMRESOURCE - -inline HCURSOR AtlLoadSysCursorImage(ATL::_U_STRINGorID cursor, UINT fuLoad = LR_DEFAULTCOLOR | LR_DEFAULTSIZE, int cxDesired = 0, int cyDesired = 0) -{ -#ifdef _DEBUG - WORD wID = (WORD)cursor.m_lpstr; - ATLASSERT((wID >= 32512 && wID <= 32516) || (wID >= 32640 && wID <= 32648) || (wID == 32650) || (wID == 32651)); - ATLASSERT((fuLoad & LR_LOADFROMFILE) == 0); // this one doesn't load from a file -#endif // _DEBUG - return (HCURSOR)::LoadImage(NULL, cursor.m_lpstr, IMAGE_CURSOR, cxDesired, cyDesired, fuLoad); -} - -inline HICON AtlLoadSysIconImage(ATL::_U_STRINGorID icon, UINT fuLoad = LR_DEFAULTCOLOR | LR_DEFAULTSIZE, int cxDesired = 0, int cyDesired = 0) -{ -#ifdef _DEBUG - WORD wID = (WORD)icon.m_lpstr; - ATLASSERT(wID >= 32512 && wID <= 32517); - ATLASSERT((fuLoad & LR_LOADFROMFILE) == 0); // this one doesn't load from a file -#endif // _DEBUG - return (HICON)::LoadImage(NULL, icon.m_lpstr, IMAGE_ICON, cxDesired, cyDesired, fuLoad); -} - -#if (_ATL_VER < 0x0700) -inline int AtlLoadString(UINT uID, LPTSTR lpBuffer, int nBufferMax) -{ - return ::LoadString(_Module.GetResourceInstance(), uID, lpBuffer, nBufferMax); -} -#endif // (_ATL_VER < 0x0700) - -#ifdef _WIN32_WCE // CE only direct access to the resource -inline LPCTSTR AtlLoadString(UINT uID) -{ - LPCTSTR s = (LPCTSTR)::LoadString(ModuleHelper::GetResourceInstance(), uID, NULL, 0); -#ifdef DEBUG // Check for null-termination - if(s != NULL) - // Note: RC -n compiles null-terminated resource strings - ATLASSERT(s[*((WORD*)s -1) - 1] == L'\0'); -#endif - return s; -} -#endif // _WIN32_WCE - -inline bool AtlLoadString(UINT uID, BSTR& bstrText) -{ - USES_CONVERSION; - ATLASSERT(bstrText == NULL); - - LPTSTR lpstrText = NULL; - int nRes = 0; - for(int nLen = 256; ; nLen *= 2) - { - ATLTRY(lpstrText = new TCHAR[nLen]); - if(lpstrText == NULL) - break; - nRes = ::LoadString(ModuleHelper::GetResourceInstance(), uID, lpstrText, nLen); - if(nRes < nLen - 1) - break; - delete [] lpstrText; - lpstrText = NULL; - } - - if(lpstrText != NULL) - { - if(nRes != 0) - bstrText = ::SysAllocString(T2OLE(lpstrText)); - delete [] lpstrText; - } - - return (bstrText != NULL) ? true : false; -} - - -/////////////////////////////////////////////////////////////////////////////// -// Global functions for stock GDI objects - -inline HPEN AtlGetStockPen(int nPen) -{ -#if (_WIN32_WINNT >= 0x0500) && !defined(_WIN32_WCE) - ATLASSERT(nPen == WHITE_PEN || nPen == BLACK_PEN || nPen == NULL_PEN || nPen == DC_PEN); -#else - ATLASSERT(nPen == WHITE_PEN || nPen == BLACK_PEN || nPen == NULL_PEN); -#endif - return (HPEN)::GetStockObject(nPen); -} - -inline HBRUSH AtlGetStockBrush(int nBrush) -{ -#if (_WIN32_WINNT >= 0x0500) && !defined(_WIN32_WCE) - ATLASSERT((nBrush >= WHITE_BRUSH && nBrush <= HOLLOW_BRUSH) || nBrush == DC_BRUSH); -#else - ATLASSERT(nBrush >= WHITE_BRUSH && nBrush <= HOLLOW_BRUSH); -#endif - return (HBRUSH)::GetStockObject(nBrush); -} - -inline HFONT AtlGetStockFont(int nFont) -{ -#ifndef _WIN32_WCE - ATLASSERT((nFont >= OEM_FIXED_FONT && nFont <= SYSTEM_FIXED_FONT) || nFont == DEFAULT_GUI_FONT); -#else // CE specific - ATLASSERT(nFont == SYSTEM_FONT); -#endif // _WIN32_WCE - return (HFONT)::GetStockObject(nFont); -} - -inline HPALETTE AtlGetStockPalette(int nPalette) -{ - ATLASSERT(nPalette == DEFAULT_PALETTE); // the only one supported - return (HPALETTE)::GetStockObject(nPalette); -} - - -/////////////////////////////////////////////////////////////////////////////// -// Global function for compacting a path by replacing parts with ellipsis - -// helper for multi-byte character sets -inline bool _IsDBCSTrailByte(LPCTSTR lpstr, int nChar) -{ -#ifndef _UNICODE - int i = nChar; - for( ; i > 0; i--) - { - if(!::IsDBCSLeadByte(lpstr[i - 1])) - break; - } - return ((nChar > 0) && (((nChar - i) & 1) != 0)); -#else // _UNICODE - lpstr; nChar; - return false; -#endif // _UNICODE -} - -inline bool AtlCompactPath(LPTSTR lpstrOut, LPCTSTR lpstrIn, int cchLen) -{ - ATLASSERT(lpstrOut != NULL); - ATLASSERT(lpstrIn != NULL); - ATLASSERT(cchLen > 0); - - LPCTSTR szEllipsis = _T("..."); - const int cchEndEllipsis = 3; - const int cchMidEllipsis = 4; - - if(lstrlen(lpstrIn) < cchLen) - { - SecureHelper::strcpy_x(lpstrOut, cchLen, lpstrIn); - return true; - } - - lpstrOut[0] = 0; - - // check if the separator is a slash or a backslash - TCHAR chSlash = _T('\\'); - for(LPTSTR lpstr = (LPTSTR)lpstrIn; *lpstr != 0; lpstr = ::CharNext(lpstr)) - { - if((*lpstr == _T('/')) || (*lpstr == _T('\\'))) - chSlash = *lpstr; - } - - // find the filename portion of the path - LPCTSTR lpstrFileName = lpstrIn; - for(LPCTSTR pPath = lpstrIn; *pPath; pPath = ::CharNext(pPath)) - { - if((pPath[0] == _T('\\') || pPath[0] == _T(':') || pPath[0] == _T('/')) - && pPath[1] && pPath[1] != _T('\\') && pPath[1] != _T('/')) - lpstrFileName = pPath + 1; - } - int cchFileName = lstrlen(lpstrFileName); - - // handle just the filename without a path - if(lpstrFileName == lpstrIn && cchLen > cchEndEllipsis) - { - bool bRet = (SecureHelper::strncpy_x(lpstrOut, cchLen, lpstrIn, cchLen - cchEndEllipsis - 1) == 0); - if(bRet) - { -#ifndef _UNICODE - if(_IsDBCSTrailByte(lpstrIn, cchLen - cchEndEllipsis)) - lpstrOut[cchLen - cchEndEllipsis - 1] = 0; -#endif // _UNICODE - SecureHelper::strcat_x(lpstrOut, cchLen, szEllipsis); - } - return bRet; - } - - // handle just ellipsis - if((cchLen < (cchMidEllipsis + cchEndEllipsis))) - { - for(int i = 0; i < cchLen - 1; i++) - lpstrOut[i] = ((i + 1) == cchMidEllipsis) ? chSlash : _T('.'); - lpstrOut[cchLen - 1] = 0; - return true; - } - - // calc how much we have to copy - int cchToCopy = cchLen - (cchMidEllipsis + cchFileName) - 1; - - if(cchToCopy < 0) - cchToCopy = 0; - -#ifndef _UNICODE - if(cchToCopy > 0 && _IsDBCSTrailByte(lpstrIn, cchToCopy)) - cchToCopy--; -#endif // _UNICODE - - bool bRet = (SecureHelper::strncpy_x(lpstrOut, cchLen, lpstrIn, cchToCopy) == 0); - if(!bRet) - return false; - - // add ellipsis - SecureHelper::strcat_x(lpstrOut, cchLen, szEllipsis); - if(!bRet) - return false; - TCHAR szSlash[2] = { chSlash, 0 }; - SecureHelper::strcat_x(lpstrOut, cchLen, szSlash); - if(!bRet) - return false; - - // add filename (and ellipsis, if needed) - if(cchLen > (cchMidEllipsis + cchFileName)) - { - SecureHelper::strcat_x(lpstrOut, cchLen, lpstrFileName); - } - else - { - cchToCopy = cchLen - cchMidEllipsis - cchEndEllipsis - 1; -#ifndef _UNICODE - if(cchToCopy > 0 && _IsDBCSTrailByte(lpstrFileName, cchToCopy)) - cchToCopy--; -#endif // _UNICODE - bRet = (SecureHelper::strncpy_x(&lpstrOut[cchMidEllipsis], cchLen - cchMidEllipsis, lpstrFileName, cchToCopy) == 0); - if(bRet) - SecureHelper::strcat_x(lpstrOut, cchLen, szEllipsis); - } - - return bRet; -} - -}; // namespace WTL - -#endif // __ATLMISC_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/atlprint.h b/prog/3rdPartyLibs/wtl-8.1/include/atlprint.h deleted file mode 100644 index 5b81b2bf4..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/atlprint.h +++ /dev/null @@ -1,1113 +0,0 @@ -// Windows Template Library - WTL version 8.1 -// Copyright (C) Microsoft Corporation. All rights reserved. -// -// This file is a part of the Windows Template Library. -// The use and distribution terms for this software are covered by the -// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php) -// which can be found in the file CPL.TXT at the root of this distribution. -// By using this software in any fashion, you are agreeing to be bound by -// the terms of this license. You must not remove this notice, or -// any other, from this software. - -#ifndef __ATLPRINT_H__ -#define __ATLPRINT_H__ - -#pragma once - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#ifdef _WIN32_WCE - #error atlprint.h is not supported on Windows CE -#endif - -#ifndef __ATLAPP_H__ - #error atlprint.h requires atlapp.h to be included first -#endif - -#ifndef __ATLWIN_H__ - #error atlprint.h requires atlwin.h to be included first -#endif - - -/////////////////////////////////////////////////////////////////////////////// -// Classes in this file: -// -// CPrinterInfo -// CPrinterT -// CDevModeT -// CPrinterDC -// CPrintJobInfo -// CPrintJob -// CPrintPreview -// CPrintPreviewWindowImpl -// CPrintPreviewWindow -// CZoomPrintPreviewWindowImpl -// CZoomPrintPreviewWindow - -namespace WTL -{ - -/////////////////////////////////////////////////////////////////////////////// -// CPrinterInfo - This class wraps all of the PRINTER_INFO_* structures -// and provided by ::GetPrinter. - -template -class _printer_info -{ -public: - typedef void infotype; -}; - -template <> class _printer_info<1> { public: typedef PRINTER_INFO_1 infotype; }; -template <> class _printer_info<2> { public: typedef PRINTER_INFO_2 infotype; }; -template <> class _printer_info<3> { public: typedef PRINTER_INFO_3 infotype; }; -template <> class _printer_info<4> { public: typedef PRINTER_INFO_4 infotype; }; -template <> class _printer_info<5> { public: typedef PRINTER_INFO_5 infotype; }; -template <> class _printer_info<6> { public: typedef PRINTER_INFO_6 infotype; }; -template <> class _printer_info<7> { public: typedef PRINTER_INFO_7 infotype; }; -// these are not in the old (vc6.0) headers -#ifdef _ATL_USE_NEW_PRINTER_INFO -template <> class _printer_info<8> { public: typedef PRINTER_INFO_8 infotype; }; -template <> class _printer_info<9> { public: typedef PRINTER_INFO_9 infotype; }; -#endif // _ATL_USE_NEW_PRINTER_INFO - - -template -class CPrinterInfo -{ -public: -// Data members - typename _printer_info::infotype* m_pi; - -// Constructor/destructor - CPrinterInfo() : m_pi(NULL) - { } - - CPrinterInfo(HANDLE hPrinter) : m_pi(NULL) - { - GetPrinterInfo(hPrinter); - } - - ~CPrinterInfo() - { - Cleanup(); - } - -// Operations - bool GetPrinterInfo(HANDLE hPrinter) - { - Cleanup(); - return GetPrinterInfoHelper(hPrinter, (BYTE**)&m_pi, t_nInfo); - } - -// Implementation - void Cleanup() - { - delete [] (BYTE*)m_pi; - m_pi = NULL; - } - - static bool GetPrinterInfoHelper(HANDLE hPrinter, BYTE** pi, int nIndex) - { - ATLASSERT(pi != NULL); - DWORD dw = 0; - BYTE* pb = NULL; - ::GetPrinter(hPrinter, nIndex, NULL, 0, &dw); - if (dw > 0) - { - ATLTRY(pb = new BYTE[dw]); - if (pb != NULL) - { - memset(pb, 0, dw); - DWORD dwNew; - if (!::GetPrinter(hPrinter, nIndex, pb, dw, &dwNew)) - { - delete [] pb; - pb = NULL; - } - } - } - *pi = pb; - return (pb != NULL); - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CPrinter - Wrapper class for a HANDLE to a printer - -template -class CPrinterT -{ -public: -// Data members - HANDLE m_hPrinter; - -// Constructor/destructor - CPrinterT(HANDLE hPrinter = NULL) : m_hPrinter(hPrinter) - { } - - ~CPrinterT() - { - ClosePrinter(); - } - -// Operations - CPrinterT& operator =(HANDLE hPrinter) - { - if (hPrinter != m_hPrinter) - { - ClosePrinter(); - m_hPrinter = hPrinter; - } - return *this; - } - - bool IsNull() const { return (m_hPrinter == NULL); } - - bool OpenPrinter(HANDLE hDevNames, const DEVMODE* pDevMode = NULL) - { - bool b = false; - DEVNAMES* pdn = (DEVNAMES*)::GlobalLock(hDevNames); - if (pdn != NULL) - { - LPTSTR lpszPrinterName = (LPTSTR)pdn + pdn->wDeviceOffset; - b = OpenPrinter(lpszPrinterName, pDevMode); - ::GlobalUnlock(hDevNames); - } - return b; - } - - bool OpenPrinter(LPCTSTR lpszPrinterName, const DEVMODE* pDevMode = NULL) - { - ClosePrinter(); - PRINTER_DEFAULTS pdefs = { NULL, (DEVMODE*)pDevMode, PRINTER_ACCESS_USE }; - ::OpenPrinter((LPTSTR) lpszPrinterName, &m_hPrinter, (pDevMode == NULL) ? NULL : &pdefs); - - return (m_hPrinter != NULL); - } - - bool OpenPrinter(LPCTSTR lpszPrinterName, PRINTER_DEFAULTS* pprintdefs) - { - ClosePrinter(); - ::OpenPrinter((LPTSTR) lpszPrinterName, &m_hPrinter, pprintdefs); - return (m_hPrinter != NULL); - } - - bool OpenDefaultPrinter(const DEVMODE* pDevMode = NULL) - { - ClosePrinter(); - const int cchBuff = 512; - TCHAR buffer[cchBuff]; - buffer[0] = 0; - ::GetProfileString(_T("windows"), _T("device"), _T(",,,"), buffer, cchBuff); - int nLen = lstrlen(buffer); - if (nLen != 0) - { - LPTSTR lpsz = buffer; - while (*lpsz) - { - if (*lpsz == _T(',')) - { - *lpsz = 0; - break; - } - lpsz = CharNext(lpsz); - } - PRINTER_DEFAULTS pdefs = { NULL, (DEVMODE*)pDevMode, PRINTER_ACCESS_USE }; - ::OpenPrinter(buffer, &m_hPrinter, (pDevMode == NULL) ? NULL : &pdefs); - } - return m_hPrinter != NULL; - } - - void ClosePrinter() - { - if (m_hPrinter != NULL) - { - if (t_bManaged) - ::ClosePrinter(m_hPrinter); - m_hPrinter = NULL; - } - } - - bool PrinterProperties(HWND hWnd = NULL) - { - if (hWnd == NULL) - hWnd = ::GetActiveWindow(); - return !!::PrinterProperties(hWnd, m_hPrinter); - } - - HANDLE CopyToHDEVNAMES() const - { - HANDLE h = NULL; - CPrinterInfo<5> pinfon5; - CPrinterInfo<2> pinfon2; - LPTSTR lpszPrinterName = NULL; - // Some printers fail for PRINTER_INFO_5 in some situations - if (pinfon5.GetPrinterInfo(m_hPrinter)) - lpszPrinterName = pinfon5.m_pi->pPrinterName; - else if (pinfon2.GetPrinterInfo(m_hPrinter)) - lpszPrinterName = pinfon2.m_pi->pPrinterName; - if (lpszPrinterName != NULL) - { - int nLen = sizeof(DEVNAMES) + (lstrlen(lpszPrinterName) + 1) * sizeof(TCHAR); - h = ::GlobalAlloc(GMEM_MOVEABLE, nLen); - BYTE* pv = (BYTE*)::GlobalLock(h); - DEVNAMES* pdev = (DEVNAMES*)pv; - if (pv != NULL) - { - memset(pv, 0, nLen); - pdev->wDeviceOffset = sizeof(DEVNAMES) / sizeof(TCHAR); - pv = pv + sizeof(DEVNAMES); // now points to end - SecureHelper::strcpy_x((LPTSTR)pv, lstrlen(lpszPrinterName) + 1, lpszPrinterName); - ::GlobalUnlock(h); - } - } - return h; - } - - HDC CreatePrinterDC(const DEVMODE* pdm = NULL) const - { - CPrinterInfo<5> pinfo5; - CPrinterInfo<2> pinfo2; - HDC hDC = NULL; - LPTSTR lpszPrinterName = NULL; - // Some printers fail for PRINTER_INFO_5 in some situations - if (pinfo5.GetPrinterInfo(m_hPrinter)) - lpszPrinterName = pinfo5.m_pi->pPrinterName; - else if (pinfo2.GetPrinterInfo(m_hPrinter)) - lpszPrinterName = pinfo2.m_pi->pPrinterName; - if (lpszPrinterName != NULL) - hDC = ::CreateDC(NULL, lpszPrinterName, NULL, pdm); - return hDC; - } - - HDC CreatePrinterIC(const DEVMODE* pdm = NULL) const - { - CPrinterInfo<5> pinfo5; - CPrinterInfo<2> pinfo2; - HDC hDC = NULL; - LPTSTR lpszPrinterName = NULL; - // Some printers fail for PRINTER_INFO_5 in some situations - if (pinfo5.GetPrinterInfo(m_hPrinter)) - lpszPrinterName = pinfo5.m_pi->pPrinterName; - else if (pinfo2.GetPrinterInfo(m_hPrinter)) - lpszPrinterName = pinfo2.m_pi->pPrinterName; - if (lpszPrinterName != NULL) - hDC = ::CreateIC(NULL, lpszPrinterName, NULL, pdm); - return hDC; - } - - void Attach(HANDLE hPrinter) - { - ClosePrinter(); - m_hPrinter = hPrinter; - } - - HANDLE Detach() - { - HANDLE hPrinter = m_hPrinter; - m_hPrinter = NULL; - return hPrinter; - } - - operator HANDLE() const { return m_hPrinter; } -}; - -typedef CPrinterT CPrinterHandle; -typedef CPrinterT CPrinter; - - -/////////////////////////////////////////////////////////////////////////////// -// CDevMode - Wrapper class for DEVMODE - -template -class CDevModeT -{ -public: -// Data members - HANDLE m_hDevMode; - DEVMODE* m_pDevMode; - -// Constructor/destructor - CDevModeT(HANDLE hDevMode = NULL) : m_hDevMode(hDevMode) - { - m_pDevMode = (m_hDevMode != NULL) ? (DEVMODE*)::GlobalLock(m_hDevMode) : NULL; - } - - ~CDevModeT() - { - Cleanup(); - } - -// Operations - CDevModeT& operator =(HANDLE hDevMode) - { - Attach(hDevMode); - return *this; - } - - void Attach(HANDLE hDevModeNew) - { - Cleanup(); - m_hDevMode = hDevModeNew; - m_pDevMode = (m_hDevMode != NULL) ? (DEVMODE*)::GlobalLock(m_hDevMode) : NULL; - } - - HANDLE Detach() - { - if (m_hDevMode != NULL) - ::GlobalUnlock(m_hDevMode); - HANDLE hDevMode = m_hDevMode; - m_hDevMode = NULL; - return hDevMode; - } - - bool IsNull() const { return (m_hDevMode == NULL); } - - bool CopyFromPrinter(HANDLE hPrinter) - { - CPrinterInfo<2> pinfo; - bool b = pinfo.GetPrinterInfo(hPrinter); - if (b) - b = CopyFromDEVMODE(pinfo.m_pi->pDevMode); - return b; - } - - bool CopyFromDEVMODE(const DEVMODE* pdm) - { - if (pdm == NULL) - return false; - int nSize = pdm->dmSize + pdm->dmDriverExtra; - HANDLE h = ::GlobalAlloc(GMEM_MOVEABLE, nSize); - if (h != NULL) - { - void* p = ::GlobalLock(h); - SecureHelper::memcpy_x(p, nSize, pdm, nSize); - ::GlobalUnlock(h); - } - Attach(h); - return (h != NULL); - } - - bool CopyFromHDEVMODE(HANDLE hdm) - { - bool b = false; - if (hdm != NULL) - { - DEVMODE* pdm = (DEVMODE*)::GlobalLock(hdm); - b = CopyFromDEVMODE(pdm); - ::GlobalUnlock(hdm); - } - return b; - } - - HANDLE CopyToHDEVMODE() - { - if ((m_hDevMode == NULL) || (m_pDevMode == NULL)) - return NULL; - int nSize = m_pDevMode->dmSize + m_pDevMode->dmDriverExtra; - HANDLE h = ::GlobalAlloc(GMEM_MOVEABLE, nSize); - if (h != NULL) - { - void* p = ::GlobalLock(h); - SecureHelper::memcpy_x(p, nSize, m_pDevMode, nSize); - ::GlobalUnlock(h); - } - return h; - } - - // If this devmode was for another printer, this will create a new devmode - // based on the existing devmode, but retargeted at the new printer - bool UpdateForNewPrinter(HANDLE hPrinter) - { - bool bRet = false; - LONG nLen = ::DocumentProperties(NULL, hPrinter, NULL, NULL, NULL, 0); - CTempBuffer buff; - DEVMODE* pdm = buff.AllocateBytes(nLen); - if(pdm != NULL) - { - memset(pdm, 0, nLen); - LONG l = ::DocumentProperties(NULL, hPrinter, NULL, pdm, m_pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER); - if (l == IDOK) - bRet = CopyFromDEVMODE(pdm); - } - - return bRet; - } - - bool DocumentProperties(HANDLE hPrinter, HWND hWnd = NULL) - { - CPrinterInfo<1> pi; - pi.GetPrinterInfo(hPrinter); - if (hWnd == NULL) - hWnd = ::GetActiveWindow(); - - bool bRet = false; - LONG nLen = ::DocumentProperties(hWnd, hPrinter, pi.m_pi->pName, NULL, NULL, 0); - CTempBuffer buff; - DEVMODE* pdm = buff.AllocateBytes(nLen); - if(pdm != NULL) - { - memset(pdm, 0, nLen); - LONG l = ::DocumentProperties(hWnd, hPrinter, pi.m_pi->pName, pdm, m_pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER | DM_PROMPT); - if (l == IDOK) - bRet = CopyFromDEVMODE(pdm); - } - - return bRet; - } - - operator HANDLE() const { return m_hDevMode; } - - operator DEVMODE*() const { return m_pDevMode; } - -// Implementation - void Cleanup() - { - if (m_hDevMode != NULL) - { - ::GlobalUnlock(m_hDevMode); - if(t_bManaged) - ::GlobalFree(m_hDevMode); - m_hDevMode = NULL; - } - } -}; - -typedef CDevModeT CDevModeHandle; -typedef CDevModeT CDevMode; - - -/////////////////////////////////////////////////////////////////////////////// -// CPrinterDC - -class CPrinterDC : public CDC -{ -public: -// Constructors/destructor - CPrinterDC() - { - CPrinter printer; - printer.OpenDefaultPrinter(); - Attach(printer.CreatePrinterDC()); - ATLASSERT(m_hDC != NULL); - } - - CPrinterDC(HANDLE hPrinter, const DEVMODE* pdm = NULL) - { - CPrinterHandle p; - p.Attach(hPrinter); - Attach(p.CreatePrinterDC(pdm)); - ATLASSERT(m_hDC != NULL); - } - - ~CPrinterDC() - { - DeleteDC(); - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CPrintJob - Wraps a set of tasks for a specific printer (StartDoc/EndDoc) -// Handles aborting, background printing - -// Defines callbacks used by CPrintJob (not a COM interface) -class ATL_NO_VTABLE IPrintJobInfo -{ -public: - virtual void BeginPrintJob(HDC hDC) = 0; // allocate handles needed, etc. - virtual void EndPrintJob(HDC hDC, bool bAborted) = 0; // free handles, etc. - virtual void PrePrintPage(UINT nPage, HDC hDC) = 0; - virtual bool PrintPage(UINT nPage, HDC hDC) = 0; - virtual void PostPrintPage(UINT nPage, HDC hDC) = 0; - // If you want per page devmodes, return the DEVMODE* to use for nPage. - // You can optimize by only returning a new DEVMODE* when it is different - // from the one for nLastPage, otherwise return NULL. - // When nLastPage==0, the current DEVMODE* will be the default passed to - // StartPrintJob. - // Note: During print preview, nLastPage will always be "0". - virtual DEVMODE* GetNewDevModeForPage(UINT nLastPage, UINT nPage) = 0; - virtual bool IsValidPage(UINT nPage) = 0; -}; - -// Provides a default implementatin for IPrintJobInfo -// Typically, MI'd into a document or view class -class ATL_NO_VTABLE CPrintJobInfo : public IPrintJobInfo -{ -public: - virtual void BeginPrintJob(HDC /*hDC*/) // allocate handles needed, etc - { - } - - virtual void EndPrintJob(HDC /*hDC*/, bool /*bAborted*/) // free handles, etc - { - } - - virtual void PrePrintPage(UINT /*nPage*/, HDC hDC) - { - m_nPJState = ::SaveDC(hDC); - } - - virtual bool PrintPage(UINT /*nPage*/, HDC /*hDC*/) = 0; - - virtual void PostPrintPage(UINT /*nPage*/, HDC hDC) - { - RestoreDC(hDC, m_nPJState); - } - - virtual DEVMODE* GetNewDevModeForPage(UINT /*nLastPage*/, UINT /*nPage*/) - { - return NULL; - } - - virtual bool IsValidPage(UINT /*nPage*/) - { - return true; - } - -// Implementation - data - int m_nPJState; -}; - - -class CPrintJob -{ -public: -// Data members - CPrinterHandle m_printer; - IPrintJobInfo* m_pInfo; - DEVMODE* m_pDefDevMode; - DOCINFO m_docinfo; - int m_nJobID; - bool m_bCancel; - bool m_bComplete; - unsigned long m_nStartPage; - unsigned long m_nEndPage; - -// Constructor/destructor - CPrintJob() : m_nJobID(0), m_bCancel(false), m_bComplete(true) - { } - - ~CPrintJob() - { - ATLASSERT(IsJobComplete()); // premature destruction? - } - -// Operations - bool IsJobComplete() const - { - return m_bComplete; - } - - bool StartPrintJob(bool bBackground, HANDLE hPrinter, DEVMODE* pDefaultDevMode, - IPrintJobInfo* pInfo, LPCTSTR lpszDocName, - unsigned long nStartPage, unsigned long nEndPage, - bool bPrintToFile = false, LPCTSTR lpstrOutputFile = NULL) - { - ATLASSERT(m_bComplete); // previous job not done yet? - if (pInfo == NULL) - return false; - - memset(&m_docinfo, 0, sizeof(m_docinfo)); - m_docinfo.cbSize = sizeof(m_docinfo); - m_docinfo.lpszDocName = lpszDocName; - m_pInfo = pInfo; - m_nStartPage = nStartPage; - m_nEndPage = nEndPage; - m_printer.Attach(hPrinter); - m_pDefDevMode = pDefaultDevMode; - m_bComplete = false; - - if(bPrintToFile) - m_docinfo.lpszOutput = (lpstrOutputFile != NULL) ? lpstrOutputFile : _T("FILE:"); - - if (!bBackground) - { - m_bComplete = true; - return StartHelper(); - } - - // Create a thread and return - DWORD dwThreadID = 0; -#if !defined(_ATL_MIN_CRT) && defined(_MT) - HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, (UINT (WINAPI*)(void*))StartProc, this, 0, (UINT*)&dwThreadID); -#else - HANDLE hThread = ::CreateThread(NULL, 0, StartProc, (void*)this, 0, &dwThreadID); -#endif - if (hThread == NULL) - return false; - - ::CloseHandle(hThread); - - return true; - } - -// Implementation - static DWORD WINAPI StartProc(void* p) - { - CPrintJob* pThis = (CPrintJob*)p; - pThis->StartHelper(); - pThis->m_bComplete = true; - return 0; - } - - bool StartHelper() - { - CDC dcPrinter; - dcPrinter.Attach(m_printer.CreatePrinterDC(m_pDefDevMode)); - if (dcPrinter.IsNull()) - return false; - - m_nJobID = ::StartDoc(dcPrinter, &m_docinfo); - if (m_nJobID <= 0) - return false; - - m_pInfo->BeginPrintJob(dcPrinter); - - // print all the pages now - unsigned long nLastPage = 0; - for (unsigned long nPage = m_nStartPage; nPage <= m_nEndPage; nPage++) - { - if (!m_pInfo->IsValidPage(nPage)) - break; - DEVMODE* pdm = m_pInfo->GetNewDevModeForPage(nLastPage, nPage); - if (pdm != NULL) - dcPrinter.ResetDC(pdm); - dcPrinter.StartPage(); - m_pInfo->PrePrintPage(nPage, dcPrinter); - if (!m_pInfo->PrintPage(nPage, dcPrinter)) - m_bCancel = true; - m_pInfo->PostPrintPage(nPage, dcPrinter); - dcPrinter.EndPage(); - if (m_bCancel) - break; - nLastPage = nPage; - } - - m_pInfo->EndPrintJob(dcPrinter, m_bCancel); - if (m_bCancel) - ::AbortDoc(dcPrinter); - else - ::EndDoc(dcPrinter); - m_nJobID = 0; - return true; - } - - // Cancels a print job. Can be called asynchronously. - void CancelPrintJob() - { - m_bCancel = true; - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CPrintPreview - Adds print preview support to an existing window - -class CPrintPreview -{ -public: -// Data members - IPrintJobInfo* m_pInfo; - CPrinterHandle m_printer; - CEnhMetaFile m_meta; - DEVMODE* m_pDefDevMode; - DEVMODE* m_pCurDevMode; - SIZE m_sizeCurPhysOffset; - -// Constructor - CPrintPreview() : m_pInfo(NULL), m_pDefDevMode(NULL), m_pCurDevMode(NULL) - { - m_sizeCurPhysOffset.cx = 0; - m_sizeCurPhysOffset.cy = 0; - } - -// Operations - void SetPrintPreviewInfo(HANDLE hPrinter, DEVMODE* pDefaultDevMode, IPrintJobInfo* pji) - { - m_printer.Attach(hPrinter); - m_pDefDevMode = pDefaultDevMode; - m_pInfo = pji; - m_nCurPage = 0; - m_pCurDevMode = NULL; - } - - void SetEnhMetaFile(HENHMETAFILE hEMF) - { - m_meta = hEMF; - } - - void SetPage(int nPage) - { - if (!m_pInfo->IsValidPage(nPage)) - return; - m_nCurPage = nPage; - m_pCurDevMode = m_pInfo->GetNewDevModeForPage(0, nPage); - if (m_pCurDevMode == NULL) - m_pCurDevMode = m_pDefDevMode; - CDC dcPrinter = m_printer.CreatePrinterDC(m_pCurDevMode); - - int iWidth = dcPrinter.GetDeviceCaps(PHYSICALWIDTH); - int iHeight = dcPrinter.GetDeviceCaps(PHYSICALHEIGHT); - int nLogx = dcPrinter.GetDeviceCaps(LOGPIXELSX); - int nLogy = dcPrinter.GetDeviceCaps(LOGPIXELSY); - - RECT rcMM = { 0, 0, ::MulDiv(iWidth, 2540, nLogx), ::MulDiv(iHeight, 2540, nLogy) }; - - m_sizeCurPhysOffset.cx = dcPrinter.GetDeviceCaps(PHYSICALOFFSETX); - m_sizeCurPhysOffset.cy = dcPrinter.GetDeviceCaps(PHYSICALOFFSETY); - - CEnhMetaFileDC dcMeta(dcPrinter, &rcMM); - m_pInfo->PrePrintPage(nPage, dcMeta); - m_pInfo->PrintPage(nPage, dcMeta); - m_pInfo->PostPrintPage(nPage, dcMeta); - m_meta.Attach(dcMeta.Close()); - } - - void GetPageRect(RECT& rc, LPRECT prc) - { - int x1 = rc.right-rc.left; - int y1 = rc.bottom - rc.top; - if ((x1 < 0) || (y1 < 0)) - return; - - CEnhMetaFileInfo emfinfo(m_meta); - ENHMETAHEADER* pmh = emfinfo.GetEnhMetaFileHeader(); - - // Compute whether we are OK vertically or horizontally - int x2 = pmh->szlDevice.cx; - int y2 = pmh->szlDevice.cy; - int y1p = MulDiv(x1, y2, x2); - int x1p = MulDiv(y1, x2, y2); - ATLASSERT((x1p <= x1) || (y1p <= y1)); - if (x1p <= x1) - { - prc->left = rc.left + (x1 - x1p) / 2; - prc->right = prc->left + x1p; - prc->top = rc.top; - prc->bottom = rc.bottom; - } - else - { - prc->left = rc.left; - prc->right = rc.right; - prc->top = rc.top + (y1 - y1p) / 2; - prc->bottom = prc->top + y1p; - } - } - -// Painting helpers - void DoPaint(CDCHandle dc) - { - // this one is not used - } - - void DoPaint(CDCHandle dc, RECT& rc) - { - CEnhMetaFileInfo emfinfo(m_meta); - ENHMETAHEADER* pmh = emfinfo.GetEnhMetaFileHeader(); - int nOffsetX = MulDiv(m_sizeCurPhysOffset.cx, rc.right-rc.left, pmh->szlDevice.cx); - int nOffsetY = MulDiv(m_sizeCurPhysOffset.cy, rc.bottom-rc.top, pmh->szlDevice.cy); - - dc.OffsetWindowOrg(-nOffsetX, -nOffsetY); - dc.PlayMetaFile(m_meta, &rc); - } - -// Implementation - data - int m_nCurPage; -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CPrintPreviewWindow - Implements a print preview window - -template -class ATL_NO_VTABLE CPrintPreviewWindowImpl : public ATL::CWindowImpl, public CPrintPreview -{ -public: - DECLARE_WND_CLASS_EX(NULL, CS_VREDRAW | CS_HREDRAW, -1) - - enum { m_cxOffset = 10, m_cyOffset = 10 }; - -// Constructor - CPrintPreviewWindowImpl() : m_nMaxPage(0), m_nMinPage(0) - { } - -// Operations - void SetPrintPreviewInfo(HANDLE hPrinter, DEVMODE* pDefaultDevMode, - IPrintJobInfo* pji, int nMinPage, int nMaxPage) - { - CPrintPreview::SetPrintPreviewInfo(hPrinter, pDefaultDevMode, pji); - m_nMinPage = nMinPage; - m_nMaxPage = nMaxPage; - } - - bool NextPage() - { - if (m_nCurPage == m_nMaxPage) - return false; - SetPage(m_nCurPage + 1); - Invalidate(); - return true; - } - - bool PrevPage() - { - if (m_nCurPage == m_nMinPage) - return false; - if (m_nCurPage == 0) - return false; - SetPage(m_nCurPage - 1); - Invalidate(); - return true; - } - -// Message map and handlers - BEGIN_MSG_MAP(CPrintPreviewWindowImpl) - MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd) - MESSAGE_HANDLER(WM_PAINT, OnPaint) - MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) - END_MSG_MAP() - - LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - return 1; // no need for the background - } - - LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - RECT rc = { 0 }; - - if(wParam != NULL) - { - pT->DoPrePaint((HDC)wParam, rc); - pT->DoPaint((HDC)wParam, rc); - } - else - { - CPaintDC dc(m_hWnd); - pT->DoPrePaint(dc.m_hDC, rc); - pT->DoPaint(dc.m_hDC, rc); - } - - return 0; - } - -// Painting helper - void DoPrePaint(CDCHandle dc, RECT& rc) - { - RECT rcClient = { 0 }; - GetClientRect(&rcClient); - RECT rcArea = rcClient; - T* pT = static_cast(this); - pT; // avoid level 4 warning - ::InflateRect(&rcArea, -pT->m_cxOffset, -pT->m_cyOffset); - if (rcArea.left > rcArea.right) - rcArea.right = rcArea.left; - if (rcArea.top > rcArea.bottom) - rcArea.bottom = rcArea.top; - GetPageRect(rcArea, &rc); - CRgn rgn1, rgn2; - rgn1.CreateRectRgnIndirect(&rc); - rgn2.CreateRectRgnIndirect(&rcClient); - rgn2.CombineRgn(rgn1, RGN_DIFF); - dc.SelectClipRgn(rgn2); - dc.FillRect(&rcClient, COLOR_BTNSHADOW); - dc.SelectClipRgn(NULL); - dc.FillRect(&rc, (HBRUSH)::GetStockObject(WHITE_BRUSH)); - } - -// Implementation - data - int m_nMinPage; - int m_nMaxPage; -}; - - -class CPrintPreviewWindow : public CPrintPreviewWindowImpl -{ -public: - DECLARE_WND_CLASS_EX(_T("WTL_PrintPreview"), CS_VREDRAW | CS_HREDRAW, -1) -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CZoomPrintPreviewWindowImpl - Implements print preview window with zooming - -#ifdef __ATLSCRL_H__ - -template -class ATL_NO_VTABLE CZoomPrintPreviewWindowImpl : public CPrintPreviewWindowImpl< T, TBase, TWinTraits >, public CZoomScrollImpl< T > -{ -public: - bool m_bSized; - - CZoomPrintPreviewWindowImpl() - { - SetScrollExtendedStyle(SCRL_DISABLENOSCROLL); - InitZoom(); - } - - // should be called to reset data members before recreating window - void InitZoom() - { - m_bSized = false; - m_nZoomMode = ZOOMMODE_OFF; - m_fZoomScaleMin = 1.0; - m_fZoomScale = 1.0; - } - - BEGIN_MSG_MAP(CZoomPrintPreviewWindowImpl) - MESSAGE_HANDLER(WM_SETCURSOR, CZoomScrollImpl< T >::OnSetCursor) - MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll) - MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll) - MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel) -#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) - MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel) -#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) - MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange) - MESSAGE_HANDLER(WM_LBUTTONDOWN, CZoomScrollImpl< T >::OnLButtonDown) - MESSAGE_HANDLER(WM_MOUSEMOVE, CZoomScrollImpl< T >::OnMouseMove) - MESSAGE_HANDLER(WM_LBUTTONUP, CZoomScrollImpl< T >::OnLButtonUp) - MESSAGE_HANDLER(WM_CAPTURECHANGED, CZoomScrollImpl< T >::OnCaptureChanged) - MESSAGE_HANDLER(WM_SIZE, OnSize) - MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd) - MESSAGE_HANDLER(WM_PAINT, OnPaint) - MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) - ALT_MSG_MAP(1) - COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp) - COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown) - COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp) - COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown) - COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop) - COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom) - COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft) - COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight) - COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft) - COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight) - COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft) - COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight) - END_MSG_MAP() - - LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - SIZE sizeClient = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)}; - POINT ptOffset = m_ptOffset; - SIZE sizeAll = m_sizeAll; - SetScrollSize(sizeClient); - if(sizeAll.cx > 0) - ptOffset.x = ::MulDiv(ptOffset.x, m_sizeAll.cx, sizeAll.cx); - if(sizeAll.cy > 0) - ptOffset.y = ::MulDiv(ptOffset.y, m_sizeAll.cy, sizeAll.cy); - SetScrollOffset(ptOffset); - CScrollImpl< T >::OnSize(uMsg, wParam, lParam, bHandled); - if(!m_bSized) - { - m_bSized = true; - T* pT = static_cast(this); - pT->ShowScrollBar(SB_HORZ, TRUE); - pT->ShowScrollBar(SB_VERT, TRUE); - } - return 0; - } - - LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - return 1; - } - - LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - RECT rc = { 0 }; - - if(wParam != NULL) - { - CDCHandle dc = (HDC)wParam; - int nMapModeSav = dc.GetMapMode(); - dc.SetMapMode(MM_ANISOTROPIC); - SIZE szWindowExt = { 0, 0 }; - dc.SetWindowExt(m_sizeLogAll, &szWindowExt); - SIZE szViewportExt = { 0, 0 }; - dc.SetViewportExt(m_sizeAll, &szViewportExt); - POINT ptViewportOrg = { 0, 0 }; - dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg); - - pT->DoPrePaint(dc, rc); - pT->DoPaint(dc, rc); - - dc.SetMapMode(nMapModeSav); - dc.SetWindowExt(szWindowExt); - dc.SetViewportExt(szViewportExt); - dc.SetViewportOrg(ptViewportOrg); - } - else - { - CPaintDC dc(pT->m_hWnd); - pT->PrepareDC(dc.m_hDC); - pT->DoPrePaint(dc.m_hDC, rc); - pT->DoPaint(dc.m_hDC, rc); - } - - return 0; - } - - // Painting helpers - void DoPaint(CDCHandle dc) - { - // this one is not used - } - - void DoPrePaint(CDCHandle dc, RECT& rc) - { - RECT rcClient; - GetClientRect(&rcClient); - RECT rcArea = rcClient; - T* pT = static_cast(this); - pT; // avoid level 4 warning - ::InflateRect(&rcArea, -pT->m_cxOffset, -pT->m_cyOffset); - if (rcArea.left > rcArea.right) - rcArea.right = rcArea.left; - if (rcArea.top > rcArea.bottom) - rcArea.bottom = rcArea.top; - GetPageRect(rcArea, &rc); - HBRUSH hbrOld = dc.SelectBrush(::GetSysColorBrush(COLOR_BTNSHADOW)); - dc.PatBlt(rcClient.left, rcClient.top, rc.left - rcClient.left, rcClient.bottom - rcClient.top, PATCOPY); - dc.PatBlt(rc.left, rcClient.top, rc.right - rc.left, rc.top - rcClient.top, PATCOPY); - dc.PatBlt(rc.right, rcClient.top, rcClient.right - rc.right, rcClient.bottom - rcClient.top, PATCOPY); - dc.PatBlt(rc.left, rc.bottom, rc.right - rc.left, rcClient.bottom - rc.bottom, PATCOPY); - dc.SelectBrush((HBRUSH)::GetStockObject(WHITE_BRUSH)); - dc.PatBlt(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY); - dc.SelectBrush(::GetSysColorBrush(COLOR_3DDKSHADOW)); - dc.PatBlt(rc.right, rc.top + 4, 4, rc.bottom - rc.top, PATCOPY); - dc.PatBlt(rc.left + 4, rc.bottom, rc.right - rc.left, 4, PATCOPY); - dc.SelectBrush(hbrOld); - } - - void DoPaint(CDCHandle dc, RECT& rc) - { - CEnhMetaFileInfo emfinfo(m_meta); - ENHMETAHEADER* pmh = emfinfo.GetEnhMetaFileHeader(); - int nOffsetX = MulDiv(m_sizeCurPhysOffset.cx, rc.right-rc.left, pmh->szlDevice.cx); - int nOffsetY = MulDiv(m_sizeCurPhysOffset.cy, rc.bottom-rc.top, pmh->szlDevice.cy); - - dc.OffsetWindowOrg(-nOffsetX, -nOffsetY); - dc.PlayMetaFile(m_meta, &rc); - } -}; - -class CZoomPrintPreviewWindow : public CZoomPrintPreviewWindowImpl -{ -public: - DECLARE_WND_CLASS_EX(_T("WTL_ZoomPrintPreview"), CS_VREDRAW | CS_HREDRAW, -1) -}; - -#endif // __ATLSCRL_H__ - -}; // namespace WTL - -#endif // __ATLPRINT_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/atlres.h b/prog/3rdPartyLibs/wtl-8.1/include/atlres.h deleted file mode 100644 index b8b3e8f09..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/atlres.h +++ /dev/null @@ -1,262 +0,0 @@ -// Windows Template Library - WTL version 8.1 -// Copyright (C) Microsoft Corporation. All rights reserved. -// -// This file is a part of the Windows Template Library. -// The use and distribution terms for this software are covered by the -// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php) -// which can be found in the file CPL.TXT at the root of this distribution. -// By using this software in any fashion, you are agreeing to be bound by -// the terms of this license. You must not remove this notice, or -// any other, from this software. - -#ifndef __ATLRES_H__ -#define __ATLRES_H__ - -#pragma once - -#if defined(_WIN32_WCE) && !defined(__ATLRESCE_H__) - #error Use atlresCE.h instead of atlres.h for Windows CE -#endif - - -#ifdef RC_INVOKED -#ifndef _INC_WINDOWS - - #define _INC_WINDOWS - - #ifndef _WIN32_WCE - #define VS_VERSION_INFO 1 - - #ifdef APSTUDIO_INVOKED - #define APSTUDIO_HIDDEN_SYMBOLS // Ignore following symbols - #endif // APSTUDIO_INVOKED - - #ifndef WINVER - #define WINVER 0x0400 // default to Windows Version 4.0 - #endif // !WINVER - - #include - - // operation messages sent to DLGINIT - #define LB_ADDSTRING (WM_USER+1) - #define CB_ADDSTRING (WM_USER+3) - #endif // !_WIN32_WCE - - #ifdef APSTUDIO_INVOKED - #undef APSTUDIO_HIDDEN_SYMBOLS - #endif // APSTUDIO_INVOKED - - #ifdef IDC_STATIC - #undef IDC_STATIC - #endif // IDC_STATIC - #define IDC_STATIC (-1) - -#endif // !_INC_WINDOWS -#endif // RC_INVOKED - -#ifdef APSTUDIO_INVOKED - #define APSTUDIO_HIDDEN_SYMBOLS -#endif // APSTUDIO_INVOKED - -/////////////////////////////////////////////////////////////////////////////// -// ATL resource types - -#ifndef RC_INVOKED - #define RT_DLGINIT MAKEINTRESOURCE(240) - #define RT_TOOLBAR MAKEINTRESOURCE(241) -#endif // RC_INVOKED - -/////////////////////////////////////////////////////////////////////////////// - -#ifdef APSTUDIO_INVOKED - #undef APSTUDIO_HIDDEN_SYMBOLS -#endif // APSTUDIO_INVOKED - -/////////////////////////////////////////////////////////////////////////////// -// Standard window components - -#define ID_SEPARATOR 0 // special separator value -#define ID_DEFAULT_PANE 0 // default status bar pane - -#ifndef RC_INVOKED // code only -// standard control bars (IDW = window ID) - #define ATL_IDW_TOOLBAR 0xE800 // main Toolbar for window - #define ATL_IDW_STATUS_BAR 0xE801 // Status bar window - #define ATL_IDW_COMMAND_BAR 0xE802 // Command bar window - -// parts of a frame window - #define ATL_IDW_CLIENT 0xE900 - #define ATL_IDW_PANE_FIRST 0xE900 // first pane (256 max) - #define ATL_IDW_PANE_LAST 0xE9FF - #define ATL_IDW_HSCROLL_FIRST 0xEA00 // first Horz scrollbar (16 max) - #define ATL_IDW_VSCROLL_FIRST 0xEA10 // first Vert scrollbar (16 max) - - #define ATL_IDW_SIZE_BOX 0xEA20 // size box for splitters - #define ATL_IDW_PANE_SAVE 0xEA21 // to shift ATL_IDW_PANE_FIRST - -// bands for a rebar - #define ATL_IDW_BAND_FIRST 0xEB00 - #define ATL_IDW_BAND_LAST 0xEBFF -#endif // !RC_INVOKED - -/////////////////////////////////////////////////////////////////////////////// -// Standard Commands - -// File commands -#define ID_FILE_NEW 0xE100 -#define ID_FILE_OPEN 0xE101 -#define ID_FILE_CLOSE 0xE102 -#define ID_FILE_SAVE 0xE103 -#define ID_FILE_SAVE_AS 0xE104 -#define ID_FILE_PAGE_SETUP 0xE105 -#define ID_FILE_PRINT_SETUP 0xE106 -#define ID_FILE_PRINT 0xE107 -#define ID_FILE_PRINT_DIRECT 0xE108 -#define ID_FILE_PRINT_PREVIEW 0xE109 -#define ID_FILE_UPDATE 0xE10A -#define ID_FILE_SAVE_COPY_AS 0xE10B -#define ID_FILE_SEND_MAIL 0xE10C - -#define ID_FILE_MRU_FIRST 0xE110 -#define ID_FILE_MRU_FILE1 0xE110 // range - 16 max -#define ID_FILE_MRU_FILE2 0xE111 -#define ID_FILE_MRU_FILE3 0xE112 -#define ID_FILE_MRU_FILE4 0xE113 -#define ID_FILE_MRU_FILE5 0xE114 -#define ID_FILE_MRU_FILE6 0xE115 -#define ID_FILE_MRU_FILE7 0xE116 -#define ID_FILE_MRU_FILE8 0xE117 -#define ID_FILE_MRU_FILE9 0xE118 -#define ID_FILE_MRU_FILE10 0xE119 -#define ID_FILE_MRU_FILE11 0xE11A -#define ID_FILE_MRU_FILE12 0xE11B -#define ID_FILE_MRU_FILE13 0xE11C -#define ID_FILE_MRU_FILE14 0xE11D -#define ID_FILE_MRU_FILE15 0xE11E -#define ID_FILE_MRU_FILE16 0xE11F -#define ID_FILE_MRU_LAST 0xE11F - -// Edit commands -#define ID_EDIT_CLEAR 0xE120 -#define ID_EDIT_CLEAR_ALL 0xE121 -#define ID_EDIT_COPY 0xE122 -#define ID_EDIT_CUT 0xE123 -#define ID_EDIT_FIND 0xE124 -#define ID_EDIT_PASTE 0xE125 -#define ID_EDIT_PASTE_LINK 0xE126 -#define ID_EDIT_PASTE_SPECIAL 0xE127 -#define ID_EDIT_REPEAT 0xE128 -#define ID_EDIT_REPLACE 0xE129 -#define ID_EDIT_SELECT_ALL 0xE12A -#define ID_EDIT_UNDO 0xE12B -#define ID_EDIT_REDO 0xE12C - -// Window commands -#define ID_WINDOW_NEW 0xE130 -#define ID_WINDOW_ARRANGE 0xE131 -#define ID_WINDOW_CASCADE 0xE132 -#define ID_WINDOW_TILE_HORZ 0xE133 -#define ID_WINDOW_TILE_VERT 0xE134 -#define ID_WINDOW_SPLIT 0xE135 -#ifndef RC_INVOKED // code only - #define ATL_IDM_WINDOW_FIRST 0xE130 - #define ATL_IDM_WINDOW_LAST 0xE13F - #define ATL_IDM_FIRST_MDICHILD 0xFF00 // window list starts here - #define ATL_IDM_LAST_MDICHILD 0xFFFD -#endif // !RC_INVOKED -// TabView -#define ID_WINDOW_TABFIRST 0xFF00 // = ATL_IDM_FIRST_MDICHILD -#define ID_WINDOW_TABLAST 0xFFFD -#define ID_WINDOW_SHOWTABLIST 0xFFFE - -// Help and App commands -#define ID_APP_ABOUT 0xE140 -#define ID_APP_EXIT 0xE141 -#define ID_HELP_INDEX 0xE142 -#define ID_HELP_FINDER 0xE143 -#define ID_HELP_USING 0xE144 -#define ID_CONTEXT_HELP 0xE145 // shift-F1 -// special commands for processing help -#define ID_HELP 0xE146 // first attempt for F1 -#define ID_DEFAULT_HELP 0xE147 // last attempt - -// Misc -#define ID_NEXT_PANE 0xE150 -#define ID_PREV_PANE 0xE151 -#define ID_PANE_CLOSE 0xE152 - -// Format -#define ID_FORMAT_FONT 0xE160 - -// Scroll -#define ID_SCROLL_UP 0xE170 -#define ID_SCROLL_DOWN 0xE171 -#define ID_SCROLL_PAGE_UP 0xE172 -#define ID_SCROLL_PAGE_DOWN 0xE173 -#define ID_SCROLL_TOP 0xE174 -#define ID_SCROLL_BOTTOM 0xE175 -#define ID_SCROLL_LEFT 0xE176 -#define ID_SCROLL_RIGHT 0xE177 -#define ID_SCROLL_PAGE_LEFT 0xE178 -#define ID_SCROLL_PAGE_RIGHT 0xE179 -#define ID_SCROLL_ALL_LEFT 0xE17A -#define ID_SCROLL_ALL_RIGHT 0xE17B - -// OLE commands -#define ID_OLE_INSERT_NEW 0xE200 -#define ID_OLE_EDIT_LINKS 0xE201 -#define ID_OLE_EDIT_CONVERT 0xE202 -#define ID_OLE_EDIT_CHANGE_ICON 0xE203 -#define ID_OLE_EDIT_PROPERTIES 0xE204 -#define ID_OLE_VERB_FIRST 0xE210 // range - 16 max -#ifndef RC_INVOKED // code only - #define ID_OLE_VERB_LAST 0xE21F -#endif // !RC_INVOKED - -// View commands (same number used as IDW used for toolbar and status bar) -#define ID_VIEW_TOOLBAR 0xE800 -#define ID_VIEW_STATUS_BAR 0xE801 -#define ID_VIEW_REFRESH 0xE803 - -/////////////////////////////////////////////////////////////////////////////// -// Standard control IDs - -#ifdef IDC_STATIC - #undef IDC_STATIC -#endif // IDC_STATIC -#define IDC_STATIC (-1) // all static controls - -/////////////////////////////////////////////////////////////////////////////// -// Standard string error/warnings - -// idle status bar message -#define ATL_IDS_IDLEMESSAGE 0xE001 - -#ifndef RC_INVOKED // code only - #define ATL_IDS_SCFIRST 0xEF00 -#endif // !RC_INVOKED - -#define ATL_IDS_SCSIZE 0xEF00 -#define ATL_IDS_SCMOVE 0xEF01 -#define ATL_IDS_SCMINIMIZE 0xEF02 -#define ATL_IDS_SCMAXIMIZE 0xEF03 -#define ATL_IDS_SCNEXTWINDOW 0xEF04 -#define ATL_IDS_SCPREVWINDOW 0xEF05 -#define ATL_IDS_SCCLOSE 0xEF06 -#define ATL_IDS_SCRESTORE 0xEF12 -#define ATL_IDS_SCTASKLIST 0xEF13 - -#define ATL_IDS_MDICHILD 0xEF1F -#define ATL_IDS_MRU_FILE 0xEFDA - -/////////////////////////////////////////////////////////////////////////////// -// Misc. control IDs - -// Property Sheet control id's (determined with Spy++) -#define ID_APPLY_NOW 0x3021 -#define ID_WIZBACK 0x3023 -#define ID_WIZNEXT 0x3024 -#define ID_WIZFINISH 0x3025 -#define ATL_IDC_TAB_CONTROL 0x3020 - -#endif // __ATLRES_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/atlresce.h b/prog/3rdPartyLibs/wtl-8.1/include/atlresce.h deleted file mode 100644 index 96211ee66..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/atlresce.h +++ /dev/null @@ -1,93 +0,0 @@ -// Windows Template Library - WTL version 8.1 -// Copyright (C) Microsoft Corporation. All rights reserved. -// -// This file is a part of the Windows Template Library. -// The use and distribution terms for this software are covered by the -// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php) -// which can be found in the file CPL.TXT at the root of this distribution. -// By using this software in any fashion, you are agreeing to be bound by -// the terms of this license. You must not remove this notice, or -// any other, from this software. - -#ifndef __ATLRESCE_H__ -#define __ATLRESCE_H__ - -#pragma once - -#ifndef _WIN32_WCE - #error atlresCE.h is only for Windows CE -#endif - - -#ifdef RC_INVOKED -#ifndef _INC_WINDOWS - - #define VS_VERSION_INFO 1 - - #ifdef APSTUDIO_INVOKED - #define APSTUDIO_HIDDEN_SYMBOLS // Ignore following symbols - #endif // APSTUDIO_INVOKED - - #ifndef WINVER - #define WINVER 0x0400 // default to Windows Version 4.0 - #endif // !WINVER - - #if !defined(WCEOLE_ENABLE_DIALOGEX) - #define DIALOGEX DIALOG DISCARDABLE - #endif - - #include - #define SHMENUBAR RCDATA - - #if defined(SHELLSDK_MODULES_AYGSHELL) - #include - #else - #define NOMENU 0xFFFF - #define IDS_SHNEW 1 - #define IDM_SHAREDNEW 10 - #define IDM_SHAREDNEWDEFAULT 11 - #endif - #ifndef I_IMAGENONE - #define I_IMAGENONE (-2) - #endif - - #include - -#endif // !_INC_WINDOWS -#endif // RC_INVOKED - -#include "atlres.h" - -#ifdef APSTUDIO_INVOKED - #undef APSTUDIO_HIDDEN_SYMBOLS -#endif // APSTUDIO_INVOKED - -// Visual Studio dialog editor bug fix -#ifndef DS_FIXEDSYS - #define DS_FIXEDSYS 0 -#endif - -#define IDC_INFOSTATIC 0xFFFE // == IDC_STATIC -1 - -/////////////////////////////////////////////////////////////////////////////// -// Smartphone and PPC 2005 Resource IDs - -// Command and associated string resource IDs -#define ID_MENU_OK 0xE790 -#define ID_MENU_CANCEL 0xE791 -#define ID_MENU 0xE792 -#define ID_ACTION 0xE793 -#define ID_VIEW_FULLSCREEN 0xE802 - -// MenuBar resource IDs -#define ATL_IDM_MENU_DONE 0xE701 -#define ATL_IDM_MENU_CANCEL 0xE702 -#define ATL_IDM_MENU_DONECANCEL 0xE703 - -// Default device MenuBar control ID and MenuBar resource ID -#define ATL_IDW_MENU_BAR 0xE802 - -// SmartPhone spinned controls ID offset for CSpinCtrl -#define ATL_IDW_SPIN_ID 9999 - -#endif // __ATLRESCE_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/atlscrl.h b/prog/3rdPartyLibs/wtl-8.1/include/atlscrl.h deleted file mode 100644 index e98451eef..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/atlscrl.h +++ /dev/null @@ -1,2015 +0,0 @@ -// Windows Template Library - WTL version 8.1 -// Copyright (C) Microsoft Corporation. All rights reserved. -// -// This file is a part of the Windows Template Library. -// The use and distribution terms for this software are covered by the -// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php) -// which can be found in the file CPL.TXT at the root of this distribution. -// By using this software in any fashion, you are agreeing to be bound by -// the terms of this license. You must not remove this notice, or -// any other, from this software. - -#ifndef __ATLSCRL_H__ -#define __ATLSCRL_H__ - -#pragma once - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#ifndef __ATLAPP_H__ - #error atlscrl.h requires atlapp.h to be included first -#endif - -#ifndef __ATLWIN_H__ - #error atlscrl.h requires atlwin.h to be included first -#endif - -#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) - #include -#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) - -#ifndef GET_WHEEL_DELTA_WPARAM - #define GET_WHEEL_DELTA_WPARAM(wParam) ((short)HIWORD(wParam)) -#endif - -#ifndef WM_MOUSEHWHEEL - #define WM_MOUSEHWHEEL 0x020E -#endif - - -/////////////////////////////////////////////////////////////////////////////// -// Classes in this file: -// -// CScrollImpl -// CScrollWindowImpl -// CMapScrollImpl -// CMapScrollWindowImpl -// CFSBWindowT -// CZoomScrollImpl -// CZoomScrollWindowImpl -// CScrollContainerImpl -// CScrollContainer - -namespace WTL -{ - -/////////////////////////////////////////////////////////////////////////////// -// CScrollImpl - Provides scrolling support to any window - -// Scroll extended styles -#define SCRL_SCROLLCHILDREN 0x00000001 -#define SCRL_ERASEBACKGROUND 0x00000002 -#define SCRL_NOTHUMBTRACKING 0x00000004 -#if (WINVER >= 0x0500) -#define SCRL_SMOOTHSCROLL 0x00000008 -#endif // (WINVER >= 0x0500) -#define SCRL_DISABLENOSCROLLV 0x00000010 -#define SCRL_DISABLENOSCROLLH 0x00000020 -#define SCRL_DISABLENOSCROLL (SCRL_DISABLENOSCROLLV | SCRL_DISABLENOSCROLLH) - - -template -class CScrollImpl -{ -public: - enum { uSCROLL_FLAGS = SW_INVALIDATE }; - - POINT m_ptOffset; - SIZE m_sizeAll; - SIZE m_sizeLine; - SIZE m_sizePage; - SIZE m_sizeClient; - int m_zDelta; // current wheel value - int m_nWheelLines; // number of lines to scroll on wheel -#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) - // Note that this message must be forwarded from a top level window - UINT m_uMsgMouseWheel; // MSH_MOUSEWHEEL -#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) - int m_zHDelta; // current horizontal wheel value - int m_nHWheelChars; // number of chars to scroll on horizontal wheel - UINT m_uScrollFlags; - DWORD m_dwExtendedStyle; // scroll specific extended styles - -// Constructor - CScrollImpl() : m_zDelta(0), m_nWheelLines(3), -#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) - m_uMsgMouseWheel(0U), -#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) - m_zHDelta(0), m_nHWheelChars(3), - m_uScrollFlags(0U), m_dwExtendedStyle(0) - { - m_ptOffset.x = 0; - m_ptOffset.y = 0; - m_sizeAll.cx = 0; - m_sizeAll.cy = 0; - m_sizePage.cx = 0; - m_sizePage.cy = 0; - m_sizeLine.cx = 0; - m_sizeLine.cy = 0; - m_sizeClient.cx = 0; - m_sizeClient.cy = 0; - - SetScrollExtendedStyle(SCRL_SCROLLCHILDREN | SCRL_ERASEBACKGROUND); - } - -// Attributes & Operations - DWORD GetScrollExtendedStyle() const - { - return m_dwExtendedStyle; - } - - DWORD SetScrollExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0) - { - DWORD dwPrevStyle = m_dwExtendedStyle; - if(dwMask == 0) - m_dwExtendedStyle = dwExtendedStyle; - else - m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask); - // cache scroll flags - T* pT = static_cast(this); - pT; // avoid level 4 warning - m_uScrollFlags = pT->uSCROLL_FLAGS | (IsScrollingChildren() ? SW_SCROLLCHILDREN : 0) | (IsErasingBackground() ? SW_ERASE : 0); -#if (WINVER >= 0x0500) && !defined(_WIN32_WCE) - m_uScrollFlags |= (IsSmoothScroll() ? SW_SMOOTHSCROLL : 0); -#endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE) - return dwPrevStyle; - } - - // offset operations - void SetScrollOffset(int x, int y, BOOL bRedraw = TRUE) - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - - pT->AdjustScrollOffset(x, y); - - int dx = m_ptOffset.x - x; - int dy = m_ptOffset.y - y; - m_ptOffset.x = x; - m_ptOffset.y = y; - - // block: set horizontal scroll bar - { - SCROLLINFO si = { sizeof(SCROLLINFO) }; - si.fMask = SIF_POS; - if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLH) != 0) - si.fMask |= SIF_DISABLENOSCROLL; - si.nPos = m_ptOffset.x; - pT->SetScrollInfo(SB_HORZ, &si, bRedraw); - } - - // block: set vertical scroll bar - { - SCROLLINFO si = { sizeof(SCROLLINFO) }; - si.fMask = SIF_POS; - if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLV) != 0) - si.fMask |= SIF_DISABLENOSCROLL; - si.nPos = m_ptOffset.y; - pT->SetScrollInfo(SB_VERT, &si, bRedraw); - } - - // Move all children if needed - if(IsScrollingChildren() && (dx != 0 || dy != 0)) - { - for(HWND hWndChild = ::GetWindow(pT->m_hWnd, GW_CHILD); hWndChild != NULL; hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT)) - { - RECT rect = { 0 }; - ::GetWindowRect(hWndChild, &rect); - ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 1); - ::SetWindowPos(hWndChild, NULL, rect.left + dx, rect.top + dy, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); - } - } - - if(bRedraw) - pT->Invalidate(); - } - - void SetScrollOffset(POINT ptOffset, BOOL bRedraw = TRUE) - { - SetScrollOffset(ptOffset.x, ptOffset.y, bRedraw); - } - - void GetScrollOffset(POINT& ptOffset) const - { - ptOffset = m_ptOffset; - } - - // size operations - void SetScrollSize(int cx, int cy, BOOL bRedraw = TRUE, bool bResetOffset = true) - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - - m_sizeAll.cx = cx; - m_sizeAll.cy = cy; - - int x = 0; - int y = 0; - if(!bResetOffset) - { - x = m_ptOffset.x; - y = m_ptOffset.y; - pT->AdjustScrollOffset(x, y); - } - - int dx = m_ptOffset.x - x; - int dy = m_ptOffset.y - y; - m_ptOffset.x = x; - m_ptOffset.y = y; - - // block: set horizontal scroll bar - { - SCROLLINFO si = { sizeof(SCROLLINFO) }; - si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; - if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLH) != 0) - si.fMask |= SIF_DISABLENOSCROLL; - si.nMin = 0; - si.nMax = m_sizeAll.cx - 1; - si.nPage = m_sizeClient.cx; - si.nPos = m_ptOffset.x; - pT->SetScrollInfo(SB_HORZ, &si, bRedraw); - } - - // block: set vertical scroll bar - { - SCROLLINFO si = { sizeof(SCROLLINFO) }; - si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; - if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLV) != 0) - si.fMask |= SIF_DISABLENOSCROLL; - si.nMin = 0; - si.nMax = m_sizeAll.cy - 1; - si.nPage = m_sizeClient.cy; - si.nPos = m_ptOffset.y; - pT->SetScrollInfo(SB_VERT, &si, bRedraw); - } - - // Move all children if needed - if(IsScrollingChildren() && (dx != 0 || dy != 0)) - { - for(HWND hWndChild = ::GetWindow(pT->m_hWnd, GW_CHILD); hWndChild != NULL; hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT)) - { - RECT rect = { 0 }; - ::GetWindowRect(hWndChild, &rect); - ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 1); - ::SetWindowPos(hWndChild, NULL, rect.left + dx, rect.top + dy, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); - } - } - - SetScrollLine(0, 0); - SetScrollPage(0, 0); - - if(bRedraw) - pT->Invalidate(); - } - - void SetScrollSize(SIZE size, BOOL bRedraw = TRUE, bool bResetOffset = true) - { - SetScrollSize(size.cx, size.cy, bRedraw, bResetOffset); - } - - void GetScrollSize(SIZE& sizeWnd) const - { - sizeWnd = m_sizeAll; - } - - // line operations - void SetScrollLine(int cxLine, int cyLine) - { - ATLASSERT(cxLine >= 0 && cyLine >= 0); - ATLASSERT(m_sizeAll.cx != 0 && m_sizeAll.cy != 0); - - m_sizeLine.cx = T::CalcLineOrPage(cxLine, m_sizeAll.cx, 100); - m_sizeLine.cy = T::CalcLineOrPage(cyLine, m_sizeAll.cy, 100); - } - - void SetScrollLine(SIZE sizeLine) - { - SetScrollLine(sizeLine.cx, sizeLine.cy); - } - - void GetScrollLine(SIZE& sizeLine) const - { - sizeLine = m_sizeLine; - } - - // page operations - void SetScrollPage(int cxPage, int cyPage) - { - ATLASSERT(cxPage >= 0 && cyPage >= 0); - ATLASSERT(m_sizeAll.cx != 0 && m_sizeAll.cy != 0); - - m_sizePage.cx = T::CalcLineOrPage(cxPage, m_sizeAll.cx, 10); - m_sizePage.cy = T::CalcLineOrPage(cyPage, m_sizeAll.cy, 10); - } - - void SetScrollPage(SIZE sizePage) - { - SetScrollPage(sizePage.cx, sizePage.cy); - } - - void GetScrollPage(SIZE& sizePage) const - { - sizePage = m_sizePage; - } - - // commands - void ScrollLineDown() - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - pT->DoScroll(SB_VERT, SB_LINEDOWN, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy); - } - - void ScrollLineUp() - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - pT->DoScroll(SB_VERT, SB_LINEUP, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy); - } - - void ScrollPageDown() - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - pT->DoScroll(SB_VERT, SB_PAGEDOWN, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy); - } - - void ScrollPageUp() - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - pT->DoScroll(SB_VERT, SB_PAGEUP, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy); - } - - void ScrollTop() - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - pT->DoScroll(SB_VERT, SB_TOP, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy); - } - - void ScrollBottom() - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - pT->DoScroll(SB_VERT, SB_BOTTOM, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy); - } - - void ScrollLineRight() - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - pT->DoScroll(SB_HORZ, SB_LINEDOWN, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx); - } - - void ScrollLineLeft() - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - pT->DoScroll(SB_HORZ, SB_LINEUP, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx); - } - - void ScrollPageRight() - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - pT->DoScroll(SB_HORZ, SB_PAGEDOWN, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx); - } - - void ScrollPageLeft() - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - pT->DoScroll(SB_HORZ, SB_PAGEUP, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx); - } - - void ScrollAllLeft() - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - pT->DoScroll(SB_HORZ, SB_TOP, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx); - } - - void ScrollAllRight() - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - pT->DoScroll(SB_HORZ, SB_BOTTOM, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx); - } - - // scroll to make point/view/window visible - void ScrollToView(POINT pt) - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - RECT rect = { pt.x, pt.y, pt.x, pt.y }; - pT->ScrollToView(rect); - } - - void ScrollToView(RECT& rect) - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - - RECT rcClient = { 0 }; - pT->GetClientRect(&rcClient); - - int x = m_ptOffset.x; - if(rect.left < m_ptOffset.x) - x = rect.left; - else if(rect.right > (m_ptOffset.x + rcClient.right)) - x = rect.right - rcClient.right; - - int y = m_ptOffset.y; - if(rect.top < m_ptOffset.y) - y = rect.top; - else if(rect.bottom > (m_ptOffset.y + rcClient.bottom)) - y = rect.bottom - rcClient.bottom; - - SetScrollOffset(x, y); - } - - void ScrollToView(HWND hWnd) - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - - RECT rect = { 0 }; - ::GetWindowRect(hWnd, &rect); - ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 2); - ScrollToView(rect); - } - - BEGIN_MSG_MAP(CScrollImpl) - MESSAGE_HANDLER(WM_CREATE, OnCreate) - MESSAGE_HANDLER(WM_VSCROLL, OnVScroll) - MESSAGE_HANDLER(WM_HSCROLL, OnHScroll) - MESSAGE_HANDLER(WM_MOUSEWHEEL, OnMouseWheel) -#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) - MESSAGE_HANDLER(m_uMsgMouseWheel, OnMouseWheel) -#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) - MESSAGE_HANDLER(WM_MOUSEHWHEEL, OnMouseHWheel) - MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange) - MESSAGE_HANDLER(WM_SIZE, OnSize) - MESSAGE_HANDLER(WM_PAINT, OnPaint) -#ifndef _WIN32_WCE - MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) -#endif // !_WIN32_WCE - // standard scroll commands - ALT_MSG_MAP(1) - COMMAND_ID_HANDLER(ID_SCROLL_UP, OnScrollUp) - COMMAND_ID_HANDLER(ID_SCROLL_DOWN, OnScrollDown) - COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, OnScrollPageUp) - COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, OnScrollPageDown) - COMMAND_ID_HANDLER(ID_SCROLL_TOP, OnScrollTop) - COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, OnScrollBottom) - COMMAND_ID_HANDLER(ID_SCROLL_LEFT, OnScrollLeft) - COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, OnScrollRight) - COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, OnScrollPageLeft) - COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, OnScrollPageRight) - COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, OnScrollAllLeft) - COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, OnScrollAllRight) - END_MSG_MAP() - - LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - GetSystemSettings(); - bHandled = FALSE; - return 1; - } - - LRESULT OnVScroll(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - pT->DoScroll(SB_VERT, (int)(short)LOWORD(wParam), (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy); - return 0; - } - - LRESULT OnHScroll(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - pT->DoScroll(SB_HORZ, (int)(short)LOWORD(wParam), (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx); - return 0; - } - - LRESULT OnMouseWheel(UINT uMsg, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - -#if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400) || defined(_WIN32_WCE) - uMsg; - int zDelta = (int)GET_WHEEL_DELTA_WPARAM(wParam); -#else - int zDelta = (uMsg == WM_MOUSEWHEEL) ? (int)GET_WHEEL_DELTA_WPARAM(wParam) : (int)wParam; -#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400) || defined(_WIN32_WCE)) - int nScrollCode = (m_nWheelLines == WHEEL_PAGESCROLL) ? ((zDelta > 0) ? SB_PAGEUP : SB_PAGEDOWN) : ((zDelta > 0) ? SB_LINEUP : SB_LINEDOWN); - m_zDelta += zDelta; // cumulative - int zTotal = (m_nWheelLines == WHEEL_PAGESCROLL) ? abs(m_zDelta) : abs(m_zDelta) * m_nWheelLines; - if(m_sizeAll.cy > m_sizeClient.cy) - { - for(int i = 0; i < zTotal; i += WHEEL_DELTA) - { - pT->DoScroll(SB_VERT, nScrollCode, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy); - pT->UpdateWindow(); - } - } - else // can't scroll vertically, scroll horizontally - { - for(int i = 0; i < zTotal; i += WHEEL_DELTA) - { - pT->DoScroll(SB_HORZ, nScrollCode, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx); - pT->UpdateWindow(); - } - } - m_zDelta %= WHEEL_DELTA; - - return 0; - } - - LRESULT OnMouseHWheel(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - - int zDelta = (int)GET_WHEEL_DELTA_WPARAM(wParam); - int nScrollCode = (m_nHWheelChars == WHEEL_PAGESCROLL) ? ((zDelta > 0) ? SB_PAGERIGHT : SB_PAGELEFT) : ((zDelta > 0) ? SB_LINERIGHT : SB_LINELEFT); - m_zHDelta += zDelta; // cumulative - int zTotal = (m_nHWheelChars == WHEEL_PAGESCROLL) ? abs(m_zHDelta) : abs(m_zHDelta) * m_nHWheelChars; - if(m_sizeAll.cx > m_sizeClient.cx) - { - for(int i = 0; i < zTotal; i += WHEEL_DELTA) - { - pT->DoScroll(SB_HORZ, nScrollCode, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx); - pT->UpdateWindow(); - } - } - m_zHDelta %= WHEEL_DELTA; - - return 0; - } - - LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - GetSystemSettings(); - return 0; - } - - LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - - m_sizeClient.cx = GET_X_LPARAM(lParam); - m_sizeClient.cy = GET_Y_LPARAM(lParam); - - // block: set horizontal scroll bar - { - SCROLLINFO si = { sizeof(SCROLLINFO) }; - si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; - si.nMin = 0; - si.nMax = m_sizeAll.cx - 1; - if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLH) != 0) - si.fMask |= SIF_DISABLENOSCROLL; - si.nPage = m_sizeClient.cx; - si.nPos = m_ptOffset.x; - pT->SetScrollInfo(SB_HORZ, &si, TRUE); - } - - // block: set vertical scroll bar - { - SCROLLINFO si = { sizeof(SCROLLINFO) }; - si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; - si.nMin = 0; - si.nMax = m_sizeAll.cy - 1; - if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLV) != 0) - si.fMask |= SIF_DISABLENOSCROLL; - si.nPage = m_sizeClient.cy; - si.nPos = m_ptOffset.y; - pT->SetScrollInfo(SB_VERT, &si, TRUE); - } - - int x = m_ptOffset.x; - int y = m_ptOffset.y; - if(pT->AdjustScrollOffset(x, y)) - { - // Children will be moved in SetScrollOffset, if needed - pT->ScrollWindowEx(m_ptOffset.x - x, m_ptOffset.y - y, (m_uScrollFlags & ~SCRL_SCROLLCHILDREN)); - SetScrollOffset(x, y, FALSE); - } - - bHandled = FALSE; - return 1; - } - - LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - if(wParam != NULL) - { - CDCHandle dc = (HDC)wParam; - POINT ptViewportOrg = { 0, 0 }; - dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg); - pT->DoPaint(dc); - dc.SetViewportOrg(ptViewportOrg); - } - else - { - CPaintDC dc(pT->m_hWnd); - dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y); - pT->DoPaint(dc.m_hDC); - } - return 0; - } - - // scrolling handlers - LRESULT OnScrollUp(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) - { - ScrollLineUp(); - return 0; - } - - LRESULT OnScrollDown(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) - { - ScrollLineDown(); - return 0; - } - - LRESULT OnScrollPageUp(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) - { - ScrollPageUp(); - return 0; - } - - LRESULT OnScrollPageDown(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) - { - ScrollPageDown(); - return 0; - } - - LRESULT OnScrollTop(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) - { - ScrollTop(); - return 0; - } - - LRESULT OnScrollBottom(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) - { - ScrollBottom(); - return 0; - } - - LRESULT OnScrollLeft(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) - { - ScrollLineLeft(); - return 0; - } - - LRESULT OnScrollRight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) - { - ScrollLineRight(); - return 0; - } - - LRESULT OnScrollPageLeft(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) - { - ScrollPageLeft(); - return 0; - } - - LRESULT OnScrollPageRight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) - { - ScrollPageRight(); - return 0; - } - - LRESULT OnScrollAllLeft(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) - { - ScrollAllLeft(); - return 0; - } - - LRESULT OnScrollAllRight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) - { - ScrollAllRight(); - return 0; - } - -// Overrideables - void DoPaint(CDCHandle /*dc*/) - { - // must be implemented in a derived class - ATLASSERT(FALSE); - } - -// Implementation - void DoScroll(int nType, int nScrollCode, int& cxyOffset, int cxySizeAll, int cxySizePage, int cxySizeLine) - { - T* pT = static_cast(this); - RECT rect = { 0 }; - pT->GetClientRect(&rect); - int cxyClient = (nType == SB_VERT) ? rect.bottom : rect.right; - int cxyMax = cxySizeAll - cxyClient; - - if(cxyMax < 0) // can't scroll, client area is bigger - return; - - bool bUpdate = true; - int cxyScroll = 0; - - switch(nScrollCode) - { - case SB_TOP: // top or all left - cxyScroll = cxyOffset; - cxyOffset = 0; - break; - case SB_BOTTOM: // bottom or all right - cxyScroll = cxyOffset - cxyMax; - cxyOffset = cxyMax; - break; - case SB_LINEUP: // line up or line left - if(cxyOffset >= cxySizeLine) - { - cxyScroll = cxySizeLine; - cxyOffset -= cxySizeLine; - } - else - { - cxyScroll = cxyOffset; - cxyOffset = 0; - } - break; - case SB_LINEDOWN: // line down or line right - if(cxyOffset < cxyMax - cxySizeLine) - { - cxyScroll = -cxySizeLine; - cxyOffset += cxySizeLine; - } - else - { - cxyScroll = cxyOffset - cxyMax; - cxyOffset = cxyMax; - } - break; - case SB_PAGEUP: // page up or page left - if(cxyOffset >= cxySizePage) - { - cxyScroll = cxySizePage; - cxyOffset -= cxySizePage; - } - else - { - cxyScroll = cxyOffset; - cxyOffset = 0; - } - break; - case SB_PAGEDOWN: // page down or page right - if(cxyOffset < cxyMax - cxySizePage) - { - cxyScroll = -cxySizePage; - cxyOffset += cxySizePage; - } - else - { - cxyScroll = cxyOffset - cxyMax; - cxyOffset = cxyMax; - } - break; - case SB_THUMBTRACK: - if(IsNoThumbTracking()) - break; - // else fall through - case SB_THUMBPOSITION: - { - SCROLLINFO si = { sizeof(SCROLLINFO), SIF_TRACKPOS }; - if(pT->GetScrollInfo(nType, &si)) - { - cxyScroll = cxyOffset - si.nTrackPos; - cxyOffset = si.nTrackPos; - } - } - break; - case SB_ENDSCROLL: - default: - bUpdate = false; - break; - } - - if(bUpdate && cxyScroll != 0) - { - pT->SetScrollPos(nType, cxyOffset, TRUE); - if(nType == SB_VERT) - pT->ScrollWindowEx(0, cxyScroll, m_uScrollFlags); - else - pT->ScrollWindowEx(cxyScroll, 0, m_uScrollFlags); - } - } - - static int CalcLineOrPage(int nVal, int nMax, int nDiv) - { - if(nVal == 0) - { - nVal = nMax / nDiv; - if(nVal < 1) - nVal = 1; - } - else if(nVal > nMax) - { - nVal = nMax; - } - - return nVal; - } - - bool AdjustScrollOffset(int& x, int& y) - { - int xOld = x; - int yOld = y; - - int cxMax = m_sizeAll.cx - m_sizeClient.cx; - if(x > cxMax) - x = (cxMax >= 0) ? cxMax : 0; - else if(x < 0) - x = 0; - - int cyMax = m_sizeAll.cy - m_sizeClient.cy; - if(y > cyMax) - y = (cyMax >= 0) ? cyMax : 0; - else if(y < 0) - y = 0; - - return (x != xOld || y != yOld); - } - - void GetSystemSettings() - { -#ifndef _WIN32_WCE -#ifndef SPI_GETWHEELSCROLLLINES - const UINT SPI_GETWHEELSCROLLLINES = 104; -#endif // !SPI_GETWHEELSCROLLLINES - ::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &m_nWheelLines, 0); - -#ifndef SPI_GETWHEELSCROLLCHARS - const UINT SPI_GETWHEELSCROLLCHARS = 0x006C; -#endif // !SPI_GETWHEELSCROLLCHARS - ::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &m_nHWheelChars, 0); - -#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) - if(m_uMsgMouseWheel != 0) - m_uMsgMouseWheel = ::RegisterWindowMessage(MSH_MOUSEWHEEL); - - HWND hWndWheel = FindWindow(MSH_WHEELMODULE_CLASS, MSH_WHEELMODULE_TITLE); - if(::IsWindow(hWndWheel)) - { - UINT uMsgScrollLines = ::RegisterWindowMessage(MSH_SCROLL_LINES); - if(uMsgScrollLines != 0) - m_nWheelLines = (int)::SendMessage(hWndWheel, uMsgScrollLines, 0, 0L); - } -#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) -#endif // !_WIN32_WCE - } - - bool IsScrollingChildren() const - { - return (m_dwExtendedStyle & SCRL_SCROLLCHILDREN) != 0; - } - - bool IsErasingBackground() const - { - return (m_dwExtendedStyle & SCRL_ERASEBACKGROUND) != 0; - } - - bool IsNoThumbTracking() const - { - return (m_dwExtendedStyle & SCRL_NOTHUMBTRACKING) != 0; - } - -#if (WINVER >= 0x0500) - bool IsSmoothScroll() const - { - return (m_dwExtendedStyle & SCRL_SMOOTHSCROLL) != 0; - } -#endif // (WINVER >= 0x0500) -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CScrollWindowImpl - Implements a scrollable window - -template -class ATL_NO_VTABLE CScrollWindowImpl : public ATL::CWindowImpl, public CScrollImpl< T > -{ -public: - BEGIN_MSG_MAP(CScrollWindowImpl) - MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll) - MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll) - MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel) -#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) - MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel) -#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE) - MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel) - MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange) - MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize) - MESSAGE_HANDLER(WM_PAINT, CScrollImpl< T >::OnPaint) -#ifndef _WIN32_WCE - MESSAGE_HANDLER(WM_PRINTCLIENT, CScrollImpl< T >::OnPaint) -#endif // !_WIN32_WCE - ALT_MSG_MAP(1) - COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp) - COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown) - COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp) - COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown) - COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop) - COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom) - COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft) - COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight) - COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft) - COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight) - COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft) - COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight) - END_MSG_MAP() -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CMapScrollImpl - Provides mapping and scrolling support to any window - -#ifndef _WIN32_WCE - -template -class CMapScrollImpl : public CScrollImpl< T > -{ -public: - int m_nMapMode; - RECT m_rectLogAll; - SIZE m_sizeLogLine; - SIZE m_sizeLogPage; - -// Constructor - CMapScrollImpl() : m_nMapMode(MM_TEXT) - { - ::SetRectEmpty(&m_rectLogAll); - m_sizeLogPage.cx = 0; - m_sizeLogPage.cy = 0; - m_sizeLogLine.cx = 0; - m_sizeLogLine.cy = 0; - } - -// Attributes & Operations - // mapping mode operations - void SetScrollMapMode(int nMapMode) - { - ATLASSERT(nMapMode >= MM_MIN && nMapMode <= MM_MAX_FIXEDSCALE); - m_nMapMode = nMapMode; - } - - int GetScrollMapMode() const - { - ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE); - return m_nMapMode; - } - - // offset operations - void SetScrollOffset(int x, int y, BOOL bRedraw = TRUE) - { - ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE); - POINT ptOff = { x, y }; - // block: convert logical to device units - { - CWindowDC dc(NULL); - dc.SetMapMode(m_nMapMode); - dc.LPtoDP(&ptOff); - } - CScrollImpl< T >::SetScrollOffset(ptOff, bRedraw); - } - - void SetScrollOffset(POINT ptOffset, BOOL bRedraw = TRUE) - { - SetScrollOffset(ptOffset.x, ptOffset.y, bRedraw); - } - - void GetScrollOffset(POINT& ptOffset) const - { - ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE); - ptOffset = m_ptOffset; - // block: convert device to logical units - { - CWindowDC dc(NULL); - dc.SetMapMode(m_nMapMode); - dc.DPtoLP(&ptOffset); - } - } - - // size operations - void SetScrollSize(int xMin, int yMin, int xMax, int yMax, BOOL bRedraw = TRUE, bool bResetOffset = true) - { - ATLASSERT(xMax > xMin && yMax > yMin); - ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE); - - ::SetRect(&m_rectLogAll, xMin, yMin, xMax, yMax); - - SIZE sizeAll = { 0 }; - sizeAll.cx = xMax - xMin + 1; - sizeAll.cy = yMax - yMin + 1; - // block: convert logical to device units - { - CWindowDC dc(NULL); - dc.SetMapMode(m_nMapMode); - dc.LPtoDP(&sizeAll); - } - CScrollImpl< T >::SetScrollSize(sizeAll, bRedraw, bResetOffset); - SetScrollLine(0, 0); - SetScrollPage(0, 0); - } - - void SetScrollSize(RECT& rcScroll, BOOL bRedraw = TRUE, bool bResetOffset = true) - { - SetScrollSize(rcScroll.left, rcScroll.top, rcScroll.right, rcScroll.bottom, bRedraw, bResetOffset); - } - - void SetScrollSize(int cx, int cy, BOOL bRedraw = TRUE, bool bResetOffset = true) - { - SetScrollSize(0, 0, cx, cy, bRedraw, bResetOffset); - } - - void SetScrollSize(SIZE size, BOOL bRedraw = TRUE, bool bResetOffset = true) - { - SetScrollSize(0, 0, size.cx, size.cy, bRedraw, bResetOffset); - } - - void GetScrollSize(RECT& rcScroll) const - { - ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE); - rcScroll = m_rectLogAll; - } - - // line operations - void SetScrollLine(int cxLine, int cyLine) - { - ATLASSERT(cxLine >= 0 && cyLine >= 0); - ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE); - - m_sizeLogLine.cx = cxLine; - m_sizeLogLine.cy = cyLine; - SIZE sizeLine = m_sizeLogLine; - // block: convert logical to device units - { - CWindowDC dc(NULL); - dc.SetMapMode(m_nMapMode); - dc.LPtoDP(&sizeLine); - } - CScrollImpl< T >::SetScrollLine(sizeLine); - } - - void SetScrollLine(SIZE sizeLine) - { - SetScrollLine(sizeLine.cx, sizeLine.cy); - } - - void GetScrollLine(SIZE& sizeLine) const - { - ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE); - sizeLine = m_sizeLogLine; - } - - // page operations - void SetScrollPage(int cxPage, int cyPage) - { - ATLASSERT(cxPage >= 0 && cyPage >= 0); - ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE); - - m_sizeLogPage.cx = cxPage; - m_sizeLogPage.cy = cyPage; - SIZE sizePage = m_sizeLogPage; - // block: convert logical to device units - { - CWindowDC dc(NULL); - dc.SetMapMode(m_nMapMode); - dc.LPtoDP(&sizePage); - } - CScrollImpl< T >::SetScrollPage(sizePage); - } - - void SetScrollPage(SIZE sizePage) - { - SetScrollPage(sizePage.cx, sizePage.cy); - } - - void GetScrollPage(SIZE& sizePage) const - { - ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE); - sizePage = m_sizeLogPage; - } - - BEGIN_MSG_MAP(CMapScrollImpl) - MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll) - MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll) - MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel) -#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) - MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel) -#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) - MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel) - MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange) - MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize) - MESSAGE_HANDLER(WM_PAINT, OnPaint) - MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) - ALT_MSG_MAP(1) - COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp) - COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown) - COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp) - COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown) - COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop) - COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom) - COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft) - COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight) - COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft) - COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight) - COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft) - COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight) - END_MSG_MAP() - - LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - if(wParam != NULL) - { - CDCHandle dc = (HDC)wParam; - int nMapModeSav = dc.GetMapMode(); - dc.SetMapMode(m_nMapMode); - POINT ptViewportOrg = { 0, 0 }; - if(m_nMapMode == MM_TEXT) - dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg); - else - dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y + m_sizeAll.cy, &ptViewportOrg); - POINT ptWindowOrg = { 0, 0 }; - dc.SetWindowOrg(m_rectLogAll.left, m_rectLogAll.top, &ptWindowOrg); - - pT->DoPaint(dc); - - dc.SetMapMode(nMapModeSav); - dc.SetViewportOrg(ptViewportOrg); - dc.SetWindowOrg(ptWindowOrg); - } - else - { - CPaintDC dc(pT->m_hWnd); - dc.SetMapMode(m_nMapMode); - if(m_nMapMode == MM_TEXT) - dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y); - else - dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y + m_sizeAll.cy); - dc.SetWindowOrg(m_rectLogAll.left, m_rectLogAll.top); - pT->DoPaint(dc.m_hDC); - } - return 0; - } -}; - -#endif // !_WIN32_WCE - - -/////////////////////////////////////////////////////////////////////////////// -// CMapScrollWindowImpl - Implements scrolling window with mapping - -#ifndef _WIN32_WCE - -template -class ATL_NO_VTABLE CMapScrollWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CMapScrollImpl< T > -{ -public: - BEGIN_MSG_MAP(CMapScrollWindowImpl) - MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll) - MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll) - MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel) -#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) - MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel) -#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) - MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel) - MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange) - MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize) - MESSAGE_HANDLER(WM_PAINT, CMapScrollImpl< T >::OnPaint) - MESSAGE_HANDLER(WM_PRINTCLIENT, CMapScrollImpl< T >::OnPaint) - ALT_MSG_MAP(1) - COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp) - COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown) - COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp) - COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown) - COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop) - COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom) - COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft) - COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight) - COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft) - COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight) - COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft) - COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight) - END_MSG_MAP() -}; - -#endif // !_WIN32_WCE - - -/////////////////////////////////////////////////////////////////////////////// -// CFSBWindow - Use as a base instead of CWindow to get flat scroll bar support - -#if defined(__ATLCTRLS_H__) && (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) - -template -class CFSBWindowT : public TBase, public CFlatScrollBarImpl > -{ -public: -// Constructors - CFSBWindowT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CFSBWindowT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - -// CWindow overrides that use flat scroll bar API -// (only those methods that are used by scroll window classes) - int SetScrollPos(int nBar, int nPos, BOOL bRedraw = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return FlatSB_SetScrollPos(nBar, nPos, bRedraw); - } - - BOOL GetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo) - { - ATLASSERT(::IsWindow(m_hWnd)); - return FlatSB_GetScrollInfo(nBar, lpScrollInfo); - } - - BOOL SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - return FlatSB_SetScrollInfo(nBar, lpScrollInfo, bRedraw); - } -}; - -typedef CFSBWindowT CFSBWindow; - -#endif // defined(__ATLCTRLS_H__) && (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE) - - -/////////////////////////////////////////////////////////////////////////////// -// CZoomScrollImpl - Provides zooming and scrolling support to any window - -#ifndef _WIN32_WCE - -// The zoom modes that can be set with the SetZoomMode method -enum -{ - ZOOMMODE_OFF, - ZOOMMODE_IN, // If left mouse button is clicked or dragged, zoom in on point clicked or rectangle dragged. - ZOOMMODE_OUT // If left mouse button clicked, zoom out on point clicked. -}; - -// Notification to parent that zoom scale changed as a result of user mouse action. -#define ZSN_ZOOMCHANGED (NM_FIRST - 50) - -template -class CZoomScrollImpl : public CScrollImpl< T > -{ -public: - enum { m_cxyMinZoomRect = 12 }; // min rect size to zoom in on rect. - -// Data members - SIZE m_sizeLogAll; - SIZE m_sizeLogLine; - SIZE m_sizeLogPage; - float m_fZoomScale; - float m_fZoomScaleMin; - float m_fZoomDelta; // Used in ZOOMMODE_IN and ZOOMMODE_OUT on left-button click. - int m_nZoomMode; - RECT m_rcTrack; - bool m_bTracking; - -// Constructor - CZoomScrollImpl(): - m_fZoomScale(1.0), - m_fZoomScaleMin(0.5), - m_fZoomDelta(0.5), - m_nZoomMode(ZOOMMODE_OFF), - m_bTracking(false) - { - m_sizeLogAll.cx = 0; - m_sizeLogAll.cy = 0; - m_sizeLogPage.cx = 0; - m_sizeLogPage.cy = 0; - m_sizeLogLine.cx = 0; - m_sizeLogLine.cy = 0; - ::SetRectEmpty(&m_rcTrack); - } - -// Attributes & Operations - - // size operations - void SetScrollSize(int cxLog, int cyLog, BOOL bRedraw = TRUE, bool bResetOffset = true) - { - ATLASSERT(cxLog >= 0 && cyLog >= 0); - - // Set up the defaults - if (cxLog == 0 && cyLog == 0) - { - cxLog = 1; - cyLog = 1; - } - - m_sizeLogAll.cx = cxLog; - m_sizeLogAll.cy = cyLog; - SIZE sizeAll = { 0 }; - sizeAll.cx = (int)((float)m_sizeLogAll.cx * m_fZoomScale); - sizeAll.cy = (int)((float)m_sizeLogAll.cy * m_fZoomScale); - - CScrollImpl< T >::SetScrollSize(sizeAll, bRedraw, bResetOffset); - } - - void SetScrollSize(SIZE sizeLog, BOOL bRedraw = TRUE, bool bResetOffset = true) - { - SetScrollSize(sizeLog.cx, sizeLog.cy, bRedraw, bResetOffset); - } - - void GetScrollSize(SIZE& sizeLog) const - { - sizeLog = m_sizeLogAll; - } - - // line operations - void SetScrollLine(int cxLogLine, int cyLogLine) - { - ATLASSERT(cxLogLine >= 0 && cyLogLine >= 0); - - m_sizeLogLine.cx = cxLogLine; - m_sizeLogLine.cy = cyLogLine; - - SIZE sizeLine = { 0 }; - sizeLine.cx = (int)((float)m_sizeLogLine.cx * m_fZoomScale); - sizeLine.cy = (int)((float)m_sizeLogLine.cy * m_fZoomScale); - CScrollImpl< T >::SetScrollLine(sizeLine); - } - - void SetScrollLine(SIZE sizeLogLine) - { - SetScrollLine(sizeLogLine.cx, sizeLogLine.cy); - } - - void GetScrollLine(SIZE& sizeLogLine) const - { - sizeLogLine = m_sizeLogLine; - } - - // page operations - void SetScrollPage(int cxLogPage, int cyLogPage) - { - ATLASSERT(cxLogPage >= 0 && cyLogPage >= 0); - - m_sizeLogPage.cx = cxLogPage; - m_sizeLogPage.cy = cyLogPage; - - SIZE sizePage = { 0 }; - sizePage.cx = (int)((float)m_sizeLogPage.cx * m_fZoomScale); - sizePage.cy = (int)((float)m_sizeLogPage.cy * m_fZoomScale); - - CScrollImpl< T >::SetScrollPage(sizePage); - } - - void SetScrollPage(SIZE sizeLogPage) - { - SetScrollPage(sizeLogPage.cx, sizeLogPage.cy); - } - - void GetScrollPage(SIZE& sizeLogPage) const - { - sizeLogPage = m_sizeLogPage; - } - - void SetZoomScale(float fZoomScale) - { - ATLASSERT(fZoomScale > 0); - - if(fZoomScale > 0 && fZoomScale >= m_fZoomScaleMin) - m_fZoomScale = fZoomScale; - } - - float GetZoomScale() const - { - return m_fZoomScale; - } - - void SetZoomScaleMin(float fZoomScaleMin) - { - m_fZoomScaleMin = fZoomScaleMin; - } - - float GetZoomScaleMin() const - { - return m_fZoomScaleMin; - } - - void SetZoomDelta(float fZoomDelta) - { - ATLASSERT(fZoomDelta >= 0); - - if(fZoomDelta >= 0) - m_fZoomDelta = fZoomDelta; - } - - float GetZoomDelta() const - { - return m_fZoomDelta; - } - - void SetZoomMode(int nZoomMode) - { - m_nZoomMode = nZoomMode; - } - - int GetZoomMode() const - { - return m_nZoomMode; - } - - void Zoom(int x, int y, float fZoomScale) - { - if(fZoomScale <= 0) - return; - - fZoomScale = max(fZoomScale, m_fZoomScaleMin); - - T* pT = static_cast(this); - POINT pt = { x, y }; - if(!pT->PtInDevRect(pt)) - return; - - pT->ViewDPtoLP(&pt); - pT->Zoom(fZoomScale, false); - pT->CenterOnLogicalPoint(pt); - } - - void Zoom(POINT pt, float fZoomScale) - { - T* pT = static_cast(this); - pT->Zoom(pt.x, pt.y, fZoomScale); - } - - void Zoom(RECT& rc) - { - T* pT = static_cast(this); - RECT rcZoom = rc; - pT->NormalizeRect(rcZoom); - SIZE size = { rcZoom.right - rcZoom.left, rcZoom.bottom - rcZoom.top }; - POINT pt = { rcZoom.left + size.cx / 2, rcZoom.top + size.cy / 2 }; - if(size.cx < m_cxyMinZoomRect || size.cy < m_cxyMinZoomRect) - { - pT->Zoom(pt, m_fZoomScale + m_fZoomDelta); - return; - } - - ATLASSERT(size.cx > 0 && size.cy > 0); - - float fScaleH = (float)(m_sizeClient.cx + 1) / (float)size.cx; - float fScaleV = (float)(m_sizeClient.cy + 1) / (float)size.cy; - float fZoomScale = min(fScaleH, fScaleV) * m_fZoomScale; - pT->Zoom(pt, fZoomScale); - } - - void Zoom(float fZoomScale, bool bCenter = true) - { - if(fZoomScale <= 0) - return; - - fZoomScale = max(fZoomScale, m_fZoomScaleMin); - - - T* pT = static_cast(this); - POINT pt = { 0 }; - if(bCenter) - { - RECT rc; - ::GetClientRect(pT->m_hWnd, &rc); - pt.x = rc.right / 2; - pt.y = rc.bottom / 2; - pT->ViewDPtoLP(&pt); - } - - // Modify the Viewport extent - m_fZoomScale = fZoomScale; - SIZE sizeAll = { 0 }; - sizeAll.cx = (int)((float)m_sizeLogAll.cx * fZoomScale); - sizeAll.cy = (int)((float)m_sizeLogAll.cy * fZoomScale); - - // Update scroll bars and window - CScrollImpl< T >::SetScrollSize(sizeAll); - - if(bCenter) - pT->CenterOnLogicalPoint(pt); - } - - // Helper functions - void PrepareDC(CDCHandle dc) - { - ATLASSERT(m_sizeAll.cx >= 0 && m_sizeAll.cy >= 0); - dc.SetMapMode(MM_ANISOTROPIC); - dc.SetWindowExt(m_sizeLogAll); - dc.SetViewportExt(m_sizeAll); - dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y); - } - - void ViewDPtoLP(LPPOINT lpPoints, int nCount = 1) - { - ATLASSERT(lpPoints); - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - - CWindowDC dc(pT->m_hWnd); - pT->PrepareDC(dc.m_hDC); - dc.DPtoLP(lpPoints, nCount); - } - - void ViewLPtoDP(LPPOINT lpPoints, int nCount = 1) - { - ATLASSERT(lpPoints); - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - - CWindowDC dc(pT->m_hWnd); - pT->PrepareDC(dc.m_hDC); - dc.LPtoDP(lpPoints, nCount); - } - - void ClientToDevice(POINT &pt) - { - pt.x += m_ptOffset.x; - pt.y += m_ptOffset.y; - } - - void DeviceToClient(POINT &pt) - { - pt.x -= m_ptOffset.x; - pt.y -= m_ptOffset.y; - } - - void CenterOnPoint(POINT pt) - { - T* pT = static_cast(this); - RECT rect; - pT->GetClientRect(&rect); - - int xOfs = pt.x - (rect.right / 2) + m_ptOffset.x; - if(xOfs < 0) - { - xOfs = 0; - } - else - { - int xMax = max((int)(m_sizeAll.cx - rect.right), 0); - if(xOfs > xMax) - xOfs = xMax; - } - - int yOfs = pt.y - (rect.bottom / 2) + m_ptOffset.y; - if(yOfs < 0) - { - yOfs = 0; - } - else - { - int yMax = max((int)(m_sizeAll.cy - rect.bottom), 0); - if(yOfs > yMax) - yOfs = yMax; - } - - CScrollImpl< T >::SetScrollOffset(xOfs, yOfs); - } - - void CenterOnLogicalPoint(POINT ptLog) - { - T* pT = static_cast(this); - pT->ViewLPtoDP(&ptLog); - pT->DeviceToClient(ptLog); - pT->CenterOnPoint(ptLog); - } - - BOOL PtInDevRect(POINT pt) - { - RECT rc = { 0, 0, m_sizeAll.cx, m_sizeAll.cy }; - ::OffsetRect(&rc, -m_ptOffset.x, -m_ptOffset.y); - return ::PtInRect(&rc, pt); - } - - void NormalizeRect(RECT& rc) - { - if(rc.left > rc.right) - { - int r = rc.right; - rc.right = rc.left; - rc.left = r; - } - if(rc.top > rc.bottom) - { - int b = rc.bottom; - rc.bottom = rc.top; - rc.top = b; - } - } - - void DrawTrackRect() - { - T* pT = static_cast(this); - const SIZE sizeLines = { 2, 2 }; - RECT rc = m_rcTrack; - pT->NormalizeRect(rc); - if(!::IsRectEmpty(&rc)) - { - ::MapWindowPoints(pT->m_hWnd, NULL, (LPPOINT)&rc, 2); - CWindowDC dc(NULL); - dc.DrawDragRect(&rc, sizeLines, NULL, sizeLines); - } - } - - void NotifyParentZoomChanged() - { - T* pT = static_cast(this); - int nId = pT->GetDlgCtrlID(); - NMHDR nmhdr = { pT->m_hWnd, nId, ZSN_ZOOMCHANGED }; - ::SendMessage(pT->GetParent(), WM_NOTIFY, (WPARAM)nId, (LPARAM)&nmhdr); - } - - BEGIN_MSG_MAP(CZoomScrollImpl) - MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor) - MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll) - MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll) - MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel) -#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) - MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel) -#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) - MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel) - MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange) - MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize) - MESSAGE_HANDLER(WM_PAINT, OnPaint) - MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) - MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown) - MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove) - MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp) - MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged) - ALT_MSG_MAP(1) - COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp) - COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown) - COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp) - COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown) - COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop) - COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom) - COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft) - COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight) - COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft) - COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight) - COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft) - COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight) - END_MSG_MAP() - - LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - ATLASSERT(m_sizeLogAll.cx >= 0 && m_sizeLogAll.cy >= 0); - ATLASSERT(m_sizeAll.cx >= 0 && m_sizeAll.cy >= 0); - - if(wParam != NULL) - { - CDCHandle dc = (HDC)wParam; - int nMapModeSav = dc.GetMapMode(); - dc.SetMapMode(MM_ANISOTROPIC); - SIZE szWindowExt = { 0, 0 }; - dc.SetWindowExt(m_sizeLogAll, &szWindowExt); - SIZE szViewportExt = { 0, 0 }; - dc.SetViewportExt(m_sizeAll, &szViewportExt); - POINT ptViewportOrg = { 0, 0 }; - dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg); - - pT->DoPaint(dc); - - dc.SetMapMode(nMapModeSav); - dc.SetWindowExt(szWindowExt); - dc.SetViewportExt(szViewportExt); - dc.SetViewportOrg(ptViewportOrg); - } - else - { - CPaintDC dc(pT->m_hWnd); - pT->PrepareDC(dc.m_hDC); - pT->DoPaint(dc.m_hDC); - } - return 0; - } - - LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) - { - if(m_nZoomMode == ZOOMMODE_IN && !m_bTracking) - { - T* pT = static_cast(this); - POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; - if(pT->PtInDevRect(pt)) - { - pT->SetCapture(); - m_bTracking = true; - ::SetRect(&m_rcTrack, pt.x, pt.y, pt.x, pt.y); - } - } - bHandled = FALSE; - return 0; - } - - LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) - { - if(m_bTracking) - { - T* pT = static_cast(this); - POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; - if(pT->PtInDevRect(pt)) - { - pT->DrawTrackRect(); - m_rcTrack.right = pt.x; - m_rcTrack.bottom = pt.y; - pT->DrawTrackRect(); - } - } - bHandled = FALSE; - return 0; - } - - LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) - { - ::ReleaseCapture(); - if(m_nZoomMode == ZOOMMODE_OUT) - { - T* pT = static_cast(this); - pT->Zoom(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), m_fZoomScale - m_fZoomDelta); - pT->NotifyParentZoomChanged(); - } - bHandled = FALSE; - return 0; - } - - LRESULT OnCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - if(m_bTracking) - { - m_bTracking = false; - T* pT = static_cast(this); - pT->DrawTrackRect(); - pT->Zoom(m_rcTrack); - pT->NotifyParentZoomChanged(); - ::SetRectEmpty(&m_rcTrack); - } - bHandled = FALSE; - return 0; - } - - LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - if(LOWORD(lParam) == HTCLIENT && m_nZoomMode != ZOOMMODE_OFF) - { - T* pT = static_cast(this); - if((HWND)wParam == pT->m_hWnd) - { - DWORD dwPos = ::GetMessagePos(); - POINT pt = { GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos) }; - pT->ScreenToClient(&pt); - if(pT->PtInDevRect(pt)) - { - ::SetCursor(::LoadCursor(NULL, IDC_CROSS)); - return 1; - } - } - } - bHandled = FALSE; - return 0; - } -}; - -/////////////////////////////////////////////////////////////////////////////// -// CZoomScrollWindowImpl - Implements scrolling window with zooming - -template -class ATL_NO_VTABLE CZoomScrollWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CZoomScrollImpl< T > -{ -public: - BEGIN_MSG_MAP(CZoomScrollWindowImpl) - MESSAGE_HANDLER(WM_SETCURSOR, CZoomScrollImpl< T >::OnSetCursor) - MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll) - MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll) - MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel) -#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) - MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel) -#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) - MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel) - MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange) - MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize) - MESSAGE_HANDLER(WM_PAINT, CZoomScrollImpl< T >::OnPaint) - MESSAGE_HANDLER(WM_PRINTCLIENT, CZoomScrollImpl< T >::OnPaint) - MESSAGE_HANDLER(WM_LBUTTONDOWN, CZoomScrollImpl< T >::OnLButtonDown) - MESSAGE_HANDLER(WM_MOUSEMOVE, CZoomScrollImpl< T >::OnMouseMove) - MESSAGE_HANDLER(WM_LBUTTONUP, CZoomScrollImpl< T >::OnLButtonUp) - MESSAGE_HANDLER(WM_CAPTURECHANGED, CZoomScrollImpl< T >::OnCaptureChanged) - ALT_MSG_MAP(1) - COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp) - COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown) - COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp) - COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown) - COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop) - COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom) - COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft) - COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight) - COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft) - COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight) - COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft) - COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight) - END_MSG_MAP() -}; - -#endif // !_WIN32_WCE - - -/////////////////////////////////////////////////////////////////////////////// -// CScrollContainer - -template -class ATL_NO_VTABLE CScrollContainerImpl : public CScrollWindowImpl< T, TBase, TWinTraits > -{ -public: - DECLARE_WND_CLASS_EX(NULL, 0, -1) - - typedef CScrollWindowImpl< T, TBase, TWinTraits > _baseClass; - -// Data members - ATL::CWindow m_wndClient; - bool m_bAutoSizeClient; - bool m_bDrawEdgeIfEmpty; - -// Constructor - CScrollContainerImpl() : m_bAutoSizeClient(true), m_bDrawEdgeIfEmpty(false) - { - // Set CScrollWindowImpl extended style - SetScrollExtendedStyle(SCRL_SCROLLCHILDREN); - } - -// Attributes - HWND GetClient() const - { - return m_wndClient; - } - - HWND SetClient(HWND hWndClient, bool bClientSizeAsMin = true) - { - ATLASSERT(::IsWindow(m_hWnd)); - - HWND hWndOldClient = m_wndClient; - m_wndClient = hWndClient; - - SetRedraw(FALSE); - SetScrollSize(1, 1, FALSE); - - if(m_wndClient.m_hWnd != NULL) - { - m_wndClient.SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE); - - if(bClientSizeAsMin) - { - RECT rect = { 0 }; - m_wndClient.GetWindowRect(&rect); - if((rect.right - rect.left) > 0 && (rect.bottom - rect.top) > 0) - SetScrollSize(rect.right - rect.left, rect.bottom - rect.top, FALSE); - } - - T* pT = static_cast(this); - pT->UpdateLayout(); - } - - SetRedraw(TRUE); - RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_UPDATENOW | RDW_ALLCHILDREN); - - return hWndOldClient; - } - -// Message map and handlers - BEGIN_MSG_MAP(CScrollContainerImpl) - MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) - MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) - MESSAGE_HANDLER(WM_SIZE, OnSize) - CHAIN_MSG_MAP(_baseClass) - FORWARD_NOTIFICATIONS() - ALT_MSG_MAP(1) - CHAIN_MSG_MAP_ALT(_baseClass, 1) - END_MSG_MAP() - - LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - if(m_wndClient.m_hWnd != NULL) - m_wndClient.SetFocus(); - - return 0; - } - - LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - return 1; // no background needed - } - - LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) - { - BOOL bTmp = TRUE; - LRESULT lRet = _baseClass::OnSize(uMsg, wParam, lParam, bTmp); - - T* pT = static_cast(this); - pT->UpdateLayout(); - - return lRet; - } - -// Overrides for CScrollWindowImpl - void DoPaint(CDCHandle dc) - { - if(!m_bAutoSizeClient || m_wndClient.m_hWnd == NULL) - { - T* pT = static_cast(this); - RECT rect = { 0 }; - pT->GetContainerRect(rect); - - if(m_bDrawEdgeIfEmpty && m_wndClient.m_hWnd == NULL) - dc.DrawEdge(&rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST); - - dc.FillRect(&rect, COLOR_APPWORKSPACE); - } - } - - void ScrollToView(POINT pt) - { - CScrollWindowImpl< T, TBase, TWinTraits >::ScrollToView(pt); - } - - void ScrollToView(RECT& rect) - { - CScrollWindowImpl< T, TBase, TWinTraits >::ScrollToView(rect); - } - - void ScrollToView(HWND hWnd) // client window coordinates - { - T* pT = static_cast(this); - pT; // avoid level 4 warning - ATLASSERT(::IsWindow(pT->m_hWnd)); - ATLASSERT(m_wndClient.IsWindow()); - - RECT rect = { 0 }; - ::GetWindowRect(hWnd, &rect); - ::MapWindowPoints(NULL, m_wndClient.m_hWnd, (LPPOINT)&rect, 2); - ScrollToView(rect); - } - -// Implementation - overrideable methods - void UpdateLayout() - { - ATLASSERT(::IsWindow(m_hWnd)); - - if(m_bAutoSizeClient && m_wndClient.m_hWnd != NULL) - { - T* pT = static_cast(this); - RECT rect = { 0 }; - pT->GetContainerRect(rect); - - m_wndClient.SetWindowPos(NULL, &rect, SWP_NOZORDER | SWP_NOMOVE); - } - else - { - Invalidate(); - } - } - - void GetContainerRect(RECT& rect) - { - GetClientRect(&rect); - - if(rect.right < m_sizeAll.cx) - rect.right = m_sizeAll.cx; - - if(rect.bottom < m_sizeAll.cy) - rect.bottom = m_sizeAll.cy; - } -}; - -class CScrollContainer : public CScrollContainerImpl -{ -public: - DECLARE_WND_CLASS_EX(_T("WTL_ScrollContainer"), 0, -1) -}; - -}; // namespace WTL - -#endif // __ATLSCRL_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/atlsplit.h b/prog/3rdPartyLibs/wtl-8.1/include/atlsplit.h deleted file mode 100644 index 88cc1ea12..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/atlsplit.h +++ /dev/null @@ -1,892 +0,0 @@ -// Windows Template Library - WTL version 8.1 -// Copyright (C) Microsoft Corporation. All rights reserved. -// -// This file is a part of the Windows Template Library. -// The use and distribution terms for this software are covered by the -// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php) -// which can be found in the file CPL.TXT at the root of this distribution. -// By using this software in any fashion, you are agreeing to be bound by -// the terms of this license. You must not remove this notice, or -// any other, from this software. - -#ifndef __ATLSPLIT_H__ -#define __ATLSPLIT_H__ - -#pragma once - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#ifndef __ATLAPP_H__ - #error atlsplit.h requires atlapp.h to be included first -#endif - -#ifndef __ATLWIN_H__ - #error atlsplit.h requires atlwin.h to be included first -#endif - - -/////////////////////////////////////////////////////////////////////////////// -// Classes in this file: -// -// CSplitterImpl -// CSplitterWindowImpl -// CSplitterWindowT - - -namespace WTL -{ - -/////////////////////////////////////////////////////////////////////////////// -// CSplitterImpl - Provides splitter support to any window - -// Splitter panes constants -#define SPLIT_PANE_LEFT 0 -#define SPLIT_PANE_RIGHT 1 -#define SPLIT_PANE_TOP SPLIT_PANE_LEFT -#define SPLIT_PANE_BOTTOM SPLIT_PANE_RIGHT -#define SPLIT_PANE_NONE -1 - -// Splitter extended styles -#define SPLIT_PROPORTIONAL 0x00000001 -#define SPLIT_NONINTERACTIVE 0x00000002 -#define SPLIT_RIGHTALIGNED 0x00000004 -#define SPLIT_BOTTOMALIGNED SPLIT_RIGHTALIGNED - -// Note: SPLIT_PROPORTIONAL and SPLIT_RIGHTALIGNED/SPLIT_BOTTOMALIGNED are -// mutually exclusive. If both are set, splitter defaults to SPLIT_PROPORTIONAL - - -template -class CSplitterImpl -{ -public: - enum { m_nPanesCount = 2, m_nPropMax = 10000 }; - - HWND m_hWndPane[m_nPanesCount]; - RECT m_rcSplitter; - int m_xySplitterPos; - int m_nDefActivePane; - int m_cxySplitBar; // splitter bar width/height - static HCURSOR m_hCursor; - int m_cxyMin; // minimum pane size - int m_cxyBarEdge; // splitter bar edge - bool m_bFullDrag; - int m_cxyDragOffset; - int m_nProportionalPos; - bool m_bUpdateProportionalPos; - DWORD m_dwExtendedStyle; // splitter specific extended styles - int m_nSinglePane; // single pane mode - -// Constructor - CSplitterImpl() : - m_xySplitterPos(-1), m_nDefActivePane(SPLIT_PANE_NONE), - m_cxySplitBar(0), m_cxyMin(0), m_cxyBarEdge(0), m_bFullDrag(true), - m_cxyDragOffset(0), m_nProportionalPos(0), m_bUpdateProportionalPos(true), - m_dwExtendedStyle(SPLIT_PROPORTIONAL), - m_nSinglePane(SPLIT_PANE_NONE) - { - m_hWndPane[SPLIT_PANE_LEFT] = NULL; - m_hWndPane[SPLIT_PANE_RIGHT] = NULL; - - ::SetRectEmpty(&m_rcSplitter); - - if(m_hCursor == NULL) - { - CStaticDataInitCriticalSectionLock lock; - if(FAILED(lock.Lock())) - { - ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CSplitterImpl::CSplitterImpl.\n")); - ATLASSERT(FALSE); - return; - } - - if(m_hCursor == NULL) - m_hCursor = ::LoadCursor(NULL, t_bVertical ? IDC_SIZEWE : IDC_SIZENS); - - lock.Unlock(); - } - } - -// Attributes - void SetSplitterRect(LPRECT lpRect = NULL, bool bUpdate = true) - { - if(lpRect == NULL) - { - T* pT = static_cast(this); - pT->GetClientRect(&m_rcSplitter); - } - else - { - m_rcSplitter = *lpRect; - } - - if(IsProportional()) - UpdateProportionalPos(); - else if(IsRightAligned()) - UpdateRightAlignPos(); - - if(bUpdate) - UpdateSplitterLayout(); - } - - void GetSplitterRect(LPRECT lpRect) const - { - ATLASSERT(lpRect != NULL); - *lpRect = m_rcSplitter; - } - - bool SetSplitterPos(int xyPos = -1, bool bUpdate = true) - { - if(xyPos == -1) // -1 == middle - { - if(t_bVertical) - xyPos = (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) / 2; - else - xyPos = (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge) / 2; - } - - // Adjust if out of valid range - int cxyMax = 0; - if(t_bVertical) - cxyMax = m_rcSplitter.right - m_rcSplitter.left; - else - cxyMax = m_rcSplitter.bottom - m_rcSplitter.top; - - if(xyPos < m_cxyMin + m_cxyBarEdge) - xyPos = m_cxyMin; - else if(xyPos > (cxyMax - m_cxySplitBar - m_cxyBarEdge - m_cxyMin)) - xyPos = cxyMax - m_cxySplitBar - m_cxyBarEdge - m_cxyMin; - - // Set new position and update if requested - bool bRet = (m_xySplitterPos != xyPos); - m_xySplitterPos = xyPos; - - if(m_bUpdateProportionalPos) - { - if(IsProportional()) - StoreProportionalPos(); - else if(IsRightAligned()) - StoreRightAlignPos(); - } - else - { - m_bUpdateProportionalPos = true; - } - - if(bUpdate && bRet) - UpdateSplitterLayout(); - - return bRet; - } - - void SetSplitterPosPct(int nPct, bool bUpdate = true) - { - ATLASSERT(nPct >= 0 && nPct <= 100); - - m_nProportionalPos = ::MulDiv(nPct, m_nPropMax, 100); - UpdateProportionalPos(); - - if(bUpdate) - UpdateSplitterLayout(); - } - - int GetSplitterPos() const - { - return m_xySplitterPos; - } - - bool SetSinglePaneMode(int nPane = SPLIT_PANE_NONE) - { - ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT || nPane == SPLIT_PANE_NONE); - if(!(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT || nPane == SPLIT_PANE_NONE)) - return false; - - if(nPane != SPLIT_PANE_NONE) - { - if(!::IsWindowVisible(m_hWndPane[nPane])) - ::ShowWindow(m_hWndPane[nPane], SW_SHOW); - int nOtherPane = (nPane == SPLIT_PANE_LEFT) ? SPLIT_PANE_RIGHT : SPLIT_PANE_LEFT; - ::ShowWindow(m_hWndPane[nOtherPane], SW_HIDE); - if(m_nDefActivePane != nPane) - m_nDefActivePane = nPane; - } - else if(m_nSinglePane != SPLIT_PANE_NONE) - { - int nOtherPane = (m_nSinglePane == SPLIT_PANE_LEFT) ? SPLIT_PANE_RIGHT : SPLIT_PANE_LEFT; - ::ShowWindow(m_hWndPane[nOtherPane], SW_SHOW); - } - - m_nSinglePane = nPane; - UpdateSplitterLayout(); - return true; - } - - int GetSinglePaneMode() const - { - return m_nSinglePane; - } - - DWORD GetSplitterExtendedStyle() const - { - return m_dwExtendedStyle; - } - - DWORD SetSplitterExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0) - { - DWORD dwPrevStyle = m_dwExtendedStyle; - if(dwMask == 0) - m_dwExtendedStyle = dwExtendedStyle; - else - m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask); -#ifdef _DEBUG - if(IsProportional() && IsRightAligned()) - ATLTRACE2(atlTraceUI, 0, _T("CSplitterImpl::SetSplitterExtendedStyle - SPLIT_PROPORTIONAL and SPLIT_RIGHTALIGNED are mutually exclusive, defaulting to SPLIT_PROPORTIONAL.\n")); -#endif // _DEBUG - return dwPrevStyle; - } - -// Splitter operations - void SetSplitterPanes(HWND hWndLeftTop, HWND hWndRightBottom, bool bUpdate = true) - { - m_hWndPane[SPLIT_PANE_LEFT] = hWndLeftTop; - m_hWndPane[SPLIT_PANE_RIGHT] = hWndRightBottom; - ATLASSERT(m_hWndPane[SPLIT_PANE_LEFT] == NULL || m_hWndPane[SPLIT_PANE_RIGHT] == NULL || m_hWndPane[SPLIT_PANE_LEFT] != m_hWndPane[SPLIT_PANE_RIGHT]); - if(bUpdate) - UpdateSplitterLayout(); - } - - bool SetSplitterPane(int nPane, HWND hWnd, bool bUpdate = true) - { - ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT); - - if(nPane != SPLIT_PANE_LEFT && nPane != SPLIT_PANE_RIGHT) - return false; - m_hWndPane[nPane] = hWnd; - ATLASSERT(m_hWndPane[SPLIT_PANE_LEFT] == NULL || m_hWndPane[SPLIT_PANE_RIGHT] == NULL || m_hWndPane[SPLIT_PANE_LEFT] != m_hWndPane[SPLIT_PANE_RIGHT]); - if(bUpdate) - UpdateSplitterLayout(); - return true; - } - - HWND GetSplitterPane(int nPane) const - { - ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT); - - if(nPane != SPLIT_PANE_LEFT && nPane != SPLIT_PANE_RIGHT) - return false; - return m_hWndPane[nPane]; - } - - bool SetActivePane(int nPane) - { - ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT); - - if(nPane != SPLIT_PANE_LEFT && nPane != SPLIT_PANE_RIGHT) - return false; - if(m_nSinglePane != SPLIT_PANE_NONE && nPane != m_nSinglePane) - return false; - ::SetFocus(m_hWndPane[nPane]); - m_nDefActivePane = nPane; - return true; - } - - int GetActivePane() const - { - int nRet = SPLIT_PANE_NONE; - HWND hWndFocus = ::GetFocus(); - if(hWndFocus != NULL) - { - for(int nPane = 0; nPane < m_nPanesCount; nPane++) - { - if(hWndFocus == m_hWndPane[nPane] || ::IsChild(m_hWndPane[nPane], hWndFocus)) - { - nRet = nPane; - break; - } - } - } - return nRet; - } - - bool ActivateNextPane(bool bNext = true) - { - int nPane = m_nSinglePane; - if(nPane == SPLIT_PANE_NONE) - { - switch(GetActivePane()) - { - case SPLIT_PANE_LEFT: - nPane = SPLIT_PANE_RIGHT; - break; - case SPLIT_PANE_RIGHT: - nPane = SPLIT_PANE_LEFT; - break; - default: - nPane = bNext ? SPLIT_PANE_LEFT : SPLIT_PANE_RIGHT; - break; - } - } - return SetActivePane(nPane); - } - - bool SetDefaultActivePane(int nPane) - { - ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT); - - if(nPane != SPLIT_PANE_LEFT && nPane != SPLIT_PANE_RIGHT) - return false; - m_nDefActivePane = nPane; - return true; - } - - bool SetDefaultActivePane(HWND hWnd) - { - for(int nPane = 0; nPane < m_nPanesCount; nPane++) - { - if(hWnd == m_hWndPane[nPane]) - { - m_nDefActivePane = nPane; - return true; - } - } - return false; // not found - } - - int GetDefaultActivePane() const - { - return m_nDefActivePane; - } - - void DrawSplitter(CDCHandle dc) - { - ATLASSERT(dc.m_hDC != NULL); - if(m_nSinglePane == SPLIT_PANE_NONE && m_xySplitterPos == -1) - return; - - T* pT = static_cast(this); - if(m_nSinglePane == SPLIT_PANE_NONE) - { - pT->DrawSplitterBar(dc); - - for(int nPane = 0; nPane < m_nPanesCount; nPane++) - { - if(m_hWndPane[nPane] == NULL) - pT->DrawSplitterPane(dc, nPane); - } - } - else - { - if(m_hWndPane[m_nSinglePane] == NULL) - pT->DrawSplitterPane(dc, m_nSinglePane); - } - } - -// Overrideables - void DrawSplitterBar(CDCHandle dc) - { - RECT rect; - if(GetSplitterBarRect(&rect)) - { - dc.FillRect(&rect, COLOR_3DFACE); - // draw 3D edge if needed - T* pT = static_cast(this); - if((pT->GetExStyle() & WS_EX_CLIENTEDGE) != 0) - dc.DrawEdge(&rect, EDGE_RAISED, t_bVertical ? (BF_LEFT | BF_RIGHT) : (BF_TOP | BF_BOTTOM)); - } - } - - // called only if pane is empty - void DrawSplitterPane(CDCHandle dc, int nPane) - { - RECT rect; - if(GetSplitterPaneRect(nPane, &rect)) - { - T* pT = static_cast(this); - if((pT->GetExStyle() & WS_EX_CLIENTEDGE) == 0) - dc.DrawEdge(&rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST); - dc.FillRect(&rect, COLOR_APPWORKSPACE); - } - } - -// Message map and handlers - BEGIN_MSG_MAP(CSplitterImpl) - MESSAGE_HANDLER(WM_CREATE, OnCreate) - MESSAGE_HANDLER(WM_PAINT, OnPaint) -#ifndef _WIN32_WCE - MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) -#endif // !_WIN32_WCE - if(IsInteractive()) - { - MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor) - MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove) - MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown) - MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp) - MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnLButtonDoubleClick) - MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged) - } - MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) -#ifndef _WIN32_WCE - MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActivate) -#endif // !_WIN32_WCE - MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange) - END_MSG_MAP() - - LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - GetSystemSettings(false); - bHandled = FALSE; - return 1; - } - - LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - // try setting position if not set - if(m_nSinglePane == SPLIT_PANE_NONE && m_xySplitterPos == -1) - pT->SetSplitterPos(); - // do painting - CPaintDC dc(pT->m_hWnd); - pT->DrawSplitter(dc.m_hDC); - return 0; - } - - LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - T* pT = static_cast(this); - if((HWND)wParam == pT->m_hWnd && LOWORD(lParam) == HTCLIENT) - { - DWORD dwPos = ::GetMessagePos(); - POINT ptPos = { GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos) }; - pT->ScreenToClient(&ptPos); - if(IsOverSplitterBar(ptPos.x, ptPos.y)) - return 1; - } - - bHandled = FALSE; - return 0; - } - - LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - T* pT = static_cast(this); - int xPos = GET_X_LPARAM(lParam); - int yPos = GET_Y_LPARAM(lParam); - if((wParam & MK_LBUTTON) && ::GetCapture() == pT->m_hWnd) - { - int xyNewSplitPos = 0; - if(t_bVertical) - xyNewSplitPos = xPos - m_rcSplitter.left - m_cxyDragOffset; - else - xyNewSplitPos = yPos - m_rcSplitter.top - m_cxyDragOffset; - - if(xyNewSplitPos == -1) // avoid -1, that means middle - xyNewSplitPos = -2; - - if(m_xySplitterPos != xyNewSplitPos) - { - if(m_bFullDrag) - { - if(pT->SetSplitterPos(xyNewSplitPos, true)) - pT->UpdateWindow(); - } - else - { - DrawGhostBar(); - pT->SetSplitterPos(xyNewSplitPos, false); - DrawGhostBar(); - } - } - } - else // not dragging, just set cursor - { - if(IsOverSplitterBar(xPos, yPos)) - ::SetCursor(m_hCursor); - bHandled = FALSE; - } - - return 0; - } - - LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) - { - int xPos = GET_X_LPARAM(lParam); - int yPos = GET_Y_LPARAM(lParam); - if(IsOverSplitterBar(xPos, yPos)) - { - T* pT = static_cast(this); - pT->SetCapture(); - ::SetCursor(m_hCursor); - if(!m_bFullDrag) - DrawGhostBar(); - if(t_bVertical) - m_cxyDragOffset = xPos - m_rcSplitter.left - m_xySplitterPos; - else - m_cxyDragOffset = yPos - m_rcSplitter.top - m_xySplitterPos; - } - bHandled = FALSE; - return 1; - } - - LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - ::ReleaseCapture(); - bHandled = FALSE; - return 1; - } - - LRESULT OnLButtonDoubleClick(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - pT->SetSplitterPos(); // middle - return 0; - } - - LRESULT OnCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - if(!m_bFullDrag) - { - DrawGhostBar(); - UpdateSplitterLayout(); - T* pT = static_cast(this); - pT->UpdateWindow(); - } - return 0; - } - - LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM, BOOL& bHandled) - { - if(m_nSinglePane == SPLIT_PANE_NONE) - { - if(m_nDefActivePane == SPLIT_PANE_LEFT || m_nDefActivePane == SPLIT_PANE_RIGHT) - ::SetFocus(m_hWndPane[m_nDefActivePane]); - } - else - { - ::SetFocus(m_hWndPane[m_nSinglePane]); - } - bHandled = FALSE; - return 1; - } - -#ifndef _WIN32_WCE - LRESULT OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - LRESULT lRet = pT->DefWindowProc(uMsg, wParam, lParam); - if(lRet == MA_ACTIVATE || lRet == MA_ACTIVATEANDEAT) - { - DWORD dwPos = ::GetMessagePos(); - POINT pt = { GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos) }; - pT->ScreenToClient(&pt); - RECT rcPane; - for(int nPane = 0; nPane < m_nPanesCount; nPane++) - { - if(GetSplitterPaneRect(nPane, &rcPane) && ::PtInRect(&rcPane, pt)) - { - m_nDefActivePane = nPane; - break; - } - } - } - return lRet; - } -#endif // !_WIN32_WCE - - LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - GetSystemSettings(true); - return 0; - } - -// Implementation - internal helpers - void UpdateSplitterLayout() - { - if(m_nSinglePane == SPLIT_PANE_NONE && m_xySplitterPos == -1) - return; - - T* pT = static_cast(this); - RECT rect = { 0, 0, 0, 0 }; - if(m_nSinglePane == SPLIT_PANE_NONE) - { - if(GetSplitterBarRect(&rect)) - pT->InvalidateRect(&rect); - - for(int nPane = 0; nPane < m_nPanesCount; nPane++) - { - if(GetSplitterPaneRect(nPane, &rect)) - { - if(m_hWndPane[nPane] != NULL) - ::SetWindowPos(m_hWndPane[nPane], NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER); - else - pT->InvalidateRect(&rect); - } - } - } - else - { - if(GetSplitterPaneRect(m_nSinglePane, &rect)) - { - if(m_hWndPane[m_nSinglePane] != NULL) - ::SetWindowPos(m_hWndPane[m_nSinglePane], NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER); - else - pT->InvalidateRect(&rect); - } - } - } - - bool GetSplitterBarRect(LPRECT lpRect) const - { - ATLASSERT(lpRect != NULL); - if(m_nSinglePane != SPLIT_PANE_NONE || m_xySplitterPos == -1) - return false; - - if(t_bVertical) - { - lpRect->left = m_rcSplitter.left + m_xySplitterPos; - lpRect->top = m_rcSplitter.top; - lpRect->right = m_rcSplitter.left + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge; - lpRect->bottom = m_rcSplitter.bottom; - } - else - { - lpRect->left = m_rcSplitter.left; - lpRect->top = m_rcSplitter.top + m_xySplitterPos; - lpRect->right = m_rcSplitter.right; - lpRect->bottom = m_rcSplitter.top + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge; - } - - return true; - } - - bool GetSplitterPaneRect(int nPane, LPRECT lpRect) const - { - ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT); - ATLASSERT(lpRect != NULL); - bool bRet = true; - if(m_nSinglePane != SPLIT_PANE_NONE) - { - if(nPane == m_nSinglePane) - *lpRect = m_rcSplitter; - else - bRet = false; - } - else if(nPane == SPLIT_PANE_LEFT) - { - if(t_bVertical) - { - lpRect->left = m_rcSplitter.left; - lpRect->top = m_rcSplitter.top; - lpRect->right = m_rcSplitter.left + m_xySplitterPos; - lpRect->bottom = m_rcSplitter.bottom; - } - else - { - lpRect->left = m_rcSplitter.left; - lpRect->top = m_rcSplitter.top; - lpRect->right = m_rcSplitter.right; - lpRect->bottom = m_rcSplitter.top + m_xySplitterPos; - } - } - else if(nPane == SPLIT_PANE_RIGHT) - { - if(t_bVertical) - { - lpRect->left = m_rcSplitter.left + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge; - lpRect->top = m_rcSplitter.top; - lpRect->right = m_rcSplitter.right; - lpRect->bottom = m_rcSplitter.bottom; - } - else - { - lpRect->left = m_rcSplitter.left; - lpRect->top = m_rcSplitter.top + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge; - lpRect->right = m_rcSplitter.right; - lpRect->bottom = m_rcSplitter.bottom; - } - } - else - { - bRet = false; - } - return bRet; - } - - bool IsOverSplitterRect(int x, int y) const - { - // -1 == don't check - return ((x == -1 || (x >= m_rcSplitter.left && x <= m_rcSplitter.right)) && - (y == -1 || (y >= m_rcSplitter.top && y <= m_rcSplitter.bottom))); - } - - bool IsOverSplitterBar(int x, int y) const - { - if(m_nSinglePane != SPLIT_PANE_NONE) - return false; - if(m_xySplitterPos == -1 || !IsOverSplitterRect(x, y)) - return false; - int xy = t_bVertical ? x : y; - int xyOff = t_bVertical ? m_rcSplitter.left : m_rcSplitter.top; - return ((xy >= (xyOff + m_xySplitterPos)) && (xy < xyOff + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge)); - } - - void DrawGhostBar() - { - RECT rect = { 0, 0, 0, 0 }; - if(GetSplitterBarRect(&rect)) - { - // invert the brush pattern (looks just like frame window sizing) - T* pT = static_cast(this); - CWindowDC dc(pT->m_hWnd); - CBrush brush = CDCHandle::GetHalftoneBrush(); - if(brush.m_hBrush != NULL) - { - CBrushHandle brushOld = dc.SelectBrush(brush); - dc.PatBlt(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, PATINVERT); - dc.SelectBrush(brushOld); - } - } - } - - void GetSystemSettings(bool bUpdate) - { -#ifndef _WIN32_WCE - m_cxySplitBar = ::GetSystemMetrics(t_bVertical ? SM_CXSIZEFRAME : SM_CYSIZEFRAME); -#else // CE specific - m_cxySplitBar = 2 * ::GetSystemMetrics(t_bVertical ? SM_CXEDGE : SM_CYEDGE); -#endif // _WIN32_WCE - - T* pT = static_cast(this); - if((pT->GetExStyle() & WS_EX_CLIENTEDGE)) - { - m_cxyBarEdge = 2 * ::GetSystemMetrics(t_bVertical ? SM_CXEDGE : SM_CYEDGE); - m_cxyMin = 0; - } - else - { - m_cxyBarEdge = 0; - m_cxyMin = 2 * ::GetSystemMetrics(t_bVertical ? SM_CXEDGE : SM_CYEDGE); - } - -#ifndef _WIN32_WCE - ::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &m_bFullDrag, 0); -#endif // !_WIN32_WCE - - if(bUpdate) - UpdateSplitterLayout(); - } - - bool IsProportional() const - { - return ((m_dwExtendedStyle & SPLIT_PROPORTIONAL) != 0); - } - - void StoreProportionalPos() - { - int cxyTotal = t_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge); - if(cxyTotal > 0) - m_nProportionalPos = ::MulDiv(m_xySplitterPos, m_nPropMax, cxyTotal); - else - m_nProportionalPos = 0; - ATLTRACE2(atlTraceUI, 0, _T("CSplitterImpl::StoreProportionalPos - %i\n"), m_nProportionalPos); - } - - void UpdateProportionalPos() - { - int cxyTotal = t_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge); - if(cxyTotal > 0) - { - int xyNewPos = ::MulDiv(m_nProportionalPos, cxyTotal, m_nPropMax); - m_bUpdateProportionalPos = false; - T* pT = static_cast(this); - pT->SetSplitterPos(xyNewPos, false); - } - } - - bool IsRightAligned() const - { - return ((m_dwExtendedStyle & SPLIT_RIGHTALIGNED) != 0); - } - - void StoreRightAlignPos() - { - int cxyTotal = t_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge); - if(cxyTotal > 0) - m_nProportionalPos = cxyTotal - m_xySplitterPos; - else - m_nProportionalPos = 0; - ATLTRACE2(atlTraceUI, 0, _T("CSplitterImpl::StoreRightAlignPos - %i\n"), m_nProportionalPos); - } - - void UpdateRightAlignPos() - { - int cxyTotal = t_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge); - if(cxyTotal > 0) - { - m_bUpdateProportionalPos = false; - T* pT = static_cast(this); - pT->SetSplitterPos(cxyTotal - m_nProportionalPos, false); - } - } - - bool IsInteractive() const - { - return ((m_dwExtendedStyle & SPLIT_NONINTERACTIVE) == 0); - } -}; - -template HCURSOR CSplitterImpl< T, t_bVertical>::m_hCursor = NULL; - - -/////////////////////////////////////////////////////////////////////////////// -// CSplitterWindowImpl - Implements a splitter window - -template -class ATL_NO_VTABLE CSplitterWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CSplitterImpl< T , t_bVertical > -{ -public: - DECLARE_WND_CLASS_EX(NULL, CS_DBLCLKS, COLOR_WINDOW) - - typedef CSplitterImpl< T , t_bVertical > _baseClass; - - BEGIN_MSG_MAP(CSplitterWindowImpl) - MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) - MESSAGE_HANDLER(WM_SIZE, OnSize) - CHAIN_MSG_MAP(_baseClass) - FORWARD_NOTIFICATIONS() - END_MSG_MAP() - - LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - // handled, no background painting needed - return 1; - } - - LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) - { - if(wParam != SIZE_MINIMIZED) - SetSplitterRect(); - - bHandled = FALSE; - return 1; - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CSplitterWindow - Implements a splitter window to be used as is - -template -class CSplitterWindowT : public CSplitterWindowImpl, t_bVertical> -{ -public: - DECLARE_WND_CLASS_EX(_T("WTL_SplitterWindow"), CS_DBLCLKS, COLOR_WINDOW) -}; - -typedef CSplitterWindowT CSplitterWindow; -typedef CSplitterWindowT CHorSplitterWindow; - -}; // namespace WTL - -#endif // __ATLSPLIT_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/atltheme.h b/prog/3rdPartyLibs/wtl-8.1/include/atltheme.h deleted file mode 100644 index 12c605992..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/atltheme.h +++ /dev/null @@ -1,1222 +0,0 @@ -// Windows Template Library - WTL version 8.1 -// Copyright (C) Microsoft Corporation. All rights reserved. -// -// This file is a part of the Windows Template Library. -// The use and distribution terms for this software are covered by the -// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php) -// which can be found in the file CPL.TXT at the root of this distribution. -// By using this software in any fashion, you are agreeing to be bound by -// the terms of this license. You must not remove this notice, or -// any other, from this software. - -#ifndef __ATLTHEME_H__ -#define __ATLTHEME_H__ - -#pragma once - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#ifdef _WIN32_WCE - #error atltheme.h is not supported on Windows CE -#endif - -#ifndef __ATLAPP_H__ - #error atltheme.h requires atlapp.h to be included first -#endif - -#ifndef __ATLWIN_H__ - #error atltheme.h requires atlwin.h to be included first -#endif - -#if (_WIN32_WINNT < 0x0501) - #error atltheme.h requires _WIN32_WINNT >= 0x0501 -#endif // (_WIN32_WINNT < 0x0501) - -#if defined(_WTL_USE_VSSYM32) || (defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)) - #include -#else - #ifndef TMSCHEMA_H - #include - #endif -#endif - -#ifndef _UXTHEME_H_ -#include -#endif -#pragma comment(lib, "uxtheme.lib") - -// Note: To create an application that also runs on older versions of Windows, -// use delay load of uxtheme.dll and ensure that no calls to the Theme API are -// made if theming is not supported. It is enough to check if m_hTheme is NULL. -// Example: -// if(m_hTheme != NULL) -// { -// DrawThemeBackground(dc, BP_PUSHBUTTON, PBS_NORMAL, &rect, NULL); -// DrawThemeText(dc, BP_PUSHBUTTON, PBS_NORMAL, L"Button", -1, DT_SINGLELINE | DT_CENTER | DT_VCENTER, 0, &rect); -// } -// else -// { -// dc.DrawFrameControl(&rect, DFC_BUTTON, DFCS_BUTTONPUSH); -// dc.DrawText(_T("Button"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); -// } -// -// Delay load is NOT AUTOMATIC for VC++ 7, you have to link to delayimp.lib, -// and add uxtheme.dll in the Linker.Input.Delay Loaded DLLs section of the -// project properties. -#if (_MSC_VER < 1300) && !defined(_WTL_NO_THEME_DELAYLOAD) - #pragma comment(lib, "delayimp.lib") - #pragma comment(linker, "/delayload:uxtheme.dll") -#endif // (_MSC_VER < 1300) && !defined(_WTL_NO_THEME_DELAYLOAD) - -// Hack: Signatures in uxtheme.h changed - the only way to check which variant of uxtheme.h -// is included is to check for presence of new defines MAX_THEMECOLOR and MAX_THEMESIZE -#ifndef _WTL_NEW_UXTHEME - #if defined(MAX_THEMECOLOR) && defined(MAX_THEMESIZE) - #define _WTL_NEW_UXTHEME - #endif // defined(MAX_THEMECOLOR) && defined(MAX_THEMESIZE) -#endif // _WTL_NEW_UXTHEME - - -/////////////////////////////////////////////////////////////////////////////// -// Classes in this file: -// -// CTheme -// CThemeImpl -// -// CBufferedPaint -// CBufferedPaintImpl -// CBufferedPaintWindowImpl -// CBufferedAnimation -// CBufferedAnimationImpl -// CBufferedAnimationWindowImpl -// -// Global functions: -// AtlDrawThemeClientEdge() - - -namespace WTL -{ - -/////////////////////////////////////////////////////////////////////////////// -// CTheme - wrapper for theme handle - -class CTheme -{ -public: -// Data members - HTHEME m_hTheme; - static int m_nIsThemingSupported; - -// Constructor - CTheme(HTHEME hTheme = NULL) : m_hTheme(hTheme) - { - IsThemingSupported(); - } - -// Operators and helpers - bool IsThemeNull() const - { - return (m_hTheme == NULL); - } - - CTheme& operator =(HTHEME hTheme) - { - m_hTheme = hTheme; - return *this; - } - - operator HTHEME() const - { - return m_hTheme; - } - - void Attach(HTHEME hTheme) - { - m_hTheme = hTheme; - } - - HTHEME Detach() - { - HTHEME hTheme = m_hTheme; - m_hTheme = NULL; - return hTheme; - } - -// Theme support helper - static bool IsThemingSupported() - { - if(m_nIsThemingSupported == -1) - { - CStaticDataInitCriticalSectionLock lock; - if(FAILED(lock.Lock())) - { - ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CTheme::IsThemingSupported.\n")); - ATLASSERT(FALSE); - return false; - } - - if(m_nIsThemingSupported == -1) - { - HMODULE hThemeDLL = ::LoadLibrary(_T("uxtheme.dll")); - m_nIsThemingSupported = (hThemeDLL != NULL) ? 1 : 0; - if(hThemeDLL != NULL) - ::FreeLibrary(hThemeDLL); - } - - lock.Unlock(); - } - - ATLASSERT(m_nIsThemingSupported != -1); - return (m_nIsThemingSupported == 1); - } - -// Operations and theme properties - HTHEME OpenThemeData(HWND hWnd, LPCWSTR pszClassList) - { - if(!IsThemingSupported()) - return NULL; - - ATLASSERT(m_hTheme == NULL); - m_hTheme = ::OpenThemeData(hWnd, pszClassList); - return m_hTheme; - } - - HRESULT CloseThemeData() - { - HRESULT hRet = S_FALSE; - if(m_hTheme != NULL) - { - hRet = ::CloseThemeData(m_hTheme); - if(SUCCEEDED(hRet)) - m_hTheme = NULL; - } - return hRet; - } - - HRESULT DrawThemeBackground(HDC hDC, int nPartID, int nStateID, LPCRECT pRect, LPCRECT pClipRect = NULL) - { - ATLASSERT(m_hTheme != NULL); - return ::DrawThemeBackground(m_hTheme, hDC, nPartID, nStateID, pRect, pClipRect); - } - - HRESULT DrawThemeBackgroundEx(HDC hDC, int nPartID, int nStateID, LPCRECT pRect, const DTBGOPTS* pOptions = NULL) - { - ATLASSERT(m_hTheme != NULL); - return ::DrawThemeBackgroundEx(m_hTheme, hDC, nPartID, nStateID, pRect, pOptions); - } - - HRESULT DrawThemeText(HDC hDC, int nPartID, int nStateID, LPCWSTR pszText, int nCharCount, DWORD dwTextFlags, DWORD dwTextFlags2, LPCRECT pRect) - { - ATLASSERT(m_hTheme != NULL); - return ::DrawThemeText(m_hTheme, hDC, nPartID, nStateID, pszText, nCharCount, dwTextFlags, dwTextFlags2, pRect); - } - - HRESULT GetThemeBackgroundContentRect(HDC hDC, int nPartID, int nStateID, LPCRECT pBoundingRect, LPRECT pContentRect) const - { - ATLASSERT(m_hTheme != NULL); - return ::GetThemeBackgroundContentRect(m_hTheme, hDC, nPartID, nStateID, pBoundingRect, pContentRect); - } - - HRESULT GetThemeBackgroundExtent(HDC hDC, int nPartID, int nStateID, LPCRECT pContentRect, LPRECT pExtentRect) const - { - ATLASSERT(m_hTheme != NULL); - return ::GetThemeBackgroundExtent(m_hTheme, hDC, nPartID, nStateID, pContentRect, pExtentRect); - } - - HRESULT GetThemePartSize(HDC hDC, int nPartID, int nStateID, LPRECT pRect, enum THEMESIZE eSize, LPSIZE pSize) const - { - ATLASSERT(m_hTheme != NULL); - return ::GetThemePartSize(m_hTheme, hDC, nPartID, nStateID, pRect, eSize, pSize); - } - - HRESULT GetThemeTextExtent(HDC hDC, int nPartID, int nStateID, LPCWSTR pszText, int nCharCount, DWORD dwTextFlags, LPCRECT pBoundingRect, LPRECT pExtentRect) const - { - ATLASSERT(m_hTheme != NULL); - return ::GetThemeTextExtent(m_hTheme, hDC, nPartID, nStateID, pszText, nCharCount, dwTextFlags, pBoundingRect, pExtentRect); - } - - HRESULT GetThemeTextMetrics(HDC hDC, int nPartID, int nStateID, PTEXTMETRICW pTextMetric) const - { - ATLASSERT(m_hTheme != NULL); -#ifdef _WTL_NEW_UXTHEME - return ::GetThemeTextMetrics(m_hTheme, hDC, nPartID, nStateID, pTextMetric); -#else // !_WTL_NEW_UXTHEME - // Note: The cast to PTEXTMETRIC is because uxtheme.h incorrectly uses it instead of PTEXTMETRICW - return ::GetThemeTextMetrics(m_hTheme, hDC, nPartID, nStateID, (PTEXTMETRIC)pTextMetric); -#endif // !_WTL_NEW_UXTHEME - } - - HRESULT GetThemeBackgroundRegion(HDC hDC, int nPartID, int nStateID, LPCRECT pRect, HRGN* pRegion) const - { - ATLASSERT(m_hTheme != NULL); - return ::GetThemeBackgroundRegion(m_hTheme, hDC, nPartID, nStateID, pRect, pRegion); - } - - HRESULT HitTestThemeBackground(HDC hDC, int nPartID, int nStateID, DWORD dwOptions, LPCRECT pRect, HRGN hrgn, POINT ptTest, WORD* pwHitTestCode) const - { - ATLASSERT(m_hTheme != NULL); - return ::HitTestThemeBackground(m_hTheme, hDC, nPartID, nStateID, dwOptions, pRect, hrgn, ptTest, pwHitTestCode); - } - - HRESULT DrawThemeEdge(HDC hDC, int nPartID, int nStateID, LPCRECT pDestRect, UINT uEdge, UINT uFlags, LPRECT pContentRect = NULL) - { - ATLASSERT(m_hTheme != NULL); - return ::DrawThemeEdge(m_hTheme, hDC, nPartID, nStateID, pDestRect, uEdge, uFlags, pContentRect); - } - - HRESULT DrawThemeIcon(HDC hDC, int nPartID, int nStateID, LPCRECT pRect, HIMAGELIST himl, int nImageIndex) - { - ATLASSERT(m_hTheme != NULL); - return ::DrawThemeIcon(m_hTheme, hDC, nPartID, nStateID, pRect, himl, nImageIndex); - } - - BOOL IsThemePartDefined(int nPartID, int nStateID) const - { - ATLASSERT(m_hTheme != NULL); - return ::IsThemePartDefined(m_hTheme, nPartID, nStateID); - } - - BOOL IsThemeBackgroundPartiallyTransparent(int nPartID, int nStateID) const - { - ATLASSERT(m_hTheme != NULL); - return ::IsThemeBackgroundPartiallyTransparent(m_hTheme, nPartID, nStateID); - } - - HRESULT GetThemeColor(int nPartID, int nStateID, int nPropID, COLORREF* pColor) const - { - ATLASSERT(m_hTheme != NULL); - return ::GetThemeColor(m_hTheme, nPartID, nStateID, nPropID, pColor); - } - - HRESULT GetThemeMetric(HDC hDC, int nPartID, int nStateID, int nPropID, int* pnVal) const - { - ATLASSERT(m_hTheme != NULL); - return ::GetThemeMetric(m_hTheme, hDC, nPartID, nStateID, nPropID, pnVal); - } - - HRESULT GetThemeString(int nPartID, int nStateID, int nPropID, LPWSTR pszBuff, int cchMaxBuffChars) const - { - ATLASSERT(m_hTheme != NULL); - return ::GetThemeString(m_hTheme, nPartID, nStateID, nPropID, pszBuff, cchMaxBuffChars); - } - - HRESULT GetThemeBool(int nPartID, int nStateID, int nPropID, BOOL* pfVal) const - { - ATLASSERT(m_hTheme != NULL); - return ::GetThemeBool(m_hTheme, nPartID, nStateID, nPropID, pfVal); - } - - HRESULT GetThemeInt(int nPartID, int nStateID, int nPropID, int* pnVal) const - { - ATLASSERT(m_hTheme != NULL); - return ::GetThemeInt(m_hTheme, nPartID, nStateID, nPropID, pnVal); - } - - HRESULT GetThemeEnumValue(int nPartID, int nStateID, int nPropID, int* pnVal) const - { - ATLASSERT(m_hTheme != NULL); - return ::GetThemeEnumValue(m_hTheme, nPartID, nStateID, nPropID, pnVal); - } - - HRESULT GetThemePosition(int nPartID, int nStateID, int nPropID, LPPOINT pPoint) const - { - ATLASSERT(m_hTheme != NULL); - return ::GetThemePosition(m_hTheme, nPartID, nStateID, nPropID, pPoint); - } - - // deprecated - HRESULT GetThemeFont(int nPartID, HDC hDC, int nStateID, int nPropID, LOGFONTW* pFont) const - { - ATLASSERT(m_hTheme != NULL); -#ifdef _WTL_NEW_UXTHEME - return ::GetThemeFont(m_hTheme, hDC, nPartID, nStateID, nPropID, pFont); -#else // !_WTL_NEW_UXTHEME - // Note: The cast to LOGFONT* is because uxtheme.h incorrectly uses it instead of LOGFONTW* - return ::GetThemeFont(m_hTheme, hDC, nPartID, nStateID, nPropID, (LOGFONT*)pFont); -#endif // !_WTL_NEW_UXTHEME - } - - HRESULT GetThemeFont(HDC hDC, int nPartID, int nStateID, int nPropID, LOGFONTW* pFont) const - { - ATLASSERT(m_hTheme != NULL); -#ifdef _WTL_NEW_UXTHEME - return ::GetThemeFont(m_hTheme, hDC, nPartID, nStateID, nPropID, pFont); -#else // !_WTL_NEW_UXTHEME - // Note: The cast to LOGFONT* is because uxtheme.h incorrectly uses it instead of LOGFONTW* - return ::GetThemeFont(m_hTheme, hDC, nPartID, nStateID, nPropID, (LOGFONT*)pFont); -#endif // !_WTL_NEW_UXTHEME - } - - HRESULT GetThemeRect(int nPartID, int nStateID, int nPropID, LPRECT pRect) const - { - ATLASSERT(m_hTheme != NULL); - return ::GetThemeRect(m_hTheme, nPartID, nStateID, nPropID, pRect); - } - - HRESULT GetThemeMargins(HDC hDC, int nPartID, int nStateID, int nPropID, LPRECT pRect, PMARGINS pMargins) const - { - ATLASSERT(m_hTheme != NULL); - return ::GetThemeMargins(m_hTheme, hDC, nPartID, nStateID, nPropID, pRect, pMargins); - } - - HRESULT GetThemeIntList(int nPartID, int nStateID, int nPropID, INTLIST* pIntList) const - { - ATLASSERT(m_hTheme != NULL); - return ::GetThemeIntList(m_hTheme, nPartID, nStateID, nPropID, pIntList); - } - - HRESULT GetThemePropertyOrigin(int nPartID, int nStateID, int nPropID, enum PROPERTYORIGIN* pOrigin) const - { - ATLASSERT(m_hTheme != NULL); - return ::GetThemePropertyOrigin(m_hTheme, nPartID, nStateID, nPropID, pOrigin); - } - - HRESULT GetThemeFilename(int nPartID, int nStateID, int nPropID, LPWSTR pszThemeFileName, int cchMaxBuffChars) const - { - ATLASSERT(m_hTheme != NULL); - return ::GetThemeFilename(m_hTheme, nPartID, nStateID, nPropID, pszThemeFileName, cchMaxBuffChars); - } - - COLORREF GetThemeSysColor(int nColorID) const - { - ATLASSERT(m_hTheme != NULL); - return ::GetThemeSysColor(m_hTheme, nColorID); - } - - HBRUSH GetThemeSysColorBrush(int nColorID) const - { - ATLASSERT(m_hTheme != NULL); - return ::GetThemeSysColorBrush(m_hTheme, nColorID); - } - - int GetThemeSysSize(int nSizeID) const - { - ATLASSERT(m_hTheme != NULL); - return ::GetThemeSysSize(m_hTheme, nSizeID); - } - - BOOL GetThemeSysBool(int nBoolID) const - { - ATLASSERT(m_hTheme != NULL); - return ::GetThemeSysBool(m_hTheme, nBoolID); - } - - HRESULT GetThemeSysFont(int nFontID, LOGFONTW* plf) const - { - ATLASSERT(m_hTheme != NULL); -#ifdef _WTL_NEW_UXTHEME - return ::GetThemeSysFont(m_hTheme, nFontID, plf); -#else // !_WTL_NEW_UXTHEME - // Note: The cast to LOGFONT* is because uxtheme.h incorrectly uses it instead of LOGFONTW* - return ::GetThemeSysFont(m_hTheme, nFontID, (LOGFONT*)plf); -#endif // !_WTL_NEW_UXTHEME - } - - HRESULT GetThemeSysString(int nStringID, LPWSTR pszStringBuff, int cchMaxStringChars) const - { - ATLASSERT(m_hTheme != NULL); - return ::GetThemeSysString(m_hTheme, nStringID, pszStringBuff, cchMaxStringChars); - } - - HRESULT GetThemeSysInt(int nIntID, int* pnValue) const - { - ATLASSERT(m_hTheme != NULL); - return ::GetThemeSysInt(m_hTheme, nIntID, pnValue); - } - -#ifdef _WTL_NEW_UXTHEME - HTHEME OpenThemeDataEx(HWND hWnd, LPCWSTR pszClassList, DWORD dwFlags) - { - if(!IsThemingSupported()) - return NULL; - - ATLASSERT(m_hTheme == NULL); - m_hTheme = ::OpenThemeDataEx(hWnd, pszClassList, dwFlags); - return m_hTheme; - } - - HRESULT DrawThemeTextEx(HDC hDC, int nPartID, int nStateID, LPCWSTR pszText, int cchText, DWORD dwTextFlags, LPRECT lpRect, const DTTOPTS* pOptions) - { - ATLASSERT(m_hTheme != NULL); - return ::DrawThemeTextEx(m_hTheme, hDC, nPartID, nStateID, pszText, cchText, dwTextFlags, lpRect, pOptions); - } - - HRESULT GetThemeTransitionDuration(int nPartID, int nFromStateID, int nToStateID, int nPropID, DWORD& dwDuration) - { - ATLASSERT(m_hTheme != NULL); - return ::GetThemeTransitionDuration(m_hTheme, nPartID, nFromStateID, nToStateID, nPropID, &dwDuration); - } -#endif // _WTL_NEW_UXTHEME - -#if (_WIN32_WINNT >= 0x0600) - HRESULT GetThemeBitmap(int nPartID, int nStateID, int nPropID, ULONG uFlags, HBITMAP& hBitmap) - { - ATLASSERT(m_hTheme != NULL); - return ::GetThemeBitmap(m_hTheme, nPartID, nStateID, nPropID, uFlags, &hBitmap); - } - - HRESULT GetThemeStream(int nPartID, int nStateID, int nPropID, VOID** ppvStream, DWORD* pcbStream, HINSTANCE hInstance) - { - ATLASSERT(m_hTheme != NULL); - return ::GetThemeStream(m_hTheme, nPartID, nStateID, nPropID, ppvStream, pcbStream, hInstance); - } -#endif // (_WIN32_WINNT >= 0x0600) -}; - -__declspec(selectany) int CTheme::m_nIsThemingSupported = -1; - - -/////////////////////////////////////////////////////////////////////////////// -// CThemeImpl - theme support implementation - -// Derive from this class to implement window with theme support. -// Example: -// class CMyThemeWindow : public CWindowImpl, public CThemeImpl -// { -// ... -// BEGIN_MSG_MAP(CMyThemeWindow) -// CHAIN_MSG_MAP(CThemeImpl) -// ... -// END_MSG_MAP() -// ... -// }; -// -// If you set theme class list, the class will automaticaly open/close/reopen theme data. - - -// Helper for drawing theme client edge -inline bool AtlDrawThemeClientEdge(HTHEME hTheme, HWND hWnd, HRGN hRgnUpdate = NULL, HBRUSH hBrush = NULL, int nPartID = 0, int nStateID = 0) -{ - ATLASSERT(hTheme != NULL); - ATLASSERT(::IsWindow(hWnd)); - - CWindowDC dc(hWnd); - if(dc.IsNull()) - return false; - - // Get border size - int cxBorder = GetSystemMetrics(SM_CXBORDER); - int cyBorder = GetSystemMetrics(SM_CYBORDER); - if(SUCCEEDED(::GetThemeInt(hTheme, nPartID, nStateID, TMT_SIZINGBORDERWIDTH, &cxBorder))) - cyBorder = cxBorder; - - RECT rect; - ::GetWindowRect(hWnd, &rect); - - // Remove the client edge from the update region - int cxEdge = GetSystemMetrics(SM_CXEDGE); - int cyEdge = GetSystemMetrics(SM_CYEDGE); - ::InflateRect(&rect, -cxEdge, -cyEdge); - CRgn rgn; - rgn.CreateRectRgnIndirect(&rect); - if(rgn.IsNull()) - return false; - - if(hRgnUpdate != NULL) - rgn.CombineRgn(hRgnUpdate, rgn, RGN_AND); - - ::OffsetRect(&rect, -rect.left, -rect.top); - - ::OffsetRect(&rect, cxEdge, cyEdge); - dc.ExcludeClipRect(&rect); - ::InflateRect(&rect, cxEdge, cyEdge); - - ::DrawThemeBackground(hTheme, dc, nPartID, nStateID, &rect, NULL); - - // Use background brush too, since theme border might not cover everything - if(cxBorder < cxEdge && cyBorder < cyEdge) - { - if(hBrush == NULL) -// need conditional code because types don't match in winuser.h -#ifdef _WIN64 - hBrush = (HBRUSH)::GetClassLongPtr(hWnd, GCLP_HBRBACKGROUND); -#else - hBrush = (HBRUSH)UlongToPtr(::GetClassLongPtr(hWnd, GCLP_HBRBACKGROUND)); -#endif - - ::InflateRect(&rect, cxBorder - cxEdge, cyBorder - cyEdge); - dc.FillRect(&rect, hBrush); - } - - ::DefWindowProc(hWnd, WM_NCPAINT, (WPARAM)rgn.m_hRgn, 0L); - - return true; -} - - -// Theme extended styles -#define THEME_EX_3DCLIENTEDGE 0x00000001 -#define THEME_EX_THEMECLIENTEDGE 0x00000002 - -template -class CThemeImpl : public TBase -{ -public: -// Data members - LPWSTR m_lpstrThemeClassList; - DWORD m_dwExtendedStyle; // theme specific extended styles - -// Constructor & destructor - CThemeImpl() : m_lpstrThemeClassList(NULL), m_dwExtendedStyle(0) - { } - - ~CThemeImpl() - { - delete [] m_lpstrThemeClassList; - } - -// Attributes - bool SetThemeClassList(LPCWSTR lpstrThemeClassList) - { - if(m_lpstrThemeClassList != NULL) - { - delete [] m_lpstrThemeClassList; - m_lpstrThemeClassList = NULL; - } - - if(lpstrThemeClassList == NULL) - return true; - - int cchLen = lstrlenW(lpstrThemeClassList) + 1; - ATLTRY(m_lpstrThemeClassList = new WCHAR[cchLen]); - if(m_lpstrThemeClassList == NULL) - return false; - - SecureHelper::strcpyW_x(m_lpstrThemeClassList, cchLen, lpstrThemeClassList); - - return true; - } - - bool GetThemeClassList(LPWSTR lpstrThemeClassList, int cchListBuffer) const - { - int cchLen = lstrlenW(m_lpstrThemeClassList) + 1; - if(cchListBuffer < cchLen) - return false; - - SecureHelper::strcpyW_x(lpstrThemeClassList, cchListBuffer, m_lpstrThemeClassList); - - return true; - } - - LPCWSTR GetThemeClassList() const - { - return m_lpstrThemeClassList; - } - - DWORD SetThemeExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0) - { - DWORD dwPrevStyle = m_dwExtendedStyle; - if(dwMask == 0) - m_dwExtendedStyle = dwExtendedStyle; - else - m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask); - return dwPrevStyle; - } - - DWORD GetThemeExtendedStyle() const - { - return m_dwExtendedStyle; - } - -// Operations - HTHEME OpenThemeData() - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - ATLASSERT(m_lpstrThemeClassList != NULL); - if(m_lpstrThemeClassList == NULL) - return NULL; - CloseThemeData(); - return TBase::OpenThemeData(pT->m_hWnd, m_lpstrThemeClassList); - } - - HTHEME OpenThemeData(LPCWSTR pszClassList) - { - if(!SetThemeClassList(pszClassList)) - return NULL; - return OpenThemeData(); - } - - HRESULT SetWindowTheme(LPCWSTR pszSubAppName, LPCWSTR pszSubIDList) - { - if(!IsThemingSupported()) - return S_FALSE; - - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - return ::SetWindowTheme(pT->m_hWnd, pszSubAppName, pszSubIDList); - } - - HTHEME GetWindowTheme() const - { - if(!IsThemingSupported()) - return NULL; - - const T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - return ::GetWindowTheme(pT->m_hWnd); - } - - HRESULT EnableThemeDialogTexture(DWORD dwFlags) - { - if(!IsThemingSupported()) - return S_FALSE; - - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - return ::EnableThemeDialogTexture(pT->m_hWnd, dwFlags); - } - - BOOL IsThemeDialogTextureEnabled() const - { - if(!IsThemingSupported()) - return FALSE; - - const T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - return ::IsThemeDialogTextureEnabled(pT->m_hWnd); - } - - HRESULT DrawThemeParentBackground(HDC hDC, const RECT* pRect = NULL) - { - if(!IsThemingSupported()) - return S_FALSE; - - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); -#ifdef _WTL_NEW_UXTHEME - return ::DrawThemeParentBackground(pT->m_hWnd, hDC, pRect); -#else - return ::DrawThemeParentBackground(pT->m_hWnd, hDC, (RECT*)pRect); -#endif - } - -#ifdef _WTL_NEW_UXTHEME - HRESULT SetWindowThemeAttribute(WINDOWTHEMEATTRIBUTETYPE type, PVOID pvAttribute, DWORD cbAttribute) - { - if(!IsThemingSupported()) - return S_FALSE; - - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - return ::SetWindowThemeAttribute(pT->m_hWnd, type, pvAttribute, cbAttribute); - } - - HRESULT SetWindowThemeNonClientAttributes(DWORD dwAttributes, DWORD dwMask) - { - if(!IsThemingSupported()) - return S_FALSE; - - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - WTA_OPTIONS opt = { dwAttributes, dwMask }; - return ::SetWindowThemeAttribute(pT->m_hWnd, WTA_NONCLIENT, (PVOID)&opt, sizeof(opt)); - } - - HRESULT DrawThemeParentBackgroundEx(HDC hDC, DWORD dwFlags, const RECT* lpRect = NULL) - { - if(!IsThemingSupported()) - return S_FALSE; - - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - return ::DrawThemeParentBackgroundEx(pT->m_hWnd, hDC, dwFlags, lpRect); - } -#endif // _WTL_NEW_UXTHEME - -// Message map and handlers - // Note: If you handle any of these messages in your derived class, - // it is better to put CHAIN_MSG_MAP at the start of your message map. - BEGIN_MSG_MAP(CThemeImpl) - MESSAGE_HANDLER(WM_CREATE, OnCreate) - MESSAGE_HANDLER(WM_DESTROY, OnDestroy) - MESSAGE_HANDLER(WM_THEMECHANGED, OnThemeChanged) - MESSAGE_HANDLER(WM_NCPAINT, OnNcPaint) - END_MSG_MAP() - - LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - if(m_lpstrThemeClassList != NULL) - OpenThemeData(); - bHandled = FALSE; - return 1; - } - - LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - CloseThemeData(); - bHandled = FALSE; - return 1; - } - - LRESULT OnThemeChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - CloseThemeData(); - if(m_lpstrThemeClassList != NULL) - OpenThemeData(); - bHandled = FALSE; - return 1; - } - - LRESULT OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - LRESULT lRet = 0; - bHandled = FALSE; - if(IsThemingSupported() && ((pT->GetExStyle() & WS_EX_CLIENTEDGE) != 0)) - { - if((m_dwExtendedStyle & THEME_EX_3DCLIENTEDGE) != 0) - { - lRet = ::DefWindowProc(pT->m_hWnd, uMsg, wParam, lParam); - bHandled = TRUE; - } - else if((m_hTheme != NULL) && ((m_dwExtendedStyle & THEME_EX_THEMECLIENTEDGE) != 0)) - { - HRGN hRgn = (wParam != 1) ? (HRGN)wParam : NULL; - if(pT->DrawThemeClientEdge(hRgn)) - bHandled = TRUE; - } - } - return lRet; - } - -// Drawing helper - bool DrawThemeClientEdge(HRGN hRgnUpdate) - { - T* pT = static_cast(this); - return AtlDrawThemeClientEdge(m_hTheme, pT->m_hWnd, hRgnUpdate, NULL, 0, 0); - } -}; - -/////////////////////////////////////////////////////////////////////////////// -// Buffered Paint and Animation - -#ifdef _WTL_NEW_UXTHEME - -/////////////////////////////////////////////////////////////////////////////// -// CBufferedPaintBase - Buffered Paint support for othe classes - -class CBufferedPaintBase -{ -public: - static int m_nIsBufferedPaintSupported; - - CBufferedPaintBase() - { - if(IsBufferedPaintSupported()) - ATLVERIFY(SUCCEEDED(::BufferedPaintInit())); - } - - ~CBufferedPaintBase() - { - if(IsBufferedPaintSupported()) - ATLVERIFY(SUCCEEDED(::BufferedPaintUnInit())); - } - - static bool IsBufferedPaintSupported() - { - if(m_nIsBufferedPaintSupported == -1) - { - CStaticDataInitCriticalSectionLock lock; - if(FAILED(lock.Lock())) - { - ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CBufferedPaintBase::IsBufferedPaintSupported.\n")); - ATLASSERT(FALSE); - return false; - } - - if(m_nIsBufferedPaintSupported == -1) - m_nIsBufferedPaintSupported = RunTimeHelper::IsVista() ? 1 : 0; - - lock.Unlock(); - } - - ATLASSERT(m_nIsBufferedPaintSupported != -1); - return (m_nIsBufferedPaintSupported == 1); - } -}; - -__declspec(selectany) int CBufferedPaintBase::m_nIsBufferedPaintSupported = -1; - - -/////////////////////////////////////////////////////////////////////////////// -// CBufferedPaint - support for buffered paint functions - -class CBufferedPaint -{ -public: - HPAINTBUFFER m_hPaintBuffer; - - CBufferedPaint() : m_hPaintBuffer(NULL) - { } - - ~CBufferedPaint() - { - ATLVERIFY(SUCCEEDED(End())); - } - - bool IsNull() const - { - return (m_hPaintBuffer == NULL); - } - - HPAINTBUFFER Begin(HDC hdcTarget, const RECT* prcTarget, BP_BUFFERFORMAT dwFormat, BP_PAINTPARAMS* pPaintParams, HDC* phdcPaint) - { - ATLASSERT(m_hPaintBuffer == NULL); - m_hPaintBuffer = ::BeginBufferedPaint(hdcTarget, prcTarget, dwFormat, pPaintParams, phdcPaint); - return m_hPaintBuffer; - } - - HRESULT End(BOOL bUpdate = TRUE) - { - HRESULT hRet = S_FALSE; - if(m_hPaintBuffer != NULL) - { - hRet = ::EndBufferedPaint(m_hPaintBuffer, bUpdate); - m_hPaintBuffer = NULL; - } - return hRet; - } - - HRESULT GetTargetRect(LPRECT pRect) const - { - ATLASSERT(m_hPaintBuffer != NULL); - return ::GetBufferedPaintTargetRect(m_hPaintBuffer, pRect); - } - - HDC GetTargetDC() const - { - ATLASSERT(m_hPaintBuffer != NULL); - return ::GetBufferedPaintTargetDC(m_hPaintBuffer); - } - - HDC GetPaintDC() const - { - ATLASSERT(m_hPaintBuffer != NULL); - return ::GetBufferedPaintDC(m_hPaintBuffer); - } - - HRESULT GetBits(RGBQUAD** ppbBuffer, int* pcxRow) const - { - ATLASSERT(m_hPaintBuffer != NULL); - return ::GetBufferedPaintBits(m_hPaintBuffer, ppbBuffer, pcxRow); - } - - HRESULT Clear(const RECT* pRect = NULL) - { - ATLASSERT(m_hPaintBuffer != NULL); - return ::BufferedPaintClear(m_hPaintBuffer, pRect); - } - - HRESULT SetAlpha(BYTE alpha, const RECT* pRect = NULL) - { - ATLASSERT(m_hPaintBuffer != NULL); - return ::BufferedPaintSetAlpha(m_hPaintBuffer, pRect, alpha); - } - - HRESULT MakeOpaque(const RECT* pRect = NULL) - { - ATLASSERT(m_hPaintBuffer != NULL); - return ::BufferedPaintSetAlpha(m_hPaintBuffer, pRect, 255); - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CBufferedPaintImpl - provides buffered paint for any window - -template -class ATL_NO_VTABLE CBufferedPaintImpl : public CBufferedPaintBase -{ -public: - CBufferedPaint m_BufferedPaint; - BP_BUFFERFORMAT m_dwFormat; - BP_PAINTPARAMS m_PaintParams; - - CBufferedPaintImpl() : m_dwFormat(BPBF_TOPDOWNDIB) - { - memset(&m_PaintParams, 0, sizeof(BP_PAINTPARAMS)); - m_PaintParams.cbSize = sizeof(BP_PAINTPARAMS); - } - -// Message map and handlers - BEGIN_MSG_MAP(CBufferedPaintImpl) - MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) - MESSAGE_HANDLER(WM_PAINT, OnPaint) - MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) - END_MSG_MAP() - - LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - return 1; // no background needed - } - - LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - if(wParam != NULL) - { - RECT rect = { 0 }; - pT->GetClientRect(&rect); - pT->DoPaint((HDC)wParam, rect); - } - else - { - CPaintDC dc(pT->m_hWnd); - pT->DoBufferedPaint(dc.m_hDC, dc.m_ps.rcPaint); - } - - return 0; - } - -// Overrideables - void DoBufferedPaint(CDCHandle dc, RECT& rect) - { - HDC hDCPaint = NULL; - if(IsBufferedPaintSupported()) - m_BufferedPaint.Begin(dc, &rect, m_dwFormat, &m_PaintParams, &hDCPaint); - - T* pT = static_cast(this); - if(hDCPaint != NULL) - pT->DoPaint(hDCPaint, rect); - else - pT->DoPaint(dc.m_hDC, rect); - - if(IsBufferedPaintSupported()) - m_BufferedPaint.End(); - } - - void DoPaint(CDCHandle /*dc*/, RECT& /*rect*/) - { - // must be implemented in a derived class - ATLASSERT(FALSE); - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CBufferedPaintWindowImpl - implements a window that uses buffered paint - -template -class ATL_NO_VTABLE CBufferedPaintWindowImpl : - public ATL::CWindowImpl, - public CBufferedPaintImpl< T > -{ -public: - BEGIN_MSG_MAP(CBufferedPaintWindowImpl) - CHAIN_MSG_MAP(CBufferedPaintImpl< T >) - END_MSG_MAP() -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CBufferedAnimation - support for buffered animation - -class CBufferedAnimation -{ -public: - HANIMATIONBUFFER m_hAnimationBuffer; - - CBufferedAnimation() : m_hAnimationBuffer(NULL) - { } - - ~CBufferedAnimation() - { - ATLVERIFY(SUCCEEDED(End())); - } - - bool IsNull() const - { - return (m_hAnimationBuffer == NULL); - } - - HANIMATIONBUFFER Begin(HWND hWnd, HDC hDCTarget, const RECT* pRectTarget, BP_BUFFERFORMAT dwFormat, BP_PAINTPARAMS* pPaintParams, BP_ANIMATIONPARAMS* pAnimationParams, HDC* phdcFrom, HDC* phdcTo) - { - ATLASSERT(m_hAnimationBuffer == NULL); - m_hAnimationBuffer = ::BeginBufferedAnimation(hWnd, hDCTarget, pRectTarget, dwFormat, pPaintParams, pAnimationParams, phdcFrom, phdcTo); - return m_hAnimationBuffer; - } - - HRESULT End(BOOL bUpdate = TRUE) - { - HRESULT hRet = S_FALSE; - if(m_hAnimationBuffer != NULL) - { - hRet = ::EndBufferedAnimation(m_hAnimationBuffer, bUpdate); - m_hAnimationBuffer = NULL; - } - return hRet; - } - - static bool IsRendering(HWND hWnd, HDC hDC) - { - return (::BufferedPaintRenderAnimation(hWnd, hDC) != FALSE); - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CBufferedAnimationImpl - provides buffered animation support for any window - -// Note: You can either use m_State and m_NewState to store the state information -// for the animation change, or map your state to those data members. DoPaint() -// should only rely on the state information that is passed to it. - -template -class ATL_NO_VTABLE CBufferedAnimationImpl : public CBufferedPaintBase -{ -public: - BP_BUFFERFORMAT m_dwFormat; - BP_PAINTPARAMS m_PaintParams; - BP_ANIMATIONPARAMS m_AnimationParams; - - TState m_State; - TState m_NewState; - - CBufferedAnimationImpl(TState InitialState) : m_dwFormat(BPBF_TOPDOWNDIB) - { - memset(&m_PaintParams, 0, sizeof(BP_PAINTPARAMS)); - m_PaintParams.cbSize = sizeof(BP_PAINTPARAMS); - - memset(&m_AnimationParams, 0, sizeof(BP_ANIMATIONPARAMS)); - m_AnimationParams.cbSize = sizeof(BP_ANIMATIONPARAMS); - m_AnimationParams.style = BPAS_LINEAR; - m_AnimationParams.dwDuration = 500; - - T* pT = static_cast(this); - pT->SetState(InitialState); - pT->SetNewState(InitialState); - } - - DWORD GetDuration() const - { - return m_AnimationParams.dwDuration; - } - - void SetDuration(DWORD dwDuration) - { - m_AnimationParams.dwDuration = dwDuration; - } - - void DoAnimation(TState NewState, const RECT* pRect = NULL) - { - T* pT = static_cast(this); - pT->SetNewState(NewState); - - pT->InvalidateRect(pRect, FALSE); - pT->UpdateWindow(); - - pT->SetState(NewState); - } - -// Message map and handlers - BEGIN_MSG_MAP(CBufferedAnimationImpl) - MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) - MESSAGE_HANDLER(WM_PAINT, OnPaint) - MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) - END_MSG_MAP() - - LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - return 1; // no background needed - } - - LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - if(wParam != NULL) - { - RECT rect = { 0 }; - pT->GetClientRect(&rect); - pT->DoPaint((HDC)wParam, rect, m_NewState); - } - else - { - CPaintDC dc(pT->m_hWnd); - pT->DoAnimationPaint(dc.m_hDC, dc.m_ps.rcPaint); - } - - return 0; - } - -// Overrideables - void SetState(TState State) - { - m_State = State; - } - - void SetNewState(TState State) - { - m_NewState = State; - } - - bool AreStatesEqual() const - { - return (m_State == m_NewState); - } - - void DoAnimationPaint(CDCHandle dc, RECT& rect) - { - T* pT = static_cast(this); - if(IsBufferedPaintSupported() && CBufferedAnimation::IsRendering(pT->m_hWnd, dc)) - return; - - DWORD dwDurationSave = m_AnimationParams.dwDuration; - if(pT->AreStatesEqual()) - m_AnimationParams.dwDuration = 0; - - HDC hdcFrom = NULL, hdcTo = NULL; - CBufferedAnimation ba; - if(IsBufferedPaintSupported()) - ba.Begin(pT->m_hWnd, dc, &rect, m_dwFormat, &m_PaintParams, &m_AnimationParams, &hdcFrom, &hdcTo); - - if(!ba.IsNull()) - { - if(hdcFrom != NULL) - pT->DoPaint(hdcFrom, rect, m_State); - - if (hdcTo != NULL) - pT->DoPaint(hdcTo, rect, m_NewState); - } - else - { - pT->DoPaint(dc.m_hDC, rect, m_NewState); - } - - m_AnimationParams.dwDuration = dwDurationSave; - } - - void DoPaint(CDCHandle /*dc*/, RECT& /*rect*/, TState /*State*/) - { - // must be implemented in a derived class - ATLASSERT(FALSE); - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CBufferedAnimationWindowImpl - implements a window that uses buffered animation - -template -class ATL_NO_VTABLE CBufferedAnimationWindowImpl : - public ATL::CWindowImpl, - public CBufferedAnimationImpl< T, TState > -{ -public: - CBufferedAnimationWindowImpl(TState InitialState) : CBufferedAnimationImpl< T, TState >(InitialState) - { } - - typedef CBufferedAnimationImpl< T, TState > _baseBufferedAnimation; - BEGIN_MSG_MAP(CBufferedAnimationWindowImpl) - CHAIN_MSG_MAP(_baseBufferedAnimation) - END_MSG_MAP() -}; - -#endif // _WTL_NEW_UXTHEME - -}; // namespace WTL - -#endif // __ATLTHEME_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/atluser.h b/prog/3rdPartyLibs/wtl-8.1/include/atluser.h deleted file mode 100644 index a056c9b0b..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/atluser.h +++ /dev/null @@ -1,1193 +0,0 @@ -// Windows Template Library - WTL version 8.1 -// Copyright (C) Microsoft Corporation. All rights reserved. -// -// This file is a part of the Windows Template Library. -// The use and distribution terms for this software are covered by the -// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php) -// which can be found in the file CPL.TXT at the root of this distribution. -// By using this software in any fashion, you are agreeing to be bound by -// the terms of this license. You must not remove this notice, or -// any other, from this software. - -#ifndef __ATLUSER_H__ -#define __ATLUSER_H__ - -#pragma once - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#ifndef __ATLAPP_H__ - #error atluser.h requires atlapp.h to be included first -#endif - - -/////////////////////////////////////////////////////////////////////////////// -// Classes in this file: -// -// CMenuItemInfo -// CMenuT -// CAcceleratorT -// CIconT -// CCursorT -// CResource -// -// Global functions: -// AtlMessageBox() - - -namespace WTL -{ - -/////////////////////////////////////////////////////////////////////////////// -// AtlMessageBox - accepts both memory and resource based strings - -inline int AtlMessageBox(HWND hWndOwner, ATL::_U_STRINGorID message, ATL::_U_STRINGorID title = (LPCTSTR)NULL, UINT uType = MB_OK | MB_ICONINFORMATION) -{ - ATLASSERT(hWndOwner == NULL || ::IsWindow(hWndOwner)); - - LPTSTR lpstrMessage = NULL; - if(IS_INTRESOURCE(message.m_lpstr)) - { - for(int nLen = 256; ; nLen *= 2) - { - ATLTRY(lpstrMessage = new TCHAR[nLen]); - if(lpstrMessage == NULL) - { - ATLASSERT(FALSE); - return 0; - } - int nRes = ::LoadString(ModuleHelper::GetResourceInstance(), LOWORD(message.m_lpstr), lpstrMessage, nLen); - if(nRes < nLen - 1) - break; - delete [] lpstrMessage; - lpstrMessage = NULL; - } - - message.m_lpstr = lpstrMessage; - } - - LPTSTR lpstrTitle = NULL; - if(IS_INTRESOURCE(title.m_lpstr) && LOWORD(title.m_lpstr) != 0) - { - for(int nLen = 256; ; nLen *= 2) - { - ATLTRY(lpstrTitle = new TCHAR[nLen]); - if(lpstrTitle == NULL) - { - ATLASSERT(FALSE); - return 0; - } - int nRes = ::LoadString(ModuleHelper::GetResourceInstance(), LOWORD(title.m_lpstr), lpstrTitle, nLen); - if(nRes < nLen - 1) - break; - delete [] lpstrTitle; - lpstrTitle = NULL; - } - - title.m_lpstr = lpstrTitle; - } - - int nRet = ::MessageBox(hWndOwner, message.m_lpstr, title.m_lpstr, uType); - - delete [] lpstrMessage; - delete [] lpstrTitle; - - return nRet; -} - - -/////////////////////////////////////////////////////////////////////////////// -// CMenu - -#if (WINVER >= 0x0500) - #ifndef MII_SIZEOF_STRUCT - #define MII_SIZEOF_STRUCT(structname, member) (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member)) - #endif - #define MENUITEMINFO_SIZE_VERSION_400A MII_SIZEOF_STRUCT(MENUITEMINFOA, cch) - #define MENUITEMINFO_SIZE_VERSION_400W MII_SIZEOF_STRUCT(MENUITEMINFOW, cch) - #ifdef UNICODE - #define MENUITEMINFO_SIZE_VERSION_400 MENUITEMINFO_SIZE_VERSION_400W - #else - #define MENUITEMINFO_SIZE_VERSION_400 MENUITEMINFO_SIZE_VERSION_400A - #endif // !UNICODE -#endif // (WINVER >= 0x0500) - -class CMenuItemInfo : public MENUITEMINFO -{ -public: - CMenuItemInfo() - { - memset(this, 0, sizeof(MENUITEMINFO)); - cbSize = sizeof(MENUITEMINFO); -#if (WINVER >= 0x0500) - // adjust struct size if running on older version of Windows - if(AtlIsOldWindows()) - { - ATLASSERT(cbSize > MENUITEMINFO_SIZE_VERSION_400); // must be - cbSize = MENUITEMINFO_SIZE_VERSION_400; - } -#endif // (WINVER >= 0x0500) - } -}; - - -// forward declarations -template class CMenuT; -typedef CMenuT CMenuHandle; -typedef CMenuT CMenu; - - -template -class CMenuT -{ -public: -// Data members - HMENU m_hMenu; - -// Constructor/destructor/operators - CMenuT(HMENU hMenu = NULL) : m_hMenu(hMenu) - { } - - ~CMenuT() - { - if(t_bManaged && m_hMenu != NULL) - DestroyMenu(); - } - - CMenuT& operator =(HMENU hMenu) - { - Attach(hMenu); - return *this; - } - - void Attach(HMENU hMenuNew) - { - ATLASSERT(::IsMenu(hMenuNew)); - if(t_bManaged && m_hMenu != NULL && m_hMenu != hMenuNew) - ::DestroyMenu(m_hMenu); - m_hMenu = hMenuNew; - } - - HMENU Detach() - { - HMENU hMenu = m_hMenu; - m_hMenu = NULL; - return hMenu; - } - - operator HMENU() const { return m_hMenu; } - - bool IsNull() const { return (m_hMenu == NULL); } - - BOOL IsMenu() const - { - return ::IsMenu(m_hMenu); - } - -// Create/destroy methods - BOOL CreateMenu() - { - ATLASSERT(m_hMenu == NULL); - m_hMenu = ::CreateMenu(); - return (m_hMenu != NULL) ? TRUE : FALSE; - } - - BOOL CreatePopupMenu() - { - ATLASSERT(m_hMenu == NULL); - m_hMenu = ::CreatePopupMenu(); - return (m_hMenu != NULL) ? TRUE : FALSE; - } - - BOOL LoadMenu(ATL::_U_STRINGorID menu) - { - ATLASSERT(m_hMenu == NULL); - m_hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), menu.m_lpstr); - return (m_hMenu != NULL) ? TRUE : FALSE; - } - -#ifndef _WIN32_WCE - BOOL LoadMenuIndirect(const void* lpMenuTemplate) - { - ATLASSERT(m_hMenu == NULL); - m_hMenu = ::LoadMenuIndirect(lpMenuTemplate); - return (m_hMenu != NULL) ? TRUE : FALSE; - } -#endif // !_WIN32_WCE - - BOOL DestroyMenu() - { - if (m_hMenu == NULL) - return FALSE; - BOOL bRet = ::DestroyMenu(m_hMenu); - if(bRet) - m_hMenu = NULL; - return bRet; - } - -// Menu Operations - BOOL DeleteMenu(UINT nPosition, UINT nFlags) - { - ATLASSERT(::IsMenu(m_hMenu)); - return ::DeleteMenu(m_hMenu, nPosition, nFlags); - } - - BOOL TrackPopupMenu(UINT nFlags, int x, int y, HWND hWnd, LPCRECT lpRect = NULL) - { - ATLASSERT(::IsMenu(m_hMenu)); -#ifndef _WIN32_WCE -#if (WINVER >= 0x0500) - x = _FixTrackMenuPopupX(x, y); -#endif // !(WINVER >= 0x0500) - return ::TrackPopupMenu(m_hMenu, nFlags, x, y, 0, hWnd, lpRect); -#else // CE specific - lpRect; - return ::TrackPopupMenuEx(m_hMenu, nFlags, x, y, hWnd, NULL); -#endif // _WIN32_WCE - } - - BOOL TrackPopupMenuEx(UINT uFlags, int x, int y, HWND hWnd, LPTPMPARAMS lptpm = NULL) - { - ATLASSERT(::IsMenu(m_hMenu)); -#if (WINVER >= 0x0500) && !defined(_WIN32_WCE) - x = _FixTrackMenuPopupX(x, y); -#endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE) - return ::TrackPopupMenuEx(m_hMenu, uFlags, x, y, hWnd, lptpm); - } - -#if (WINVER >= 0x0500) && !defined(_WIN32_WCE) - // helper that fixes popup menu X position when it's off-screen - static int _FixTrackMenuPopupX(int x, int y) - { - POINT pt = { x, y }; - HMONITOR hMonitor = ::MonitorFromPoint(pt, MONITOR_DEFAULTTONULL); - if(hMonitor == NULL) - { - HMONITOR hMonitorNear = ::MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST); - if(hMonitorNear != NULL) - { - MONITORINFO mi = { 0 }; - mi.cbSize = sizeof(MONITORINFO); - if(::GetMonitorInfo(hMonitorNear, &mi) != FALSE) - { - if(x < mi.rcWork.left) - x = mi.rcWork.left; - else if(x > mi.rcWork.right) - x = mi.rcWork.right; - } - } - } - - return x; - } - - BOOL GetMenuInfo(LPMENUINFO lpMenuInfo) const - { - ATLASSERT(::IsMenu(m_hMenu)); - return ::GetMenuInfo(m_hMenu, lpMenuInfo); - } - - BOOL SetMenuInfo(LPCMENUINFO lpMenuInfo) - { - ATLASSERT(::IsMenu(m_hMenu)); - return ::SetMenuInfo(m_hMenu, lpMenuInfo); - } -#endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE) - -// Menu Item Operations - BOOL AppendMenu(UINT nFlags, UINT_PTR nIDNewItem = 0, LPCTSTR lpszNewItem = NULL) - { - ATLASSERT(::IsMenu(m_hMenu)); - return ::AppendMenu(m_hMenu, nFlags, nIDNewItem, lpszNewItem); - } - - BOOL AppendMenu(UINT nFlags, HMENU hSubMenu, LPCTSTR lpszNewItem) - { - ATLASSERT(::IsMenu(m_hMenu)); - ATLASSERT(::IsMenu(hSubMenu)); - return ::AppendMenu(m_hMenu, nFlags | MF_POPUP, (UINT_PTR)hSubMenu, lpszNewItem); - } - -#ifndef _WIN32_WCE - BOOL AppendMenu(UINT nFlags, UINT_PTR nIDNewItem, HBITMAP hBmp) - { - ATLASSERT(::IsMenu(m_hMenu)); - return ::AppendMenu(m_hMenu, nFlags | MF_BITMAP, nIDNewItem, (LPCTSTR)hBmp); - } - - BOOL AppendMenu(UINT nFlags, HMENU hSubMenu, HBITMAP hBmp) - { - ATLASSERT(::IsMenu(m_hMenu)); - ATLASSERT(::IsMenu(hSubMenu)); - return ::AppendMenu(m_hMenu, nFlags | (MF_BITMAP | MF_POPUP), (UINT_PTR)hSubMenu, (LPCTSTR)hBmp); - } -#endif // !_WIN32_WCE - - UINT CheckMenuItem(UINT nIDCheckItem, UINT nCheck) - { - ATLASSERT(::IsMenu(m_hMenu)); - return (UINT)::CheckMenuItem(m_hMenu, nIDCheckItem, nCheck); - } - - UINT EnableMenuItem(UINT nIDEnableItem, UINT nEnable) - { - ATLASSERT(::IsMenu(m_hMenu)); - return ::EnableMenuItem(m_hMenu, nIDEnableItem, nEnable); - } - -#ifndef _WIN32_WCE - BOOL HiliteMenuItem(HWND hWnd, UINT uIDHiliteItem, UINT uHilite) - { - ATLASSERT(::IsMenu(m_hMenu)); - return ::HiliteMenuItem(hWnd, m_hMenu, uIDHiliteItem, uHilite); - } - - int GetMenuItemCount() const - { - ATLASSERT(::IsMenu(m_hMenu)); - return ::GetMenuItemCount(m_hMenu); - } - - UINT GetMenuItemID(int nPos) const - { - ATLASSERT(::IsMenu(m_hMenu)); - return ::GetMenuItemID(m_hMenu, nPos); - } - - UINT GetMenuState(UINT nID, UINT nFlags) const - { - ATLASSERT(::IsMenu(m_hMenu)); - return ::GetMenuState(m_hMenu, nID, nFlags); - } - - int GetMenuString(UINT nIDItem, LPTSTR lpString, int nMaxCount, UINT nFlags) const - { - ATLASSERT(::IsMenu(m_hMenu)); - return ::GetMenuString(m_hMenu, nIDItem, lpString, nMaxCount, nFlags); - } - - int GetMenuStringLen(UINT nIDItem, UINT nFlags) const - { - ATLASSERT(::IsMenu(m_hMenu)); - return ::GetMenuString(m_hMenu, nIDItem, NULL, 0, nFlags); - } - -#ifndef _ATL_NO_COM - BOOL GetMenuString(UINT nIDItem, BSTR& bstrText, UINT nFlags) const - { - USES_CONVERSION; - ATLASSERT(::IsMenu(m_hMenu)); - ATLASSERT(bstrText == NULL); - - int nLen = GetMenuStringLen(nIDItem, nFlags); - if(nLen == 0) - { - bstrText = ::SysAllocString(OLESTR("")); - return (bstrText != NULL) ? TRUE : FALSE; - } - - nLen++; // increment to include terminating NULL char - CTempBuffer buff; - LPTSTR lpszText = buff.Allocate(nLen); - if(lpszText == NULL) - return FALSE; - - if(!GetMenuString(nIDItem, lpszText, nLen, nFlags)) - return FALSE; - - bstrText = ::SysAllocString(T2OLE(lpszText)); - return (bstrText != NULL) ? TRUE : FALSE; - } -#endif // !_ATL_NO_COM - -#elif _ATL_VER >= 0x800 - int GetMenuItemCount() const - { - ATLASSERT(::IsMenu(m_hMenu)); - return ATL::GetMenuItemCount(m_hMenu); - } - - UINT GetMenuItemID(int nPos) const - { - ATLASSERT(::IsMenu(m_hMenu)); - return ATL::GetMenuItemID(m_hMenu, nPos); - } - - UINT GetMenuState(UINT nID, UINT nFlags) const - { - ATLASSERT(::IsMenu(m_hMenu)); - return ATL::GetMenuState(m_hMenu, nID, nFlags); - } - - int GetMenuString(UINT nIDItem, LPTSTR lpString, int nMaxCount, UINT nFlags) const - { - ATLASSERT(::IsMenu(m_hMenu)); - return ATL::GetMenuString(m_hMenu, nIDItem, lpString, nMaxCount, nFlags); - } - - int GetMenuStringLen(UINT nIDItem, UINT nFlags) const - { - ATLASSERT(::IsMenu(m_hMenu)); - return ATL::GetMenuString(m_hMenu, nIDItem, NULL, 0, nFlags); - } -#endif // _ATL_VER >= 0x800 - -#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - int GetMenuString(UINT nIDItem, _CSTRING_NS::CString& strText, UINT nFlags) const - { - ATLASSERT(::IsMenu(m_hMenu)); - - int nLen = GetMenuStringLen(nIDItem, nFlags); - if(nLen == 0) - return 0; - - nLen++; // increment to include terminating NULL char - LPTSTR lpstr = strText.GetBufferSetLength(nLen); - if(lpstr == NULL) - return 0; - int nRet = GetMenuString(nIDItem, lpstr, nLen, nFlags); - strText.ReleaseBuffer(); - return nRet; - } -#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - - CMenuHandle GetSubMenu(int nPos) const - { - ATLASSERT(::IsMenu(m_hMenu)); - return CMenuHandle(::GetSubMenu(m_hMenu, nPos)); - } - - BOOL InsertMenu(UINT nPosition, UINT nFlags, UINT_PTR nIDNewItem = 0, LPCTSTR lpszNewItem = NULL) - { - ATLASSERT(::IsMenu(m_hMenu)); - return ::InsertMenu(m_hMenu, nPosition, nFlags, nIDNewItem, lpszNewItem); - } - - BOOL InsertMenu(UINT nPosition, UINT nFlags, HMENU hSubMenu, LPCTSTR lpszNewItem) - { - ATLASSERT(::IsMenu(m_hMenu)); - ATLASSERT(::IsMenu(hSubMenu)); - return ::InsertMenu(m_hMenu, nPosition, nFlags | MF_POPUP, (UINT_PTR)hSubMenu, lpszNewItem); - } - -#ifndef _WIN32_WCE - BOOL InsertMenu(UINT nPosition, UINT nFlags, UINT_PTR nIDNewItem, HBITMAP hBmp) - { - ATLASSERT(::IsMenu(m_hMenu)); - return ::InsertMenu(m_hMenu, nPosition, nFlags | MF_BITMAP, nIDNewItem, (LPCTSTR)hBmp); - } - - BOOL InsertMenu(UINT nPosition, UINT nFlags, HMENU hSubMenu, HBITMAP hBmp) - { - ATLASSERT(::IsMenu(m_hMenu)); - ATLASSERT(::IsMenu(hSubMenu)); - return ::InsertMenu(m_hMenu, nPosition, nFlags | (MF_BITMAP | MF_POPUP), (UINT_PTR)hSubMenu, (LPCTSTR)hBmp); - } - - BOOL ModifyMenu(UINT nPosition, UINT nFlags, UINT_PTR nIDNewItem = 0, LPCTSTR lpszNewItem = NULL) - { - ATLASSERT(::IsMenu(m_hMenu)); - return ::ModifyMenu(m_hMenu, nPosition, nFlags, nIDNewItem, lpszNewItem); - } - - BOOL ModifyMenu(UINT nPosition, UINT nFlags, HMENU hSubMenu, LPCTSTR lpszNewItem) - { - ATLASSERT(::IsMenu(m_hMenu)); - ATLASSERT(::IsMenu(hSubMenu)); - return ::ModifyMenu(m_hMenu, nPosition, nFlags | MF_POPUP, (UINT_PTR)hSubMenu, lpszNewItem); - } - - BOOL ModifyMenu(UINT nPosition, UINT nFlags, UINT_PTR nIDNewItem, HBITMAP hBmp) - { - ATLASSERT(::IsMenu(m_hMenu)); - return ::ModifyMenu(m_hMenu, nPosition, nFlags | MF_BITMAP, nIDNewItem, (LPCTSTR)hBmp); - } - - BOOL ModifyMenu(UINT nPosition, UINT nFlags, HMENU hSubMenu, HBITMAP hBmp) - { - ATLASSERT(::IsMenu(m_hMenu)); - ATLASSERT(::IsMenu(hSubMenu)); - return ::ModifyMenu(m_hMenu, nPosition, nFlags | (MF_BITMAP | MF_POPUP), (UINT_PTR)hSubMenu, (LPCTSTR)hBmp); - } -#endif // !_WIN32_WCE - - BOOL RemoveMenu(UINT nPosition, UINT nFlags) - { - ATLASSERT(::IsMenu(m_hMenu)); - return ::RemoveMenu(m_hMenu, nPosition, nFlags); - } - -#ifndef _WIN32_WCE - BOOL SetMenuItemBitmaps(UINT nPosition, UINT nFlags, HBITMAP hBmpUnchecked, HBITMAP hBmpChecked) - { - ATLASSERT(::IsMenu(m_hMenu)); - return ::SetMenuItemBitmaps(m_hMenu, nPosition, nFlags, hBmpUnchecked, hBmpChecked); - } -#endif // !_WIN32_WCE - - BOOL CheckMenuRadioItem(UINT nIDFirst, UINT nIDLast, UINT nIDItem, UINT nFlags) - { - ATLASSERT(::IsMenu(m_hMenu)); - return ::CheckMenuRadioItem(m_hMenu, nIDFirst, nIDLast, nIDItem, nFlags); - } - - BOOL GetMenuItemInfo(UINT uItem, BOOL bByPosition, LPMENUITEMINFO lpmii) const - { - ATLASSERT(::IsMenu(m_hMenu)); - return (BOOL)::GetMenuItemInfo(m_hMenu, uItem, bByPosition, lpmii); - } - - BOOL SetMenuItemInfo(UINT uItem, BOOL bByPosition, LPMENUITEMINFO lpmii) - { - ATLASSERT(::IsMenu(m_hMenu)); - return (BOOL)::SetMenuItemInfo(m_hMenu, uItem, bByPosition, lpmii); - } - -#ifndef _WIN32_WCE - BOOL InsertMenuItem(UINT uItem, BOOL bByPosition, LPMENUITEMINFO lpmii) - { - ATLASSERT(::IsMenu(m_hMenu)); - return (BOOL)::InsertMenuItem(m_hMenu, uItem, bByPosition, lpmii); - } - - UINT GetMenuDefaultItem(BOOL bByPosition = FALSE, UINT uFlags = 0U) const - { - ATLASSERT(::IsMenu(m_hMenu)); - return ::GetMenuDefaultItem(m_hMenu, (UINT)bByPosition, uFlags); - } - - BOOL SetMenuDefaultItem(UINT uItem = (UINT)-1, BOOL bByPosition = FALSE) - { - ATLASSERT(::IsMenu(m_hMenu)); - return ::SetMenuDefaultItem(m_hMenu, uItem, (UINT)bByPosition); - } - - BOOL GetMenuItemRect(HWND hWnd, UINT uItem, LPRECT lprcItem) const - { - ATLASSERT(::IsMenu(m_hMenu)); - return ::GetMenuItemRect(hWnd, m_hMenu, uItem, lprcItem); - } - - int MenuItemFromPoint(HWND hWnd, POINT point) const - { - ATLASSERT(::IsMenu(m_hMenu)); - return ::MenuItemFromPoint(hWnd, m_hMenu, point); - } - -// Context Help Functions - BOOL SetMenuContextHelpId(DWORD dwContextHelpId) - { - ATLASSERT(::IsMenu(m_hMenu)); - return ::SetMenuContextHelpId(m_hMenu, dwContextHelpId); - } - - DWORD GetMenuContextHelpId() const - { - ATLASSERT(::IsMenu(m_hMenu)); - return ::GetMenuContextHelpId(m_hMenu); - } -#endif // !_WIN32_WCE -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CAccelerator - -template -class CAcceleratorT -{ -public: - HACCEL m_hAccel; - -// Constructor/destructor/operators - CAcceleratorT(HACCEL hAccel = NULL) : m_hAccel(hAccel) - { } - - ~CAcceleratorT() - { - if(t_bManaged && m_hAccel != NULL) - ::DestroyAcceleratorTable(m_hAccel); - } - - CAcceleratorT& operator =(HACCEL hAccel) - { - Attach(hAccel); - return *this; - } - - void Attach(HACCEL hAccel) - { - if(t_bManaged && m_hAccel != NULL) - ::DestroyAcceleratorTable(m_hAccel); - m_hAccel = hAccel; - } - - HACCEL Detach() - { - HACCEL hAccel = m_hAccel; - m_hAccel = NULL; - return hAccel; - } - - operator HACCEL() const { return m_hAccel; } - - bool IsNull() const { return m_hAccel == NULL; } - -// Create/destroy methods - HACCEL LoadAccelerators(ATL::_U_STRINGorID accel) - { - ATLASSERT(m_hAccel == NULL); - m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceInstance(), accel.m_lpstr); - return m_hAccel; - } - - HACCEL CreateAcceleratorTable(LPACCEL pAccel, int cEntries) - { - ATLASSERT(m_hAccel == NULL); - ATLASSERT(pAccel != NULL); - m_hAccel = ::CreateAcceleratorTable(pAccel, cEntries); - return m_hAccel; - } - - void DestroyObject() - { - if(m_hAccel != NULL) - { - ::DestroyAcceleratorTable(m_hAccel); - m_hAccel = NULL; - } - } - -// Operations -#ifndef _WIN32_WCE - int CopyAcceleratorTable(LPACCEL lpAccelDst, int cEntries) - { - ATLASSERT(m_hAccel != NULL); - ATLASSERT(lpAccelDst != NULL); - return ::CopyAcceleratorTable(m_hAccel, lpAccelDst, cEntries); - } - - int GetEntriesCount() const - { - ATLASSERT(m_hAccel != NULL); - return ::CopyAcceleratorTable(m_hAccel, NULL, 0); - } -#endif // !_WIN32_WCE - - BOOL TranslateAccelerator(HWND hWnd, LPMSG pMsg) - { - ATLASSERT(m_hAccel != NULL); - ATLASSERT(::IsWindow(hWnd)); - ATLASSERT(pMsg != NULL); - return ::TranslateAccelerator(hWnd, m_hAccel, pMsg); - } -}; - -typedef CAcceleratorT CAcceleratorHandle; -typedef CAcceleratorT CAccelerator; - - -/////////////////////////////////////////////////////////////////////////////// -// CIcon - -template -class CIconT -{ -public: - HICON m_hIcon; - -// Constructor/destructor/operators - CIconT(HICON hIcon = NULL) : m_hIcon(hIcon) - { } - - ~CIconT() - { - if(t_bManaged && m_hIcon != NULL) - ::DestroyIcon(m_hIcon); - } - - CIconT& operator =(HICON hIcon) - { - Attach(hIcon); - return *this; - } - - void Attach(HICON hIcon) - { - if(t_bManaged && m_hIcon != NULL) - ::DestroyIcon(m_hIcon); - m_hIcon = hIcon; - } - - HICON Detach() - { - HICON hIcon = m_hIcon; - m_hIcon = NULL; - return hIcon; - } - - operator HICON() const { return m_hIcon; } - - bool IsNull() const { return m_hIcon == NULL; } - -// Create/destroy methods - HICON LoadIcon(ATL::_U_STRINGorID icon) - { - ATLASSERT(m_hIcon == NULL); - m_hIcon = ::LoadIcon(ModuleHelper::GetResourceInstance(), icon.m_lpstr); - return m_hIcon; - } - - HICON LoadIcon(ATL::_U_STRINGorID icon, int cxDesired, int cyDesired, UINT fuLoad = 0) - { - ATLASSERT(m_hIcon == NULL); - m_hIcon = (HICON) ::LoadImage(ModuleHelper::GetResourceInstance(), icon.m_lpstr, IMAGE_ICON, cxDesired, cyDesired, fuLoad); - return m_hIcon; - } - -#ifndef _WIN32_WCE - HICON LoadOEMIcon(LPCTSTR lpstrIconName) - { - ATLASSERT(m_hIcon == NULL); - ATLASSERT(IsOEMIcon(lpstrIconName)); - m_hIcon = ::LoadIcon(NULL, lpstrIconName); - return m_hIcon; - } - - HICON CreateIcon(int nWidth, int nHeight, BYTE cPlanes, BYTE cBitsPixel, CONST BYTE* lpbANDbits, CONST BYTE *lpbXORbits) - { - ATLASSERT(m_hIcon == NULL); - ATLASSERT(lpbANDbits != NULL); - ATLASSERT(lpbXORbits != NULL); - m_hIcon = ::CreateIcon(ModuleHelper::GetResourceInstance(), nWidth, nHeight, cPlanes, cBitsPixel, lpbANDbits, lpbXORbits); - return m_hIcon; - } - - HICON CreateIconFromResource(PBYTE pBits, DWORD dwResSize, DWORD dwVersion = 0x00030000) - { - ATLASSERT(m_hIcon == NULL); - ATLASSERT(pBits != NULL); - m_hIcon = ::CreateIconFromResource(pBits, dwResSize, TRUE, dwVersion); - return m_hIcon; - } - - HICON CreateIconFromResourceEx(PBYTE pbBits, DWORD cbBits, DWORD dwVersion = 0x00030000, int cxDesired = 0, int cyDesired = 0, UINT uFlags = LR_DEFAULTCOLOR) - { - ATLASSERT(m_hIcon == NULL); - ATLASSERT(pbBits != NULL); - ATLASSERT(cbBits > 0); - m_hIcon = ::CreateIconFromResourceEx(pbBits, cbBits, TRUE, dwVersion, cxDesired, cyDesired, uFlags); - return m_hIcon; - } -#endif // !_WIN32_WCE - - HICON CreateIconIndirect(PICONINFO pIconInfo) - { - ATLASSERT(m_hIcon == NULL); - ATLASSERT(pIconInfo != NULL); - m_hIcon = ::CreateIconIndirect(pIconInfo); - return m_hIcon; - } - -#ifndef _WIN32_WCE - HICON ExtractIcon(LPCTSTR lpszExeFileName, UINT nIconIndex) - { - ATLASSERT(m_hIcon == NULL); - ATLASSERT(lpszExeFileName != NULL); - m_hIcon = ::ExtractIcon(ModuleHelper::GetModuleInstance(), lpszExeFileName, nIconIndex); - return m_hIcon; - } - - HICON ExtractAssociatedIcon(HINSTANCE hInst, LPTSTR lpIconPath, LPWORD lpiIcon) - { - ATLASSERT(m_hIcon == NULL); - ATLASSERT(lpIconPath != NULL); - ATLASSERT(lpiIcon != NULL); - m_hIcon = ::ExtractAssociatedIcon(hInst, lpIconPath, lpiIcon); - return m_hIcon; - } -#endif // !_WIN32_WCE - - BOOL DestroyIcon() - { - ATLASSERT(m_hIcon != NULL); - BOOL bRet = ::DestroyIcon(m_hIcon); - if(bRet != FALSE) - m_hIcon = NULL; - return bRet; - } - -// Operations -#ifndef _WIN32_WCE - HICON CopyIcon() - { - ATLASSERT(m_hIcon != NULL); - return ::CopyIcon(m_hIcon); - } - - HICON DuplicateIcon() - { - ATLASSERT(m_hIcon != NULL); - return ::DuplicateIcon(NULL, m_hIcon); - } -#endif // !_WIN32_WCE - - BOOL DrawIcon(HDC hDC, int x, int y) - { - ATLASSERT(m_hIcon != NULL); -#ifndef _WIN32_WCE - return ::DrawIcon(hDC, x, y, m_hIcon); -#else // CE specific - return ::DrawIconEx(hDC, x, y, m_hIcon, 0, 0, 0, NULL, DI_NORMAL); -#endif // _WIN32_WCE - } - - BOOL DrawIcon(HDC hDC, POINT pt) - { - ATLASSERT(m_hIcon != NULL); -#ifndef _WIN32_WCE - return ::DrawIcon(hDC, pt.x, pt.y, m_hIcon); -#else // CE specific - return ::DrawIconEx(hDC, pt.x, pt.y, m_hIcon, 0, 0, 0, NULL, DI_NORMAL); -#endif // _WIN32_WCE - } - - BOOL DrawIconEx(HDC hDC, int x, int y, int cxWidth, int cyWidth, UINT uStepIfAniCur = 0, HBRUSH hbrFlickerFreeDraw = NULL, UINT uFlags = DI_NORMAL) - { - ATLASSERT(m_hIcon != NULL); - return ::DrawIconEx(hDC, x, y, m_hIcon, cxWidth, cyWidth, uStepIfAniCur, hbrFlickerFreeDraw, uFlags); - } - - BOOL DrawIconEx(HDC hDC, POINT pt, SIZE size, UINT uStepIfAniCur = 0, HBRUSH hbrFlickerFreeDraw = NULL, UINT uFlags = DI_NORMAL) - { - ATLASSERT(m_hIcon != NULL); - return ::DrawIconEx(hDC, pt.x, pt.y, m_hIcon, size.cx, size.cy, uStepIfAniCur, hbrFlickerFreeDraw, uFlags); - } - -#ifndef _WIN32_WCE - BOOL GetIconInfo(PICONINFO pIconInfo) const - { - ATLASSERT(m_hIcon != NULL); - ATLASSERT(pIconInfo != NULL); - return ::GetIconInfo(m_hIcon, pIconInfo); - } - -#if (_WIN32_WINNT >= 0x0600) - BOOL GetIconInfoEx(PICONINFOEX pIconInfo) const - { - ATLASSERT(m_hIcon != NULL); - ATLASSERT(pIconInfo != NULL); - return ::GetIconInfoEx(m_hIcon, pIconInfo); - } -#endif // (_WIN32_WINNT >= 0x0600) - -#if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) - HRESULT LoadIconMetric(ATL::_U_STRINGorID icon, int lims) - { - ATLASSERT(m_hIcon == NULL); - USES_CONVERSION; - return ::LoadIconMetric(ModuleHelper::GetResourceInstance(), T2CW(icon.m_lpstr), lims, &m_hIcon); - } - - HRESULT LoadIconWithScaleDown(ATL::_U_STRINGorID icon, int cx, int cy) - { - ATLASSERT(m_hIcon == NULL); - USES_CONVERSION; - return ::LoadIconWithScaleDown(ModuleHelper::GetResourceInstance(), T2CW(icon.m_lpstr), cx, cy, &m_hIcon); - } - - HRESULT LoadOEMIconMetric(LPCTSTR lpstrIconName, int lims) - { - ATLASSERT(m_hIcon == NULL); - ATLASSERT(IsOEMIcon(lpstrIconName)); - return ::LoadIconMetric(NULL, (LPCWSTR)lpstrIconName, lims, &m_hIcon); - } - - HRESULT LoadOEMIconWithScaleDown(LPCTSTR lpstrIconName, int cx, int cy) - { - ATLASSERT(m_hIcon == NULL); - ATLASSERT(IsOEMIcon(lpstrIconName)); - USES_CONVERSION; - return ::LoadIconWithScaleDown(NULL, (LPCWSTR)lpstrIconName, cx, cy, &m_hIcon); - } -#endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) -#endif // !_WIN32_WCE - - // Helper -#ifndef _WIN32_WCE - static bool IsOEMIcon(LPCTSTR lpstrIconName) - { -#if (WINVER >= 0x0600) - return (lpstrIconName == IDI_APPLICATION || lpstrIconName == IDI_ASTERISK || lpstrIconName == IDI_EXCLAMATION || - lpstrIconName == IDI_HAND || lpstrIconName == IDI_QUESTION || lpstrIconName == IDI_WINLOGO || - lpstrIconName == IDI_SHIELD); -#else // !(WINVER >= 0x0600) - return (lpstrIconName == IDI_APPLICATION || lpstrIconName == IDI_ASTERISK || lpstrIconName == IDI_EXCLAMATION || - lpstrIconName == IDI_HAND || lpstrIconName == IDI_QUESTION || lpstrIconName == IDI_WINLOGO); -#endif // !(WINVER >= 0x0600) - } -#endif // !_WIN32_WCE -}; - -typedef CIconT CIconHandle; -typedef CIconT CIcon; - - -/////////////////////////////////////////////////////////////////////////////// -// CCursor - -// protect template member from a winuser.h macro -#ifdef CopyCursor - #undef CopyCursor -#endif - -template -class CCursorT -{ -public: - HCURSOR m_hCursor; - -// Constructor/destructor/operators - CCursorT(HCURSOR hCursor = NULL) : m_hCursor(hCursor) - { } - - ~CCursorT() - { - if(t_bManaged && m_hCursor != NULL) - DestroyCursor(); - } - - CCursorT& operator =(HCURSOR hCursor) - { - Attach(hCursor); - return *this; - } - - void Attach(HCURSOR hCursor) - { - if(t_bManaged && m_hCursor != NULL) - DestroyCursor(); - m_hCursor = hCursor; - } - - HCURSOR Detach() - { - HCURSOR hCursor = m_hCursor; - m_hCursor = NULL; - return hCursor; - } - - operator HCURSOR() const { return m_hCursor; } - - bool IsNull() const { return m_hCursor == NULL; } - -// Create/destroy methods - HCURSOR LoadCursor(ATL::_U_STRINGorID cursor) - { - ATLASSERT(m_hCursor == NULL); - m_hCursor = ::LoadCursor(ModuleHelper::GetResourceInstance(), cursor.m_lpstr); - return m_hCursor; - } - - HCURSOR LoadSysCursor(LPCTSTR lpstrCursorName) - { - ATLASSERT(m_hCursor == NULL); -#if (WINVER >= 0x0500) - ATLASSERT(lpstrCursorName == IDC_ARROW || lpstrCursorName == IDC_IBEAM || lpstrCursorName == IDC_WAIT || - lpstrCursorName == IDC_CROSS || lpstrCursorName == IDC_UPARROW || lpstrCursorName == IDC_SIZE || - lpstrCursorName == IDC_ICON || lpstrCursorName == IDC_SIZENWSE || lpstrCursorName == IDC_SIZENESW || - lpstrCursorName == IDC_SIZEWE || lpstrCursorName == IDC_SIZENS || lpstrCursorName == IDC_SIZEALL || - lpstrCursorName == IDC_NO || lpstrCursorName == IDC_APPSTARTING || lpstrCursorName == IDC_HELP || - lpstrCursorName == IDC_HAND); -#else // !(WINVER >= 0x0500) - ATLASSERT(lpstrCursorName == IDC_ARROW || lpstrCursorName == IDC_IBEAM || lpstrCursorName == IDC_WAIT || - lpstrCursorName == IDC_CROSS || lpstrCursorName == IDC_UPARROW || lpstrCursorName == IDC_SIZE || - lpstrCursorName == IDC_ICON || lpstrCursorName == IDC_SIZENWSE || lpstrCursorName == IDC_SIZENESW || - lpstrCursorName == IDC_SIZEWE || lpstrCursorName == IDC_SIZENS || lpstrCursorName == IDC_SIZEALL || - lpstrCursorName == IDC_NO || lpstrCursorName == IDC_APPSTARTING || lpstrCursorName == IDC_HELP); -#endif // !(WINVER >= 0x0500) - m_hCursor = ::LoadCursor(NULL, lpstrCursorName); - return m_hCursor; - } - - // deprecated - HCURSOR LoadOEMCursor(LPCTSTR lpstrCursorName) - { - return LoadSysCursor(lpstrCursorName); - } - - HCURSOR LoadCursor(ATL::_U_STRINGorID cursor, int cxDesired, int cyDesired, UINT fuLoad = 0) - { - ATLASSERT(m_hCursor == NULL); - m_hCursor = (HCURSOR) ::LoadImage(ModuleHelper::GetResourceInstance(), cursor.m_lpstr, IMAGE_CURSOR, cxDesired, cyDesired, fuLoad); - return m_hCursor; - } - -#ifndef _WIN32_WCE - HCURSOR LoadCursorFromFile(LPCTSTR pstrFilename) - { - ATLASSERT(m_hCursor == NULL); - ATLASSERT(pstrFilename != NULL); - m_hCursor = ::LoadCursorFromFile(pstrFilename); - return m_hCursor; - } -#endif // !_WIN32_WCE - -#if !defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP))) - HCURSOR CreateCursor(int xHotSpot, int yHotSpot, int nWidth, int nHeight, CONST VOID *pvANDPlane, CONST VOID *pvXORPlane) - { - ATLASSERT(m_hCursor == NULL); - m_hCursor = ::CreateCursor(ModuleHelper::GetResourceInstance(), xHotSpot, yHotSpot, nWidth, nHeight, pvANDPlane, pvXORPlane); - return m_hCursor; - } -#endif // !defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP))) - -#ifndef _WIN32_WCE - HCURSOR CreateCursorFromResource(PBYTE pBits, DWORD dwResSize, DWORD dwVersion = 0x00030000) - { - ATLASSERT(m_hCursor == NULL); - ATLASSERT(pBits != NULL); - m_hCursor = (HCURSOR)::CreateIconFromResource(pBits, dwResSize, FALSE, dwVersion); - return m_hCursor; - } - - HCURSOR CreateCursorFromResourceEx(PBYTE pbBits, DWORD cbBits, DWORD dwVersion = 0x00030000, int cxDesired = 0, int cyDesired = 0, UINT uFlags = LR_DEFAULTCOLOR) - { - ATLASSERT(m_hCursor == NULL); - ATLASSERT(pbBits != NULL); - ATLASSERT(cbBits > 0); - m_hCursor = (HCURSOR)::CreateIconFromResourceEx(pbBits, cbBits, FALSE, dwVersion, cxDesired, cyDesired, uFlags); - return m_hCursor; - } -#endif // !_WIN32_WCE - - BOOL DestroyCursor() - { - ATLASSERT(m_hCursor != NULL); -#if !defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP))) - BOOL bRet = ::DestroyCursor(m_hCursor); - if(bRet != FALSE) - m_hCursor = NULL; - return bRet; -#else // !(!defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP)))) - ATLTRACE2(atlTraceUI, 0, _T("Warning: This version of Windows CE does not have ::DestroyCursor()\n")); - return FALSE; -#endif // !(!defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP)))) - } - -// Operations -#ifndef _WIN32_WCE - HCURSOR CopyCursor() - { - ATLASSERT(m_hCursor != NULL); - return (HCURSOR)::CopyIcon((HICON)m_hCursor); - } -#endif // !_WIN32_WCE - -#if (WINVER >= 0x0500) && !defined(_WIN32_WCE) - BOOL GetCursorInfo(LPCURSORINFO pCursorInfo) - { - ATLASSERT(m_hCursor != NULL); - ATLASSERT(pCursorInfo != NULL); - return ::GetCursorInfo(pCursorInfo); - } -#endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE) -}; - -typedef CCursorT CCursorHandle; -typedef CCursorT CCursor; - - -/////////////////////////////////////////////////////////////////////////////// -// CResource - Wraps a generic Windows resource. -// Use it with custom resource types other than the -// standard RT_CURSOR, RT_BITMAP, etc. - -class CResource -{ -public: - HGLOBAL m_hGlobal; - HRSRC m_hResource; - -// Constructor/destructor - CResource() : m_hGlobal(NULL), m_hResource(NULL) - { } - - ~CResource() - { - Release(); - } - -// Load methods - bool Load(ATL::_U_STRINGorID Type, ATL::_U_STRINGorID ID) - { - ATLASSERT(m_hResource == NULL); - ATLASSERT(m_hGlobal == NULL); - - m_hResource = ::FindResource(ModuleHelper::GetResourceInstance(), ID.m_lpstr, Type.m_lpstr); - if(m_hResource == NULL) - return false; - - m_hGlobal = ::LoadResource(ModuleHelper::GetResourceInstance(), m_hResource); - if(m_hGlobal == NULL) - { - m_hResource = NULL; - return false; - } - - return true; - } - -#ifndef _WIN32_WCE - bool LoadEx(ATL::_U_STRINGorID Type, ATL::_U_STRINGorID ID, WORD wLanguage) - { - ATLASSERT(m_hResource == NULL); - ATLASSERT(m_hGlobal == NULL); - - m_hResource = ::FindResourceEx(ModuleHelper::GetResourceInstance(), ID.m_lpstr, Type.m_lpstr, wLanguage); - if(m_hResource == NULL) - return false; - - m_hGlobal = ::LoadResource(ModuleHelper::GetResourceInstance(), m_hResource); - if(m_hGlobal == NULL) - { - m_hResource = NULL; - return false; - } - - return true; - } -#endif // !_WIN32_WCE - -// Misc. operations - DWORD GetSize() const - { - ATLASSERT(m_hResource != NULL); - return ::SizeofResource(ModuleHelper::GetResourceInstance(), m_hResource); - } - - LPVOID Lock() - { - ATLASSERT(m_hResource != NULL); - ATLASSERT(m_hGlobal != NULL); - LPVOID pVoid = ::LockResource(m_hGlobal); - ATLASSERT(pVoid != NULL); - return pVoid; - } - - void Release() - { - if(m_hGlobal != NULL) - { - FreeResource(m_hGlobal); - m_hGlobal = NULL; - m_hResource = NULL; - } - } -}; - -}; // namespace WTL - -#endif // __ATLUSER_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/atlwince.h b/prog/3rdPartyLibs/wtl-8.1/include/atlwince.h deleted file mode 100644 index fc6f873a9..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/atlwince.h +++ /dev/null @@ -1,3001 +0,0 @@ -// Windows Template Library - WTL version 8.1 -// Copyright (C) Microsoft Corporation. All rights reserved. -// -// This file is a part of the Windows Template Library. -// The use and distribution terms for this software are covered by the -// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php) -// which can be found in the file CPL.TXT at the root of this distribution. -// By using this software in any fashion, you are agreeing to be bound by -// the terms of this license. You must not remove this notice, or -// any other, from this software. - -#ifndef __ATLWINCE_H__ -#define __ATLWINCE_H__ - -#pragma once - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#ifndef __ATLAPP_H__ - #error atlwince.h requires atlapp.h to be included first -#endif - -#ifndef __ATLWIN_H__ - #error atlwince.h requires atlwin.h to be included first -#endif - -#ifndef _WIN32_WCE - #error atlwince.h compiles under Windows CE only -#elif (_WIN32_WCE < 300) - #error atlwince.h requires Windows CE 3.0 or higher. -#endif - -#if defined(WIN32_PLATFORM_WFSP) && _MSC_VER < 1400 // EVC compiling SmartPhone code - #if (WIN32_PLATFORM_WFSP < 200) - #error atlwince.h requires Smartphone 2003 or higher - #endif -#endif // WIN32_PLATFORM_WFSP - -#if defined(WIN32_PLATFORM_PSPC) && _MSC_VER < 1400 // EVC compiling Pocket PC code - #if (WIN32_PLATFORM_PSPC < 310) - #error atlwince.h requires Pocket PC 2002 or higher - #endif -#endif // WIN32_PLATFORM_PSPC - -#if !defined(_AYGSHELL_H_) && !defined(__AYGSHELL_H__) - #error atlwince.h requires aygshell.h to be included first -#else - #if defined(WIN32_PLATFORM_WFSP) && !defined(_TPCSHELL_H_) - #error SmartPhone dialog classes require tpcshell.h to be included first - #endif -#endif - -#if (_MSC_VER >= 1400) // VS2005 - #include - #define _WTL_CE_DRA -#endif // (_MSC_VER >= 1400) - -#if !defined(_WTL_CE_NO_DIALOGS) && !defined(__ATLFRAME_H__) - #error Orientation aware dialog classes require atlframe.h to be included first -#endif - -#if !defined(_WTL_CE_NO_APPWINDOW) && !defined(__ATLFRAME_H__) - #error Application window class require atlframe.h to be included first -#endif - -#if !defined(_WTL_CE_NO_ZOOMSCROLL) && !defined(__ATLSCRL_H__) - #error ZoomScroll implementation requires atlscrl.h to be included first -#endif - -#if !defined(_WTL_CE_NO_ZOOMSCROLL) - #if !(defined(__ATLTYPES_H__) || (defined(__ATLMISC_H__) && !defined(_WTL_NO_WTYPES))) - #error ZoomScroll requires _WTL_NO_WTYPES not to be defined and either atlmisc.h or atltypes.h to be included first - #endif // !(defined(__ATLTYPES_H__) || (defined(__ATLMISC_H__) && !defined(_WTL_NO_WTYPES))) -#endif // !defined(_WTL_CE_NO_ZOOMSCROLL) - -#if !defined(WIN32_PLATFORM_WFSP) && !defined(WIN32_PLATFORM_PSPC) - #define _WTL_CE_NO_CONTROLS -#endif // !defined(WIN32_PLATFORM_WFSP) && !defined(WIN32_PLATFORM_PSPC) - -#ifndef _WTL_CE_NO_CONTROLS - #ifndef __ATLCTRLS_H__ - #error The PPC/SmartPhone controls classes require atlctrls.h to be included first - #endif - - #include - #pragma comment(lib, "htmlview.lib") - - #include - #pragma comment(lib, "voicectl.lib") - - #ifdef WIN32_PLATFORM_PSPC - #include - #pragma comment(lib, "richink.lib") - - #include - #pragma comment(lib, "inkx.lib") - - #include - #pragma comment(lib, "doclist.lib") - #endif -#endif - - -/////////////////////////////////////////////////////////////////////////////// -// Classes in this file: -// -// CStdDialogBase : Standard PPC/SmartPhone dialog base class -// CStdDialogImplBase - Base implementation of standard dialog -// CStdDialogImpl : Standard dialog implementation -// CStdIndirectDialogImpl - implementation of standard indirect PPC/SmartPhone dialog -// CStdAxDialogImpl : Standard AxDialog implementation -// CStdSimpleDialog : Standard simple dialog -// CStdDialogResizeImplBase - Base implementation of orientation resizing standard dialog -// CStdDialogResizeImpl : Orientation resizing standard dialog implementation -// CStdAxDialogResizeImpl - implementation of orientation resizing standard AxDialog -// CStdSimpleDialogResizeImpl : Standard resizing simple dialog implementation -// CStdOrientedDialogBase - Oriented PPC standard dialog base class -// CStdOrientedDialogImplBase - Oriented PPC standard dialog base implementation -// CStdOrientedDialogImpl : Oriented PPC standard dialog implementation -// CStdAxOrientedDialogImpl - Oriented PPC standard AxDialog implementation -// CStdSimpleOrientedDialog : Standard simple orientable dialog -// -// CAppInfoBase : Helper for application state save/restore to registry -// CAppInfoT : CAppInfoBase constructed from a CAppWindow -// CAppWindowBase : Base class for PPC/SmartPhone well-behaved application window or dialog -// CAppWindow : PPC/SmartPhone well-behaved application window class -// CAppDialog : PPC/SmartPhone well-behaved application dialog class -// CAppStdDialogImplBase - Base implementation of standard application dialogs -// CAppStdDialogImpl : Implementation of standard application dialog -// CAppStdDialogResizeImpl - implementation of orientation resizing standard application dialog -// CAppStdAxDialogImpl - Implementation of standard application AxDialog -// CAppStdAxDialogResizeImpl - implementation of orientation resizing standard application AxDialog -// CAppStdOrientedDialogImpl - implementation of oriented PPC standard application dialog -// CAppStdAxOrientedDialogImpl - implementation of oriented PPC standard application AxDialog -// -// CFullScreenFrame : Full screen frame class -// -// CZoomScrollImpl : WinCE zooming implementation -// -// CBottomTabViewImpl - CBottomTabView -// CHtmlCtrlT - CHtmlCtrl -// CRichInkCtrlT - CRichInkCtrl -// CInkXCtrlT - CInkXCtrl -// CVoiceRecorderCtrlT - CVoiceRecorderCtrl -// CDocListCtrlT - CDocListCtrl -// CCapEditT - CCapEdit -// CTTStaticT - CTTStatic -// CTTButtonT - CTTButton -// -// CSpinCtrlT - CSpinCtrl : SmartPhone specific UpDown control -// CSpinned : SmartPhone association of control and Spin -// CSpinListBox : SmartPhone spinned ListBox control -// CExpandListBox : SmartPhone expandable ListBox control -// CExpandEdit : SmartPhone expandable Edit control -// CExpandCapEdit : SmartPhone expandable CapEdit control -// -// Global functions: -// AtlCreateMenuBar() -// AtlCreateEmptyMenuBar() -// AtlIsEditFocus() -// AtlActivateBackKey() - -namespace WTL -{ - -/////////////////////////////////////////////////////////////////////////////// -// MenuBar creation functions for property sheets and dialogs -// Frame windows use CreateSimpleCEMenuBar - -inline HWND AtlCreateMenuBar(SHMENUBARINFO& mbi) -{ - ATLASSERT(::IsWindow(mbi.hwndParent)); - ATLVERIFY(::SHCreateMenuBar(&mbi) != FALSE); - return mbi.hwndMB; -}; - -inline HWND AtlCreateMenuBar(HWND hWnd, UINT nToolBarId = ATL_IDW_TOOLBAR, DWORD dwFlags = 0, int nBmpId = 0, int cBmpImages = 0, COLORREF clrBk = 0) -{ - SHMENUBARINFO mbi = { sizeof(mbi), hWnd, dwFlags, nToolBarId, ModuleHelper::GetResourceInstance(), nBmpId, cBmpImages, 0, clrBk }; - return AtlCreateMenuBar(mbi); -} - -inline HWND AtlCreateEmptyMenuBar(HWND hWnd, bool bSip = true) -{ - SHMENUBARINFO embi = { sizeof(SHMENUBARINFO), hWnd, SHCMBF_EMPTYBAR }; - if (!bSip) - embi.dwFlags |= SHCMBF_HIDESIPBUTTON; - - return AtlCreateMenuBar(embi); -} - -/////////////////////////////////////////////////////////////////////////////// -// Helper functions for SmartPhone back key handling - -inline bool AtlIsEditFocus() -{ - ATL::CWindow wCtrl = GetFocus(); - if (wCtrl.IsWindow()) - { - TCHAR szClassName[8] = {0}; - ATLVERIFY(::GetClassName(wCtrl.m_hWnd, szClassName, 8)); - return !_tcscmp(szClassName, _T("Edit")) || !_tcscmp(szClassName, WC_CAPEDIT); - } - return false; -} - -#if defined WIN32_PLATFORM_WFSP -inline void AtlActivateBackKey(HWND hMenuBar) -{ - ATLASSERT(::IsWindow(hMenuBar)); - ::SendMessage(hMenuBar, SHCMBM_OVERRIDEKEY, VK_TBACK, - MAKELPARAM(SHMBOF_NODEFAULT | SHMBOF_NOTIFY, SHMBOF_NODEFAULT | SHMBOF_NOTIFY)); -} -#endif // WIN32_PLATFORM_WFSP - -// --- Standard PPC/SmartPhone dialogs --- - -#ifndef _WTL_CE_NO_DIALOGS - -/////////////////////////////////////////////////////////////////////////////// -// CStdDialogBase - base class for standard PPC/SmartPhone dialogs - -#define WTL_STD_SHIDIF SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN -#define WTL_SP_SHIDIF SHIDIF_SIZEDLGFULLSCREEN - -// Title setting macros -#define WTL_DLG_TITLEHEIGHT(iHeight) static const int GetTitleHeight(){return iHeight;} -#define WTL_DLG_NOTITLE WTL_DLG_TITLEHEIGHT(0) - -/////////////////////////////////////////////////////////////////////////////// -// CStdDialogBase - Base class for standard PPC/SmartPhone dialog - -template -class CStdDialogBase -{ -public: -#ifdef WIN32_PLATFORM_PSPC -// Pocket PC only Dialog title handling - const int nTitleHeight; - - CStdDialogBase() : nTitleHeight(T::GetTitleHeight()) - { } - -// Overloads - BOOL GetClientRect(LPRECT lpRect) - { - T* pT = static_cast(this); - ATLASSERT(pT->IsWindow()); - BOOL bRes = ::GetClientRect(pT->m_hWnd, lpRect); - if (nTitleHeight) - lpRect->top += nTitleHeight + 1; - return bRes; - } - - BOOL SetWindowText(LPCTSTR lpszString) - { - T* pT = static_cast(this); - ATLASSERT(pT->IsWindow()); - BOOL bRes = ::SetWindowText(pT->m_hWnd, lpszString); - if (nTitleHeight != 0) - pT->DoPaintTitle(); - return bRes; - } - -// Overrideables - static const int GetTitleHeight() - { - #ifdef _WTL_CE_DRA - return DRA::SCALEY(24); - #else // !_WTL_CE_DRA - CWindowDC dc(NULL); - return dc.GetDeviceCaps(LOGPIXELSY) >> 2; // LOGPIXELSY * 24 / 96, - #endif // !_WTL_CE_DRA - } - - // Title painting - bool DoPaintTitle() - { - T* pT = static_cast(this); - ATLASSERT(pT->IsWindow()); - TCHAR sTitle[48]; - - // Preparation - CPaintDC dc(pT->m_hWnd); - CFont fontTitle = AtlCreateBoldFont(); - CFontHandle fontOld = dc.SelectFont(fontTitle); - dc.SetTextColor(GetSysColor(COLOR_HIGHLIGHT)); - int nLen = pT->GetWindowText(sTitle, 48); - int nWidth = dc.GetDeviceCaps(HORZRES); - - // Display title text - RECT rTitle = { 0, 0, nWidth, nTitleHeight }; - dc.FillRect(&rTitle, COLOR_3DHIGHLIGHT); - #ifdef _WTL_CE_DRA - rTitle.left = DRA::SCALEX(8); - #else // !_WTL_CE_DRA - rTitle.left = nTitleHeight / 3; // 8 == 24 / 3 - #endif // !_WTL_CE_DRA - dc.DrawText(sTitle, nLen, &rTitle, DT_VCENTER | DT_SINGLELINE); - dc.SelectFont(fontOld); - - // Draw bottom line, 2 pixels thick if HI_RES_AWARE - CPenHandle penOld = dc.SelectStockPen(BLACK_PEN); - POINT line[4] = {{0, nTitleHeight}, {nWidth, nTitleHeight}, {0, nTitleHeight - 1}, {nWidth, nTitleHeight - 1}}; - - #ifdef _WTL_CE_DRA - int nSeg = DRA::SCALEY(1); - #else // !_WTL_CE_DRA - int nSeg = nTitleHeight / 24; - #endif // !_WTL_CE_DRA - - dc.Polyline(line, nSeg <= 2 ? nSeg * 2 : 4); - dc.SelectPen(penOld); - - return false; - } - - // Title preparation: move the dialog controls down to make room for title - void DialogTitleInit() - { - T* pT = static_cast(this); - ATLASSERT(pT->IsWindow()); - - ATL::CWindow wCtl = pT->GetWindow(GW_CHILD); - while (wCtl.IsWindow()) - { - RECT rCtl = { 0 }; - wCtl.GetWindowRect(&rCtl); - ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rCtl, 2); - ::OffsetRect(&rCtl, 0, nTitleHeight); - wCtl.MoveWindow(&rCtl, FALSE); - wCtl = wCtl.GetWindow(GW_HWNDNEXT); - } - } - - // SIP management - void DoSipInfo() - { - T* pT = static_cast(this); - ATLASSERT(pT->IsWindow()); - - SIPINFO si = {sizeof(SIPINFO)}; - SipGetInfo(&si); - if ((si.fdwFlags & SIPF_ON) ^ SIPF_ON) - si.rcVisibleDesktop.bottom = si.rcSipRect.bottom; - pT->MoveWindow(&si.rcVisibleDesktop, FALSE); - } - -// Title painting handler - LRESULT OnPaintTitle(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - T* pT = static_cast(this); - return bHandled = nTitleHeight ? pT->DoPaintTitle() : FALSE; - } - -// SIP handler - LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) - { - T* pT = static_cast(this); - if (wParam == SPI_SETSIPINFO) - { - pT->DoSipInfo(); - return TRUE; - } - return bHandled = FALSE; - } - -#elif defined WIN32_PLATFORM_WFSP -// SmartPhone VK_TBACK key standard management - LRESULT OnHotKey(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - const UINT uModif = (UINT)LOWORD(lParam); - const UINT uVirtKey = (UINT)HIWORD(lParam); - - if(uVirtKey == VK_TBACK) - if (AtlIsEditFocus()) - ::SHSendBackToFocusWindow(uMsg, wParam, lParam); - else if (uModif & MOD_KEYUP) - pT->StdCloseDialog(IDCANCEL); - return 1; - } - - // SmartPhone MenuBar and VK_TBACK key initialization - void StdSPInit() - { - T* pT = static_cast(this); - HWND hMenuBar = ::SHFindMenuBar(pT->m_hWnd); - - if (!hMenuBar && (t_shidiFlags & SHIDIF_DONEBUTTON)) - hMenuBar = CreateMenuBar(ATL_IDM_MENU_DONE); - - if(hMenuBar != NULL) - AtlActivateBackKey(hMenuBar); - } - - void SetStaticBold() - { - T* pT = static_cast(this); - ATLASSERT(pT->IsWindow()); - - CFontHandle fontBold = AtlCreateBoldFont(pT->GetFont()); - - ATL::CWindow wCtl = pT->GetWindow(GW_CHILD); - - while (wCtl.IsWindow()) - { - if ((short int)wCtl.GetDlgCtrlID() == IDC_STATIC) - wCtl.SetFont(fontBold); - wCtl = wCtl.GetWindow(GW_HWNDNEXT); - } - } -#endif // WIN32_PLATFORM_WFSP - -// Platform dependant initialization - void StdPlatformInit() - { - T* pT = static_cast(this); -#ifdef WIN32_PLATFORM_PSPC // Pocket PC title initialization - if (nTitleHeight != 0) - pT->DialogTitleInit(); -#elif defined(WIN32_PLATFORM_WFSP) - pT->StdSPInit(); - SetStaticBold(); -#endif // WIN32_PLATFORM_WFSP - } - - // Menu bar creation - HWND CreateMenuBar(UINT uiMB = T::IDD, int nBmpImages = 0) - { - T* pT = static_cast(this); - return AtlCreateMenuBar(pT->m_hWnd, uiMB, 0, nBmpImages ? uiMB : 0, nBmpImages); - } - - // Dialog closing - void StdCloseDialog(WORD wID) - { - T* pT = static_cast(this); - if (t_bModal) - ::EndDialog(pT->m_hWnd, wID); - else - pT->DestroyWindow(); - } - - // Shell dialog layout initialization - void StdShidInit() - { - T* pT = static_cast(this); - SHINITDLGINFO shidi = { SHIDIM_FLAGS, pT->m_hWnd, t_shidiFlags }; - ::SHInitDialog(&shidi); - } - -// IDC_INFOSTATIC background setting - LRESULT OnColorStatic(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - if (::GetDlgCtrlID((HWND)lParam) == IDC_INFOSTATIC) - { - ::SetBkMode((HDC)wParam, TRANSPARENT); - return (LRESULT)::GetSysColorBrush(COLOR_INFOBK); - } - return bHandled = FALSE; - } - -// Menu dialog ending - LRESULT OnMenuClose(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - pT->StdCloseDialog((WORD)(wID - ID_MENU_OK + IDOK)); - return 0; - } - -// Standard dialog ending: may be used with any command - LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - pT->StdCloseDialog(wID); - return 0; - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CStdDialogImplBase - Base implementation of standard PPC/SmartPhone dialog - -template > -class ATL_NO_VTABLE CStdDialogImplBase : - public TBase, - public CStdDialogBase -{ -public: -#ifdef WIN32_PLATFORM_PSPC - BOOL GetClientRect(LPRECT lpRect) - { - return CStdDialogBase::GetClientRect(lpRect); - } - - BOOL SetWindowText(LPCTSTR lpszString) - { - return CStdDialogBase::SetWindowText(lpszString); - } -#endif - - BEGIN_MSG_MAP(CStdDialogImplBase) -#ifdef WIN32_PLATFORM_PSPC // Pocket PC title and SIP - MESSAGE_HANDLER(WM_PAINT, OnPaintTitle) - MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange) -#elif defined(WIN32_PLATFORM_WFSP) // SmartPhone VK_TBACK key - MESSAGE_HANDLER(WM_HOTKEY, OnHotKey) -#endif - MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnColorStatic) - MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) - COMMAND_RANGE_HANDLER(IDOK, IDCANCEL, OnCloseCmd) - COMMAND_RANGE_HANDLER(ID_MENU_OK, ID_MENU_CANCEL, OnMenuClose) - END_MSG_MAP() - - LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { -#ifdef _DEBUG - T* pT = static_cast(this); - ATLASSERT(t_bModal == pT->m_bModal); -#endif - StdPlatformInit(); - StdShidInit(); - return bHandled = FALSE; - } -}; - -/////////////////////////////////////////////////////////////////////////////// -// CStdDialogImpl - implementation of standard PPC/SmartPhone dialog - -template -class ATL_NO_VTABLE CStdDialogImpl : public CStdDialogImplBase< T, t_shidiFlags, t_bModal> -{}; - -/////////////////////////////////////////////////////////////////////////////// -// CStdIndirectDialogImpl - implementation of standard indirect PPC/SmartPhone dialog - -#if defined __ATLDLGS_H__ - -template -class ATL_NO_VTABLE CStdIndirectDialogImpl : - public CIndirectDialogImpl< T, CMemDlgTemplate, CStdDialogImpl > -{ -public: - typedef CIndirectDialogImpl< T, CMemDlgTemplate, CStdDialogImpl > _baseClass; - typedef CStdDialogImpl _baseStd; - - void CheckStyle() - { - // Mobile devices don't support DLGTEMPLATEEX - ATLASSERT(!m_Template.IsTemplateEx()); - - // Standard dialogs need only DS_CENTER - DWORD &dwStyle = m_Template.GetTemplatePtr()->style; - if (dwStyle & DS_CENTER) - if(t_bModal) - { - ATLASSERT((dwStyle & WS_CHILD) != WS_CHILD); - dwStyle |= WS_POPUP; - } - else - { - if((dwStyle & WS_CHILD) != WS_CHILD) - dwStyle |= WS_POPUP; - } - } - - INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow(), LPARAM dwInitParam = NULL) - { - ATLASSERT(t_bModal); - - if (!m_Template.IsValid()) - CreateTemplate(); - - CheckStyle(); - - return _baseClass::DoModal(hWndParent, dwInitParam); - } - - HWND Create(HWND hWndParent, LPARAM dwInitParam = NULL) - { - ATLASSERT(!t_bModal); - - if (!m_Template.IsValid()) - CreateTemplate(); - - CheckStyle(); - - return _baseClass::Create(hWndParent, dwInitParam); - } - - BEGIN_MSG_MAP(CStdIndirectDialogImpl) - CHAIN_MSG_MAP(_baseStd) - END_MSG_MAP() - -}; - -#endif // defined __ATLDLGS_H__ - -#ifndef _ATL_NO_HOSTING - -/////////////////////////////////////////////////////////////////////////////// -// CStdAxDialogImpl - implementation of standard PPC/SmartPhone AxDialog - -template -class ATL_NO_VTABLE CStdAxDialogImpl : public CStdDialogImplBase< T, t_shidiFlags, t_bModal, ATL::CAxDialogImpl< T > > -{}; -#endif // _ATL_NO_HOSTING - -/////////////////////////////////////////////////////////////////////////////// -// CStdSimpleDialog - standard PPC/SmartPhone simple dialog with SHIDIF_xxx flags - -template -class CStdSimpleDialog : - public ATL::CSimpleDialog, - public CStdDialogBase, t_shidiFlags> -{ -public: - typedef CStdDialogBase, t_shidiFlags> baseClass; - -#ifdef WIN32_PLATFORM_PSPC - BOOL GetClientRect(LPRECT lpRect) - { - return baseClass::GetClientRect(lpRect); - } - - BOOL SetWindowText(LPCTSTR lpszString) - { - return baseClass::SetWindowText(lpszString); - } -#endif - - BEGIN_MSG_MAP(CStdSimpleDialog) -#ifdef WIN32_PLATFORM_PSPC // Pocket PC title and SIP - MESSAGE_HANDLER(WM_PAINT, OnPaintTitle) - MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange) -#elif defined(WIN32_PLATFORM_WFSP) // SmartPhone VK_TBACK key - MESSAGE_HANDLER(WM_HOTKEY, OnHotKey) -#endif - MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnColorStatic) - MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) - COMMAND_RANGE_HANDLER(ID_MENU_OK, ID_MENU_CANCEL, OnMenuClose) - COMMAND_RANGE_HANDLER(IDOK, IDCANCEL, baseClass::OnCloseCmd) - END_MSG_MAP() - - LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - StdPlatformInit(); - StdShidInit(); - return bHandled = FALSE; - } -}; - -/////////////////////////////////////////////////////////////////////////////// -// CStdDialogResizeImplBase - Base implementation of orientation resizing standard PPC/SmartPhone dialog - -template > -class ATL_NO_VTABLE CStdDialogResizeImplBase : - public CStdDialogImplBase< T, t_shidiFlags, t_bModal, TBase>, - public CDialogResize -{ -public: - // Note: BEGIN_DLGRESIZE_MAP is required in the derived class. - - BEGIN_MSG_MAP(CStdResizeDialogImplBase) -#ifdef WIN32_PLATFORM_PSPC // Pocket PC title - MESSAGE_HANDLER(WM_PAINT, OnPaintTitle) -#elif defined(WIN32_PLATFORM_WFSP) // SmartPhone VK_TBACK key - MESSAGE_HANDLER(WM_HOTKEY, OnHotKey) -#endif - MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnColorStatic) - MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) - COMMAND_RANGE_HANDLER(IDOK, IDCANCEL, OnCloseCmd) - COMMAND_RANGE_HANDLER(ID_MENU_OK, ID_MENU_CANCEL, OnMenuClose) - CHAIN_MSG_MAP(CDialogResize< T >) - END_MSG_MAP() - - LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { -#ifdef _DEBUG - T* pT = static_cast(this); - ATLASSERT(t_bModal == pT->m_bModal); -#endif - StdPlatformInit(); - DlgResize_Init(FALSE); - StdShidInit(); - return bHandled = FALSE; - } -}; - -/////////////////////////////////////////////////////////////////////////////// -// CStdDialogResizeImpl - implementation of orientation resizing standard PPC/SmartPhone dialog - -template -class ATL_NO_VTABLE CStdDialogResizeImpl : public CStdDialogResizeImplBase< T, t_shidiFlags, t_bModal> -{}; - -#ifndef _ATL_NO_HOSTING - -/////////////////////////////////////////////////////////////////////////////// -// CStdAxDialogResizeImpl - implementation of orientation resizing standard PPC/SmartPhone AxDialog - -template -class ATL_NO_VTABLE CStdAxDialogResizeImpl : public CStdDialogResizeImplBase< T, t_shidiFlags, t_bModal, ATL::CAxDialogImpl > -{}; -#endif // _ATL_NO_HOSTING - -/////////////////////////////////////////////////////////////////////////////// -// CStdSimpleDialogResizeImpl - implementation of standard resizing simple dialog with SHIDIF_xxx flags - -// Usage: -// class CMyDlg : public CStdSimpleDialogResize -// { -// public: -// BEGIN_DLGRESIZE_MAP(CMyDlg) -// ... -// END_DLGRESIZE_MAP() -// }; - -template -class ATL_NO_VTABLE CStdSimpleDialogResizeImpl : - public CStdSimpleDialog, - public CDialogResize< T > -{ -public: - typedef CStdSimpleDialog::baseClass baseClass; - - BEGIN_MSG_MAP(CStdSimpleDialogResizeImpl) -#ifdef WIN32_PLATFORM_PSPC // Pocket PC title - MESSAGE_HANDLER(WM_PAINT, OnPaintTitle) -#elif defined(WIN32_PLATFORM_WFSP) // SmartPhone VK_TBACK key - MESSAGE_HANDLER(WM_HOTKEY, OnHotKey) -#endif - MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnColorStatic) - MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) - COMMAND_RANGE_HANDLER(IDOK, IDCANCEL, baseClass::OnCloseCmd) - COMMAND_RANGE_HANDLER(ID_MENU_OK, ID_MENU_CANCEL, OnMenuClose) - CHAIN_MSG_MAP(CDialogResize< T >) - END_MSG_MAP() - - LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - StdPlatformInit(); - DlgResize_Init(FALSE); - StdShidInit(); - return bHandled = FALSE; - } -}; - -#if defined(_WTL_CE_DRA) && defined(WIN32_PLATFORM_PSPC) - -/////////////////////////////////////////////////////////////////////////////// -// CStdOrientedDialogBase - Oriented PPC standard dialog base class - -template -class CStdOrientedDialogBase -{ -public: -// Operation - BOOL SetOrientation(DRA::DisplayMode mode) - { - T* pT = static_cast(this); - ATLASSERT(pT->IsWindow()); - ATLASSERT(mode == DRA::GetDisplayMode()); - - // Derived dialog must enumerate TWO dialog templates with the same control ids and types ie: - // enum { IDD = IDD_MYDLG, IDD_LANDSCAPE = IDD_MYDLG_L }; - UINT iResource = (mode == DRA::Landscape)? T::IDD_LANDSCAPE : T::IDD; - - BOOL bRes = DRA::RelayoutDialog(ModuleHelper::GetResourceInstance(), pT->m_hWnd, MAKEINTRESOURCE(iResource)); - pT->OnOrientation(mode); - return bRes; - } - -// Override - void OnOrientation(DRA::DisplayMode /*mode*/) - {} - -// Message handlers - LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) - { - T* pT = static_cast(this); - ATLASSERT(pT->IsWindow()); - if (wParam == SETTINGCHANGE_RESET) - { - SetOrientation(DRA::GetDisplayMode()); - pT->StdPlatformInit(); - pT->StdShidInit(); - } - else if (wParam == SPI_SETSIPINFO) - { - pT->DoSipInfo(); - return TRUE; - } - return bHandled = FALSE; - } -}; - -/////////////////////////////////////////////////////////////////////////////// -// CStdOrientedDialogImplBase - Oriented PPC standard dialog base implementation - -template > -class ATL_NO_VTABLE CStdOrientedDialogImplBase : - public CStdDialogImplBase< T, t_shidiFlags, t_bModal, TBase>, - public CStdOrientedDialogBase -{ -public: - BEGIN_MSG_MAP(CStdOrientedDialogImpl) - MESSAGE_HANDLER(WM_PAINT, OnPaintTitle) - MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnColorStatic) - MESSAGE_HANDLER(WM_SETTINGCHANGE, CStdOrientedDialogBase::OnSettingChange) - MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) - COMMAND_RANGE_HANDLER(IDOK, IDCANCEL, OnCloseCmd) - COMMAND_RANGE_HANDLER(ID_MENU_OK, ID_MENU_CANCEL, OnMenuClose) - END_MSG_MAP() - - LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - T* pT = static_cast(this); -#ifdef _DEBUG - ATLASSERT(t_bModal == pT->m_bModal); -#endif - if (DRA::GetDisplayMode() == DRA::Landscape) - SetOrientation(DRA::Landscape); - pT->StdPlatformInit(); - pT->StdShidInit(); - return bHandled = FALSE; - } -}; - -/////////////////////////////////////////////////////////////////////////////// -// CStdOrientedDialogImpl - Oriented PPC standard dialog implementation - -template -class ATL_NO_VTABLE CStdOrientedDialogImpl : public CStdOrientedDialogImplBase< T, t_shidiFlags, t_bModal> -{}; - -#ifndef _ATL_NO_HOSTING -/////////////////////////////////////////////////////////////////////////////// -// CStdAxOrientedDialogImpl - Oriented PPC standard AxDialog implementation - -template -class ATL_NO_VTABLE CStdAxOrientedDialogImpl : public CStdOrientedDialogImplBase< T, t_shidiFlags, t_bModal, ATL::CAxDialogImpl > -{}; -#endif // _ATL_NO_HOSTING - -/////////////////////////////////////////////////////////////////////////////// -// CStdSimpleOrientedDialog - Standard simple orientable dialog - -template -class CStdSimpleOrientedDialog : - public CStdSimpleDialog, - public CStdOrientedDialogBase > -{ -public: - typedef CStdSimpleDialog::baseClass baseClass; - typedef CStdOrientedDialogBase > baseOriented; - - enum {IDD = t_wDlgTemplateID, IDD_LANDSCAPE = t_wDlgLandscapeID}; - - BEGIN_MSG_MAP(CStdSimpleDialog) - MESSAGE_HANDLER(WM_PAINT, OnPaintTitle) - MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnColorStatic) - MESSAGE_HANDLER(WM_SETTINGCHANGE, baseOriented::OnSettingChange) - MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) - COMMAND_RANGE_HANDLER(IDOK, IDCANCEL, baseClass::OnCloseCmd) - COMMAND_RANGE_HANDLER(ID_MENU_OK, ID_MENU_CANCEL, OnMenuClose) - END_MSG_MAP() - - LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - if (DRA::GetDisplayMode() == DRA::Landscape) - SetOrientation(DRA::Landscape); - StdPlatformInit(); - StdShidInit(); - return bHandled = FALSE; - } -}; - -#endif // _WTL_CE_DRA - - -#endif // _WTL_CE_NO_DIALOGS - - -// --- PPC/SmartPhone application window and helpers --- - -#ifndef _WTL_CE_NO_APPWINDOW - -/////////////////////////////////////////////////////////////////////////////// -// CAppInfoBase - Helper for application state save/restore to registry - -class CAppInfoBase -{ -public: - ATL::CRegKey m_Key; - - CAppInfoBase(ATL::_U_STRINGorID sAppKey) - { - m_Key.Create(HKEY_CURRENT_USER, sAppKey.m_lpstr); - ATLASSERT(m_Key.m_hKey); - } - - template - LONG Save(V& val, ATL::_U_STRINGorID sName) - { - return ::RegSetValueEx(m_Key, sName.m_lpstr, 0, REG_BINARY, (LPBYTE)&val, sizeof(V)); - } - - template - LONG Save(int nb, V& val0, ATL::_U_STRINGorID sName) - { - return ::RegSetValueEx(m_Key, sName.m_lpstr, 0, REG_BINARY, (LPBYTE)&val0, nb * sizeof(V)); - } - - template - LONG Restore(V& val, ATL::_U_STRINGorID sName) - { - DWORD valtype; - DWORD bufSize = sizeof(V); - return ::RegQueryValueEx(m_Key, sName.m_lpstr, 0, &valtype, (LPBYTE)&val, &bufSize); - } - - template - LONG Restore(int nb, V& val0, ATL::_U_STRINGorID sName) - { - DWORD valtype; - DWORD bufSize = nb * sizeof(V); - return ::RegQueryValueEx(m_Key, sName.m_lpstr, 0, &valtype, (LPBYTE)&val0, &bufSize); - } - -#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) -#if (_ATL_VER < 0x0800) - LONG Save(_CSTRING_NS::CString& sval, ATL::_U_STRINGorID sName) - { - return m_Key.SetValue(sval, sName.m_lpstr); - } - - LONG Restore(_CSTRING_NS::CString& sval, ATL::_U_STRINGorID sName) - { - DWORD size = MAX_PATH; - LONG res = m_Key.QueryValue(sval.GetBuffer(size), sName.m_lpstr, &size); - sval.ReleaseBuffer(); - return res; - } -#else // !(_ATL_VER < 0x0800) - LONG Save(_CSTRING_NS::CString& sval, ATL::_U_STRINGorID sName) - { - return m_Key.SetStringValue(sName.m_lpstr, sval); - } - - LONG Restore(_CSTRING_NS::CString& sval, ATL::_U_STRINGorID sName) - { - DWORD size = MAX_PATH; - LONG res = m_Key.QueryStringValue(sName.m_lpstr, sval.GetBuffer(size), &size); - sval.ReleaseBuffer(); - return res; - } -#endif // !(_ATL_VER < 0x0800) -#else - #pragma message("Warning: CAppInfoBase compiles without CString support. Do not use CString in Save or Restore.") -#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) - -#if (_ATL_VER < 0x0800) - LONG Save(LPCTSTR sval, ATL::_U_STRINGorID sName) - { - return m_Key.SetValue(sval, sName.m_lpstr); - } - - LONG Restore(LPTSTR sval, ATL::_U_STRINGorID sName, DWORD *plength) - { - return m_Key.QueryValue(sval, sName.m_lpstr, plength); - } -#else // !(_ATL_VER < 0x0800) - LONG Save(LPCTSTR sval, ATL::_U_STRINGorID sName) - { - return m_Key.SetStringValue(sName.m_lpstr, sval); - } - - LONG Restore(LPTSTR sval, ATL::_U_STRINGorID sName, DWORD *plength) - { - return m_Key.QueryStringValue(sName.m_lpstr, sval, plength); - } -#endif // !(_ATL_VER < 0x0800) - - LONG Delete(ATL::_U_STRINGorID sName) - { - return m_Key.DeleteValue(sName.m_lpstr); - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CAppInfoT - CAppInfoBase constructed from a class with T::GetAppKey() - -// Macro for declaring AppKey -#define DECLARE_APPKEY(uAppKey) \ - static LPCTSTR GetAppKey() \ - { \ - static LPCTSTR sAppKey = ATL::_U_STRINGorID(uAppKey).m_lpstr; \ - return sAppKey; \ - } - -template -class CAppInfoT : public CAppInfoBase -{ -public: - CAppInfoT() : CAppInfoBase(T::GetAppKey()){} -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CAppWindowBase - Base class for PPC/SmartPhone "well-behaved" application window or dialog - -// Macros for declaring frame WNDCLASS and AppKey -#define DECLARE_APP_FRAME_CLASS(WndClassName, uCommonResourceID, uAppKey) \ - DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \ - DECLARE_APPKEY(uAppKey) - -#define DECLARE_APP_FRAME_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd, uAppKey) \ - DECLARE_FRAME_WND_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd) \ - DECLARE_APPKEY(uAppKey) - -template -class CAppWindowBase -{ -public: - typedef class CAppInfoT< T > CAppInfo; - -#ifndef WIN32_PLATFORM_WFSP - SHACTIVATEINFO m_sai; // NoOp on SmartPhones -#endif // WIN32_PLATFORM_WFSP - - bool m_bHibernate; - - CAppWindowBase< T >() : m_bHibernate(false) - { -#ifndef WIN32_PLATFORM_WFSP - SHACTIVATEINFO sai = { sizeof(SHACTIVATEINFO) }; - m_sai = sai; -#endif // WIN32_PLATFORM_WFSP - }; - - // Same as WTL 7.1 AppWizard generated ActivatePreviousInstance + SendMessage WM_COPYDATA - static HRESULT ActivatePreviousInstance(HINSTANCE hInstance, LPCTSTR lpstrCmdLine, bool bDialog) - { - // requires T does DECLARE_APP_FRAME_CLASS, DECLARE_APP_FRAME_CLASS_EX or DECLARE_APP_DLG_CLASS - CFrameWndClassInfo& classInfo = T::GetWndClassInfo(); - - ATLVERIFY(::LoadString(hInstance, classInfo.m_uCommonResourceID, classInfo.m_szAutoName, sizeof(classInfo.m_szAutoName)/sizeof(classInfo.m_szAutoName[0])) != 0); - - classInfo.m_wc.lpszClassName = classInfo.m_szAutoName; - - const TCHAR* pszClass = classInfo.m_wc.lpszClassName; - - if(NULL == pszClass || '\0' == *pszClass) - { - return E_FAIL; - } - - const DWORD dRetryInterval = 100; - const int iMaxRetries = 25; - - for(int i = 0; i < iMaxRetries; ++i) - { - HANDLE hMutex = CreateMutex(NULL, FALSE, pszClass); - - DWORD dw = GetLastError(); - - if(NULL == hMutex) - { - HRESULT hr; - - switch(dw) - { - case ERROR_INVALID_HANDLE: - // A non-mutext object with this name already exists. - hr = E_INVALIDARG; - break; - default: - // This should never happen... - hr = E_FAIL; - } - - return hr; - } - - // If the mutex already exists, then there should be another instance running - if(dw == ERROR_ALREADY_EXISTS) - { - CloseHandle(hMutex); - - HWND hwnd = NULL; - if (bDialog) - hwnd = FindWindow(NULL, pszClass); - else - hwnd = FindWindow(pszClass, NULL); - - if(hwnd == NULL) - { - Sleep(dRetryInterval); - continue; - } - else - { - // Transmit our params to previous instance - if (lpstrCmdLine && *lpstrCmdLine) - { - COPYDATASTRUCT cd = { NULL, sizeof(TCHAR) * (wcslen(lpstrCmdLine) + 1), (PVOID)lpstrCmdLine }; - ::SendMessage(hwnd, WM_COPYDATA, NULL, (LPARAM)&cd); - } - // Set the previous instance as the foreground window - if(0 != SetForegroundWindow(reinterpret_cast(reinterpret_cast(hwnd) | 0x1))) - return S_FALSE; - } - } - else - { - return S_OK; - } - } - return S_OK; - } - -// Operations overriden in derived class - bool AppHibernate(bool /*bHibernate*/) - { - return false; - } - - bool AppNewInstance(LPCTSTR /*lpstrCmdLine*/) - { - return false; - } - - void AppSave() - { - } - -#ifdef WIN32_PLATFORM_WFSP - void AppBackKey() - { - ::SHNavigateBack(); - } -#endif - -// Message map and handlers - BEGIN_MSG_MAP(CAppWindowBase) - MESSAGE_HANDLER(WM_ACTIVATE, OnActivate) -#ifdef WIN32_PLATFORM_WFSP - MESSAGE_HANDLER(WM_HOTKEY, OnHotKey) -#else - MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange) -#endif // WIN32_PLATFORM_WFSP - MESSAGE_HANDLER(WM_HIBERNATE, OnHibernate) - MESSAGE_HANDLER(WM_COPYDATA, OnNewInstance) - MESSAGE_HANDLER(WM_CLOSE, OnClose) - END_MSG_MAP() - - LRESULT OnActivate(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - T* pT = static_cast(this); - if (m_bHibernate) - m_bHibernate = pT->AppHibernate(false); -#ifndef WIN32_PLATFORM_WFSP - ::SHHandleWMActivate(pT->m_hWnd, wParam, lParam, &m_sai, 0); -#else - wParam; - lParam; -#endif // WIN32_PLATFORM_WFSP - return bHandled = FALSE; - } - -#ifdef WIN32_PLATFORM_WFSP -// SmartPhone VK_TBACK key standard management - LRESULT OnHotKey(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - const UINT uModif = (UINT)LOWORD(lParam); - const UINT uVirtKey = (UINT)HIWORD(lParam); - if(uVirtKey == VK_TBACK) - if (AtlIsEditFocus()) - ::SHSendBackToFocusWindow(uMsg, wParam, lParam); - else if (uModif & MOD_KEYUP) - pT->AppBackKey(); - return 1; - } - -#else // !WIN32_PLATFORM_WFSP -// PPC SIP handling - LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - T* pT = static_cast(this); - bHandled = FALSE; - return ::SHHandleWMSettingChange(pT->m_hWnd, wParam, lParam, &m_sai); - } -#endif // !WIN32_PLATFORM_WFSP - - LRESULT OnHibernate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - return m_bHibernate = pT->AppHibernate(true); - } - - LRESULT OnNewInstance(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - PCOPYDATASTRUCT pcds = (PCOPYDATASTRUCT)lParam; - return pT->AppNewInstance((LPCTSTR)pcds->lpData); - } - - LRESULT OnClose(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - T* pT = static_cast(this); - pT->AppSave(); - bHandled = FALSE; - return 1; - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CAppWindow - PPC/SmartPhone "well-behaved" application window class - -template -class CAppWindow : public CAppWindowBase< T > -{ -public: - // Same as WTL 7.1 AppWizard generated Run + lpstrCmdLine in CreateEx - static int AppRun(LPTSTR lpstrCmdLine = NULL, int nCmdShow = SW_SHOWNORMAL) - { - CMessageLoop theLoop; - _Module.AddMessageLoop(&theLoop); - - T wndMain; - - if(wndMain.CreateEx(NULL, NULL, 0, 0, lpstrCmdLine) == NULL) - { - ATLTRACE2(atlTraceUI, 0, _T("Main window creation failed!\n")); - return 0; - } - - wndMain.ShowWindow(nCmdShow); - - int nRet = theLoop.Run(); - - _Module.RemoveMessageLoop(); - return nRet; - } - - static HRESULT ActivatePreviousInstance(HINSTANCE hInstance, LPCTSTR lpstrCmdLine) - { - return CAppWindowBase< T >::ActivatePreviousInstance(hInstance, lpstrCmdLine, false); - } -}; - - -#ifndef _WTL_CE_NO_DIALOGS - -/////////////////////////////////////////////////////////////////////////////// -// CAppDialog - PPC/SmartPhone "well-behaved" dialog application class - -// Macro for declaring dialog WNDCLASS and AppKey -#define DECLARE_APP_DLG_CLASS(WndClassName, uCommonResourceID, uAppKey) \ - static WTL::CFrameWndClassInfo& GetWndClassInfo() \ - { \ - static WTL::CFrameWndClassInfo wc = \ - { \ - { 0, (WNDPROC)StartDialogProc, \ - 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName }, \ - NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \ - }; \ - return wc; \ - }; \ - DECLARE_APPKEY(uAppKey) - -template -class CAppDialog : public CAppWindowBase< T > -{ -public: - static int AppRun(LPTSTR lpstrCmdLine = NULL, int nCmdShow = SW_SHOWNORMAL) - { - CMessageLoop theLoop; - _Module.AddMessageLoop(&theLoop); - - T dlgMain; - - if(dlgMain.Create(NULL, (LPARAM)lpstrCmdLine) == NULL) - { - ATLTRACE2(atlTraceUI, 0, _T("Main dialog creation failed!\n")); - return 0; - } - - dlgMain.ShowWindow(nCmdShow); - - int nRet = theLoop.Run(); - - _Module.RemoveMessageLoop(); - return nRet; - } - - static HRESULT ActivatePreviousInstance(HINSTANCE hInstance, LPCTSTR lpstrCmdLine) - { - return CAppWindowBase< T >::ActivatePreviousInstance(hInstance, lpstrCmdLine, true); - }; -}; - -// PPC/SmartPhone standard application dialogs - -#ifdef WIN32_PLATFORM_WFSP -#define WTL_APP_SHIDIF WTL_SP_SHIDIF -#else -#define WTL_APP_SHIDIF WTL_STD_SHIDIF -#endif - -/////////////////////////////////////////////////////////////////////////////// -// CAppStdDialogImplBase - Base implementation of standard application dialogs - -template -class ATL_NO_VTABLE CAppStdDialogImplBase : - public TImplBase, - public CAppDialog< T > -{ -public: - WTL_DLG_NOTITLE; - - void StdCloseDialog(int nVal) - { - T* pT = static_cast(this); - if (nVal != IDCANCEL) - pT->AppSave(); - if (t_bModal == false) - { - pT->DestroyWindow(); - ::PostQuitMessage(nVal); - } - else - ::EndDialog(pT->m_hWnd, nVal); - } - - BEGIN_MSG_MAP(CAppStdDialogImplBase) - MESSAGE_HANDLER(WM_CLOSE, OnSystemClose) - CHAIN_MSG_MAP(TImplBase) - CHAIN_MSG_MAP(CAppDialog< T >) - END_MSG_MAP() - - LRESULT OnSystemClose(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - T* pT = static_cast(this); - pT->StdCloseDialog(IDCANCEL); - return 0; - } -}; - -/////////////////////////////////////////////////////////////////////////////// -// CAppStdDialogImpl - Implementation of standard application dialog - -template -class ATL_NO_VTABLE CAppStdDialogImpl : - public CAppStdDialogImplBase, t_shidiFlags, t_bModal> -{}; - -/////////////////////////////////////////////////////////////////////////////// -// CAppStdDialogResizeImpl - implementation of orientation resizing standard application dialog - -template -class ATL_NO_VTABLE CAppStdDialogResizeImpl : - public CAppStdDialogImplBase, t_shidiFlags, t_bModal> -{}; - -#ifndef _ATL_NO_HOSTING -/////////////////////////////////////////////////////////////////////////////// -// CAppStdAxDialogImpl - Implementation of standard application AxDialog - -template -class ATL_NO_VTABLE CAppStdAxDialogImpl : - public CAppStdDialogImplBase, t_shidiFlags, t_bModal> -{}; - -/////////////////////////////////////////////////////////////////////////////// -// CAppStdAxDialogResizeImpl - implementation of orientation resizing standard application AxDialog - -template -class ATL_NO_VTABLE CAppStdAxDialogResizeImpl : - public CAppStdDialogImplBase, t_shidiFlags, t_bModal> -{}; -#endif // _ATL_NO_HOSTING - -#if defined(_WTL_CE_DRA) && defined(WIN32_PLATFORM_PSPC) -/////////////////////////////////////////////////////////////////////////////// -// CAppStdOrientedDialogImpl - implementation of oriented PPC standard application dialog - -template -class ATL_NO_VTABLE CAppStdOrientedDialogImpl : - public CAppStdDialogImplBase, t_shidiFlags, t_bModal> -{}; - -#ifndef _ATL_NO_HOSTING -/////////////////////////////////////////////////////////////////////////////// -// CAppStdAxOrientedDialogImpl - implementation of oriented PPC standard application AxDialog - -template -class ATL_NO_VTABLE CAppStdAxOrientedDialogImpl : - public CAppStdDialogImplBase, t_shidiFlags, t_bModal> -{}; -#endif // _ATL_NO_HOSTING - -#endif // defined(_WTL_CE_DRA) && defined(WIN32_PLATFORM_PSPC) - -#endif // _WTL_CE_NO_DIALOGS - -#endif // _WTL_CE_NO_APPWINDOW - - -// --- Full screen support --- - -#ifndef _WTL_CE_NO_FULLSCREEN - -/////////////////////////////////////////////////////////////////////////////// -// CFullScreenFrame - full screen frame implementation - -template -class CFullScreenFrame -{ -public: - bool m_bFullScreen; - - CFullScreenFrame() : m_bFullScreen(false) - { } - -// Operation - void SetFullScreen(bool bFull) - { - m_bFullScreen = bFull; - ShowTaskBar(!bFull, false); - ShowMenuBar(!bFull); - } - -// Manage TaskBar for modal dialogs and property sheets - template - int FSDoModal(D& dlg) - { - T* pT = static_cast(this); - pT; // avoid level 4 warning - ATLASSERT(pT->IsWindow()); - if (m_bFullScreen) // Show taskbar if hidden - ShowTaskBar(true, false); - int iRet = dlg.DoModal(); - if (m_bFullScreen) // Hide taskbar if restored - ShowTaskBar(false); - return iRet; - } - -// Implementation - void ShowMenuBar(bool bShow) - { - T* pT = static_cast(this); - ATLASSERT(pT->IsWindow()); - ATL::CWindow MenuBar = pT->m_hWndCECommandBar; - ATLASSERT(MenuBar.IsWindow()); - MenuBar.ShowWindow(bShow ? SW_SHOWNORMAL : SW_HIDE); - pT->SizeToMenuBar(); - } - - void ShowTaskBar(bool bShow, bool bRepaint = true) - { - T* pT = static_cast(this); - ATLASSERT(pT->IsWindow()); - RECT rect = { 0 }; - SystemParametersInfo(SPI_GETWORKAREA, NULL, &rect, FALSE); - if (!bShow) - rect.top = 0; - -#ifdef WIN32_PLATFORM_PSPC // Pocket PC code - UINT uShow = t_bHasSip ? SHFS_SHOWTASKBAR | SHFS_SHOWSIPBUTTON : SHFS_SHOWTASKBAR | SHFS_HIDESIPBUTTON; - SHFullScreen(pT->m_hWnd, bShow ? uShow : SHFS_HIDETASKBAR | SHFS_HIDESIPBUTTON); -#elif _WIN32_WCE > 0x500 // Smartphone 2005 code - SHFullScreen(pT->m_hWnd, bShow ? SHFS_SHOWTASKBAR : SHFS_HIDETASKBAR); -#else // Smartphone 2003 - HWND hTaskBar = FindWindow(_T("tray"), NULL); - ATLASSERT(::IsWindow(hTaskBar)); - ::ShowWindow(hTaskBar, bShow ? SW_SHOW : SW_HIDE); -#endif // WIN32_PLATFORM_PSPC - - pT->MoveWindow(&rect, bRepaint); - } - -// Message map and handler - BEGIN_MSG_MAP(CFullScreenFrame) - MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange) - MESSAGE_HANDLER(WM_ACTIVATE, OnActivate) - END_MSG_MAP() - - LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) - { -#ifndef SETTINGCHANGE_RESET // not defined for PPC 2002 - #define SETTINGCHANGE_RESET SPI_SETWORKAREA -#endif - if (m_bFullScreen && (wParam == SETTINGCHANGE_RESET)) - SetFullScreen(m_bFullScreen); - return bHandled = FALSE; - } - - LRESULT OnActivate(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) - { - if (m_bFullScreen) - { - ShowTaskBar(!wParam); - ShowMenuBar(!wParam); - } - return bHandled = FALSE; - } -}; - -#endif // _WTL_CE_NO_FULLSCREEN - - -// --- WinCE zoom support --- - -#ifndef _WTL_CE_NO_ZOOMSCROLL - -/////////////////////////////////////////////////////////////////////////////// -// CZoomScrollImpl - WinCE zooming implementation on top of CScrollImpl - -template -class CZoomScrollImpl: public CScrollImpl< T > -{ -public: -// Data members - _WTYPES_NS::CSize m_sizeTrue; - double m_fzoom; - -// Creation - CZoomScrollImpl() : m_sizeTrue(0), m_fzoom(1.) - { } - -// Zoom operations and access - void SetZoomScrollSize(_WTYPES_NS::CSize sizeTrue, double fzoom = 1., BOOL bRedraw = TRUE) - { - ATLASSERT(fzoom > 0.); - m_sizeTrue = sizeTrue; - m_fzoom = fzoom; - - CScrollImpl< T >::SetScrollSize(sizeTrue / fzoom, bRedraw); - } - - void SetZoomScrollSize(int cx, int cy, double fzoom=1., BOOL bRedraw = TRUE) - { - SetZoomScrollSize(_WTYPES_NS::CSize(cx, cy), fzoom, bRedraw); - } - - void SetZoom(double fzoom, BOOL bRedraw = TRUE) - { - _WTYPES_NS::CPoint ptCenter = WndtoTrue(m_sizeClient / 2); - _WTYPES_NS::CSize sizePage = GetScrollPage(); - _WTYPES_NS::CSize sizeLine = GetScrollLine(); - - SetZoomScrollSize(GetScrollSize(), fzoom, bRedraw); - - SetScrollLine(sizeLine); - SetScrollPage(sizePage); - _WTYPES_NS::CPoint ptOffset = ptCenter - (m_sizeClient / 2) * fzoom; - SetScrollOffset(ptOffset, bRedraw); - } - - double GetZoom() - { - return m_fzoom; - } - -// CScrollImpl overrides - void SetScrollOffset(int x, int y, BOOL bRedraw = TRUE) - { - CScrollImpl< T >::SetScrollOffset((int)(x / m_fzoom), (int)(y / m_fzoom), bRedraw); - } - - void SetScrollOffset(POINT ptOffset, BOOL bRedraw = TRUE) - { - SetScrollOffset(ptOffset.x, ptOffset.y, bRedraw); - } - - void GetScrollOffset(POINT& ptOffset) - { - ptOffset.x = (LONG)(m_ptOffset.x * m_fzoom); - ptOffset.y = (LONG)(m_ptOffset.y * m_fzoom); - } - - void SetScrollSize(int cx, int cy, BOOL bRedraw = TRUE) - { - SetZoomScrollSize(cx, cy, GetZoom(), bRedraw); - } - - void SetScrollSize(SIZE sizeTrue, BOOL bRedraw = TRUE) - { - SetZoomScrollSize(sizeTrue, GetZoom(), bRedraw); - } - - void GetScrollSize(SIZE& sizeTrue) const - { - sizeTrue = m_sizeTrue; - } - - void SetScrollPage(int cxPage, int cyPage) - { - SetScrollPage(_WTYPES_NS::CSize(cxPage, cyPage)); - } - - void SetScrollPage(SIZE sizePage) - { - CScrollImpl< T >::SetScrollPage(sizePage / m_fzoom); - } - - void GetScrollPage(SIZE& sizePage) const - { - sizePage = m_sizePage * m_fzoom; - } - - void SetScrollLine(int cxLine, int cyLine) - { - SetScrollLine(_WTYPES_NS::CSize(cxLine, cyLine)); - } - - void SetScrollLine(SIZE sizeLine) - { - CScrollImpl< T >::SetScrollLine(sizeLine / m_fzoom); - } - - void GetScrollLine(SIZE& sizeLine) const - { - sizeLine = m_sizeLine * m_fzoom; - } - -// Data access complements - _WTYPES_NS::CSize GetScrollSize() - { - return m_sizeTrue; - } - - _WTYPES_NS::CSize GetScrollPage() - { - return m_sizePage * m_fzoom; - } - - _WTYPES_NS::CSize GetScrollLine() - { - return m_sizeLine * m_fzoom; - } - - _WTYPES_NS::CPoint GetScrollOffset() - { - return (_WTYPES_NS::CSize)m_ptOffset * m_fzoom; - } - -// Helper coordinate functions - _WTYPES_NS::CPoint WndtoTrue(CPoint ptW) - { - return (_WTYPES_NS::CSize)ptW * GetZoom() + GetScrollOffset(); - } - - void WndtoTrue(LPPOINT aptW, int nPts) // in place coord transformation - { - for (int i = 0 ; i < nPts ; i++) - aptW[i] = WndtoTrue(aptW[i]); - } - - void WndtoTrue(LPRECT prectW) // in place coord transformation - { - WndtoTrue((LPPOINT)prectW, 2); - } - - _WTYPES_NS::CPoint TruetoWnd(CPoint ptT) - { - return (ptT - GetScrollOffset()) / GetZoom(); - } - - void TruetoWnd(LPPOINT aptT, int nPts) // in place coord transformation - { - for (int i = 0 ; i < nPts ; i++) - aptT[i] = TruetoWnd(aptT[i]); - } - - void TruetoWnd(LPRECT prectT) // in place coord transformation - { - TruetoWnd((LPPOINT)prectT, 2); - } - -// Drawing operations : assume adequate setting of data members - BOOL Draw(HBITMAP hbm, HDC hdestDC, DWORD dwROP = SRCCOPY) - { - CDC memDC = CreateCompatibleDC(hdestDC); - CBitmapHandle bmpOld = memDC.SelectBitmap(hbm); - BOOL bRes = Draw(memDC, hdestDC, dwROP); - memDC.SelectBitmap(bmpOld); - return bRes; - } - - BOOL Draw(HDC hsourceDC, HDC hdestDC, DWORD dwROP = SRCCOPY) - { - CDCHandle destDC = hdestDC; - destDC.SetViewportOrg(0,0); - _WTYPES_NS::CPoint ptOffset = GetScrollOffset(); - _WTYPES_NS::CSize sizeZClient = m_sizeClient * GetZoom(); - return destDC.StretchBlt(0, 0, m_sizeClient.cx, m_sizeClient.cy, hsourceDC, ptOffset.x, ptOffset.y, sizeZClient.cx, sizeZClient.cy, dwROP); - } - -#ifdef _IMAGING_H - BOOL Draw(IImage* pIImage, HDC hdestDC) - { - CDCHandle destDC = hdestDC; - destDC.SetViewportOrg(0,0); - return SUCCEEDED(pIImage->Draw(destDC, _WTYPES_NS::CRect(-_WTYPES_NS::CPoint(m_ptOffset), m_sizeAll), NULL)); - } -#endif - -// Message map and handlers - BEGIN_MSG_MAP(CZoomScrollImpl< T >) - MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd) - CHAIN_MSG_MAP(CScrollImpl< T >) - END_MSG_MAP() - - LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) - { - T* pT = static_cast(this); - ATLASSERT(::IsWindow(pT->m_hWnd)); - if ((GetScrollExtendedStyle() & SCRL_ERASEBACKGROUND)) - { - _WTYPES_NS::CRect rect; - pT->GetClientRect(rect); - _WTYPES_NS::CSize sizeClient=rect.Size(); - - if (m_sizeAll.cx < sizeClient.cx || m_sizeAll.cy < sizeClient.cy) - { - CDCHandle hdc = (HDC)wParam; - HBRUSH hbr = GetSysColorBrush((int)T::GetWndClassInfo().m_wc.hbrBackground - 1); - - if (m_sizeAll.cx < sizeClient.cx) - { - _WTYPES_NS::CRect rectBG(_WTYPES_NS::CPoint(m_sizeAll.cx, 0), sizeClient); - hdc.FillRect(rectBG, hbr); - } - - if (m_sizeAll.cy < sizeClient.cy) - { - _WTYPES_NS::CRect rectBG(_WTYPES_NS::CPoint(0, m_sizeAll.cy), sizeClient); - hdc.FillRect(rectBG, hbr); - } - } - } - else - { - bHandled = FALSE; - } - - return 1; - } -}; - -#endif // _WTL_CE_NO_ZOOMSCROLL - -#ifndef _WTL_CE_NO_CONTROLS - -// --- PPC bottom TabView control --- - -#if defined(__ATLCTRLX_H__) && defined(WIN32_PLATFORM_PSPC) - -/////////////////////////////////////////////////////////////////////////////// -// CBottomTabViewImpl - -template -class ATL_NO_VTABLE CBottomTabViewImpl : public CTabViewImpl -{ -public: - DECLARE_WND_CLASS_EX(NULL, 0, COLOR_APPWORKSPACE) - -// Implementation overrideables - bool CreateTabControl() - { - m_tab.Create(m_hWnd, rcDefault, NULL, WS_CHILD | TCS_BOTTOM, 0, m_nTabID); - - ATLASSERT(m_tab.m_hWnd != NULL); - if(m_tab.m_hWnd == NULL) - return false; - - m_tab.SendMessage(CCM_SETVERSION, COMCTL32_VERSION); - m_tab.SetItemExtra(sizeof(TABVIEWPAGE)); - - T* pT = static_cast(this); - m_cyTabHeight = pT->CalcTabHeight(); - - return true; - } - - int CalcTabHeight() - { - int nCount = m_tab.GetItemCount(); - TCITEMEXTRA tcix = { 0 }; - tcix.tciheader.mask = TCIF_TEXT; - tcix.tciheader.pszText = _T("NS"); - int nIndex = m_tab.InsertItem(nCount, tcix); - - RECT rect = { 0 }; - SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0); - RECT rcWnd = rect; - - m_tab.AdjustRect(FALSE, &rect); - rcWnd.top = rect.bottom; - ::AdjustWindowRectEx(&rcWnd, m_tab.GetStyle(), FALSE, m_tab.GetExStyle()); - m_tab.DeleteItem(nIndex); - - return rcWnd.bottom - rcWnd.top; - } - - void UpdateLayout() - { - RECT rect; - GetClientRect(&rect); - - if(m_tab.IsWindow() && ((m_tab.GetStyle() & WS_VISIBLE) != 0)) - m_tab.SetWindowPos(NULL, 0, rect.bottom - m_cyTabHeight, rect.right - rect.left, m_cyTabHeight, SWP_NOZORDER /*| SWP_SHOWWINDOW*/); - - if(m_nActivePage != -1) - ::SetWindowPos(GetPageHWND(m_nActivePage), NULL, 0, 0, rect.right - rect.left, rect.bottom - m_cyTabHeight, SWP_NOZORDER); - } - -}; - -class CBottomTabView : public CBottomTabViewImpl -{ -public: - DECLARE_WND_CLASS_EX(_T("WTL_BottomTabView"), 0, COLOR_APPWORKSPACE) -}; - -#endif // defined(__ATLCTRLX_H__) && defined(WIN32_PLATFORM_PSPC) - - -// --- PPC/SmartPhone controls --- - -//////////////////////////////////////////////////////////////////////////////// -// These are wrapper classes for the Pocket PC 2002/2003 and SmartPhone 2003 controls -// To implement a window based on a control, use following: -// Example: Implementing a window based on a Html control -// -// class CMyHtml : CWindowImpl -// { -// public: -// BEGIN_MSG_MAP(CMyHtml) -// // put your message handler entries here -// END_MSG_MAP() -// }; -/////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////// -// CHtmlCtrl - -template -class CHtmlCtrlT : public TBase -{ -public: -// Constructors - CHtmlCtrlT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CHtmlCtrlT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - HWND hWnd = TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - ATLASSERT(hWnd != NULL); // Did you remember to call InitHTMLControl(hInstance) ?? - return hWnd; - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return WC_HTML; - } - -#if (_WIN32_WCE >= 400) - void AddStyle(LPCWSTR pszStyle) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, DTM_ADDSTYLE, 0, (LPARAM)pszStyle); - } -#endif // (_WIN32_WCE >= 400) - - void AddText(BOOL bPlainText, LPCSTR pszText) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, DTM_ADDTEXT, (WPARAM)bPlainText, (LPARAM)pszText); - } - - void AddHTML(LPCSTR pszHTML) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, DTM_ADDTEXT, (WPARAM)FALSE, (LPARAM)pszHTML); - } - - void AddText(BOOL bPlainText, LPCWSTR pszText) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, DTM_ADDTEXTW, (WPARAM)bPlainText, (LPARAM)pszText); - } - - void AddHTML(LPCWSTR pszHTML) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, DTM_ADDTEXTW, (WPARAM)FALSE, (LPARAM)pszHTML); - } - - void Anchor(LPCSTR pszAnchor) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, DTM_ANCHOR, 0, (LPARAM)pszAnchor); - } - - void Anchor(LPCWSTR pszAnchor) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, DTM_ANCHORW, 0, (LPARAM)pszAnchor); - } - -#if (_WIN32_WCE >= 420) - void GetBrowserDispatch(IDispatch** ppDispatch) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(ppDispatch); - ATLASSERT(*ppDispatch==NULL); - ::SendMessage(m_hWnd, DTM_BROWSERDISPATCH, 0, (LPARAM)ppDispatch); - } - void GetDocumentDispatch(IDispatch** ppDispatch) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(ppDispatch); - ATLASSERT(*ppDispatch==NULL); - ::SendMessage(m_hWnd, DTM_DOCUMENTDISPATCH , 0, (LPARAM)ppDispatch); - } -#endif // (_WIN32_WCE >= 420) - - void Clear() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, DTM_CLEAR, 0, 0L); - } - - void EnableClearType(BOOL bEnable = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, DTM_ENABLECLEARTYPE, 0, (LPARAM)bEnable); - } - - void EnableContextMenu(BOOL bEnable = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, DTM_ENABLECONTEXTMENU, 0, (LPARAM)bEnable); - } - - void EnableScripting(BOOL bEnable = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, DTM_ENABLESCRIPTING, 0, (LPARAM)bEnable); - } - - void EnableShrink(BOOL bEnable = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, DTM_ENABLESHRINK, 0, (LPARAM)bEnable); - } - - void EndOfSource() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, DTM_ENDOFSOURCE, 0, 0L); - } - - void ImageFail(DWORD dwCookie) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, DTM_IMAGEFAIL, 0, (LPARAM)dwCookie); - } - - int GetLayoutHeight() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, DTM_LAYOUTHEIGHT, 0, 0L); - } - - int GetLayoutWidth() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, DTM_LAYOUTWIDTH, 0, 0L); - } - - void Navigate(LPCTSTR pstrURL, UINT uFlags = 0) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(pstrURL); - ::SendMessage(m_hWnd, DTM_NAVIGATE, (WPARAM)uFlags, (LPARAM)pstrURL); - } - - void SelectAll() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, DTM_SELECTALL, 0, 0L); - } - - void SetImage(INLINEIMAGEINFO* pImageInfo) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(pImageInfo); - ::SendMessage(m_hWnd, DTM_SETIMAGE, 0, (LPARAM)pImageInfo); - } - - void ZoomLevel(int iLevel) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, DTM_ZOOMLEVEL, 0, (LPARAM)iLevel); - } - -#if (_WIN32_WCE >= 400) - void Stop() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, DTM_STOP, 0, 0L); - } -#endif // (_WIN32_WCE >= 400) - - void GetScriptDispatch(IDispatch** ppDispatch) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(ppDispatch); - ATLASSERT(*ppDispatch==NULL); - ::SendMessage(m_hWnd, DTM_SCRIPTDISPATCH, 0, (LPARAM)ppDispatch); - } -}; - -typedef CHtmlCtrlT CHtmlCtrl; - - -#ifdef WIN32_PLATFORM_PSPC - -/////////////////////////////////////////////////////////////////////////////// -// CRichInkCtrl - -template -class CRichInkCtrlT : public TBase -{ -public: -// Constructors - CRichInkCtrlT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CRichInkCtrlT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - HWND hWnd = TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - ATLASSERT(hWnd != NULL); // Did you remember to call InitRichInkDLL() ?? - return hWnd; - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return WC_RICHINK; - } - - BOOL CanPaste(UINT uFormat = 0) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_CANPASTE, (WPARAM)uFormat, 0L); - } - - BOOL CanRedo() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_CANREDO, 0, 0L); - } - - BOOL CanUndo() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_CANUNDO, 0, 0L); - } - - void ClearAll(BOOL bRepaint = TRUE) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_CLEARALL, (WPARAM)bRepaint, 0L); - } - - BOOL GetModify() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, EM_GETMODIFY, 0, 0L); - } - - UINT GetPageStyle() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::SendMessage(m_hWnd, EM_GETPAGESTYLE, 0, 0L); - } - - UINT GetPenMode() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::SendMessage(m_hWnd, EM_GETPENMODE, 0, 0L); - } - - UINT GetViewStyle() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::SendMessage(m_hWnd, EM_GETVIEW, 0, 0L); - } - - UINT GetWrapMode() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::SendMessage(m_hWnd, EM_GETWRAPMODE, 0, 0L); - } - - UINT GetZoomPercent() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::SendMessage(m_hWnd, EM_GETZOOMPERCENT, 0, 0L); - } - - void InsertLinks(LPWSTR lpString, int cchLength = -1) - { - ATLASSERT(::IsWindow(m_hWnd)); - if(cchLength == -1) - cchLength = lstrlen(lpString); - ::SendMessage(m_hWnd, EM_INSERTLINKS, (WPARAM)cchLength, (LPARAM)lpString); - } - - void RedoEvent() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_REDOEVENT, 0, 0L); - } - - UINT SetInkLayer(UINT uLayer) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (UINT)::SendMessage(m_hWnd, EM_SETINKLAYER, (WPARAM)uLayer, 0L); - } - - void SetPageStyle(UINT uStyle) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_SETPAGESTYLE, (WPARAM)uStyle, 0L); - } - - void SetPenMode(UINT uMode) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_SETPENMODE, (WPARAM)uMode, 0L); - } - - void SetViewStyle(UINT uStyle) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_SETVIEW, (WPARAM)uStyle, 0L); - } - - void SetViewAttributes(VIEWATTRIBUTES* pAttribs) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(pAttribs); - ::SendMessage(m_hWnd, EM_SETVIEWATTRIBUTES, 0, (LPARAM)pAttribs); - } - - void SetWrapMode(UINT uMode) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_SETWRAPMODE, (WPARAM)uMode, 0L); - } - - void SetZoomPercent(UINT uPercent) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_SETZOOMPERCENT, (WPARAM)uPercent, 0L); - } - - LONG StreamIn(UINT uFormat, EDITSTREAM& es) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (LONG)::SendMessage(m_hWnd, EM_STREAMIN, (WPARAM)uFormat, (LPARAM)&es); - } - - LONG StreamOut(UINT uFormat, EDITSTREAM& es) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (LONG)::SendMessage(m_hWnd, EM_STREAMOUT, (WPARAM)uFormat, (LPARAM)&es); - } - - void UndoEvent() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_UNDOEVENT, 0, 0L); - } - -// Standard EM_xxx messages - DWORD GetSel() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, EM_GETSEL, 0, 0L); - } - - void GetSel(int& nStartChar, int& nEndChar) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_GETSEL, (WPARAM)&nStartChar, (LPARAM)&nEndChar); - } - - void ReplaceSel(LPCTSTR lpszNewText, BOOL bCanUndo = FALSE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_REPLACESEL, (WPARAM)bCanUndo, (LPARAM)lpszNewText); - } - - void SetModify(BOOL bModified = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, EM_SETMODIFY, (WPARAM)bModified, 0L); - } - - int GetTextLength() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, WM_GETTEXTLENGTH, 0, 0L); - } - -// Clipboard operations - void Clear() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_CLEAR, 0, 0L); - } - - void Copy() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_COPY, 0, 0L); - } - - void Cut() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_CUT, 0, 0L); - } - - void Paste() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_PASTE, 0, 0L); - } -}; - -typedef CRichInkCtrlT CRichInkCtrl; - - -/////////////////////////////////////////////////////////////////////////////// -// CInkXCtrl - -template -class CInkXCtrlT : public TBase -{ -public: -// Constructors - CInkXCtrlT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CInkXCtrlT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - HWND hWnd = TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - ATLASSERT(hWnd != NULL); // Did you remember to call InitInkX() ?? - return hWnd; - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return WC_INKX; - } - - static UINT GetHotRecordingMessage() - { - return ::RegisterWindowMessage(szHotRecording); - } - - void ClearAll() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, IM_CLEARALL, 0, 0L); - } - - int GetData(BYTE* lpBuffer, INT cbBuffer) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(lpBuffer); - return (int)::SendMessage(m_hWnd, IM_GETDATA, (WPARAM)cbBuffer, (LPARAM)lpBuffer); - } - - int GetDataLen() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, IM_GETDATALEN, 0, 0L); - } - - CRichInkCtrl GetRichInk() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HWND)::SendMessage(m_hWnd, IM_GETRICHINK, 0, 0L); - } - - BOOL IsRecording() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, IM_RECORDING, 0, 0L); - } - - void ReInit() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, IM_REINIT, 0, 0L); - } - - void SetData(const BYTE* lpInkData, INT cbInkData) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(lpInkData); - ::SendMessage(m_hWnd, IM_SETDATA, (WPARAM)cbInkData, (LPARAM)lpInkData); - } - - void VoicePlay() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, IM_VOICE_PLAY, 0, 0L); - } - - BOOL IsVoicePlaying() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, IM_VOICE_PLAYING, 0, 0L); - } - - BOOL VoiceRecord() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, IM_VOICE_RECORD, 0, 0L); - } - - void VoiceStop() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, IM_VOICE_STOP, 0, 0L); - } - - void ShowVoiceBar(BOOL bShow = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, IM_VOICEBAR, (WPARAM)bShow, 0L); - } -}; - -typedef CInkXCtrlT CInkXCtrl; - -#endif // WIN32_PLATFORM_PSPC - - -/////////////////////////////////////////////////////////////////////////////// -// CVoiceRecorderCtrl - -template -class CVoiceRecorderCtrlT : public TBase -{ -public: -// Constructors - CVoiceRecorderCtrlT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CVoiceRecorderCtrlT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, const POINT pt, LPTSTR pstrFileName, UINT nID, DWORD dwStyle = 0) - { - ATLASSERT(pstrFileName != NULL); - CM_VOICE_RECORDER cmvr = { 0 }; - cmvr.cb = sizeof(CM_VOICE_RECORDER); - cmvr.dwStyle = dwStyle; - cmvr.xPos = pt.x; - cmvr.yPos = pt.y; - cmvr.hwndParent = hWndParent; - cmvr.id = nID; - cmvr.lpszRecordFileName = pstrFileName; - m_hWnd = VoiceRecorder_Create(&cmvr); - return m_hWnd; - } - - HWND Create(LPCM_VOICE_RECORDER pAttribs) - { - ATLASSERT(pAttribs); - m_hWnd = VoiceRecorder_Create(pAttribs); - return m_hWnd; - } - -// Attributes - void Record() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, VRM_RECORD, 0, 0L); - } - - void Play() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, VRM_PLAY, 0, 0L); - } - - void Stop() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, VRM_STOP, 0, 0L); - } - - void Cancel() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, VRM_CANCEL, 0, 0L); - } - - void Done() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, VRM_OK, 0, 0L); - } -}; - -typedef CVoiceRecorderCtrlT CVoiceRecorderCtrl; - - -#ifdef WIN32_PLATFORM_PSPC - -/////////////////////////////////////////////////////////////////////////////// -// CDocListCtrl - -template -class CDocListCtrlT : public TBase -{ -public: -// Attributes - DOCLISTCREATE m_dlc; - TCHAR m_szPath[MAX_PATH]; - -// Constructors - CDocListCtrlT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CDocListCtrlT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, WORD wId, LPCTSTR pszFolder = NULL, LPCTSTR pstrFilter = NULL, - WORD wFilterIndex = 0, DWORD dwFlags = DLF_SHOWEXTENSION) - { - ATLASSERT(pstrFilter != NULL); // It seems to need a filter badly!! - ::ZeroMemory(&m_dlc, sizeof(DOCLISTCREATE)); - ::ZeroMemory(m_szPath, sizeof(m_szPath)); - if(pszFolder != NULL) - ::lstrcpyn(m_szPath, pszFolder, MAX_PATH - 1); - m_dlc.dwStructSize = sizeof(DOCLISTCREATE); - m_dlc.hwndParent = hWndParent; - m_dlc.pszFolder = m_szPath; - m_dlc.pstrFilter = pstrFilter; - m_dlc.wFilterIndex = wFilterIndex; - m_dlc.wId = wId; - m_dlc.dwFlags = dwFlags; - m_hWnd = DocList_Create(&m_dlc); - return m_hWnd; - } - - HWND Create(DOCLISTCREATE* pDlc) - { - m_dlc = *pDlc; - m_hWnd = DocList_Create(&m_dlc); - return m_hWnd; - } - -// Attributes - void DeleteSel() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, DLM_DELETESEL, 0, 0L); - } - - void DisableUpdates() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, DLM_DISABLEUPDATES, 0, 0L); - } - - void EnableUpdates() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, DLM_ENABLEUPDATES, 0, 0L); - } - - int GetFilterIndex() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, DLM_GETFILTERINDEX, 0, 0L); - } - - int GetItemCount() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, DLM_GETITEMCOUNT, 0, 0L); - } - - int GetNextItem(int iIndex, DWORD dwRelation = LVNI_ALL) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, DLM_GETNEXTITEM, (WPARAM)iIndex, (LPARAM)dwRelation); - } - - int GetFirstItem(DWORD dwRelation = LVNI_ALL) const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, DLM_GETNEXTITEM, (WPARAM)-1, (LPARAM)dwRelation); - } - - BOOL GetNextWave(int* pIndex) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(pIndex); - return (BOOL)::SendMessage(m_hWnd, DLM_GETNEXTWAVE, 0, (LPARAM)pIndex); - } - - BOOL GetPrevWave(int* pIndex) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(pIndex); - return (BOOL)::SendMessage(m_hWnd, DLM_GETPREVWAVE, 0, (LPARAM)pIndex); - } - - int GetSelCount() const - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, DLM_GETSELCOUNT, 0, 0L); - } - - BOOL GetSelPathName(LPTSTR pstrPath, int cchMax) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(pstrPath); - return (BOOL)::SendMessage(m_hWnd, DLM_GETSELPATHNAME, (WPARAM)cchMax, (LPARAM)pstrPath); - } - - void ReceiveIR(LPCTSTR pstrPath) const - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(pstrPath); - ::SendMessage(m_hWnd, DLM_RECEIVEIR, 0, (LPARAM)pstrPath); - } - - void Refresh() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, DLM_REFRESH, 0, 0L); - } - - BOOL RenameMoveSelectedItems() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, DLM_RENAMEMOVE, 0, 0L); - } - - int SelectAll() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, DLM_SELECTALL, 0, 0L); - } - - HRESULT SelectItem(LPCTSTR pstrPath, BOOL bVisible = TRUE) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(pstrPath); - return (HRESULT)::SendMessage(m_hWnd, DLM_SELECTITEM, (WPARAM)bVisible, (LPARAM)pstrPath); - } - - void SendEMail(LPCTSTR pstrAttachment) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, DLM_SENDEMAIL, 0, (LPARAM)pstrAttachment); - } - - void SendIR(LPCTSTR pstrPath) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, DLM_SENDIR, 0, (LPARAM)pstrPath); - } - - HRESULT SetFilterIndex(int iIndex) - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HRESULT)::SendMessage(m_hWnd, DLM_SETFILTERINDEX, (WPARAM)iIndex, 0L); - } - - void SetFolder(LPCTSTR pstrPath) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(pstrPath); - ::SendMessage(m_hWnd, DLM_SETFOLDER, 0, (LPARAM)pstrPath); - } - - BOOL SetItemState(int iIndex, const LVITEM* pItem) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(pItem); - return (BOOL)::SendMessage(m_hWnd, DLM_SETITEMSTATE, (WPARAM)iIndex, (LPARAM)pItem); - } - - BOOL SetItemState(int iIndex, UINT uState, UINT uMask) - { - ATLASSERT(::IsWindow(m_hWnd)); - LV_ITEM lvi = { 0 }; - lvi.stateMask = uMask; - lvi.state = uState; - return (BOOL)::SendMessage(m_hWnd, DLM_SETITEMSTATE, (WPARAM)iIndex, (LPARAM)&lvi); - } - - void SetOneItem(int iIndex, LPCVOID pPA) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, DLM_SETONEITEM, (WPARAM)iIndex, (LPARAM)pPA); - } - - void SetSelect(int iIndex) - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, DLM_SETSELECT, (WPARAM)iIndex, 0L); - } - - void SetSelPathName(LPCTSTR pstrPath) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(pstrPath); - ::SendMessage(m_hWnd, DLM_SETSELPATHNAME, 0, (LPARAM)pstrPath); - } - - BOOL SetSortOrder() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, DLM_SETSORTORDER, 0, 0L); - } - - HRESULT Update() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HRESULT)::SendMessage(m_hWnd, DLM_UPDATE, 0, 0L); - } - - BOOL ValidateFolder() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (BOOL)::SendMessage(m_hWnd, DLM_VALIDATEFOLDER, 0, 0L); - } - -// Functions - BOOL GetFirstSelectedWaveFile(int* pIndex, LPTSTR szPath, const size_t cchPath) - { - ATLASSERT(::IsWindow(m_hWnd)); - return DocList_GetFirstSelectedWaveFile(m_hWnd, pIndex, szPath, cchPath); - } - - BOOL GetNextSelectedWaveFile(int* pIndex, LPTSTR szPath, const size_t cchPath) - { - ATLASSERT(::IsWindow(m_hWnd)); - return DocList_GetNextSelectedWaveFile(m_hWnd, pIndex, szPath, cchPath); - } -}; - -typedef CDocListCtrlT CDocListCtrl; - -#endif // WIN32_PLATFORM_PSPC - - -/////////////////////////////////////////////////////////////////////////////// -// CCapEdit - -template -class CCapEditT : public TBase -{ -public: -// Constructors - CCapEditT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CCapEditT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - HWND hWnd = /*TBase*/CWindow::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - ATLASSERT(hWnd != NULL); // Did you remember to call SHInitExtraControls() ?? - return hWnd; - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return WC_CAPEDIT; - } -}; - -typedef CCapEditT CCapEdit; - -/////////////////////////////////////////////////////////////////////////////// -// CTTStatic - -#ifndef WIN32_PLATFORM_WFSP // Tooltips not supported on SmartPhone - -template -class CTTStaticT : public TBase -{ -public: -// Constructors - CTTStaticT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CTTStaticT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - HWND hWnd = TBase::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - ATLASSERT(hWnd != NULL); // Did you remember to call SHInitExtraControls() ?? - return hWnd; - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return WC_TSTATIC; - } - -// Operations - BOOL SetToolTipText(LPCTSTR pstrTipText) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(pstrTipText); - ATLASSERT(lstrlen(pstrTipText)<= 253); - CTempBuffer buff; - LPTSTR pstr = buff.Allocate(lstrlen(pstrTipText) + 3); - if(pstr == NULL) - return FALSE; - ::lstrcpy(pstr, _T("~~")); - ::lstrcat(pstr, pstrTipText); - return SetWindowText(pstr); - } -}; - -typedef CTTStaticT CTTStatic; - - -/////////////////////////////////////////////////////////////////////////////// -// CTTButton - -template -class CTTButtonT : public TBase -{ -public: -// Constructors - CTTButtonT(HWND hWnd = NULL) : TBase(hWnd) - { } - - CTTButtonT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - HWND hWnd = TBase::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); - ATLASSERT(hWnd != NULL); // Did you remember to call SHInitExtraControls() ?? - return hWnd; - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return WC_TBUTTON; - } - -// Operations - BOOL SetToolTipText(LPCTSTR pstrTipText) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(pstrTipText); - ATLASSERT(lstrlen(pstrTipText)<= 253); - CTempBuffer buff; - LPTSTR pstr = buff.Allocate(lstrlen(pstrTipText) + 3); - if(pstr == NULL) - return FALSE; - ::lstrcpy(pstr, _T("~~")); - ::lstrcat(pstr, pstrTipText); - return SetWindowText(pstr); - } -}; - -typedef CTTButtonT CTTButton; - -#endif // !WIN32_PLATFORM_WFSP - - -// --- SmartPhone specific controls --- - -#ifdef WIN32_PLATFORM_WFSP - -/////////////////////////////////////////////////////////////////////////////// -// CSpinCtrlT - CSpinCtrl : SmartPhone adapted UpDown control - -template -class CSpinCtrlT : public CUpDownCtrlT< TBase > -{ -public: -// Constructors - CSpinCtrlT(HWND hWnd = NULL) : CUpDownCtrlT< TBase >(hWnd) - { } - - CSpinCtrlT< TBase >& operator =(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - - HWND Create(HWND hWndParent, HWND hBuddy, DWORD dwStyle, int nID, LPCTSTR szExpandedName = NULL) - { - ATLASSERT(::IsWindow(hWndParent)); - CUpDownCtrlT< TBase >::Create(hWndParent, NULL, szExpandedName, dwStyle, 0, nID, NULL); - ATLASSERT(m_hWnd != NULL); // Did you remember to call AtlInitCommonControls(ICC_UPDOWN_CLASS)? - if (hBuddy != NULL) - { - ATLASSERT(::IsWindow(hBuddy)); - SetBuddy(hBuddy); - } - return m_hWnd; - } -}; - -typedef CSpinCtrlT CSpinCtrl; - - -/////////////////////////////////////////////////////////////////////////////// -// CSpinned - SmartPhone association of control and Spin - -template -class CSpinned : public TBase -{ -public: - CSpinCtrl m_SpinCtrl; - DWORD m_dwSpinnedStyle; - -// Constructors - CSpinned(HWND hWnd = NULL) : TBase(hWnd) - { - m_dwSpinnedStyle = WS_VISIBLE | UDS_ALIGNRIGHT | UDS_EXPANDABLE; - - if (t_bExpandOnly == true) - m_dwSpinnedStyle |= UDS_NOSCROLL; - else - m_dwSpinnedStyle |= UDS_HORZ | UDS_ARROWKEYS | UDS_SETBUDDYINT | UDS_WRAP; - - if (hWnd != NULL) - AttachOrCreateSpinCtrl(); - } - - CSpinned& operator =(HWND hWnd) - { - Attach(hWnd); - return *this; - } - - void Attach(HWND hWnd) - { - ATLASSERT(!IsWindow()); - TBase* pT = static_cast(this); - pT->m_hWnd = hWnd; - if (hWnd != NULL) - AttachOrCreateSpinCtrl(); - } - - HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szExpandedName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - - TBase* pT = static_cast(this); - TBase::Create(hWndParent, rect, NULL, dwStyle, dwExStyle, MenuOrID, lpCreateParam); - ATLASSERT(pT->m_hWnd != NULL); - - m_SpinCtrl.Create(hWndParent, pT->m_hWnd, m_dwSpinnedStyle, ATL_IDW_SPIN_ID + (int)MenuOrID.m_hMenu, szExpandedName); - - ATLASSERT(m_SpinCtrl.m_hWnd != NULL); // Did you remember to call AtlInitCommonControls(ICC_UPDOWN_CLASS)? - - return pT->m_hWnd; - } - -// Attributes - CSpinCtrl& GetSpinCtrl() - { - return m_SpinCtrl; - } - -// Implementation - // Attach our existing SpinCtrl or create one - bool AttachOrCreateSpinCtrl() - { - TBase* pT = static_cast(this); - - HWND hSpin = ::GetDlgItem(pT->GetParent(), ATL_IDW_SPIN_ID + pT->GetDlgCtrlID()); - - if (hSpin != NULL) - { - m_SpinCtrl.Attach(hSpin); -#ifdef DEBUG - TCHAR sClassName[16]; - ::GetClassName(hSpin, sClassName, 16); - ATLASSERT(!_tcscmp(sClassName, UPDOWN_CLASS)); - ATLASSERT(m_SpinCtrl.GetBuddy().m_hWnd == pT->m_hWnd); -#endif // DEBUG - } - else - { - m_SpinCtrl.Create(pT->GetParent(), pT->m_hWnd, m_dwSpinnedStyle, ATL_IDW_SPIN_ID + pT->GetDlgCtrlID()); - } - - return m_SpinCtrl.m_hWnd != NULL; - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// CSpinListBox - SmartPhone spinned ListBox control -// CExpandListBox - SmartPhone expandable ListBox control -// CExpandEdit - SmartPhone expandable Edit control -// CExpandCapEdit - SmartPhone expandable CapEdit control - -typedef CSpinned CSpinListBox; -typedef CSpinned CExpandListBox; -typedef CSpinned CExpandEdit; -typedef CSpinned CExpandCapEdit; - -#endif // WIN32_PLATFORM_WFSP - -#endif // _WTL_CE_NO_CONTROLS - -}; // namespace WTL - -#endif // __ATLWINCE_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/atlwinx.h b/prog/3rdPartyLibs/wtl-8.1/include/atlwinx.h deleted file mode 100644 index a7e31d37d..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/atlwinx.h +++ /dev/null @@ -1,529 +0,0 @@ -// Windows Template Library - WTL version 8.1 -// Copyright (C) Microsoft Corporation. All rights reserved. -// -// This file is a part of the Windows Template Library. -// The use and distribution terms for this software are covered by the -// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php) -// which can be found in the file CPL.TXT at the root of this distribution. -// By using this software in any fashion, you are agreeing to be bound by -// the terms of this license. You must not remove this notice, or -// any other, from this software. - -#ifndef __ATLWINX_H__ -#define __ATLWINX_H__ - -#pragma once - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#ifndef __ATLAPP_H__ - #error atlwinx.h requires atlapp.h to be included first -#endif - -#if (_ATL_VER >= 0x0700) - #include -#endif // (_ATL_VER >= 0x0700) - - -/////////////////////////////////////////////////////////////////////////////// -// Classes in this file: -// -// _U_RECT -// _U_MENUorID -// _U_STRINGorID - - -/////////////////////////////////////////////////////////////////////////////// -// Command Chaining Macros - -#define CHAIN_COMMANDS(theChainClass) \ - if(uMsg == WM_COMMAND) \ - CHAIN_MSG_MAP(theChainClass) - -#define CHAIN_COMMANDS_ALT(theChainClass, msgMapID) \ - if(uMsg == WM_COMMAND) \ - CHAIN_MSG_MAP_ALT(theChainClass, msgMapID) - -#define CHAIN_COMMANDS_MEMBER(theChainMember) \ - if(uMsg == WM_COMMAND) \ - CHAIN_MSG_MAP_MEMBER(theChainMember) - -#define CHAIN_COMMANDS_ALT_MEMBER(theChainMember, msgMapID) \ - if(uMsg == WM_COMMAND) \ - CHAIN_MSG_MAP_ALT_MEMBER(theChainMember, msgMapID) - - -/////////////////////////////////////////////////////////////////////////////// -// Macros for parent message map to selectively reflect control messages - -// NOTE: ReflectNotifications is a member of ATL's CWindowImplRoot -// (and overridden in 2 cases - CContainedWindowT and CAxHostWindow) -// Since we can't modify ATL, we'll provide the needed additions -// in a separate function (that is not a member of CWindowImplRoot) - -namespace WTL -{ - -inline LRESULT WtlReflectNotificationsFiltered(HWND hWndParent, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled, - UINT uMsgFilter = WM_NULL, UINT_PTR idFromFilter = 0, HWND hWndChildFilter = NULL) -{ - if((uMsgFilter != WM_NULL) && (uMsgFilter != uMsg)) - { - // The notification message doesn't match the filter. - bHandled = FALSE; - return 1; - } - - HWND hWndChild = NULL; - UINT_PTR idFrom = 0; - - switch(uMsg) - { - case WM_COMMAND: - if(lParam != NULL) // not from a menu - { - hWndChild = (HWND)lParam; - idFrom = (UINT_PTR)LOWORD(wParam); - } - break; - case WM_NOTIFY: - hWndChild = ((LPNMHDR)lParam)->hwndFrom; - idFrom = ((LPNMHDR)lParam)->idFrom; - break; -#ifndef _WIN32_WCE - case WM_PARENTNOTIFY: - switch(LOWORD(wParam)) - { - case WM_CREATE: - case WM_DESTROY: - hWndChild = (HWND)lParam; - idFrom = (UINT_PTR)HIWORD(wParam); - break; - default: - hWndChild = ::GetDlgItem(hWndParent, HIWORD(wParam)); - idFrom = (UINT_PTR)::GetDlgCtrlID(hWndChild); - break; - } - break; -#endif // !_WIN32_WCE - case WM_DRAWITEM: - if(wParam) // not from a menu - { - hWndChild = ((LPDRAWITEMSTRUCT)lParam)->hwndItem; - idFrom = (UINT_PTR)wParam; - } - break; - case WM_MEASUREITEM: - if(wParam) // not from a menu - { - hWndChild = ::GetDlgItem(hWndParent, ((LPMEASUREITEMSTRUCT)lParam)->CtlID); - idFrom = (UINT_PTR)wParam; - } - break; - case WM_COMPAREITEM: - if(wParam) // not from a menu - { - hWndChild = ((LPCOMPAREITEMSTRUCT)lParam)->hwndItem; - idFrom = (UINT_PTR)wParam; - } - break; - case WM_DELETEITEM: - if(wParam) // not from a menu - { - hWndChild = ((LPDELETEITEMSTRUCT)lParam)->hwndItem; - idFrom = (UINT_PTR)wParam; - } - break; - case WM_VKEYTOITEM: - case WM_CHARTOITEM: - case WM_HSCROLL: - case WM_VSCROLL: - hWndChild = (HWND)lParam; - idFrom = (UINT_PTR)::GetDlgCtrlID(hWndChild); - break; - case WM_CTLCOLORBTN: - case WM_CTLCOLORDLG: - case WM_CTLCOLOREDIT: - case WM_CTLCOLORLISTBOX: - case WM_CTLCOLORMSGBOX: - case WM_CTLCOLORSCROLLBAR: - case WM_CTLCOLORSTATIC: - hWndChild = (HWND)lParam; - idFrom = (UINT_PTR)::GetDlgCtrlID(hWndChild); - break; - default: - break; - } - - if((hWndChild == NULL) || - ((hWndChildFilter != NULL) && (hWndChildFilter != hWndChild))) - { - // Either hWndChild isn't valid, or - // hWndChild doesn't match the filter. - bHandled = FALSE; - return 1; - } - - if((idFromFilter != 0) && (idFromFilter != idFrom)) - { - // The dialog control id doesn't match the filter. - bHandled = FALSE; - return 1; - } - - ATLASSERT(::IsWindow(hWndChild)); - LRESULT lResult = ::SendMessage(hWndChild, OCM__BASE + uMsg, wParam, lParam); - if((lResult == 0) && (uMsg >= WM_CTLCOLORMSGBOX) && (uMsg <= WM_CTLCOLORSTATIC)) - { - // Try to prevent problems with WM_CTLCOLOR* messages when - // the message wasn't really handled - bHandled = FALSE; - } - - return lResult; -} - -}; // namespace WTL - -// Try to prevent problems with WM_CTLCOLOR* messages when -// the message wasn't really handled -#define REFLECT_NOTIFICATIONS_EX() \ -{ \ - bHandled = TRUE; \ - lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \ - if((lResult == 0) && (uMsg >= WM_CTLCOLORMSGBOX) && (uMsg <= WM_CTLCOLORSTATIC)) \ - bHandled = FALSE; \ - if(bHandled) \ - return TRUE; \ -} - -#define REFLECT_NOTIFICATIONS_MSG_FILTERED(uMsgFilter) \ - { \ - bHandled = TRUE; \ - lResult = WTL::WtlReflectNotificationsFiltered(m_hWnd, uMsg, wParam, lParam, bHandled, uMsgFilter, 0, NULL); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECT_NOTIFICATIONS_ID_FILTERED(idFromFilter) \ - { \ - bHandled = TRUE; \ - lResult = WTL::WtlReflectNotificationsFiltered(m_hWnd, uMsg, wParam, lParam, bHandled, WM_NULL, idFromFilter, NULL); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECT_NOTIFICATIONS_HWND_FILTERED(hWndChildFilter) \ - { \ - bHandled = TRUE; \ - lResult = WTL::WtlReflectNotificationsFiltered(m_hWnd, uMsg, wParam, lParam, bHandled, WM_NULL, 0, hWndChildFilter); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECT_NOTIFICATIONS_MSG_ID_FILTERED(uMsgFilter, idFromFilter) \ - { \ - bHandled = TRUE; \ - lResult = WTL::WtlReflectNotificationsFiltered(m_hWnd, uMsg, wParam, lParam, bHandled, uMsgFilter, idFromFilter, NULL); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECT_NOTIFICATIONS_MSG_HWND_FILTERED(uMsgFilter, hWndChildFilter) \ - { \ - bHandled = TRUE; \ - lResult = WTL::WtlReflectNotificationsFiltered(m_hWnd, uMsg, wParam, lParam, bHandled, uMsgFilter, 0, hWndChildFilter); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECT_COMMAND(id, code) \ - if(uMsg == WM_COMMAND && id == LOWORD(wParam) && code == HIWORD(wParam)) \ - { \ - bHandled = TRUE; \ - lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECT_COMMAND_ID(id) \ - if(uMsg == WM_COMMAND && id == LOWORD(wParam)) \ - { \ - bHandled = TRUE; \ - lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECT_COMMAND_CODE(code) \ - if(uMsg == WM_COMMAND && code == HIWORD(wParam)) \ - { \ - bHandled = TRUE; \ - lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECT_COMMAND_RANGE(idFirst, idLast) \ - if(uMsg == WM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \ - { \ - bHandled = TRUE; \ - lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECT_COMMAND_RANGE_CODE(idFirst, idLast, code) \ - if(uMsg == WM_COMMAND && code == HIWORD(wParam) && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \ - { \ - bHandled = TRUE; \ - lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECT_NOTIFY(id, cd) \ - if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code) \ - { \ - bHandled = TRUE; \ - lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECT_NOTIFY_ID(id) \ - if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) \ - { \ - bHandled = TRUE; \ - lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECT_NOTIFY_CODE(cd) \ - if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \ - { \ - bHandled = TRUE; \ - lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECT_NOTIFY_RANGE(idFirst, idLast) \ - if(uMsg == WM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \ - { \ - bHandled = TRUE; \ - lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECT_NOTIFY_RANGE_CODE(idFirst, idLast, cd) \ - if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \ - { \ - bHandled = TRUE; \ - lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - - -/////////////////////////////////////////////////////////////////////////////// -// Reflected message handler macros for message maps (for ATL 3.0) - -#if (_ATL_VER < 0x0700) - -#define REFLECTED_COMMAND_HANDLER(id, code, func) \ - if(uMsg == OCM_COMMAND && id == LOWORD(wParam) && code == HIWORD(wParam)) \ - { \ - bHandled = TRUE; \ - lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECTED_COMMAND_ID_HANDLER(id, func) \ - if(uMsg == OCM_COMMAND && id == LOWORD(wParam)) \ - { \ - bHandled = TRUE; \ - lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECTED_COMMAND_CODE_HANDLER(code, func) \ - if(uMsg == OCM_COMMAND && code == HIWORD(wParam)) \ - { \ - bHandled = TRUE; \ - lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECTED_COMMAND_RANGE_HANDLER(idFirst, idLast, func) \ - if(uMsg == OCM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \ - { \ - bHandled = TRUE; \ - lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECTED_COMMAND_RANGE_CODE_HANDLER(idFirst, idLast, code, func) \ - if(uMsg == OCM_COMMAND && code == HIWORD(wParam) && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \ - { \ - bHandled = TRUE; \ - lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECTED_NOTIFY_HANDLER(id, cd, func) \ - if(uMsg == OCM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code) \ - { \ - bHandled = TRUE; \ - lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECTED_NOTIFY_ID_HANDLER(id, func) \ - if(uMsg == OCM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) \ - { \ - bHandled = TRUE; \ - lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECTED_NOTIFY_CODE_HANDLER(cd, func) \ - if(uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \ - { \ - bHandled = TRUE; \ - lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECTED_NOTIFY_RANGE_HANDLER(idFirst, idLast, func) \ - if(uMsg == OCM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \ - { \ - bHandled = TRUE; \ - lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECTED_NOTIFY_RANGE_CODE_HANDLER(idFirst, idLast, cd, func) \ - if(uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \ - { \ - bHandled = TRUE; \ - lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#endif // (_ATL_VER < 0x0700) - - -/////////////////////////////////////////////////////////////////////////////// -// Dual argument helper classes (for ATL 3.0) - -#if (_ATL_VER < 0x0700) - -namespace ATL -{ - -class _U_RECT -{ -public: - _U_RECT(LPRECT lpRect) : m_lpRect(lpRect) - { } - _U_RECT(RECT& rc) : m_lpRect(&rc) - { } - LPRECT m_lpRect; -}; - -class _U_MENUorID -{ -public: - _U_MENUorID(HMENU hMenu) : m_hMenu(hMenu) - { } - _U_MENUorID(UINT nID) : m_hMenu((HMENU)LongToHandle(nID)) - { } - HMENU m_hMenu; -}; - -class _U_STRINGorID -{ -public: - _U_STRINGorID(LPCTSTR lpString) : m_lpstr(lpString) - { } - _U_STRINGorID(UINT nID) : m_lpstr(MAKEINTRESOURCE(nID)) - { } - LPCTSTR m_lpstr; -}; - -}; // namespace ATL - -#endif // (_ATL_VER < 0x0700) - - -namespace WTL -{ - -/////////////////////////////////////////////////////////////////////////////// -// Forward notifications support for message maps (for ATL 3.0) - -#if (_ATL_VER < 0x0700) - -// forward notifications support -#define FORWARD_NOTIFICATIONS() \ - { \ - bHandled = TRUE; \ - lResult = WTL::Atl3ForwardNotifications(m_hWnd, uMsg, wParam, lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -static LRESULT Atl3ForwardNotifications(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) -{ - LRESULT lResult = 0; - switch(uMsg) - { - case WM_COMMAND: - case WM_NOTIFY: -#ifndef _WIN32_WCE - case WM_PARENTNOTIFY: -#endif // !_WIN32_WCE - case WM_DRAWITEM: - case WM_MEASUREITEM: - case WM_COMPAREITEM: - case WM_DELETEITEM: - case WM_VKEYTOITEM: - case WM_CHARTOITEM: - case WM_HSCROLL: - case WM_VSCROLL: - case WM_CTLCOLORBTN: - case WM_CTLCOLORDLG: - case WM_CTLCOLOREDIT: - case WM_CTLCOLORLISTBOX: - case WM_CTLCOLORMSGBOX: - case WM_CTLCOLORSCROLLBAR: - case WM_CTLCOLORSTATIC: - lResult = ::SendMessage(::GetParent(hWnd), uMsg, wParam, lParam); - break; - default: - bHandled = FALSE; - break; - } - return lResult; -} - -#endif // (_ATL_VER < 0x0700) - -}; // namespace WTL - -#endif // __ATLWINX_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/ATLComMem.h b/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/ATLComMem.h deleted file mode 100644 index 6a352615a..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/ATLComMem.h +++ /dev/null @@ -1,138 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLCOMMEM_H__ -#define __ATLCOMMEM_H__ - -#pragma once - -#ifndef __ATLMEM_H__ - #error ATLComMem.h requires atlmem.h to be included first -#endif // __ATLMEM_H__ - -#include -namespace ATL -{ - -class CComHeap : - public IAtlMemMgr -{ -// IAtlMemMgr -public: - virtual void* Allocate( size_t nBytes ) throw() - { -#ifdef _WIN64 - if( nBytes > INT_MAX ) - { - return( NULL ); - } -#endif - return( ::CoTaskMemAlloc( ULONG( nBytes ) ) ); - } - virtual void Free( void* p ) throw() - { - ::CoTaskMemFree( p ); - } - virtual void* Reallocate( void* p, size_t nBytes ) throw() - { -#ifdef _WIN64 - if( nBytes > INT_MAX ) - { - return( NULL ); - } -#endif - return( ::CoTaskMemRealloc( p, ULONG( nBytes ) ) ); - } - virtual size_t GetSize( void* p ) throw() - { - CComPtr< IMalloc > pMalloc; - - HRESULT hr = ::CoGetMalloc( 1, &pMalloc ); - if (FAILED(hr)) - return 0; - - return( pMalloc->GetSize( p ) ); - } -}; - -///////////////////////////////////////////////////////////////////////////// -// OLE task memory allocation support - -inline LPWSTR AtlAllocTaskWideString(LPCWSTR lpszString) throw() -{ - if (lpszString == NULL) - return NULL; - UINT nSize = (UINT)((wcslen(lpszString)+1) * sizeof(WCHAR)); - LPWSTR lpszResult = (LPWSTR)CoTaskMemAlloc(nSize); - if (lpszResult != NULL) - memcpy(lpszResult, lpszString, nSize); - return lpszResult; -} - -inline LPWSTR AtlAllocTaskWideString(LPCSTR lpszString) throw() -{ - if (lpszString == NULL) - return NULL; - UINT nLen = lstrlenA(lpszString)+1; - LPWSTR lpszResult = (LPWSTR)CoTaskMemAlloc(nLen*sizeof(WCHAR)); - if (lpszResult != NULL) - { - int nRet = MultiByteToWideChar(CP_ACP, 0, lpszString, -1, lpszResult, nLen); - ATLASSERT(nRet != 0); - if (nRet == 0) - { - CoTaskMemFree(lpszResult); - lpszResult = NULL; - } - } - return lpszResult; -} - -inline LPSTR AtlAllocTaskAnsiString(LPCWSTR lpszString) throw() -{ - if (lpszString == NULL) - return NULL; - UINT nBytes = (UINT)((wcslen(lpszString)+1)*2); - LPSTR lpszResult = (LPSTR)CoTaskMemAlloc(nBytes); - if (lpszResult != NULL) - { - int nRet = WideCharToMultiByte(CP_ACP, 0, lpszString, -1, lpszResult, nBytes, NULL, NULL); - ATLASSERT(nRet != 0); - if (nRet == 0) - { - CoTaskMemFree(lpszResult); - lpszResult = NULL; - } - } - return lpszResult; -} - -inline LPSTR AtlAllocTaskAnsiString(LPCSTR lpszString) throw() -{ - if (lpszString == NULL) - return NULL; - UINT nSize = lstrlenA(lpszString)+1; - LPSTR lpszResult = (LPSTR)CoTaskMemAlloc(nSize); - if (lpszResult != NULL) - memcpy(lpszResult, lpszString, nSize); - return lpszResult; -} - -#ifdef _UNICODE - #define AtlAllocTaskString(x) AtlAllocTaskWideString(x) -#else - #define AtlAllocTaskString(x) AtlAllocTaskAnsiString(x) -#endif - -#define AtlAllocTaskOleString(x) AtlAllocTaskWideString(x) - -} // namespace ATL - -#endif // __ATLCOMMEM_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlalloc.h b/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlalloc.h deleted file mode 100644 index 60518da0e..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlalloc.h +++ /dev/null @@ -1,433 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#pragma once -#ifndef __ATLALLOC_H__ -#define __ATLALLOC_H__ -#endif - -namespace ATL -{ -///////////////////////////////////////////////////////////////////////////// -// Allocation helpers - -class CCRTAllocator -{ -public: - static void* Reallocate(void* p, size_t nBytes) throw() - { - return realloc(p, nBytes); - } - - static void* Allocate(size_t nBytes) throw() - { - return malloc(nBytes); - } - - static void Free(void* p) throw() - { - free(p); - } -}; - -class CLocalAllocator -{ -public: - static void* Allocate(size_t nBytes) throw() - { - return ::LocalAlloc(LMEM_FIXED, nBytes); - } - static void* Reallocate(void* p, size_t nBytes) throw() - { - return ::LocalReAlloc(p, nBytes, 0); - } - static void Free(void* p) throw() - { - ::LocalFree(p); - } -}; - -class CGlobalAllocator -{ -public: - static void* Allocate(size_t nBytes) throw() - { - return ::GlobalAlloc(GMEM_FIXED, nBytes); - } - static void* Reallocate(void* p, size_t nBytes) throw() - { - return ::GlobalReAlloc(p, nBytes, 0); - } - static void Free(void* p) throw() - { - ::GlobalFree(p); - } -}; - -template -class CHeapPtrBase -{ -protected: - CHeapPtrBase() throw() : - m_pData(NULL) - { - } - CHeapPtrBase(CHeapPtrBase& p) throw() - { - m_pData = p.Detach(); // Transfer ownership - } - explicit CHeapPtrBase(T* pData) throw() : - m_pData(pData) - { - } - -public: - ~CHeapPtrBase() throw() - { - Free(); - } - -protected: - CHeapPtrBase& operator=(CHeapPtrBase& p) throw() - { - if(m_pData != p.m_pData) - Attach(p.Detach()); // Transfer ownership - return *this; - } - -public: - operator T*() const throw() - { - return m_pData; - } - - T* operator->() const throw() - { - ATLASSERT(m_pData != NULL); - return m_pData; - } - - T** operator&() throw() - { - ATLASSERT(m_pData == NULL); - return &m_pData; - } - - // Allocate a buffer with the given number of bytes - bool AllocateBytes(size_t nBytes) throw() - { - ATLASSERT(m_pData == NULL); - m_pData = static_cast(Allocator::Allocate(nBytes)); - if (m_pData == NULL) - return false; - - return true; - } - - // Attach to an existing pointer (takes ownership) - void Attach(T* pData) throw() - { - Allocator::Free(m_pData); - m_pData = pData; - } - - // Detach the pointer (releases ownership) - T* Detach() throw() - { - T* pTemp = m_pData; - m_pData = NULL; - return pTemp; - } - - // Free the memory pointed to, and set the pointer to NULL - void Free() throw() - { - Allocator::Free(m_pData); - m_pData = NULL; - } - - // Reallocate the buffer to hold a given number of bytes - bool ReallocateBytes(size_t nBytes) throw() - { - T* pNew; - - pNew = static_cast(Allocator::Reallocate(m_pData, nBytes)); - if (pNew == NULL) - return false; - m_pData = pNew; - - return true; - } - -public: - T* m_pData; -}; - -template -class CHeapPtr : - public CHeapPtrBase -{ -public: - CHeapPtr() throw() - { - } - CHeapPtr(CHeapPtr& p) throw() : - CHeapPtrBase(p) - { - } - explicit CHeapPtr(T* p) throw() : - CHeapPtrBase(p) - { - } - - CHeapPtr& operator=(CHeapPtr& p) throw() - { - CHeapPtrBase::operator=(p); - - return *this; - } - - // Allocate a buffer with the given number of elements - bool Allocate(size_t nElements = 1) throw() - { - return AllocateBytes(nElements*sizeof(T)); - } - - // Reallocate the buffer to hold a given number of elements - bool Reallocate(size_t nElements) throw() - { - return ReallocateBytes(nElements*sizeof(T)); - } -}; - -template< typename T, int t_nFixedBytes = 128, class Allocator = CCRTAllocator > -class CTempBuffer -{ -public: - CTempBuffer() throw() : - m_p( NULL ) - { - } - CTempBuffer( size_t nElements ) throw( ... ) : - m_p( NULL ) - { - Allocate( nElements ); - } - - ~CTempBuffer() throw() - { - if( m_p != reinterpret_cast< T* >( m_abFixedBuffer ) ) - { - FreeHeap(); - } - } - - operator T*() const throw() - { - return( m_p ); - } - T* operator->() const throw() - { - ATLASSERT( m_p != NULL ); - return( m_p ); - } - - T* Allocate( size_t nElements ) throw( ... ) - { - return( AllocateBytes( nElements*sizeof( T ) ) ); - } - - T* Reallocate( size_t nElements ) throw( ... ) - { - size_t nNewSize = nElements*sizeof( T ) ; - - if (m_p == NULL) - return AllocateBytes(nNewSize); - - if (nNewSize > t_nFixedBytes) - { - if( m_p == reinterpret_cast< T* >( m_abFixedBuffer ) ) - { - // We have to allocate from the heap and copy the contents into the new buffer - AllocateHeap(nNewSize); - memcpy(m_p, m_abFixedBuffer, t_nFixedBytes); - } - else - { - ReAllocateHeap( nNewSize ); - } - } - else - { - m_p = reinterpret_cast< T* >( m_abFixedBuffer ); - } - - return m_p; - } - - T* AllocateBytes( size_t nBytes ) - { - ATLASSERT( m_p == NULL ); - if( nBytes > t_nFixedBytes ) - { - AllocateHeap( nBytes ); - } - else - { - m_p = reinterpret_cast< T* >( m_abFixedBuffer ); - } - - return( m_p ); - } - -private: - ATL_NOINLINE void AllocateHeap( size_t nBytes ) - { - T* p = static_cast< T* >( Allocator::Allocate( nBytes ) ); - if( p == NULL ) - { - AtlThrow( E_OUTOFMEMORY ); - } - m_p = p; - } - - ATL_NOINLINE void ReAllocateHeap( size_t nNewSize) - { - T* p = static_cast< T* >( Allocator::Reallocate(m_p, nNewSize) ); - if ( p == NULL ) - { - AtlThrow( E_OUTOFMEMORY ); - } - m_p = p; - } - - ATL_NOINLINE void FreeHeap() throw() - { - Allocator::Free( m_p ); - } - -private: - T* m_p; - BYTE m_abFixedBuffer[t_nFixedBytes]; -}; - -// Allocating memory on the stack without causing stack overflow. -// Only use these through the _ATL_SAFE_ALLOCA_* macros -namespace _ATL_SAFE_ALLOCA_IMPL -{ -#ifndef _ATL_STACK_MARGIN -#define _ATL_STACK_MARGIN 0x2000 // Minimum stack available after call to _ATL_SAFE_ALLOCA -#endif - -// Verifies if sufficient space is available on the stack. -inline bool _AtlVerifyStackAvailable(SIZE_T Size) -{ - bool bStackAvailable = true; - - __try - { - PVOID p = _alloca(Size + _ATL_STACK_MARGIN); - (p); - } - __except ((EXCEPTION_STACK_OVERFLOW == GetExceptionCode()) ? - EXCEPTION_EXECUTE_HANDLER : - EXCEPTION_CONTINUE_SEARCH) - { - bStackAvailable = false; - _resetstkoflw(); - } - return bStackAvailable; -} - -// Helper Classes to manage heap buffers for _ATL_SAFE_ALLOCA -template < class Allocator> -class CAtlSafeAllocBufferManager -{ -private : - struct CAtlSafeAllocBufferNode - { - CAtlSafeAllocBufferNode* m_pNext; -#if defined(_M_IX86) - BYTE _pad[4]; -#elif defined(_M_IA64) - BYTE _pad[8]; -#elif - #error Only supported for X86 and IA64 -#endif - void* GetData() - { - return (this + 1); - } - }; - - CAtlSafeAllocBufferNode* m_pHead; -public : - - CAtlSafeAllocBufferManager() : m_pHead(NULL) {}; - void* Allocate(SIZE_T nRequestedSize) - { - CAtlSafeAllocBufferNode *p = (CAtlSafeAllocBufferNode*)Allocator::Allocate(nRequestedSize + sizeof(CAtlSafeAllocBufferNode)); - if (p == NULL) - return NULL; - - // Add buffer to the list - p->m_pNext = m_pHead; - m_pHead = p; - - return p->GetData(); - } - ~CAtlSafeAllocBufferManager() - { - // Walk the list and free the buffers - while (m_pHead != NULL) - { - CAtlSafeAllocBufferNode* p = m_pHead; - m_pHead = m_pHead->m_pNext; - Allocator::Free(p); - } - } -}; - -} // namespace _ATL_SAFE_ALLOCA_IMPL - -} // namespace ATL - -// Use one of the following macros before using _ATL_SAFE_ALLOCA -// EX version allows specifying a different heap allocator -#define USES_ATL_SAFE_ALLOCA_EX(x) ATL::_ATL_SAFE_ALLOCA_IMPL::CAtlSafeAllocBufferManager _AtlSafeAllocaManager - -#ifndef USES_ATL_SAFE_ALLOCA -#define USES_ATL_SAFE_ALLOCA USES_ATL_SAFE_ALLOCA_EX(ATL::CCRTAllocator) -#endif - -// nRequestedSize - requested size in bytes -// nThreshold - size in bytes beyond which memory is allocated from the heap. - -// Defining _ATL_SAFE_ALLOCA_ALWAYS_ALLOCATE_THRESHOLD_SIZE always allocates the size specified -// for threshold if the stack space is available irrespective of requested size. -// This available for testing purposes. It will help determine the max stack usage due to _alloca's - -#ifdef _ATL_SAFE_ALLOCA_ALWAYS_ALLOCATE_THRESHOLD_SIZE -#define _ATL_SAFE_ALLOCA(nRequestedSize, nThreshold) \ - ((nRequestedSize <= nThreshold && ATL::_ATL_SAFE_ALLOCA_IMPL::_AtlVerifyStackAvailable(nThreshold) ) ? \ - _alloca(nThreshold) : \ - ((ATL::_ATL_SAFE_ALLOCA_IMPL::_AtlVerifyStackAvailable(nThreshold)) ? _alloca(nThreshold) : 0), \ - _AtlSafeAllocaManager.Allocate(nRequestedSize)) -#else -#define _ATL_SAFE_ALLOCA(nRequestedSize, nThreshold) \ - ((nRequestedSize <= nThreshold && ATL::_ATL_SAFE_ALLOCA_IMPL::_AtlVerifyStackAvailable(nRequestedSize) ) ? \ - _alloca(nRequestedSize) : \ - _AtlSafeAllocaManager.Allocate(nRequestedSize)) -#endif - -// Use 1024 bytes as the default threshold in ATL -#ifndef _ATL_SAFE_ALLOCA_DEF_THRESHOLD -#define _ATL_SAFE_ALLOCA_DEF_THRESHOLD 1024 -#endif diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlbase.h b/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlbase.h deleted file mode 100644 index 8c3aa248d..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlbase.h +++ /dev/null @@ -1,6697 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLBASE_H__ -#define __ATLBASE_H__ - -#pragma once - -// Warnings outside of the push/pop sequence will be disabled for all user -// projects. The only warnings that should be disabled outside the push/pop -// are warnings that are a) benign and b) will show up in user projects -// without being directly caused by the user - -#pragma warning(disable: 4505) // unreferenced local function has been removed -#pragma warning(disable: 4710) // function couldn't be inlined -#pragma warning(disable: 4514) // unreferenced inlines are common - -// These two warnings will occur in any class that contains or derives from a -// class with a private copy constructor or copy assignment operator. -#pragma warning(disable: 4511) // copy constructor could not be generated -#pragma warning(disable: 4512) // assignment operator could not be generated -#pragma warning(disable: 4355) // 'this' : used in base member initializer list - -#ifdef _ATL_ALL_WARNINGS -#pragma warning( push ) -#endif - -#pragma warning(disable : 4668) // is not defined as a preprocessor macro, replacing with '0' for '#if/#elif -#pragma warning(disable : 4820) // padding added after member -#pragma warning(disable : 4917) // a GUID can only be associated with a class, interface or namespace - -#pragma warning(disable : 4217) // member template functions cannot be used for copy-assignment or copy-construction - -#pragma warning(disable: 4127) // constant expression -#pragma warning(disable: 4097) // typedef name used as synonym for class-name -#pragma warning(disable: 4786) // identifier was truncated in the debug information -#pragma warning(disable: 4291) // allow placement new -#pragma warning(disable: 4201) // nameless unions are part of C++ -#pragma warning(disable: 4103) // pragma pack -#pragma warning(disable: 4268) // const static/global data initialized to zeros - -#pragma warning (push) - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif -#ifndef ATL_NO_LEAN_AND_MEAN -#define ATL_NO_LEAN_AND_MEAN -#endif - -#include - -#ifndef _WINSOCKAPI_ -#include -#endif - -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include - -#if !defined(_ATL_MIN_CRT) & defined(_MT) -#include -#include // for _beginthreadex, _endthreadex -#endif - -#ifdef _DEBUG -#include -#include -#endif - -#include -#include -#include -#include -#include - -#define _ATL_TYPELIB_INDEX_LENGTH 10 -#define _ATL_QUOTES_SPACE 2 - -#pragma pack(push, _ATL_PACKING) - -#ifndef _ATL_NO_DEFAULT_LIBS - -#if defined(_ATL_DLL) - #pragma comment(lib, "atl.lib") -#endif - -#ifdef _DEBUG - #pragma comment(lib, "atlsd.lib") -#else - #pragma comment(lib, "atls.lib") -#ifdef _ATL_MIN_CRT - #pragma comment(lib, "atlmincrt.lib") -#endif -#endif - -#endif // !_ATL_NO_DEFAULT_LIBS - -extern "C" const __declspec(selectany) GUID LIBID_ATLLib = {0x44EC0535,0x400F,0x11D0,{0x9D,0xCD,0x00,0xA0,0xC9,0x03,0x91,0xD3}}; -extern "C" const __declspec(selectany) CLSID CLSID_Registrar = {0x44EC053A,0x400F,0x11D0,{0x9D,0xCD,0x00,0xA0,0xC9,0x03,0x91,0xD3}}; -extern "C" const __declspec(selectany) IID IID_IRegistrar = {0x44EC053B,0x400F,0x11D0,{0x9D,0xCD,0x00,0xA0,0xC9,0x03,0x91,0xD3}}; -extern "C" const __declspec(selectany) IID IID_IAxWinHostWindow = {0xb6ea2050,0x048a,0x11d1,{0x82,0xb9,0x00,0xc0,0x4f,0xb9,0x94,0x2e}}; -extern "C" const __declspec(selectany) IID IID_IAxWinAmbientDispatch = {0xb6ea2051,0x048a,0x11d1,{0x82,0xb9,0x00,0xc0,0x4f,0xb9,0x94,0x2e}}; -extern "C" const __declspec(selectany) IID IID_IInternalConnection = {0x72AD0770,0x6A9F,0x11d1,{0xBC,0xEC,0x00,0x60,0x08,0x8F,0x44,0x4E}}; -extern "C" const __declspec(selectany) IID IID_IDocHostUIHandlerDispatch = {0x425B5AF0,0x65F1,0x11d1,{0x96,0x11,0x00,0x00,0xF8,0x1E,0x0D,0x0D}}; -extern "C" const __declspec(selectany) IID IID_IAxWinHostWindowLic = {0x3935BDA8,0x4ED9,0x495c,{0x86,0x50,0xE0,0x1F,0xC1,0xE3,0x8A,0x4B}}; -extern "C" const __declspec(selectany) IID IID_IAxWinAmbientDispatchEx = {0xB2D0778B,0xAC99,0x4c58,{0xA5,0xC8,0xE7,0x72,0x4E,0x53,0x16,0xB5}}; - -// REVIEW: Temp until it gets back into UUID.LIB -extern "C" const __declspec(selectany) CLSID CLSID_StdGlobalInterfaceTable = {0x00000323,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}}; - - -#ifndef _delayimp_h -extern "C" IMAGE_DOS_HEADER __ImageBase; -#endif - -#ifdef _AFX -void AFXAPI AfxOleLockApp(); -void AFXAPI AfxOleUnlockApp(); -#endif // _AFX - -namespace ATL -{ - -struct _ATL_CATMAP_ENTRY -{ - int iType; - const CATID* pcatid; -}; - -#define _ATL_CATMAP_ENTRY_END 0 -#define _ATL_CATMAP_ENTRY_IMPLEMENTED 1 -#define _ATL_CATMAP_ENTRY_REQUIRED 2 - -typedef HRESULT (WINAPI _ATL_CREATORFUNC)(void* pv, REFIID riid, LPVOID* ppv); -typedef HRESULT (WINAPI _ATL_CREATORARGFUNC)(void* pv, REFIID riid, LPVOID* ppv, DWORD_PTR dw); -typedef HRESULT (WINAPI _ATL_MODULEFUNC)(DWORD_PTR dw); -typedef LPCTSTR (WINAPI _ATL_DESCRIPTIONFUNC)(); -typedef const struct _ATL_CATMAP_ENTRY* (_ATL_CATMAPFUNC)(); -typedef void (__stdcall _ATL_TERMFUNC)(DWORD_PTR dw); - -struct _ATL_TERMFUNC_ELEM -{ - _ATL_TERMFUNC* pFunc; - DWORD_PTR dw; - _ATL_TERMFUNC_ELEM* pNext; -}; - -/* -struct _ATL_OBJMAP_ENTRY20 -{ - const CLSID* pclsid; - HRESULT (WINAPI *pfnUpdateRegistry)(BOOL bRegister); - _ATL_CREATORFUNC* pfnGetClassObject; - _ATL_CREATORFUNC* pfnCreateInstance; - IUnknown* pCF; - DWORD dwRegister; - _ATL_DESCRIPTIONFUNC* pfnGetObjectDescription; -}; -*/ - -// Can't inherit from _ATL_OBJMAP_ENTRY20 -// because it messes up the OBJECT_MAP macros -struct _ATL_OBJMAP_ENTRY30 -{ - const CLSID* pclsid; - HRESULT (WINAPI *pfnUpdateRegistry)(BOOL bRegister); - _ATL_CREATORFUNC* pfnGetClassObject; - _ATL_CREATORFUNC* pfnCreateInstance; - IUnknown* pCF; - DWORD dwRegister; - _ATL_DESCRIPTIONFUNC* pfnGetObjectDescription; - _ATL_CATMAPFUNC* pfnGetCategoryMap; - HRESULT WINAPI RevokeClassObject() - { - if (dwRegister == 0) - return S_OK; - return CoRevokeClassObject(dwRegister); - } - HRESULT WINAPI RegisterClassObject(DWORD dwClsContext, DWORD dwFlags) - { - IUnknown* p = NULL; - if (pfnGetClassObject == NULL) - return S_OK; - HRESULT hRes = pfnGetClassObject(pfnCreateInstance, __uuidof(IUnknown), (LPVOID*) &p); - if (SUCCEEDED(hRes)) - hRes = CoRegisterClassObject(*pclsid, p, dwClsContext, dwFlags, &dwRegister); - if (p != NULL) - p->Release(); - return hRes; - } -// Added in ATL 3.0 - void (WINAPI *pfnObjectMain)(bool bStarting); -}; - -typedef _ATL_OBJMAP_ENTRY30 _ATL_OBJMAP_ENTRY; - -// Auto Object Map - -#if defined(_M_IA64) || defined(_M_IX86) - -#pragma section("ATL$__a", read, shared) -#pragma section("ATL$__z", read, shared) -#pragma section("ATL$__m", read, shared) -extern "C" -{ -__declspec(selectany) __declspec(allocate("ATL$__a")) _ATL_OBJMAP_ENTRY* __pobjMapEntryFirst = NULL; -__declspec(selectany) __declspec(allocate("ATL$__z")) _ATL_OBJMAP_ENTRY* __pobjMapEntryLast = NULL; -} - -#if !defined(_M_IA64) -#pragma comment(linker, "/merge:ATL=.rdata") -#endif - -#else - -extern "C" -{ -__declspec(selectany) _ATL_OBJMAP_ENTRY* __pobjMapEntryFirst = NULL; -__declspec(selectany) _ATL_OBJMAP_ENTRY* __pobjMapEntryLast = NULL; -} - -#endif // defined(_M_IA64) || defined(_M_IX86) - -struct _ATL_REGMAP_ENTRY -{ - LPCOLESTR szKey; - LPCOLESTR szData; -}; - -struct _AtlCreateWndData -{ - void* m_pThis; - DWORD m_dwThreadID; - _AtlCreateWndData* m_pNext; -}; - - -// perfmon registration/unregistration function definitions -typedef HRESULT (*_ATL_PERFREGFUNC)(HINSTANCE hDllInstance); -typedef HRESULT (*_ATL_PERFUNREGFUNC)(); -__declspec(selectany) _ATL_PERFREGFUNC _pPerfRegFunc = NULL; -__declspec(selectany) _ATL_PERFUNREGFUNC _pPerfUnRegFunc = NULL; - -///////////////////////////////////////////////////////////////////////////// -// Threading Model Support - -template< class TLock > -class CComCritSecLock -{ -public: - CComCritSecLock( TLock& cs, bool bInitialLock = true ); - ~CComCritSecLock() throw(); - - HRESULT Lock() throw(); - void Unlock() throw(); - -// Implementation -private: - TLock& m_cs; - bool m_bLocked; - -// Private to avoid accidental use - CComCritSecLock( const CComCritSecLock& ) throw(); - CComCritSecLock& operator=( const CComCritSecLock& ) throw(); -}; - -template< class TLock > -inline CComCritSecLock< TLock >::CComCritSecLock( TLock& cs, bool bInitialLock ) : - m_cs( cs ), - m_bLocked( false ) -{ - if( bInitialLock ) - { - HRESULT hr; - - hr = Lock(); - if( FAILED( hr ) ) - { - AtlThrow( hr ); - } - } -} - -template< class TLock > -inline CComCritSecLock< TLock >::~CComCritSecLock() throw() -{ - if( m_bLocked ) - { - Unlock(); - } -} - -template< class TLock > -inline HRESULT CComCritSecLock< TLock >::Lock() throw() -{ - HRESULT hr; - - ATLASSERT( !m_bLocked ); - hr = m_cs.Lock(); - if( FAILED( hr ) ) - { - return( hr ); - } - m_bLocked = true; - - return( S_OK ); -} - -template< class TLock > -inline void CComCritSecLock< TLock >::Unlock() throw() -{ - ATLASSERT( m_bLocked ); - m_cs.Unlock(); - m_bLocked = false; -} - -class CComMultiThreadModelNoCS -{ -public: - static ULONG WINAPI Increment(LPLONG p) throw() {return InterlockedIncrement(p);} - static ULONG WINAPI Decrement(LPLONG p) throw() {return InterlockedDecrement(p);} - typedef CComFakeCriticalSection AutoCriticalSection; - typedef CComFakeCriticalSection CriticalSection; - typedef CComMultiThreadModelNoCS ThreadModelNoCS; -}; - -class CComMultiThreadModel -{ -public: - static ULONG WINAPI Increment(LPLONG p) throw() {return InterlockedIncrement(p);} - static ULONG WINAPI Decrement(LPLONG p) throw() {return InterlockedDecrement(p);} - typedef CComAutoCriticalSection AutoCriticalSection; - typedef CComCriticalSection CriticalSection; - typedef CComMultiThreadModelNoCS ThreadModelNoCS; -}; - -class CComSingleThreadModel -{ -public: - static ULONG WINAPI Increment(LPLONG p) throw() {return ++(*p);} - static ULONG WINAPI Decrement(LPLONG p) throw() {return --(*p);} - typedef CComFakeCriticalSection AutoCriticalSection; - typedef CComFakeCriticalSection CriticalSection; - typedef CComSingleThreadModel ThreadModelNoCS; -}; - -#if defined(_ATL_SINGLE_THREADED) - -#if defined(_ATL_APARTMENT_THREADED) || defined(_ATL_FREE_THREADED) -#pragma message ("More than one global threading model defined.") -#endif - - typedef CComSingleThreadModel CComObjectThreadModel; - typedef CComSingleThreadModel CComGlobalsThreadModel; - -#elif defined(_ATL_APARTMENT_THREADED) - -#if defined(_ATL_SINGLE_THREADED) || defined(_ATL_FREE_THREADED) -#pragma message ("More than one global threading model defined.") -#endif - - typedef CComSingleThreadModel CComObjectThreadModel; - typedef CComMultiThreadModel CComGlobalsThreadModel; - -#elif defined(_ATL_FREE_THREADED) - -#if defined(_ATL_SINGLE_THREADED) || defined(_ATL_APARTMENT_THREADED) -#pragma message ("More than one global threading model defined.") -#endif - - typedef CComMultiThreadModel CComObjectThreadModel; - typedef CComMultiThreadModel CComGlobalsThreadModel; - -#else -#pragma message ("No global threading model defined") -#endif - -///////////////////////////////////////////////////////////////////////////// -// Module - -// Used by COM related code in ATL -struct _ATL_COM_MODULE70 -{ - UINT cbSize; - HINSTANCE m_hInstTypeLib; - _ATL_OBJMAP_ENTRY** m_ppAutoObjMapFirst; - _ATL_OBJMAP_ENTRY** m_ppAutoObjMapLast; - CComCriticalSection m_csObjMap; -}; -typedef _ATL_COM_MODULE70 _ATL_COM_MODULE; - - -// Used by Windowing code in ATL -struct _ATL_WIN_MODULE70 -{ - UINT cbSize; - CComCriticalSection m_csWindowCreate; - _AtlCreateWndData* m_pCreateWndList; - CSimpleArray m_rgWindowClassAtoms; -}; -typedef _ATL_WIN_MODULE70 _ATL_WIN_MODULE; - - -struct _ATL_MODULE70 -{ - UINT cbSize; - LONG m_nLockCnt; - _ATL_TERMFUNC_ELEM* m_pTermFuncs; - CComCriticalSection m_csStaticDataInitAndTypeInfo; -}; -typedef _ATL_MODULE70 _ATL_MODULE; - -///////////////////////////////////////////////////////////////////////////// -//This define makes debugging asserts easier. -#define _ATL_SIMPLEMAPENTRY ((ATL::_ATL_CREATORARGFUNC*)1) - -struct _ATL_INTMAP_ENTRY -{ - const IID* piid; // the interface id (IID) - DWORD_PTR dw; - _ATL_CREATORARGFUNC* pFunc; //NULL:end, 1:offset, n:ptr -}; - -///////////////////////////////////////////////////////////////////////////// -// Thunks for __stdcall member functions - -#if defined(_M_IX86) -#pragma pack(push,1) -struct _stdcallthunk -{ - DWORD m_mov; // mov dword ptr [esp+0x4], pThis (esp+0x4 is hWnd) - DWORD m_this; // - BYTE m_jmp; // jmp WndProc - DWORD m_relproc; // relative jmp - void Init(DWORD_PTR proc, void* pThis) - { - m_mov = 0x042444C7; //C7 44 24 0C - m_this = PtrToUlong(pThis); - m_jmp = 0xe9; - m_relproc = DWORD((INT_PTR)proc - ((INT_PTR)this+sizeof(_stdcallthunk))); - // write block from data cache and - // flush from instruction cache - FlushInstructionCache(GetCurrentProcess(), this, sizeof(_stdcallthunk)); - } - //some thunks will dynamically allocate the memory for the code - void* GetCodeAddress() - { - return this; - } -}; -#pragma pack(pop) -#elif defined (_M_ALPHA) -// For ALPHA we will stick the this pointer into a0, which is where -// the HWND is. However, we don't actually need the HWND so this is OK. -#pragma pack(push,4) -struct _stdcallthunk //this should come out to 20 bytes -{ - DWORD ldah_at; // ldah at, HIWORD(func) - DWORD ldah_a0; // ldah a0, HIWORD(this) - DWORD lda_at; // lda at, LOWORD(func)(at) - DWORD lda_a0; // lda a0, LOWORD(this)(a0) - DWORD jmp; // jmp zero,(at),0 - void Init(DWORD_PTR proc, void* pThis) - { - ldah_at = (0x279f0000 | HIWORD(proc)) + (LOWORD(proc)>>15); - ldah_a0 = (0x261f0000 | HIWORD(pThis)) + (LOWORD(pThis)>>15); - lda_at = 0x239c0000 | LOWORD(proc); - lda_a0 = 0x22100000 | LOWORD(pThis); - jmp = 0x6bfc0000; - // write block from data cache and - // flush from instruction cache - FlushInstructionCache(GetCurrentProcess(), this, sizeof(_stdcallthunk)); - } - void* GetCodeAddress() - { - return this; - } -}; -#pragma pack(pop) -#elif defined(_SH3_) -#pragma pack(push,4) -struct _stdcallthunk // this should come out to 16 bytes -{ - WORD m_mov_r0; // mov.l pFunc,r0 - WORD m_mov_r1; // mov.l pThis,r1 - WORD m_jmp; // jmp @r0 - WORD m_nop; // nop - DWORD m_pFunc; - DWORD m_pThis; - void Init(DWORD_PTR proc, void* pThis) - { - m_mov_r0 = 0xd001; - m_mov_r1 = 0xd402; - m_jmp = 0x402b; - m_nop = 0x0009; - m_pFunc = (DWORD)proc; - m_pThis = (DWORD)pThis; - // write block from data cache and - // flush from instruction cache - FlushInstructionCache(GetCurrentProcess(), this, sizeof(_stdcallthunk)); - } - void* GetCodeAddress() - { - return this; - } -}; -#pragma pack(pop) -#elif defined(_MIPS_) -#pragma pack(push,4) -struct _stdcallthunk -{ - WORD m_pFuncHi; - WORD m_lui_t0; // lui t0,PFUNC_HIGH - WORD m_pFuncLo; - WORD m_ori_t0; // ori t0,t0,PFUNC_LOW - WORD m_pThisHi; - WORD m_lui_a0; // lui a0,PTHIS_HIGH - DWORD m_jr_t0; // jr t0 - WORD m_pThisLo; - WORD m_ori_a0; // ori a0,PTHIS_LOW - void Init(DWORD_PTR proc, void* pThis) - { - m_pFuncHi = HIWORD(proc); - m_lui_t0 = 0x3c08; - m_pFuncLo = LOWORD(proc); - m_ori_t0 = 0x3508; - m_pThisHi = HIWORD(pThis); - m_lui_a0 = 0x3c04; - m_jr_t0 = 0x01000008; - m_pThisLo = LOWORD(pThis); - m_ori_a0 = 0x3484; - // write block from data cache and - // flush from instruction cache - FlushInstructionCache(GetCurrentProcess(), this, sizeof(_stdcallthunk)); - } - void* GetCodeAddress() - { - return this; - } -}; -#pragma pack(pop) -#elif defined(_ARM_) -#pragma pack(push,4) -struct _stdcallthunk // this should come out to 16 bytes -{ - DWORD m_mov_r0; // mov r0, pThis - DWORD m_mov_pc; // mov pc, pFunc - DWORD m_pThis; - DWORD m_pFunc; - void Init(DWORD_PTR proc, void* pThis) - { - m_mov_r0 = 0xE59F0000; - m_mov_pc = 0xE59FF000; - m_pThis = (DWORD)pThis; - m_pFunc = (DWORD)proc; - // write block from data cache and - // flush from instruction cache - FlushInstructionCache(GetCurrentProcess(), this, sizeof(_stdcallthunk)); - } - void* GetCodeAddress() - { - return this; - } -}; -#pragma pack(pop) -#elif defined(_M_IA64) -#pragma pack(push,8) -#pragma section(".base", long, read, write) // Declare section to place _StdCallThunkProc in. Must be 'long' -extern "C" __declspec( allocate( ".base" ) ) void* _StdCallThunkProc; // Actually, a global label exported from StdCallThunk.s -struct _FuncDesc -{ - void* pfn; - void* gp; -}; -struct _stdcallthunk -{ - _FuncDesc m_funcdesc; - void* m_pFunc; - void* m_pThis; - void Init(DWORD_PTR proc, void* pThis) - { - m_funcdesc.pfn = &_StdCallThunkProc; // Pointer to actual beginning of StdCallThunkProc - m_funcdesc.gp = &m_pFunc; - m_pFunc = reinterpret_cast< void* >( proc ); - m_pThis = pThis; - ::FlushInstructionCache( GetCurrentProcess(), this, sizeof( _stdcallthunk ) ); - } - void* GetCodeAddress() - { - return( &m_funcdesc ); - } -}; -#pragma pack(pop) -#else -#error Only ARM, ALPHA, SH3, MIPS, IA64, and X86 supported -#endif - -#if defined(_M_IX86) -class CDynamicStdCallThunk -{ -public: - _stdcallthunk *pThunk; - - CDynamicStdCallThunk() - { - pThunk = NULL; - } - - ~CDynamicStdCallThunk() - { - if (pThunk) - HeapFree(GetProcessHeap(), 0, pThunk); - } - - void Init(DWORD_PTR proc, void *pThis) - { - if (pThunk == NULL) - pThunk = static_cast<_stdcallthunk *>(HeapAlloc(GetProcessHeap(), - HEAP_GENERATE_EXCEPTIONS, sizeof(_stdcallthunk))); - ATLASSERT(pThunk); - pThunk->Init(proc, pThis); - } - - void* GetCodeAddress() - { - ATLASSERT(pThunk); - return pThunk->GetCodeAddress(); - } -}; -typedef CDynamicStdCallThunk CStdCallThunk; -#else -typedef _stdcallthunk CStdCallThunk; -#endif // _M_IX86 - -///////////////////////////////////////////////////////////////////////////// -// Global Functions - -///////////////////////////////////////////////////////////////////////////// -// QI Support - -ATLAPI AtlInternalQueryInterface(void* pThis, - const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject); - -///////////////////////////////////////////////////////////////////////////// -// Inproc Marshaling helpers - -ATLAPI AtlFreeMarshalStream(IStream* pStream); -ATLAPI AtlMarshalPtrInProc(IUnknown* pUnk, const IID& iid, IStream** ppStream); -ATLAPI AtlUnmarshalPtr(IStream* pStream, const IID& iid, IUnknown** ppUnk); - -ATLAPI_(BOOL) AtlWaitWithMessageLoop(HANDLE hEvent); - -///////////////////////////////////////////////////////////////////////////// -// Connection Point Helpers - -ATLAPI AtlAdvise(IUnknown* pUnkCP, IUnknown* pUnk, const IID& iid, LPDWORD pdw); -ATLAPI AtlUnadvise(IUnknown* pUnkCP, const IID& iid, DWORD dw); - -///////////////////////////////////////////////////////////////////////////// -// IDispatch Error handling - -ATLAPI AtlSetErrorInfo(const CLSID& clsid, LPCOLESTR lpszDesc, - DWORD dwHelpID, LPCOLESTR lpszHelpFile, const IID& iid, HRESULT hRes, - HINSTANCE hInst); - -///////////////////////////////////////////////////////////////////////////// -// Module - -ATLAPI AtlComModuleRegisterClassObjects(_ATL_COM_MODULE* pComModule, DWORD dwClsContext, DWORD dwFlags); -ATLAPI AtlComModuleRevokeClassObjects(_ATL_COM_MODULE* pComModule); - -ATLAPI AtlComModuleGetClassObject(_ATL_COM_MODULE* pComModule, REFCLSID rclsid, REFIID riid, LPVOID* ppv); - -ATLAPI AtlComModuleRegisterServer(_ATL_COM_MODULE* pComModule, BOOL bRegTypeLib, const CLSID* pCLSID = NULL); -ATLAPI AtlComModuleUnregisterServer(_ATL_COM_MODULE* pComModule, BOOL bUnRegTypeLib, const CLSID* pCLSID = NULL); - -ATLAPI AtlRegisterClassCategoriesHelper( REFCLSID clsid, const struct _ATL_CATMAP_ENTRY* pCatMap, BOOL bRegister ); - -ATLAPI AtlUpdateRegistryFromResourceD(HINSTANCE hInst, LPCOLESTR lpszRes, - BOOL bRegister, struct _ATL_REGMAP_ENTRY* pMapEntries, IRegistrar* pReg = NULL); - -ATLAPI AtlRegisterTypeLib(HINSTANCE hInstTypeLib, LPCOLESTR lpszIndex); -ATLAPI AtlUnRegisterTypeLib(HINSTANCE hInstTypeLib, LPCOLESTR lpszIndex); -ATLAPI AtlLoadTypeLib(HINSTANCE hInstTypeLib, LPCOLESTR lpszIndex, BSTR* pbstrPath, ITypeLib** ppTypeLib); - -ATLAPI_(DWORD) AtlGetVersion(void* pReserved); - -ATLAPI AtlModuleAddTermFunc(_ATL_MODULE* pModule, _ATL_TERMFUNC* pFunc, DWORD_PTR dw); -ATLAPI_(void) AtlCallTermFunc(_ATL_MODULE* pModule); - -ATLAPI AtlWinModuleInit(_ATL_WIN_MODULE* pWinModule); -ATLAPI AtlWinModuleTerm(_ATL_WIN_MODULE* pWinModule, HINSTANCE hInst); -ATLAPI_(void) AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE* pWinModule, _AtlCreateWndData* pData, void* pObject); -ATLAPI_(void*) AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE* pWinModule); - -///////////////////////////////////////////////////////////////////////////// -// Get Registrar object from ATL DLL. - -#if !defined(_ATL_STATIC_REGISTRY) -#ifdef _ATL_DLL_IMPL -extern "C" HRESULT __stdcall AtlCreateRegistrar(IRegistrar** ppReg); -#else -extern "C" __declspec(dllimport) HRESULT __stdcall AtlCreateRegistrar(IRegistrar** ppReg); -#endif -#endif - -///////////////////////////////////////////////////////////////////////////// -// GUID comparison -inline BOOL WINAPI InlineIsEqualUnknown(REFGUID rguid1) -{ - return ( - ((PLONG) &rguid1)[0] == 0 && - ((PLONG) &rguid1)[1] == 0 && -#ifdef _ATL_BYTESWAP - ((PLONG) &rguid1)[2] == 0xC0000000 && - ((PLONG) &rguid1)[3] == 0x00000046); -#else - ((PLONG) &rguid1)[2] == 0x000000C0 && - ((PLONG) &rguid1)[3] == 0x46000000); -#endif -} - - - -template -LPCTSTR AtlDebugGetClassName(T*) -{ -#ifdef _DEBUG - const _ATL_INTMAP_ENTRY* pEntries = T::_GetEntries(); - return (LPCTSTR)pEntries[-1].dw; -#else - return NULL; -#endif -} - -// Validation macro for OUT pointer -// Used in QI and CreateInstance -#define _ATL_VALIDATE_OUT_POINTER(x) ATLASSERT(x != NULL); \ - if (x == NULL) \ - return E_POINTER; \ - *x = NULL - -///////////////////////////////////////////////////////////////////////////// -// Win32 libraries - -#ifndef _ATL_NO_DEFAULT_LIBS -#pragma comment(lib, "kernel32.lib") -#pragma comment(lib, "user32.lib") -#pragma comment(lib, "advapi32.lib") -#pragma comment(lib, "ole32.lib") -#pragma comment(lib, "shell32.lib") -#pragma comment(lib, "oleaut32.lib") -#pragma comment(lib, "uuid.lib") -#pragma comment(lib, "shlwapi.lib") -#endif // !_ATL_NO_DEFAULT_LIBS - -template< typename T > -class CAutoVectorPtr -{ -public: - CAutoVectorPtr() throw() : - m_p( NULL ) - { - } - CAutoVectorPtr( CAutoVectorPtr< T >& p ) throw() - { - m_p = p.Detach(); // Transfer ownership - } - explicit CAutoVectorPtr( T* p ) throw() : - m_p( p ) - { - } - ~CAutoVectorPtr() throw() - { - Free(); - } - - operator T*() const throw() - { - return( m_p ); - } - - CAutoVectorPtr< T >& operator=( CAutoVectorPtr< T >& p ) throw() - { - Free(); - Attach( p.Detach() ); // Transfer ownership - - return( *this ); - } - - // Allocate the vector - bool Allocate( size_t nElements ) throw() - { - ATLASSERT( m_p == NULL ); - ATLTRY( m_p = new T[nElements] ); - if( m_p == NULL ) - { - return( false ); - } - - return( true ); - } - // Attach to an existing pointer (takes ownership) - void Attach( T* p ) throw() - { - ATLASSERT( m_p == NULL ); - m_p = p; - } - // Detach the pointer (releases ownership) - T* Detach() throw() - { - T* p; - - p = m_p; - m_p = NULL; - - return( p ); - } - // Delete the vector pointed to, and set the pointer to NULL - void Free() throw() - { - delete[] m_p; - m_p = NULL; - } - -public: - T* m_p; -}; - -template< typename T > -class CAutoPtr -{ -public: - CAutoPtr() throw() : - m_p( NULL ) - { - } - template< typename TSrc > - CAutoPtr( CAutoPtr< TSrc >& p ) throw() - { - m_p = p.Detach(); // Transfer ownership - } - template<> - CAutoPtr( CAutoPtr< T >& p ) throw() - { - m_p = p.Detach(); // Transfer ownership - } - explicit CAutoPtr( T* p ) throw() : - m_p( p ) - { - } - ~CAutoPtr() throw() - { - Free(); - } - - // Templated version to allow pBase = pDerived - template< typename TSrc > - CAutoPtr< T >& operator=( CAutoPtr< TSrc >& p ) throw() - { - Free(); - Attach( p.Detach() ); // Transfer ownership - - return( *this ); - } - template<> - CAutoPtr< T >& operator=( CAutoPtr< T >& p ) throw() - { - Free(); - Attach( p.Detach() ); // Transfer ownership - - return( *this ); - } - - operator T*() const throw() - { - return( m_p ); - } - T* operator->() const throw() - { - ATLASSERT( m_p != NULL ); - return( m_p ); - } - - // Attach to an existing pointer (takes ownership) - void Attach( T* p ) throw() - { - ATLASSERT( m_p == NULL ); - m_p = p; - } - // Detach the pointer (releases ownership) - T* Detach() throw() - { - T* p; - - p = m_p; - m_p = NULL; - - return( p ); - } - // Delete the object pointed to, and set the pointer to NULL - void Free() throw() - { - delete m_p; - m_p = NULL; - } - -public: - T* m_p; -}; - -// static_cast_auto template functions. Used like static_cast, only they work on CAutoPtr objects -template< class Dest, class Src > -Dest* static_cast_auto( const CAutoPtr< Src >& pSrc ) throw() -{ - return( static_cast< Dest* >( static_cast< Src* >( pSrc ) ) ); -} - - -class CComAllocator -{ -public: - static void* Reallocate(void* p, size_t nBytes) throw() - { -#ifdef _WIN64 - if( nBytes > INT_MAX ) - { - return( NULL ); - } -#endif - return ::CoTaskMemRealloc(p, ULONG(nBytes)); - } - static void* Allocate(size_t nBytes) throw() - { -#ifdef _WIN64 - if( nBytes > INT_MAX ) - { - return( NULL ); - } -#endif - return ::CoTaskMemAlloc(ULONG(nBytes)); - } - static void Free(void* p) throw() - { - ::CoTaskMemFree(p); - } -}; - -template -class CComHeapPtr : - public CHeapPtr -{ -public: - CComHeapPtr() throw() - { - } - - explicit CComHeapPtr(T* pData) throw() : - CHeapPtr(pData) - { - } -}; - -template -T* AtlSafeRealloc(T* pT, size_t cEls) throw() -{ - T* pTemp; - - pTemp = static_cast(Reallocator::Reallocate(pT, cEls*sizeof(T))); - if (pTemp == NULL) - { - Reallocator::Free(pT); - return NULL; - } - pT = pTemp; - return pTemp; -} - -class CHandle -{ -public: - CHandle() throw(); - CHandle( CHandle& h ) throw(); - explicit CHandle( HANDLE h ) throw(); - ~CHandle() throw(); - - CHandle& operator=( CHandle& h ) throw(); - - operator HANDLE() const throw(); - - // Attach to an existing handle (takes ownership). - void Attach( HANDLE h ) throw(); - // Detach the handle from the object (releases ownership). - HANDLE Detach() throw(); - - // Close the handle. - void Close() throw(); - -public: - HANDLE m_h; -}; - -inline CHandle::CHandle() throw() : - m_h( NULL ) -{ -} - -inline CHandle::CHandle( CHandle& h ) throw() : - m_h( NULL ) -{ - Attach( h.Detach() ); -} - -inline CHandle::CHandle( HANDLE h ) throw() : - m_h( h ) -{ -} - -inline CHandle::~CHandle() throw() -{ - if( m_h != NULL ) - { - Close(); - } -} - -inline CHandle& CHandle::operator=( CHandle& h ) throw() -{ - if( this != &h ) - { - if( m_h != NULL ) - { - Close(); - } - Attach( h.Detach() ); - } - - return( *this ); -} - -inline CHandle::operator HANDLE() const throw() -{ - return( m_h ); -} - -inline void CHandle::Attach( HANDLE h ) throw() -{ - ATLASSERT( m_h == NULL ); - m_h = h; // Take ownership -} - -inline HANDLE CHandle::Detach() throw() -{ - HANDLE h; - - h = m_h; // Release ownership - m_h = NULL; - - return( h ); -} - -inline void CHandle::Close() throw() -{ - if( m_h != NULL ) - { - ::CloseHandle( m_h ); - m_h = NULL; - } -} - -class CCritSecLock -{ -public: - CCritSecLock( CRITICAL_SECTION& cs, bool bInitialLock = true ); - ~CCritSecLock() throw(); - - void Lock(); - void Unlock() throw(); - -// Implementation -private: - CRITICAL_SECTION& m_cs; - bool m_bLocked; - -// Private to avoid accidental use - CCritSecLock( const CCritSecLock& ) throw(); - CCritSecLock& operator=( const CCritSecLock& ) throw(); -}; - -inline CCritSecLock::CCritSecLock( CRITICAL_SECTION& cs, bool bInitialLock ) : - m_cs( cs ), - m_bLocked( false ) -{ - if( bInitialLock ) - { - Lock(); - } -} - -inline CCritSecLock::~CCritSecLock() throw() -{ - if( m_bLocked ) - { - Unlock(); - } -} - -inline void CCritSecLock::Lock() -{ - ATLASSERT( !m_bLocked ); - __try - { - ::EnterCriticalSection( &m_cs ); - } - __except( EXCEPTION_EXECUTE_HANDLER ) - { - AtlThrow( E_OUTOFMEMORY ); - } - m_bLocked = true; -} - -inline void CCritSecLock::Unlock() throw() -{ - ATLASSERT( m_bLocked ); - ::LeaveCriticalSection( &m_cs ); - m_bLocked = false; -} - -///////////////////////////////////////////////////////////////////////////// -// Interface debugging -#if defined(_ATL_DEBUG_INTERFACES) || defined(_ATL_DEBUG_QI) -HRESULT WINAPI AtlDumpIID(REFIID iid, LPCTSTR pszClassName, HRESULT hr) throw(); -#endif // _ATL_DEBUG_INTERFACES || _ATL_DEBUG_QI - -#ifdef _ATL_DEBUG_INTERFACES - -struct _QIThunk -{ - STDMETHOD(QueryInterface)(REFIID iid, void** pp) - { - ATLASSERT(m_dwRef >= 0); - ATLASSERT(m_pUnk != NULL); - return m_pUnk->QueryInterface(iid, pp); - } - STDMETHOD_(ULONG, AddRef)() - { - ATLASSERT(m_pUnk != NULL); - if (m_bBreak) - DebugBreak(); - m_pUnk->AddRef(); - return InternalAddRef(); - } - ULONG InternalAddRef() - { - ATLASSERT(m_pUnk != NULL); - if (m_bBreak) - DebugBreak(); - ATLASSERT(m_dwRef >= 0); - long l = InterlockedIncrement(&m_dwRef); - - TCHAR buf[512]; - wsprintf(buf, _T("QIThunk - %-10d\tAddRef :\tObject = 0x%08x\tRefcount = %d\t"), m_nIndex, m_pUnk, m_dwRef); - OutputDebugString(buf); - AtlDumpIID(m_iid, m_lpszClassName, S_OK); - - if (l > m_dwMaxRef) - m_dwMaxRef = l; - return l; - } - STDMETHOD_(ULONG, Release)(); - - STDMETHOD(f3)(); - STDMETHOD(f4)(); - STDMETHOD(f5)(); - STDMETHOD(f6)(); - STDMETHOD(f7)(); - STDMETHOD(f8)(); - STDMETHOD(f9)(); - STDMETHOD(f10)(); - STDMETHOD(f11)(); - STDMETHOD(f12)(); - STDMETHOD(f13)(); - STDMETHOD(f14)(); - STDMETHOD(f15)(); - STDMETHOD(f16)(); - STDMETHOD(f17)(); - STDMETHOD(f18)(); - STDMETHOD(f19)(); - STDMETHOD(f20)(); - STDMETHOD(f21)(); - STDMETHOD(f22)(); - STDMETHOD(f23)(); - STDMETHOD(f24)(); - STDMETHOD(f25)(); - STDMETHOD(f26)(); - STDMETHOD(f27)(); - STDMETHOD(f28)(); - STDMETHOD(f29)(); - STDMETHOD(f30)(); - STDMETHOD(f31)(); - STDMETHOD(f32)(); - STDMETHOD(f33)(); - STDMETHOD(f34)(); - STDMETHOD(f35)(); - STDMETHOD(f36)(); - STDMETHOD(f37)(); - STDMETHOD(f38)(); - STDMETHOD(f39)(); - STDMETHOD(f40)(); - STDMETHOD(f41)(); - STDMETHOD(f42)(); - STDMETHOD(f43)(); - STDMETHOD(f44)(); - STDMETHOD(f45)(); - STDMETHOD(f46)(); - STDMETHOD(f47)(); - STDMETHOD(f48)(); - STDMETHOD(f49)(); - STDMETHOD(f50)(); - STDMETHOD(f51)(); - STDMETHOD(f52)(); - STDMETHOD(f53)(); - STDMETHOD(f54)(); - STDMETHOD(f55)(); - STDMETHOD(f56)(); - STDMETHOD(f57)(); - STDMETHOD(f58)(); - STDMETHOD(f59)(); - STDMETHOD(f60)(); - STDMETHOD(f61)(); - STDMETHOD(f62)(); - STDMETHOD(f63)(); - STDMETHOD(f64)(); - STDMETHOD(f65)(); - STDMETHOD(f66)(); - STDMETHOD(f67)(); - STDMETHOD(f68)(); - STDMETHOD(f69)(); - STDMETHOD(f70)(); - STDMETHOD(f71)(); - STDMETHOD(f72)(); - STDMETHOD(f73)(); - STDMETHOD(f74)(); - STDMETHOD(f75)(); - STDMETHOD(f76)(); - STDMETHOD(f77)(); - STDMETHOD(f78)(); - STDMETHOD(f79)(); - STDMETHOD(f80)(); - STDMETHOD(f81)(); - STDMETHOD(f82)(); - STDMETHOD(f83)(); - STDMETHOD(f84)(); - STDMETHOD(f85)(); - STDMETHOD(f86)(); - STDMETHOD(f87)(); - STDMETHOD(f88)(); - STDMETHOD(f89)(); - STDMETHOD(f90)(); - STDMETHOD(f91)(); - STDMETHOD(f92)(); - STDMETHOD(f93)(); - STDMETHOD(f94)(); - STDMETHOD(f95)(); - STDMETHOD(f96)(); - STDMETHOD(f97)(); - STDMETHOD(f98)(); - STDMETHOD(f99)(); - STDMETHOD(f100)(); - STDMETHOD(f101)(); - STDMETHOD(f102)(); - STDMETHOD(f103)(); - STDMETHOD(f104)(); - STDMETHOD(f105)(); - STDMETHOD(f106)(); - STDMETHOD(f107)(); - STDMETHOD(f108)(); - STDMETHOD(f109)(); - STDMETHOD(f110)(); - STDMETHOD(f111)(); - STDMETHOD(f112)(); - STDMETHOD(f113)(); - STDMETHOD(f114)(); - STDMETHOD(f115)(); - STDMETHOD(f116)(); - STDMETHOD(f117)(); - STDMETHOD(f118)(); - STDMETHOD(f119)(); - STDMETHOD(f120)(); - STDMETHOD(f121)(); - STDMETHOD(f122)(); - STDMETHOD(f123)(); - STDMETHOD(f124)(); - STDMETHOD(f125)(); - STDMETHOD(f126)(); - STDMETHOD(f127)(); - STDMETHOD(f128)(); - STDMETHOD(f129)(); - STDMETHOD(f130)(); - STDMETHOD(f131)(); - STDMETHOD(f132)(); - STDMETHOD(f133)(); - STDMETHOD(f134)(); - STDMETHOD(f135)(); - STDMETHOD(f136)(); - STDMETHOD(f137)(); - STDMETHOD(f138)(); - STDMETHOD(f139)(); - STDMETHOD(f140)(); - STDMETHOD(f141)(); - STDMETHOD(f142)(); - STDMETHOD(f143)(); - STDMETHOD(f144)(); - STDMETHOD(f145)(); - STDMETHOD(f146)(); - STDMETHOD(f147)(); - STDMETHOD(f148)(); - STDMETHOD(f149)(); - STDMETHOD(f150)(); - STDMETHOD(f151)(); - STDMETHOD(f152)(); - STDMETHOD(f153)(); - STDMETHOD(f154)(); - STDMETHOD(f155)(); - STDMETHOD(f156)(); - STDMETHOD(f157)(); - STDMETHOD(f158)(); - STDMETHOD(f159)(); - STDMETHOD(f160)(); - STDMETHOD(f161)(); - STDMETHOD(f162)(); - STDMETHOD(f163)(); - STDMETHOD(f164)(); - STDMETHOD(f165)(); - STDMETHOD(f166)(); - STDMETHOD(f167)(); - STDMETHOD(f168)(); - STDMETHOD(f169)(); - STDMETHOD(f170)(); - STDMETHOD(f171)(); - STDMETHOD(f172)(); - STDMETHOD(f173)(); - STDMETHOD(f174)(); - STDMETHOD(f175)(); - STDMETHOD(f176)(); - STDMETHOD(f177)(); - STDMETHOD(f178)(); - STDMETHOD(f179)(); - STDMETHOD(f180)(); - STDMETHOD(f181)(); - STDMETHOD(f182)(); - STDMETHOD(f183)(); - STDMETHOD(f184)(); - STDMETHOD(f185)(); - STDMETHOD(f186)(); - STDMETHOD(f187)(); - STDMETHOD(f188)(); - STDMETHOD(f189)(); - STDMETHOD(f190)(); - STDMETHOD(f191)(); - STDMETHOD(f192)(); - STDMETHOD(f193)(); - STDMETHOD(f194)(); - STDMETHOD(f195)(); - STDMETHOD(f196)(); - STDMETHOD(f197)(); - STDMETHOD(f198)(); - STDMETHOD(f199)(); - STDMETHOD(f200)(); - STDMETHOD(f201)(); - STDMETHOD(f202)(); - STDMETHOD(f203)(); - STDMETHOD(f204)(); - STDMETHOD(f205)(); - STDMETHOD(f206)(); - STDMETHOD(f207)(); - STDMETHOD(f208)(); - STDMETHOD(f209)(); - STDMETHOD(f210)(); - STDMETHOD(f211)(); - STDMETHOD(f212)(); - STDMETHOD(f213)(); - STDMETHOD(f214)(); - STDMETHOD(f215)(); - STDMETHOD(f216)(); - STDMETHOD(f217)(); - STDMETHOD(f218)(); - STDMETHOD(f219)(); - STDMETHOD(f220)(); - STDMETHOD(f221)(); - STDMETHOD(f222)(); - STDMETHOD(f223)(); - STDMETHOD(f224)(); - STDMETHOD(f225)(); - STDMETHOD(f226)(); - STDMETHOD(f227)(); - STDMETHOD(f228)(); - STDMETHOD(f229)(); - STDMETHOD(f230)(); - STDMETHOD(f231)(); - STDMETHOD(f232)(); - STDMETHOD(f233)(); - STDMETHOD(f234)(); - STDMETHOD(f235)(); - STDMETHOD(f236)(); - STDMETHOD(f237)(); - STDMETHOD(f238)(); - STDMETHOD(f239)(); - STDMETHOD(f240)(); - STDMETHOD(f241)(); - STDMETHOD(f242)(); - STDMETHOD(f243)(); - STDMETHOD(f244)(); - STDMETHOD(f245)(); - STDMETHOD(f246)(); - STDMETHOD(f247)(); - STDMETHOD(f248)(); - STDMETHOD(f249)(); - STDMETHOD(f250)(); - STDMETHOD(f251)(); - STDMETHOD(f252)(); - STDMETHOD(f253)(); - STDMETHOD(f254)(); - STDMETHOD(f255)(); - STDMETHOD(f256)(); - STDMETHOD(f257)(); - STDMETHOD(f258)(); - STDMETHOD(f259)(); - STDMETHOD(f260)(); - STDMETHOD(f261)(); - STDMETHOD(f262)(); - STDMETHOD(f263)(); - STDMETHOD(f264)(); - STDMETHOD(f265)(); - STDMETHOD(f266)(); - STDMETHOD(f267)(); - STDMETHOD(f268)(); - STDMETHOD(f269)(); - STDMETHOD(f270)(); - STDMETHOD(f271)(); - STDMETHOD(f272)(); - STDMETHOD(f273)(); - STDMETHOD(f274)(); - STDMETHOD(f275)(); - STDMETHOD(f276)(); - STDMETHOD(f277)(); - STDMETHOD(f278)(); - STDMETHOD(f279)(); - STDMETHOD(f280)(); - STDMETHOD(f281)(); - STDMETHOD(f282)(); - STDMETHOD(f283)(); - STDMETHOD(f284)(); - STDMETHOD(f285)(); - STDMETHOD(f286)(); - STDMETHOD(f287)(); - STDMETHOD(f288)(); - STDMETHOD(f289)(); - STDMETHOD(f290)(); - STDMETHOD(f291)(); - STDMETHOD(f292)(); - STDMETHOD(f293)(); - STDMETHOD(f294)(); - STDMETHOD(f295)(); - STDMETHOD(f296)(); - STDMETHOD(f297)(); - STDMETHOD(f298)(); - STDMETHOD(f299)(); - STDMETHOD(f300)(); - STDMETHOD(f301)(); - STDMETHOD(f302)(); - STDMETHOD(f303)(); - STDMETHOD(f304)(); - STDMETHOD(f305)(); - STDMETHOD(f306)(); - STDMETHOD(f307)(); - STDMETHOD(f308)(); - STDMETHOD(f309)(); - STDMETHOD(f310)(); - STDMETHOD(f311)(); - STDMETHOD(f312)(); - STDMETHOD(f313)(); - STDMETHOD(f314)(); - STDMETHOD(f315)(); - STDMETHOD(f316)(); - STDMETHOD(f317)(); - STDMETHOD(f318)(); - STDMETHOD(f319)(); - STDMETHOD(f320)(); - STDMETHOD(f321)(); - STDMETHOD(f322)(); - STDMETHOD(f323)(); - STDMETHOD(f324)(); - STDMETHOD(f325)(); - STDMETHOD(f326)(); - STDMETHOD(f327)(); - STDMETHOD(f328)(); - STDMETHOD(f329)(); - STDMETHOD(f330)(); - STDMETHOD(f331)(); - STDMETHOD(f332)(); - STDMETHOD(f333)(); - STDMETHOD(f334)(); - STDMETHOD(f335)(); - STDMETHOD(f336)(); - STDMETHOD(f337)(); - STDMETHOD(f338)(); - STDMETHOD(f339)(); - STDMETHOD(f340)(); - STDMETHOD(f341)(); - STDMETHOD(f342)(); - STDMETHOD(f343)(); - STDMETHOD(f344)(); - STDMETHOD(f345)(); - STDMETHOD(f346)(); - STDMETHOD(f347)(); - STDMETHOD(f348)(); - STDMETHOD(f349)(); - STDMETHOD(f350)(); - STDMETHOD(f351)(); - STDMETHOD(f352)(); - STDMETHOD(f353)(); - STDMETHOD(f354)(); - STDMETHOD(f355)(); - STDMETHOD(f356)(); - STDMETHOD(f357)(); - STDMETHOD(f358)(); - STDMETHOD(f359)(); - STDMETHOD(f360)(); - STDMETHOD(f361)(); - STDMETHOD(f362)(); - STDMETHOD(f363)(); - STDMETHOD(f364)(); - STDMETHOD(f365)(); - STDMETHOD(f366)(); - STDMETHOD(f367)(); - STDMETHOD(f368)(); - STDMETHOD(f369)(); - STDMETHOD(f370)(); - STDMETHOD(f371)(); - STDMETHOD(f372)(); - STDMETHOD(f373)(); - STDMETHOD(f374)(); - STDMETHOD(f375)(); - STDMETHOD(f376)(); - STDMETHOD(f377)(); - STDMETHOD(f378)(); - STDMETHOD(f379)(); - STDMETHOD(f380)(); - STDMETHOD(f381)(); - STDMETHOD(f382)(); - STDMETHOD(f383)(); - STDMETHOD(f384)(); - STDMETHOD(f385)(); - STDMETHOD(f386)(); - STDMETHOD(f387)(); - STDMETHOD(f388)(); - STDMETHOD(f389)(); - STDMETHOD(f390)(); - STDMETHOD(f391)(); - STDMETHOD(f392)(); - STDMETHOD(f393)(); - STDMETHOD(f394)(); - STDMETHOD(f395)(); - STDMETHOD(f396)(); - STDMETHOD(f397)(); - STDMETHOD(f398)(); - STDMETHOD(f399)(); - STDMETHOD(f400)(); - STDMETHOD(f401)(); - STDMETHOD(f402)(); - STDMETHOD(f403)(); - STDMETHOD(f404)(); - STDMETHOD(f405)(); - STDMETHOD(f406)(); - STDMETHOD(f407)(); - STDMETHOD(f408)(); - STDMETHOD(f409)(); - STDMETHOD(f410)(); - STDMETHOD(f411)(); - STDMETHOD(f412)(); - STDMETHOD(f413)(); - STDMETHOD(f414)(); - STDMETHOD(f415)(); - STDMETHOD(f416)(); - STDMETHOD(f417)(); - STDMETHOD(f418)(); - STDMETHOD(f419)(); - STDMETHOD(f420)(); - STDMETHOD(f421)(); - STDMETHOD(f422)(); - STDMETHOD(f423)(); - STDMETHOD(f424)(); - STDMETHOD(f425)(); - STDMETHOD(f426)(); - STDMETHOD(f427)(); - STDMETHOD(f428)(); - STDMETHOD(f429)(); - STDMETHOD(f430)(); - STDMETHOD(f431)(); - STDMETHOD(f432)(); - STDMETHOD(f433)(); - STDMETHOD(f434)(); - STDMETHOD(f435)(); - STDMETHOD(f436)(); - STDMETHOD(f437)(); - STDMETHOD(f438)(); - STDMETHOD(f439)(); - STDMETHOD(f440)(); - STDMETHOD(f441)(); - STDMETHOD(f442)(); - STDMETHOD(f443)(); - STDMETHOD(f444)(); - STDMETHOD(f445)(); - STDMETHOD(f446)(); - STDMETHOD(f447)(); - STDMETHOD(f448)(); - STDMETHOD(f449)(); - STDMETHOD(f450)(); - STDMETHOD(f451)(); - STDMETHOD(f452)(); - STDMETHOD(f453)(); - STDMETHOD(f454)(); - STDMETHOD(f455)(); - STDMETHOD(f456)(); - STDMETHOD(f457)(); - STDMETHOD(f458)(); - STDMETHOD(f459)(); - STDMETHOD(f460)(); - STDMETHOD(f461)(); - STDMETHOD(f462)(); - STDMETHOD(f463)(); - STDMETHOD(f464)(); - STDMETHOD(f465)(); - STDMETHOD(f466)(); - STDMETHOD(f467)(); - STDMETHOD(f468)(); - STDMETHOD(f469)(); - STDMETHOD(f470)(); - STDMETHOD(f471)(); - STDMETHOD(f472)(); - STDMETHOD(f473)(); - STDMETHOD(f474)(); - STDMETHOD(f475)(); - STDMETHOD(f476)(); - STDMETHOD(f477)(); - STDMETHOD(f478)(); - STDMETHOD(f479)(); - STDMETHOD(f480)(); - STDMETHOD(f481)(); - STDMETHOD(f482)(); - STDMETHOD(f483)(); - STDMETHOD(f484)(); - STDMETHOD(f485)(); - STDMETHOD(f486)(); - STDMETHOD(f487)(); - STDMETHOD(f488)(); - STDMETHOD(f489)(); - STDMETHOD(f490)(); - STDMETHOD(f491)(); - STDMETHOD(f492)(); - STDMETHOD(f493)(); - STDMETHOD(f494)(); - STDMETHOD(f495)(); - STDMETHOD(f496)(); - STDMETHOD(f497)(); - STDMETHOD(f498)(); - STDMETHOD(f499)(); - STDMETHOD(f500)(); - STDMETHOD(f501)(); - STDMETHOD(f502)(); - STDMETHOD(f503)(); - STDMETHOD(f504)(); - STDMETHOD(f505)(); - STDMETHOD(f506)(); - STDMETHOD(f507)(); - STDMETHOD(f508)(); - STDMETHOD(f509)(); - STDMETHOD(f510)(); - STDMETHOD(f511)(); - STDMETHOD(f512)(); - STDMETHOD(f513)(); - STDMETHOD(f514)(); - STDMETHOD(f515)(); - STDMETHOD(f516)(); - STDMETHOD(f517)(); - STDMETHOD(f518)(); - STDMETHOD(f519)(); - STDMETHOD(f520)(); - STDMETHOD(f521)(); - STDMETHOD(f522)(); - STDMETHOD(f523)(); - STDMETHOD(f524)(); - STDMETHOD(f525)(); - STDMETHOD(f526)(); - STDMETHOD(f527)(); - STDMETHOD(f528)(); - STDMETHOD(f529)(); - STDMETHOD(f530)(); - STDMETHOD(f531)(); - STDMETHOD(f532)(); - STDMETHOD(f533)(); - STDMETHOD(f534)(); - STDMETHOD(f535)(); - STDMETHOD(f536)(); - STDMETHOD(f537)(); - STDMETHOD(f538)(); - STDMETHOD(f539)(); - STDMETHOD(f540)(); - STDMETHOD(f541)(); - STDMETHOD(f542)(); - STDMETHOD(f543)(); - STDMETHOD(f544)(); - STDMETHOD(f545)(); - STDMETHOD(f546)(); - STDMETHOD(f547)(); - STDMETHOD(f548)(); - STDMETHOD(f549)(); - STDMETHOD(f550)(); - STDMETHOD(f551)(); - STDMETHOD(f552)(); - STDMETHOD(f553)(); - STDMETHOD(f554)(); - STDMETHOD(f555)(); - STDMETHOD(f556)(); - STDMETHOD(f557)(); - STDMETHOD(f558)(); - STDMETHOD(f559)(); - STDMETHOD(f560)(); - STDMETHOD(f561)(); - STDMETHOD(f562)(); - STDMETHOD(f563)(); - STDMETHOD(f564)(); - STDMETHOD(f565)(); - STDMETHOD(f566)(); - STDMETHOD(f567)(); - STDMETHOD(f568)(); - STDMETHOD(f569)(); - STDMETHOD(f570)(); - STDMETHOD(f571)(); - STDMETHOD(f572)(); - STDMETHOD(f573)(); - STDMETHOD(f574)(); - STDMETHOD(f575)(); - STDMETHOD(f576)(); - STDMETHOD(f577)(); - STDMETHOD(f578)(); - STDMETHOD(f579)(); - STDMETHOD(f580)(); - STDMETHOD(f581)(); - STDMETHOD(f582)(); - STDMETHOD(f583)(); - STDMETHOD(f584)(); - STDMETHOD(f585)(); - STDMETHOD(f586)(); - STDMETHOD(f587)(); - STDMETHOD(f588)(); - STDMETHOD(f589)(); - STDMETHOD(f590)(); - STDMETHOD(f591)(); - STDMETHOD(f592)(); - STDMETHOD(f593)(); - STDMETHOD(f594)(); - STDMETHOD(f595)(); - STDMETHOD(f596)(); - STDMETHOD(f597)(); - STDMETHOD(f598)(); - STDMETHOD(f599)(); - STDMETHOD(f600)(); - STDMETHOD(f601)(); - STDMETHOD(f602)(); - STDMETHOD(f603)(); - STDMETHOD(f604)(); - STDMETHOD(f605)(); - STDMETHOD(f606)(); - STDMETHOD(f607)(); - STDMETHOD(f608)(); - STDMETHOD(f609)(); - STDMETHOD(f610)(); - STDMETHOD(f611)(); - STDMETHOD(f612)(); - STDMETHOD(f613)(); - STDMETHOD(f614)(); - STDMETHOD(f615)(); - STDMETHOD(f616)(); - STDMETHOD(f617)(); - STDMETHOD(f618)(); - STDMETHOD(f619)(); - STDMETHOD(f620)(); - STDMETHOD(f621)(); - STDMETHOD(f622)(); - STDMETHOD(f623)(); - STDMETHOD(f624)(); - STDMETHOD(f625)(); - STDMETHOD(f626)(); - STDMETHOD(f627)(); - STDMETHOD(f628)(); - STDMETHOD(f629)(); - STDMETHOD(f630)(); - STDMETHOD(f631)(); - STDMETHOD(f632)(); - STDMETHOD(f633)(); - STDMETHOD(f634)(); - STDMETHOD(f635)(); - STDMETHOD(f636)(); - STDMETHOD(f637)(); - STDMETHOD(f638)(); - STDMETHOD(f639)(); - STDMETHOD(f640)(); - STDMETHOD(f641)(); - STDMETHOD(f642)(); - STDMETHOD(f643)(); - STDMETHOD(f644)(); - STDMETHOD(f645)(); - STDMETHOD(f646)(); - STDMETHOD(f647)(); - STDMETHOD(f648)(); - STDMETHOD(f649)(); - STDMETHOD(f650)(); - STDMETHOD(f651)(); - STDMETHOD(f652)(); - STDMETHOD(f653)(); - STDMETHOD(f654)(); - STDMETHOD(f655)(); - STDMETHOD(f656)(); - STDMETHOD(f657)(); - STDMETHOD(f658)(); - STDMETHOD(f659)(); - STDMETHOD(f660)(); - STDMETHOD(f661)(); - STDMETHOD(f662)(); - STDMETHOD(f663)(); - STDMETHOD(f664)(); - STDMETHOD(f665)(); - STDMETHOD(f666)(); - STDMETHOD(f667)(); - STDMETHOD(f668)(); - STDMETHOD(f669)(); - STDMETHOD(f670)(); - STDMETHOD(f671)(); - STDMETHOD(f672)(); - STDMETHOD(f673)(); - STDMETHOD(f674)(); - STDMETHOD(f675)(); - STDMETHOD(f676)(); - STDMETHOD(f677)(); - STDMETHOD(f678)(); - STDMETHOD(f679)(); - STDMETHOD(f680)(); - STDMETHOD(f681)(); - STDMETHOD(f682)(); - STDMETHOD(f683)(); - STDMETHOD(f684)(); - STDMETHOD(f685)(); - STDMETHOD(f686)(); - STDMETHOD(f687)(); - STDMETHOD(f688)(); - STDMETHOD(f689)(); - STDMETHOD(f690)(); - STDMETHOD(f691)(); - STDMETHOD(f692)(); - STDMETHOD(f693)(); - STDMETHOD(f694)(); - STDMETHOD(f695)(); - STDMETHOD(f696)(); - STDMETHOD(f697)(); - STDMETHOD(f698)(); - STDMETHOD(f699)(); - STDMETHOD(f700)(); - STDMETHOD(f701)(); - STDMETHOD(f702)(); - STDMETHOD(f703)(); - STDMETHOD(f704)(); - STDMETHOD(f705)(); - STDMETHOD(f706)(); - STDMETHOD(f707)(); - STDMETHOD(f708)(); - STDMETHOD(f709)(); - STDMETHOD(f710)(); - STDMETHOD(f711)(); - STDMETHOD(f712)(); - STDMETHOD(f713)(); - STDMETHOD(f714)(); - STDMETHOD(f715)(); - STDMETHOD(f716)(); - STDMETHOD(f717)(); - STDMETHOD(f718)(); - STDMETHOD(f719)(); - STDMETHOD(f720)(); - STDMETHOD(f721)(); - STDMETHOD(f722)(); - STDMETHOD(f723)(); - STDMETHOD(f724)(); - STDMETHOD(f725)(); - STDMETHOD(f726)(); - STDMETHOD(f727)(); - STDMETHOD(f728)(); - STDMETHOD(f729)(); - STDMETHOD(f730)(); - STDMETHOD(f731)(); - STDMETHOD(f732)(); - STDMETHOD(f733)(); - STDMETHOD(f734)(); - STDMETHOD(f735)(); - STDMETHOD(f736)(); - STDMETHOD(f737)(); - STDMETHOD(f738)(); - STDMETHOD(f739)(); - STDMETHOD(f740)(); - STDMETHOD(f741)(); - STDMETHOD(f742)(); - STDMETHOD(f743)(); - STDMETHOD(f744)(); - STDMETHOD(f745)(); - STDMETHOD(f746)(); - STDMETHOD(f747)(); - STDMETHOD(f748)(); - STDMETHOD(f749)(); - STDMETHOD(f750)(); - STDMETHOD(f751)(); - STDMETHOD(f752)(); - STDMETHOD(f753)(); - STDMETHOD(f754)(); - STDMETHOD(f755)(); - STDMETHOD(f756)(); - STDMETHOD(f757)(); - STDMETHOD(f758)(); - STDMETHOD(f759)(); - STDMETHOD(f760)(); - STDMETHOD(f761)(); - STDMETHOD(f762)(); - STDMETHOD(f763)(); - STDMETHOD(f764)(); - STDMETHOD(f765)(); - STDMETHOD(f766)(); - STDMETHOD(f767)(); - STDMETHOD(f768)(); - STDMETHOD(f769)(); - STDMETHOD(f770)(); - STDMETHOD(f771)(); - STDMETHOD(f772)(); - STDMETHOD(f773)(); - STDMETHOD(f774)(); - STDMETHOD(f775)(); - STDMETHOD(f776)(); - STDMETHOD(f777)(); - STDMETHOD(f778)(); - STDMETHOD(f779)(); - STDMETHOD(f780)(); - STDMETHOD(f781)(); - STDMETHOD(f782)(); - STDMETHOD(f783)(); - STDMETHOD(f784)(); - STDMETHOD(f785)(); - STDMETHOD(f786)(); - STDMETHOD(f787)(); - STDMETHOD(f788)(); - STDMETHOD(f789)(); - STDMETHOD(f790)(); - STDMETHOD(f791)(); - STDMETHOD(f792)(); - STDMETHOD(f793)(); - STDMETHOD(f794)(); - STDMETHOD(f795)(); - STDMETHOD(f796)(); - STDMETHOD(f797)(); - STDMETHOD(f798)(); - STDMETHOD(f799)(); - STDMETHOD(f800)(); - STDMETHOD(f801)(); - STDMETHOD(f802)(); - STDMETHOD(f803)(); - STDMETHOD(f804)(); - STDMETHOD(f805)(); - STDMETHOD(f806)(); - STDMETHOD(f807)(); - STDMETHOD(f808)(); - STDMETHOD(f809)(); - STDMETHOD(f810)(); - STDMETHOD(f811)(); - STDMETHOD(f812)(); - STDMETHOD(f813)(); - STDMETHOD(f814)(); - STDMETHOD(f815)(); - STDMETHOD(f816)(); - STDMETHOD(f817)(); - STDMETHOD(f818)(); - STDMETHOD(f819)(); - STDMETHOD(f820)(); - STDMETHOD(f821)(); - STDMETHOD(f822)(); - STDMETHOD(f823)(); - STDMETHOD(f824)(); - STDMETHOD(f825)(); - STDMETHOD(f826)(); - STDMETHOD(f827)(); - STDMETHOD(f828)(); - STDMETHOD(f829)(); - STDMETHOD(f830)(); - STDMETHOD(f831)(); - STDMETHOD(f832)(); - STDMETHOD(f833)(); - STDMETHOD(f834)(); - STDMETHOD(f835)(); - STDMETHOD(f836)(); - STDMETHOD(f837)(); - STDMETHOD(f838)(); - STDMETHOD(f839)(); - STDMETHOD(f840)(); - STDMETHOD(f841)(); - STDMETHOD(f842)(); - STDMETHOD(f843)(); - STDMETHOD(f844)(); - STDMETHOD(f845)(); - STDMETHOD(f846)(); - STDMETHOD(f847)(); - STDMETHOD(f848)(); - STDMETHOD(f849)(); - STDMETHOD(f850)(); - STDMETHOD(f851)(); - STDMETHOD(f852)(); - STDMETHOD(f853)(); - STDMETHOD(f854)(); - STDMETHOD(f855)(); - STDMETHOD(f856)(); - STDMETHOD(f857)(); - STDMETHOD(f858)(); - STDMETHOD(f859)(); - STDMETHOD(f860)(); - STDMETHOD(f861)(); - STDMETHOD(f862)(); - STDMETHOD(f863)(); - STDMETHOD(f864)(); - STDMETHOD(f865)(); - STDMETHOD(f866)(); - STDMETHOD(f867)(); - STDMETHOD(f868)(); - STDMETHOD(f869)(); - STDMETHOD(f870)(); - STDMETHOD(f871)(); - STDMETHOD(f872)(); - STDMETHOD(f873)(); - STDMETHOD(f874)(); - STDMETHOD(f875)(); - STDMETHOD(f876)(); - STDMETHOD(f877)(); - STDMETHOD(f878)(); - STDMETHOD(f879)(); - STDMETHOD(f880)(); - STDMETHOD(f881)(); - STDMETHOD(f882)(); - STDMETHOD(f883)(); - STDMETHOD(f884)(); - STDMETHOD(f885)(); - STDMETHOD(f886)(); - STDMETHOD(f887)(); - STDMETHOD(f888)(); - STDMETHOD(f889)(); - STDMETHOD(f890)(); - STDMETHOD(f891)(); - STDMETHOD(f892)(); - STDMETHOD(f893)(); - STDMETHOD(f894)(); - STDMETHOD(f895)(); - STDMETHOD(f896)(); - STDMETHOD(f897)(); - STDMETHOD(f898)(); - STDMETHOD(f899)(); - STDMETHOD(f900)(); - STDMETHOD(f901)(); - STDMETHOD(f902)(); - STDMETHOD(f903)(); - STDMETHOD(f904)(); - STDMETHOD(f905)(); - STDMETHOD(f906)(); - STDMETHOD(f907)(); - STDMETHOD(f908)(); - STDMETHOD(f909)(); - STDMETHOD(f910)(); - STDMETHOD(f911)(); - STDMETHOD(f912)(); - STDMETHOD(f913)(); - STDMETHOD(f914)(); - STDMETHOD(f915)(); - STDMETHOD(f916)(); - STDMETHOD(f917)(); - STDMETHOD(f918)(); - STDMETHOD(f919)(); - STDMETHOD(f920)(); - STDMETHOD(f921)(); - STDMETHOD(f922)(); - STDMETHOD(f923)(); - STDMETHOD(f924)(); - STDMETHOD(f925)(); - STDMETHOD(f926)(); - STDMETHOD(f927)(); - STDMETHOD(f928)(); - STDMETHOD(f929)(); - STDMETHOD(f930)(); - STDMETHOD(f931)(); - STDMETHOD(f932)(); - STDMETHOD(f933)(); - STDMETHOD(f934)(); - STDMETHOD(f935)(); - STDMETHOD(f936)(); - STDMETHOD(f937)(); - STDMETHOD(f938)(); - STDMETHOD(f939)(); - STDMETHOD(f940)(); - STDMETHOD(f941)(); - STDMETHOD(f942)(); - STDMETHOD(f943)(); - STDMETHOD(f944)(); - STDMETHOD(f945)(); - STDMETHOD(f946)(); - STDMETHOD(f947)(); - STDMETHOD(f948)(); - STDMETHOD(f949)(); - STDMETHOD(f950)(); - STDMETHOD(f951)(); - STDMETHOD(f952)(); - STDMETHOD(f953)(); - STDMETHOD(f954)(); - STDMETHOD(f955)(); - STDMETHOD(f956)(); - STDMETHOD(f957)(); - STDMETHOD(f958)(); - STDMETHOD(f959)(); - STDMETHOD(f960)(); - STDMETHOD(f961)(); - STDMETHOD(f962)(); - STDMETHOD(f963)(); - STDMETHOD(f964)(); - STDMETHOD(f965)(); - STDMETHOD(f966)(); - STDMETHOD(f967)(); - STDMETHOD(f968)(); - STDMETHOD(f969)(); - STDMETHOD(f970)(); - STDMETHOD(f971)(); - STDMETHOD(f972)(); - STDMETHOD(f973)(); - STDMETHOD(f974)(); - STDMETHOD(f975)(); - STDMETHOD(f976)(); - STDMETHOD(f977)(); - STDMETHOD(f978)(); - STDMETHOD(f979)(); - STDMETHOD(f980)(); - STDMETHOD(f981)(); - STDMETHOD(f982)(); - STDMETHOD(f983)(); - STDMETHOD(f984)(); - STDMETHOD(f985)(); - STDMETHOD(f986)(); - STDMETHOD(f987)(); - STDMETHOD(f988)(); - STDMETHOD(f989)(); - STDMETHOD(f990)(); - STDMETHOD(f991)(); - STDMETHOD(f992)(); - STDMETHOD(f993)(); - STDMETHOD(f994)(); - STDMETHOD(f995)(); - STDMETHOD(f996)(); - STDMETHOD(f997)(); - STDMETHOD(f998)(); - STDMETHOD(f999)(); - STDMETHOD(f1000)(); - STDMETHOD(f1001)(); - STDMETHOD(f1002)(); - STDMETHOD(f1003)(); - STDMETHOD(f1004)(); - STDMETHOD(f1005)(); - STDMETHOD(f1006)(); - STDMETHOD(f1007)(); - STDMETHOD(f1008)(); - STDMETHOD(f1009)(); - STDMETHOD(f1010)(); - STDMETHOD(f1011)(); - STDMETHOD(f1012)(); - STDMETHOD(f1013)(); - STDMETHOD(f1014)(); - STDMETHOD(f1015)(); - STDMETHOD(f1016)(); - STDMETHOD(f1017)(); - STDMETHOD(f1018)(); - STDMETHOD(f1019)(); - STDMETHOD(f1020)(); - STDMETHOD(f1021)(); - STDMETHOD(f1022)(); - STDMETHOD(f1023)(); - _QIThunk(IUnknown* pOrig, LPCTSTR p, const IID& i, UINT n, bool b) - { - m_lpszClassName = p; - m_iid = i; - m_nIndex = n; - m_dwRef = 0; - m_dwMaxRef = 0; - m_pUnk = pOrig; - m_bBreak = b; - m_bNonAddRefThunk = false; - } - IUnknown* m_pUnk; - long m_dwRef; - long m_dwMaxRef; - LPCTSTR m_lpszClassName; - IID m_iid; - UINT m_nIndex; - bool m_bBreak; - bool m_bNonAddRefThunk; - void Dump() throw(); -}; - -#endif - -///////////////////////////////////////////////////////////////////////////// -// Module Classes - -#ifdef _ATL_STATIC_REGISTRY -#define UpdateRegistryFromResource UpdateRegistryFromResourceS -#else -#define UpdateRegistryFromResource UpdateRegistryFromResourceD -#endif // _ATL_STATIC_REGISTRY - - -class CAtlComModule : public _ATL_COM_MODULE -{ -public: - - CAtlComModule() throw() - { - cbSize = sizeof(_ATL_COM_MODULE); - - m_hInstTypeLib = reinterpret_cast(&__ImageBase); - - m_ppAutoObjMapFirst = &__pobjMapEntryFirst + 1; - m_ppAutoObjMapLast = &__pobjMapEntryLast; - - if (FAILED(m_csObjMap.Init())) - { - ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to initialize critical section in CAtlComModule\n")); - ATLASSERT(0); - CAtlBaseModule::m_bInitFailed = true; - } - } - - ~CAtlComModule() - { - Term(); - } - - // Called from ~CAtlComModule or from ~CAtlExeModule. - void Term() - { - if (cbSize == 0) - return; - - for (_ATL_OBJMAP_ENTRY** ppEntry = m_ppAutoObjMapFirst; ppEntry < m_ppAutoObjMapLast; ppEntry++) - { - if (*ppEntry != NULL) - { - _ATL_OBJMAP_ENTRY* pEntry = *ppEntry; - if (pEntry->pCF != NULL) - pEntry->pCF->Release(); - pEntry->pCF = NULL; - } - } - m_csObjMap.Term(); - // Set to 0 to indicate that this function has been called - // At this point no one should be concerned about cbsize - // having the correct value - cbSize = 0; - } - - // Registry support (helpers) - HRESULT RegisterTypeLib() - { - return AtlRegisterTypeLib(m_hInstTypeLib, NULL); - } - HRESULT RegisterTypeLib(LPCTSTR lpszIndex) - { - USES_CONVERSION_EX; - LPCOLESTR pwszTemp = NULL; - if( lpszIndex != NULL ) - { - pwszTemp = T2COLE_EX(lpszIndex, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if( pwszTemp == NULL ) - return E_OUTOFMEMORY; -#endif - } - return AtlRegisterTypeLib(m_hInstTypeLib, pwszTemp); - } - HRESULT UnRegisterTypeLib() - { - return AtlUnRegisterTypeLib(m_hInstTypeLib, NULL); - } - HRESULT UnRegisterTypeLib(LPCTSTR lpszIndex) - { - USES_CONVERSION_EX; - LPCOLESTR pwszTemp = NULL; - if( lpszIndex != NULL ) - { - pwszTemp = T2COLE_EX(lpszIndex, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if( pwszTemp == NULL ) - return E_OUTOFMEMORY; -#endif - } - return AtlUnRegisterTypeLib(m_hInstTypeLib, pwszTemp); - } - - // RegisterServer walks the ATL Autogenerated object map and registers each object in the map - // If pCLSID is not NULL then only the object referred to by pCLSID is registered (The default case) - // otherwise all the objects are registered - HRESULT RegisterServer(BOOL bRegTypeLib = FALSE, const CLSID* pCLSID = NULL) - { - return AtlComModuleRegisterServer(this, bRegTypeLib, pCLSID); - } - - // UnregisterServer walks the ATL Autogenerated object map and unregisters each object in the map - // If pCLSID is not NULL then only the object referred to by pCLSID is unregistered (The default case) - // otherwise all the objects are unregistered. - HRESULT UnregisterServer(BOOL bRegTypeLib = FALSE, const CLSID* pCLSID = NULL) - { - return AtlComModuleUnregisterServer(this, bRegTypeLib, pCLSID); - } - - // Implementation - - // Call ObjectMain for all the objects. - void ExecuteObjectMain(bool bStarting) - { - for (_ATL_OBJMAP_ENTRY** ppEntry = m_ppAutoObjMapFirst; ppEntry < m_ppAutoObjMapLast; ppEntry++) - { - if (*ppEntry != NULL) - (*ppEntry)->pfnObjectMain(bStarting); - } - } -}; - -extern CAtlComModule _AtlComModule; - -#ifdef _ATL_DEBUG_INTERFACES - -class CAtlDebugInterfacesModule -{ -public: - CAtlDebugInterfacesModule() throw() : - m_nIndexQI( 0 ), - m_nIndexBreakAt( 0 ) - { - if (FAILED(m_cs.Init())) - { - ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to initialize critical section in CAtlDebugInterfacesModule\n")); - ATLASSERT(0); - CAtlBaseModule::m_bInitFailed = true; - } - } - ~CAtlDebugInterfacesModule() throw() - { - // Release all the class factories. - _AtlComModule.Term(); - DumpLeakedThunks(); - m_cs.Term(); - } - - HRESULT AddThunk(IUnknown** pp, LPCTSTR lpsz, REFIID iid) throw() - { - if ((pp == NULL) || (*pp == NULL)) - return E_POINTER; - IUnknown* p = *pp; - _QIThunk* pThunk = NULL; - CComCritSecLock lock(m_cs, false); - HRESULT hr = lock.Lock(); - if (FAILED(hr)) - { - ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to lock critical section in CAtlDebugInterfacesModule\n")); - ATLASSERT(0); - return hr; - } - - // Check if exists already for identity - if (InlineIsEqualUnknown(iid)) - { - for (int i = 0; i < m_aThunks.GetSize(); i++) - { - if (m_aThunks[i]->m_pUnk == p && InlineIsEqualGUID(m_aThunks[i]->m_iid, iid)) - { - m_aThunks[i]->InternalAddRef(); - pThunk = m_aThunks[i]; - break; - } - } - } - if (pThunk == NULL) - { - ++m_nIndexQI; - if (m_nIndexBreakAt == m_nIndexQI) - DebugBreak(); - ATLTRY(pThunk = new _QIThunk(p, lpsz, iid, m_nIndexQI, (m_nIndexBreakAt == m_nIndexQI))); - if (pThunk == NULL) - { - return E_OUTOFMEMORY; - } - pThunk->InternalAddRef(); - m_aThunks.Add(pThunk); - } - *pp = (IUnknown*)pThunk; - return S_OK; - } - HRESULT AddNonAddRefThunk(IUnknown* p, LPCTSTR lpsz, IUnknown** ppThunkRet) throw() - { - if (ppThunkRet == NULL) - return E_POINTER; - *ppThunkRet = NULL; - - _QIThunk* pThunk = NULL; - CComCritSecLock lock(m_cs, false); - HRESULT hr = lock.Lock(); - if (FAILED(hr)) - { - ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to lock critical section in CAtlDebugInterfacesModule\n")); - ATLASSERT(0); - return hr; - } - - // Check if exists already for identity - for (int i = 0; i < m_aThunks.GetSize(); i++) - { - if (m_aThunks[i]->m_pUnk == p) - { - m_aThunks[i]->m_bNonAddRefThunk = true; - pThunk = m_aThunks[i]; - break; - } - } - if (pThunk == NULL) - { - ++m_nIndexQI; - if (m_nIndexBreakAt == m_nIndexQI) - DebugBreak(); - ATLTRY(pThunk = new _QIThunk(p, lpsz, __uuidof(IUnknown), m_nIndexQI, (m_nIndexBreakAt == m_nIndexQI))); - if (pThunk == NULL) - { - return E_OUTOFMEMORY; - } - pThunk->m_bNonAddRefThunk = true; - m_aThunks.Add(pThunk); - } - *ppThunkRet = (IUnknown*)pThunk; - return S_OK;; - } - void DeleteNonAddRefThunk(IUnknown* pUnk) throw() - { - CComCritSecLock lock(m_cs, false); - HRESULT hr = lock.Lock(); - if (FAILED(hr)) - { - ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to lock critical section in CAtlDebugInterfacesModule\n")); - ATLASSERT(0); - return; - } - - for (int i = 0; i < m_aThunks.GetSize(); i++) - { - if (m_aThunks[i]->m_bNonAddRefThunk && m_aThunks[i]->m_pUnk == pUnk) - { - delete m_aThunks[i]; - m_aThunks.RemoveAt(i); - break; - } - } - } - void DeleteThunk(_QIThunk* p) throw() - { - CComCritSecLock lock(m_cs, false); - HRESULT hr = lock.Lock(); - if (FAILED(hr)) - { - ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to lock critical section in CAtlDebugInterfacesModule\n")); - ATLASSERT(0); - return; - } - - int nIndex = m_aThunks.Find(p); - if (nIndex != -1) - { - m_aThunks[nIndex]->m_pUnk = NULL; - delete m_aThunks[nIndex]; - m_aThunks.RemoveAt(nIndex); - } - } - bool DumpLeakedThunks() - { - bool b = false; - for (int i = 0; i < m_aThunks.GetSize(); i++) - { - b = true; - m_aThunks[i]->Dump(); - delete m_aThunks[i]; - } - m_aThunks.RemoveAll(); - return b; - } - -public: - UINT m_nIndexQI; - UINT m_nIndexBreakAt; - CSimpleArray<_QIThunk*> m_aThunks; - CComCriticalSection m_cs; -}; - -extern CAtlDebugInterfacesModule _AtlDebugInterfacesModule; - -#ifndef _ATL_STATIC_LIB_IMPL -// Should not be pulled into the static lib -__declspec (selectany) CAtlDebugInterfacesModule _AtlDebugInterfacesModule; -#endif - -inline ULONG _QIThunk::Release() -{ - ATLASSERT(m_pUnk != NULL); - if (m_bBreak) - DebugBreak(); - ATLASSERT(m_dwRef > 0); - - // save copies of member variables we wish to use after the InterlockedDecrement - UINT nIndex = m_nIndex; - IUnknown* pUnk = m_pUnk; - IID iid = m_iid; - LPCTSTR lpszClassName = m_lpszClassName; - bool bNonAddRefThunk = m_bNonAddRefThunk; - - ULONG l = InterlockedDecrement(&m_dwRef); - - TCHAR buf[512]; - wsprintf(buf, _T("QIThunk - %-10d\tRelease :\tObject = 0x%08x\tRefcount = %d\t"), nIndex, pUnk, l); - OutputDebugString(buf); - AtlDumpIID(iid, lpszClassName, S_OK); - - bool bDeleteThunk = (l == 0 && !bNonAddRefThunk); - pUnk->Release(); - if (bDeleteThunk) - _AtlDebugInterfacesModule.DeleteThunk(this); - return l; -} - -#endif // _ATL_DEBUG_INTERFACES - - -class CAtlWinModule : public _ATL_WIN_MODULE -{ -public: - CAtlWinModule() - { - cbSize = sizeof(_ATL_WIN_MODULE); - HRESULT hr = AtlWinModuleInit(this); - if (FAILED(hr)) - CAtlBaseModule::m_bInitFailed = true; - } - - ~CAtlWinModule() - { - Term(); - } - - void Term() - { - AtlWinModuleTerm(this, _AtlBaseModule.GetModuleInstance()); - } - - void AddCreateWndData(_AtlCreateWndData* pData, void* pObject) - { - AtlWinModuleAddCreateWndData(this, pData, pObject); - } - - void* ExtractCreateWndData() - { - return AtlWinModuleExtractCreateWndData(this); - } -}; - -__declspec(selectany) CAtlWinModule _AtlWinModule; - - -class CAtlModule; -__declspec(selectany) CAtlModule* _pAtlModule = NULL; - - -class ATL_NO_VTABLE CAtlModule : public _ATL_MODULE -{ -public : - static GUID m_libid; - IGlobalInterfaceTable* m_pGIT; - - CAtlModule() throw() - { - // Should have only one instance of a class - // derived from CAtlModule in a project. - ATLASSERT(_pAtlModule == NULL); - cbSize = sizeof(_ATL_MODULE); - m_pTermFuncs = NULL; - - m_nLockCnt = 0; - _pAtlModule = this; - if (FAILED(m_csStaticDataInitAndTypeInfo.Init())) - { - ATLTRACE(atlTraceGeneral, 0, _T("ERROR : Unable to initialize critical section in CAtlModule\n")); - ATLASSERT(0); - CAtlBaseModule::m_bInitFailed = true; - } - - m_pGIT = NULL; - } - - void Term() throw() - { - // cbSize == 0 indicates that Term has already been called - if (cbSize == 0) - return; - - // Call term functions - if (m_pTermFuncs != NULL) - { - AtlCallTermFunc(this); - m_pTermFuncs = NULL; - } - - if (m_pGIT != NULL) - m_pGIT->Release(); - - m_csStaticDataInitAndTypeInfo.Term(); - - cbSize = 0; - } - - virtual ~CAtlModule() throw() - { - Term(); - } - - virtual LONG Lock() throw() - { - return CComGlobalsThreadModel::Increment(&m_nLockCnt); - } - - virtual LONG Unlock() throw() - { - return CComGlobalsThreadModel::Decrement(&m_nLockCnt); - } - - virtual LONG GetLockCount() throw() - { - return m_nLockCnt; - } - - HRESULT AddTermFunc(_ATL_TERMFUNC* pFunc, DWORD_PTR dw) throw() - { - return AtlModuleAddTermFunc(this, pFunc, dw); - } - - virtual HRESULT GetGITPtr(IGlobalInterfaceTable** ppGIT) throw() - { - ATLASSERT(ppGIT != NULL); - - if (ppGIT == NULL) - return E_POINTER; - - HRESULT hr = S_OK; - if (m_pGIT == NULL) - { - hr = ::CoCreateInstance(CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, - __uuidof(IGlobalInterfaceTable), (void**)&m_pGIT); - } - - if (SUCCEEDED(hr)) - { - ATLASSERT(m_pGIT != NULL); - *ppGIT = m_pGIT; - m_pGIT->AddRef(); - } - return hr; - } - - virtual HRESULT AddCommonRGSReplacements(IRegistrarBase* /*pRegistrar*/) throw() = 0; - - // Resource-based Registration -#ifdef _ATL_STATIC_REGISTRY - // Statically linking to Registry Ponent - HRESULT WINAPI UpdateRegistryFromResourceS(LPCTSTR lpszRes, BOOL bRegister, - struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw(); - HRESULT WINAPI UpdateRegistryFromResourceS(UINT nResID, BOOL bRegister, - struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw(); -#else - HRESULT WINAPI UpdateRegistryFromResourceD(LPCTSTR lpszRes, BOOL bRegister, - struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw() - { - if(lpszRes == NULL) - return E_INVALIDARG; - - USES_CONVERSION_EX; - LPCOLESTR pwszTemp = T2COLE_EX(lpszRes, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifdef _UNICODE - if(pwszTemp == NULL) - return E_OUTOFMEMORY; -#endif - return UpdateRegistryFromResourceDHelper(pwszTemp, bRegister, pMapEntries); - } - HRESULT WINAPI UpdateRegistryFromResourceD(UINT nResID, BOOL bRegister, - struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw() - { - return UpdateRegistryFromResourceDHelper((LPCOLESTR)MAKEINTRESOURCE(nResID), bRegister, pMapEntries); - } -#endif - - // Implementation -#if !defined(_ATL_STATIC_REGISTRY) - inline HRESULT WINAPI UpdateRegistryFromResourceDHelper(LPCOLESTR lpszRes, BOOL bRegister, - struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw() - { - CComPtr spRegistrar; - HRESULT hr = AtlCreateRegistrar(&spRegistrar); - if (FAILED(hr)) - return hr; - - if (NULL != pMapEntries) - { - while (NULL != pMapEntries->szKey) - { - ATLASSERT(NULL != pMapEntries->szData); - spRegistrar->AddReplacement(pMapEntries->szKey, pMapEntries->szData); - pMapEntries++; - } - } - - hr = AddCommonRGSReplacements(spRegistrar); - if (FAILED(hr)) - return hr; - - return AtlUpdateRegistryFromResourceD(_AtlBaseModule.GetModuleInstance(), lpszRes, bRegister, - NULL, spRegistrar); - } -#endif - - static void EscapeSingleQuote(LPOLESTR lpDest, LPCOLESTR lp) throw() - { - while (*lp) - { - *lpDest++ = *lp; - if (*lp == '\'') - *lpDest++ = *lp; - lp++; - } - *lpDest = NULL; - } - - - // search for an occurence of string p2 in string p1 - static LPCTSTR FindOneOf(LPCTSTR p1, LPCTSTR p2) throw() - { - while (p1 != NULL && *p1 != NULL) - { - LPCTSTR p = p2; - while (p != NULL && *p != NULL) - { - if (*p1 == *p) - return CharNext(p1); - p = CharNext(p); - } - p1 = CharNext(p1); - } - return NULL; - } -#pragma warning(push) -#pragma warning(disable : 4302) // 'type cast' : truncation from 'LPSTR' to 'TCHAR' - - static int WordCmpI(LPCTSTR psz1, LPCTSTR psz2) throw() - { - TCHAR c1 = (TCHAR)CharUpper((LPTSTR)*psz1); - TCHAR c2 = (TCHAR)CharUpper((LPTSTR)*psz2); - while (c1 != NULL && c1 == c2 && c1 != ' ' && c1 != '\t') - { - psz1 = CharNext(psz1); - psz2 = CharNext(psz2); - c1 = (TCHAR)CharUpper((LPTSTR)*psz1); - c2 = (TCHAR)CharUpper((LPTSTR)*psz2); - } - if ((c1 == NULL || c1 == ' ' || c1 == '\t') && (c2 == NULL || c2 == ' ' || c2 == '\t')) - return 0; - - return (c1 < c2) ? -1 : 1; - } - -#pragma warning (pop) -}; - -__declspec(selectany) GUID CAtlModule::m_libid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} }; - -#define DECLARE_LIBID(libid) \ - static void InitLibId() throw() \ - { \ - CAtlModule::m_libid = libid; \ - } - -#define DECLARE_REGISTRY_APPID_RESOURCEID(resid, appid) \ - static LPCOLESTR GetAppId() throw() \ - { \ - return OLESTR(appid); \ - } \ - static TCHAR* GetAppIdT() throw() \ - { \ - return _T(appid); \ - } \ - static HRESULT WINAPI UpdateRegistryAppId(BOOL bRegister) throw() \ - { \ - _ATL_REGMAP_ENTRY aMapEntries [] = \ - { \ - { OLESTR("APPID"), GetAppId() }, \ - { NULL, NULL } \ - }; \ - return ATL::_pAtlModule->UpdateRegistryFromResource(resid, bRegister, aMapEntries); \ - } - -inline HRESULT AtlGetGITPtr(IGlobalInterfaceTable** ppGIT) throw() -{ - if (ppGIT == NULL) - return E_POINTER; - - if (_pAtlModule == NULL) - { - return CoCreateInstance(CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, - __uuidof(IGlobalInterfaceTable), (void**)ppGIT); - } - else - { - return _pAtlModule->GetGITPtr(ppGIT); - } -} - -template -class ATL_NO_VTABLE CAtlModuleT : public CAtlModule -{ -public : - CAtlModuleT() throw() - { - T::InitLibId(); - } - - static void InitLibId() throw() - { - } - - HRESULT RegisterServer(BOOL bRegTypeLib = FALSE, const CLSID* pCLSID = NULL) throw() - { - (pCLSID); - (bRegTypeLib); - - HRESULT hr = S_OK; - -#ifndef _ATL_NO_COM_SUPPORT - - hr = _AtlComModule.RegisterServer(bRegTypeLib, pCLSID); - -#endif // _ATL_NO_COM_SUPPORT - - -#ifndef _ATL_NO_PERF_SUPPORT - - if (SUCCEEDED(hr) && _pPerfRegFunc != NULL) - hr = (*_pPerfRegFunc)(_AtlBaseModule.m_hInst); - -#endif - - return hr; - } - - HRESULT UnregisterServer(BOOL bUnRegTypeLib, const CLSID* pCLSID = NULL) throw() - { - (bUnRegTypeLib); - (pCLSID); - - HRESULT hr = S_OK; - -#ifndef _ATL_NO_PERF_SUPPORT - - if (_pPerfUnRegFunc != NULL) - hr = (*_pPerfUnRegFunc)(); - -#endif - -#ifndef _ATL_NO_COM_SUPPORT - - if (SUCCEEDED(hr)) - hr = _AtlComModule.UnregisterServer(bUnRegTypeLib, pCLSID); - -#endif // _ATL_NO_COM_SUPPORT - - return hr; - - } - - static HRESULT WINAPI UpdateRegistryAppId(BOOL /*bRegister*/) throw() - { - return S_OK; - } - HRESULT RegisterAppId() throw() - { - return T::UpdateRegistryAppId(TRUE); - } - - HRESULT UnregisterAppId() throw() - { - return T::UpdateRegistryAppId(FALSE); - } - - virtual HRESULT AddCommonRGSReplacements(IRegistrarBase* pRegistrar) throw() - { - return pRegistrar->AddReplacement(L"APPID", T::GetAppId()); - } - static LPCOLESTR GetAppId() throw() - { - return OLESTR(""); - } -}; - -template -class ATL_NO_VTABLE CAtlDllModuleT : public CAtlModuleT -{ -public : - CAtlDllModuleT() throw() - { - _AtlComModule.ExecuteObjectMain(true); - } - - ~CAtlDllModuleT() throw() - { - _AtlComModule.ExecuteObjectMain(false); - } - - BOOL WINAPI DllMain(DWORD dwReason, LPVOID /* lpReserved */) throw() - { - if (dwReason == DLL_PROCESS_ATTACH) - { - if (CAtlBaseModule::m_bInitFailed) - { - ATLASSERT(0); - return FALSE; - } - -#ifdef _ATL_MIN_CRT - DisableThreadLibraryCalls(_AtlBaseModule.GetModuleInstance()); -#endif - } -#ifdef _DEBUG - else if (dwReason == DLL_PROCESS_DETACH) - { - // Prevent false memory leak reporting. ~CAtlWinModule may be too late. - _AtlWinModule.Term(); - } -#endif // _DEBUG - return TRUE; // ok - } - - HRESULT DllCanUnloadNow() throw() - { - T* pT = static_cast(this); - return (pT->GetLockCount()==0) ? S_OK : S_FALSE; - } - - HRESULT DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) throw() - { - T* pT = static_cast(this); - return pT->GetClassObject(rclsid, riid, ppv); - } - - HRESULT DllRegisterServer(BOOL bRegTypeLib = TRUE) throw() - { - // registers object, typelib and all interfaces in typelib - T* pT = static_cast(this); - HRESULT hr = pT->RegisterAppId(); - if (SUCCEEDED(hr)) - hr = pT->RegisterServer(bRegTypeLib); - return hr; - } - - HRESULT DllUnregisterServer(BOOL bUnRegTypeLib = TRUE) throw() - { - T* pT = static_cast(this); - HRESULT hr = pT->UnregisterServer(bUnRegTypeLib); - if (SUCCEEDED(hr)) - hr = pT->UnregisterAppId(); - return hr; - } - - // Obtain a Class Factory - HRESULT GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) throw() - { - -#ifndef _ATL_OLEDB_CONFORMANCE_TESTS - ATLASSERT(ppv != NULL); -#endif - - return AtlComModuleGetClassObject(&_AtlComModule, rclsid, riid, ppv); - } -}; - -#ifndef _AFX - -template -class ATL_NO_VTABLE CAtlExeModuleT : public CAtlModuleT -{ -public : -#ifndef _ATL_NO_COM_SUPPORT - - DWORD m_dwMainThreadID; - HANDLE m_hEventShutdown; - DWORD m_dwTimeOut; - DWORD m_dwPause; - bool m_bDelayShutdown; - bool m_bActivity; - -#endif // _ATL_NO_COM_SUPPORT - - CAtlExeModuleT() throw() - -#ifndef _ATL_NO_COM_SUPPORT - - : m_dwMainThreadID(::GetCurrentThreadId()), - m_dwTimeOut(5000), - m_dwPause(1000), - m_hEventShutdown(NULL), - m_bDelayShutdown(true) - -#endif // _ATL_NO_COM_SUPPORT - - { - HRESULT hr = T::InitializeCom(); - if (FAILED(hr)) - { - CAtlBaseModule::m_bInitFailed = true; - return; - } - -#if !defined(_ATL_NO_COM_SUPPORT) - - _AtlComModule.ExecuteObjectMain(true); - -#endif // !defined(_ATL_NO_COM_SUPPORT) - - } - - ~CAtlExeModuleT() throw() - { -#ifndef _ATL_NO_COM_SUPPORT - - _AtlComModule.ExecuteObjectMain(false); - -#endif - - // Call term functions before COM is uninitialized - Term(); - -#ifndef _ATL_NO_COM_SUPPORT - - // Clean up AtlComModule before COM is uninitialized - _AtlComModule.Term(); - -#endif // _ATL_NO_COM_SUPPORT - - T::UninitializeCom(); - } - - static HRESULT InitializeCom() throw() - { - -#if ((_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM)) & defined(_ATL_FREE_THREADED) - return CoInitializeEx(NULL, COINIT_MULTITHREADED); -#else - return CoInitialize(NULL); -#endif - } - - static void UninitializeCom() throw() - { - CoUninitialize(); - } - - LONG Unlock() throw() - { - LONG lRet = CComGlobalsThreadModel::Decrement(&m_nLockCnt); - -#ifndef _ATL_NO_COM_SUPPORT - - if (lRet == 0) - { - if (m_bDelayShutdown) - { - m_bActivity = true; - ::SetEvent(m_hEventShutdown); // tell monitor that we transitioned to zero - } - else - { - ::PostThreadMessage(m_dwMainThreadID, WM_QUIT, 0, 0); - } - } - -#endif // _ATL_NO_COM_SUPPORT - - return lRet; - } - - void MonitorShutdown() throw() - { - while (1) - { - ::WaitForSingleObject(m_hEventShutdown, INFINITE); - DWORD dwWait = 0; - do - { - m_bActivity = false; - dwWait = ::WaitForSingleObject(m_hEventShutdown, m_dwTimeOut); - } while (dwWait == WAIT_OBJECT_0); - // timed out - if (!m_bActivity && m_nLockCnt == 0) // if no activity let's really bail - { -#if ((_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM)) & defined(_ATL_FREE_THREADED) - ::CoSuspendClassObjects(); - if (m_nLockCnt == 0) -#endif - break; - } - } - ::CloseHandle(m_hEventShutdown); - ::PostThreadMessage(m_dwMainThreadID, WM_QUIT, 0, 0); - } - - HANDLE StartMonitor() throw() - { - m_hEventShutdown = ::CreateEvent(NULL, false, false, NULL); - if (m_hEventShutdown == NULL) - return false; - DWORD dwThreadID; - HANDLE h = ::CreateThread(NULL, 0, MonitorProc, this, 0, &dwThreadID); - return h; - } - - static DWORD WINAPI MonitorProc(void* pv) throw() - { - CAtlExeModuleT* p = static_cast*>(pv); - p->MonitorShutdown(); - return 0; - } - - int WinMain(int nShowCmd) throw() - { - if (CAtlBaseModule::m_bInitFailed) - { - ATLASSERT(0); - return -1; - } - T* pT = static_cast(this); - HRESULT hr = S_OK; - - LPTSTR lpCmdLine = GetCommandLine(); //this line necessary for _ATL_MIN_CRT - if (pT->ParseCommandLine(lpCmdLine, &hr) == true) - hr = pT->Run(nShowCmd); - -#ifdef _DEBUG - // Prevent false memory leak reporting. ~CAtlWinModule may be too late. - _AtlWinModule.Term(); -#endif // _DEBUG - return hr; - } - - // Scan command line and perform registration - // Return value specifies if server should run - - // Parses the command line and registers/unregisters the rgs file if necessary - bool ParseCommandLine(LPCTSTR lpCmdLine, HRESULT* pnRetCode) throw() - { - *pnRetCode = S_OK; - - TCHAR szTokens[] = _T("-/"); - - T* pT = static_cast(this); - LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens); - while (lpszToken != NULL) - { - if (WordCmpI(lpszToken, _T("UnregServer"))==0) - { - *pnRetCode = pT->UnregisterServer(TRUE); - if (SUCCEEDED(*pnRetCode)) - *pnRetCode = pT->UnregisterAppId(); - return false; - } - - // Register as Local Server - if (WordCmpI(lpszToken, _T("RegServer"))==0) - { - *pnRetCode = pT->RegisterAppId(); - if (SUCCEEDED(*pnRetCode)) - *pnRetCode = pT->RegisterServer(TRUE); - return false; - } - - lpszToken = FindOneOf(lpszToken, szTokens); - } - - return true; - } - - HRESULT PreMessageLoop(int /*nShowCmd*/) throw() - { - HRESULT hr = S_OK; - T* pT = static_cast(this); - pT; - -#ifndef _ATL_NO_COM_SUPPORT - -#if ((_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM)) & defined(_ATL_FREE_THREADED) - - hr = pT->RegisterClassObjects(CLSCTX_LOCAL_SERVER, - REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED); - - if (FAILED(hr)) - return hr; - - if (hr == S_OK) - { - if (m_bDelayShutdown) - { - CHandle h(pT->StartMonitor()); - if (h.m_h == NULL) - { - hr = E_FAIL; - } - else - { - hr = CoResumeClassObjects(); - ATLASSERT(SUCCEEDED(hr)); - if (FAILED(hr)) - { - ::SetEvent(m_hEventShutdown); // tell monitor to shutdown - ::WaitForSingleObject(h, m_dwTimeOut * 2); - } - } - } - else - { - hr = CoResumeClassObjects(); - ATLASSERT(SUCCEEDED(hr)); - } - - if (FAILED(hr)) - pT->RevokeClassObjects(); - } - else - { - m_bDelayShutdown = false; - } - -#else - - hr = pT->RegisterClassObjects(CLSCTX_LOCAL_SERVER, - REGCLS_MULTIPLEUSE); - if (hr == S_OK) - { - if (m_bDelayShutdown && !pT->StartMonitor()) - { - hr = E_FAIL; - } - } - else - { - m_bDelayShutdown = false; - } - - -#endif - -#endif // _ATL_NO_COM_SUPPORT - - ATLASSERT(SUCCEEDED(hr)); - return hr; - } - - HRESULT PostMessageLoop() throw() - { - HRESULT hr = S_OK; - -#ifndef _ATL_NO_COM_SUPPORT - - T* pT = static_cast(this); - hr = pT->RevokeClassObjects(); - if (m_bDelayShutdown) - Sleep(m_dwPause); //wait for any threads to finish - -#endif // _ATL_NO_COM_SUPPORT - - return hr; - } - - void RunMessageLoop() throw() - { - MSG msg; - while (GetMessage(&msg, 0, 0, 0) > 0) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - - HRESULT Run(int nShowCmd = SW_HIDE) throw() - { - HRESULT hr = S_OK; - - T* pT = static_cast(this); - hr = pT->PreMessageLoop(nShowCmd); - - // Call RunMessageLoop only if PreMessageLoop returns S_OK. - if (hr == S_OK) - { - pT->RunMessageLoop(); - } - - // Call PostMessageLoop if PreMessageLoop returns success. - if (SUCCEEDED(hr)) - { - hr = pT->PostMessageLoop(); - } - - ATLASSERT(SUCCEEDED(hr)); - return hr; - } - - // Register/Revoke All Class Factories with the OS (EXE only) - HRESULT RegisterClassObjects(DWORD dwClsContext, DWORD dwFlags) throw() - { - return AtlComModuleRegisterClassObjects(&_AtlComModule, dwClsContext, dwFlags); - } - HRESULT RevokeClassObjects() throw() - { - return AtlComModuleRevokeClassObjects(&_AtlComModule); - } -}; - -#ifndef _ATL_NO_SERVICE -template -class ATL_NO_VTABLE CAtlServiceModuleT : public CAtlExeModuleT -{ -public : - - CAtlServiceModuleT() throw() - { - m_bService = TRUE; - LoadString(_AtlBaseModule.GetModuleInstance(), nServiceNameID, m_szServiceName, sizeof(m_szServiceName) / sizeof(TCHAR)); - - // set up the initial service status - m_hServiceStatus = NULL; - m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - m_status.dwCurrentState = SERVICE_STOPPED; - m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP; - m_status.dwWin32ExitCode = 0; - m_status.dwServiceSpecificExitCode = 0; - m_status.dwCheckPoint = 0; - m_status.dwWaitHint = 0; - } - - int WinMain(int nShowCmd) throw() - { - if (CAtlBaseModule::m_bInitFailed) - { - ATLASSERT(0); - return -1; - } - - T* pT = static_cast(this); - HRESULT hr = S_OK; - - LPTSTR lpCmdLine = GetCommandLine(); //this line necessary for _ATL_MIN_CRT - if (pT->ParseCommandLine(lpCmdLine, &hr) == true) - hr = pT->Start(nShowCmd); - -#ifdef _DEBUG - // Prevent false memory leak reporting. ~CAtlWinModule may be too late. - _AtlWinModule.Term(); -#endif // _DEBUG - return hr; - } - - HRESULT Start(int nShowCmd) throw() - { - T* pT = static_cast(this); - // Are we Service or Local Server - CRegKey keyAppID; - LONG lRes = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_READ); - if (lRes != ERROR_SUCCESS) - { - m_status.dwWin32ExitCode = lRes; - return m_status.dwWin32ExitCode; - } - - CRegKey key; - lRes = key.Open(keyAppID, pT->GetAppIdT(), KEY_READ); - if (lRes != ERROR_SUCCESS) - { - m_status.dwWin32ExitCode = lRes; - return m_status.dwWin32ExitCode; - } - - TCHAR szValue[MAX_PATH]; - DWORD dwLen = MAX_PATH; - lRes = key.QueryStringValue(_T("LocalService"), szValue, &dwLen); - - m_bService = FALSE; - if (lRes == ERROR_SUCCESS) - m_bService = TRUE; - - if (m_bService) - { - SERVICE_TABLE_ENTRY st[] = - { - { m_szServiceName, _ServiceMain }, - { NULL, NULL } - }; - if (::StartServiceCtrlDispatcher(st) == 0) - m_status.dwWin32ExitCode = GetLastError(); - return m_status.dwWin32ExitCode; - } - // local server - call Run() directly, rather than - // from ServiceMain() - m_status.dwWin32ExitCode = pT->Run(nShowCmd); - return m_status.dwWin32ExitCode; - } - - inline HRESULT RegisterAppId(bool bService = false) throw() - { - if (!Uninstall()) - return E_FAIL; - - HRESULT hr = T::UpdateRegistryAppId(TRUE); - if (FAILED(hr)) - return hr; - - CRegKey keyAppID; - LONG lRes = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_WRITE); - if (lRes != ERROR_SUCCESS) - return AtlHresultFromWin32(lRes); - - CRegKey key; - - lRes = key.Create(keyAppID, T::GetAppIdT()); - if (lRes != ERROR_SUCCESS) - return AtlHresultFromWin32(lRes); - - key.DeleteValue(_T("LocalService")); - - if (!bService) - return S_OK; - - key.SetStringValue(_T("LocalService"), m_szServiceName); - - // Create service - if (!Install()) - return E_FAIL; - return S_OK; - } - - HRESULT UnregisterAppId() throw() - { - if (!Uninstall()) - return E_FAIL; - // First remove entries not in the RGS file. - CRegKey keyAppID; - LONG lRes = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_WRITE); - if (lRes != ERROR_SUCCESS) - return AtlHresultFromWin32(lRes); - - CRegKey key; - lRes = key.Open(keyAppID, T::GetAppIdT(), KEY_WRITE); - if (lRes != ERROR_SUCCESS) - return AtlHresultFromWin32(lRes); - key.DeleteValue(_T("LocalService")); - - return T::UpdateRegistryAppId(FALSE); - } - - // Parses the command line and registers/unregisters the rgs file if necessary - bool ParseCommandLine(LPCTSTR lpCmdLine, HRESULT* pnRetCode) throw() - { - if (!CAtlExeModuleT::ParseCommandLine(lpCmdLine, pnRetCode)) - return false; - - TCHAR szTokens[] = _T("-/"); - *pnRetCode = S_OK; - - T* pT = static_cast(this); - LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens); - while (lpszToken != NULL) - { - if (WordCmpI(lpszToken, _T("Service"))==0) - { - *pnRetCode = pT->RegisterAppId(true); - if (SUCCEEDED(*pnRetCode)) - *pnRetCode = pT->RegisterServer(TRUE); - return false; - } - lpszToken = FindOneOf(lpszToken, szTokens); - } - return true; - } - - void ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv) throw() - { - lpszArgv; - dwArgc; - HRESULT hr = E_FAIL; - // Register the control request handler - m_status.dwCurrentState = SERVICE_START_PENDING; - m_hServiceStatus = RegisterServiceCtrlHandler(m_szServiceName, _Handler); - if (m_hServiceStatus == NULL) - { - LogEvent(_T("Handler not installed")); - return; - } - SetServiceStatus(SERVICE_START_PENDING); - - m_status.dwWin32ExitCode = S_OK; - m_status.dwCheckPoint = 0; - m_status.dwWaitHint = 0; - - T* pT = static_cast(this); -#ifndef _ATL_NO_COM_SUPPORT - - hr = T::InitializeCom(); - if (FAILED(hr)) - return; - - m_bDelayShutdown = false; -#endif - // When the Run function returns, the service has stopped. - m_status.dwWin32ExitCode = pT->Run(SW_HIDE); - -#ifndef _ATL_NO_COM_SUPPORT - if (m_bService) - T::UninitializeCom(); -#endif - - SetServiceStatus(SERVICE_STOPPED); - LogEvent(_T("Service stopped")); - } - - HRESULT Run(int nShowCmd = SW_HIDE) throw() - { - HRESULT hr = S_OK; - T* pT = static_cast(this); - - hr = pT->PreMessageLoop(nShowCmd); - - if (hr == S_OK) - { - if (m_bService) - { - LogEvent(_T("Service started")); - SetServiceStatus(SERVICE_RUNNING); - } - - pT->RunMessageLoop(); - } - - if (SUCCEEDED(hr)) - { - hr = pT->PostMessageLoop(); - } - - return hr; - } - - HRESULT PreMessageLoop(int nShowCmd) throw() - { - HRESULT hr = S_OK; - if (m_bService) - { - m_dwThreadID = GetCurrentThreadId(); - - T* pT = static_cast(this); - hr = pT->InitializeSecurity(); - - if (FAILED(hr)) - return hr; - } - - hr = CAtlExeModuleT::PreMessageLoop(nShowCmd); - if (FAILED(hr)) - return hr; - - return hr; - } - - void OnStop() throw() - { - SetServiceStatus(SERVICE_STOP_PENDING); - PostThreadMessage(m_dwThreadID, WM_QUIT, 0, 0); - } - - void OnPause() throw() - { - } - - void OnContinue() throw() - { - } - - void OnInterrogate() throw() - { - } - - void OnShutdown() throw() - { - } - - void OnUnknownRequest(DWORD /*dwOpcode*/) throw() - { - LogEvent(_T("Bad service request")); - } - - void Handler(DWORD dwOpcode) throw() - { - T* pT = static_cast(this); - - switch (dwOpcode) - { - case SERVICE_CONTROL_STOP: - pT->OnStop(); - break; - case SERVICE_CONTROL_PAUSE: - pT->OnPause(); - break; - case SERVICE_CONTROL_CONTINUE: - pT->OnContinue(); - break; - case SERVICE_CONTROL_INTERROGATE: - pT->OnInterrogate(); - break; - case SERVICE_CONTROL_SHUTDOWN: - pT->OnShutdown(); - break; - default: - pT->OnUnknownRequest(dwOpcode); - } - } - - BOOL IsInstalled() throw() - { - BOOL bResult = FALSE; - - SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); - - if (hSCM != NULL) - { - SC_HANDLE hService = ::OpenService(hSCM, m_szServiceName, SERVICE_QUERY_CONFIG); - if (hService != NULL) - { - bResult = TRUE; - ::CloseServiceHandle(hService); - } - ::CloseServiceHandle(hSCM); - } - return bResult; - } - BOOL Install() throw() - { - if (IsInstalled()) - return TRUE; - - // Get the executable file path - TCHAR szFilePath[MAX_PATH + _ATL_QUOTES_SPACE]; - DWORD dwFLen = ::GetModuleFileName(NULL, szFilePath + 1, MAX_PATH); - if( dwFLen == 0 || dwFLen == MAX_PATH ) - return FALSE; - - // Quote the FilePath before calling CreateService - szFilePath[0] = _T('\"'); - szFilePath[dwFLen + 1] = _T('\"'); - szFilePath[dwFLen + 2] = 0; - - SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); - if (hSCM == NULL) - { - TCHAR szBuf[1024]; - if (AtlLoadString(ATL_SERVICE_MANAGER_OPEN_ERROR, szBuf, 1024) == 0) - lstrcpy(szBuf, _T("Could not open Service Manager")); - MessageBox(NULL, szBuf, m_szServiceName, MB_OK); - return FALSE; - } - - SC_HANDLE hService = ::CreateService( - hSCM, m_szServiceName, m_szServiceName, - SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, - SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, - szFilePath, NULL, NULL, _T("RPCSS\0"), NULL, NULL); - - if (hService == NULL) - { - ::CloseServiceHandle(hSCM); - TCHAR szBuf[1024]; - if (AtlLoadString(ATL_SERVICE_START_ERROR, szBuf, 1024) == 0) - lstrcpy(szBuf, _T("Could not start service")); - MessageBox(NULL, szBuf, m_szServiceName, MB_OK); - return FALSE; - } - - ::CloseServiceHandle(hService); - ::CloseServiceHandle(hSCM); - return TRUE; - } - - BOOL Uninstall() throw() - { - if (!IsInstalled()) - return TRUE; - - SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); - - if (hSCM == NULL) - { - TCHAR szBuf[1024]; - if (AtlLoadString(ATL_SERVICE_MANAGER_OPEN_ERROR, szBuf, 1024) == 0) - lstrcpy(szBuf, _T("Could not open Service Manager")); - MessageBox(NULL, szBuf, m_szServiceName, MB_OK); - return FALSE; - } - - SC_HANDLE hService = ::OpenService(hSCM, m_szServiceName, SERVICE_STOP | DELETE); - - if (hService == NULL) - { - ::CloseServiceHandle(hSCM); - TCHAR szBuf[1024]; - if (AtlLoadString(ATL_SERVICE_OPEN_ERROR, szBuf, 1024) == 0) - lstrcpy(szBuf, _T("Could not open service")); - MessageBox(NULL, szBuf, m_szServiceName, MB_OK); - return FALSE; - } - SERVICE_STATUS status; - BOOL bRet = ::ControlService(hService, SERVICE_CONTROL_STOP, &status); - if (!bRet) - { - DWORD dwError = GetLastError(); - if (!((dwError == ERROR_SERVICE_NOT_ACTIVE) || (dwError == ERROR_SERVICE_CANNOT_ACCEPT_CTRL && status.dwCurrentState == SERVICE_STOP_PENDING))) - { - TCHAR szBuf[1024]; - if (AtlLoadString(ATL_SERVICE_STOP_ERROR, szBuf, 1024) == 0) - lstrcpy(szBuf, _T("Could not stop service")); - MessageBox(NULL, szBuf, m_szServiceName, MB_OK); - } - } - - - BOOL bDelete = ::DeleteService(hService); - ::CloseServiceHandle(hService); - ::CloseServiceHandle(hSCM); - - if (bDelete) - return TRUE; - - TCHAR szBuf[1024]; - if (AtlLoadString(ATL_SERVICE_DELETE_ERROR, szBuf, 1024) == 0) - lstrcpy(szBuf, _T("Could not delete service")); - MessageBox(NULL, szBuf, m_szServiceName, MB_OK); - return FALSE; - } - - LONG Unlock() throw() - { - LONG lRet; - if (m_bService) - { - // We are running as a service, therefore transition to zero does not - // unload the process - lRet = CAtlModuleT::Unlock(); - } - else - { - // We are running as EXE, use MonitorShutdown logic provided by CExeModule - lRet = CAtlExeModuleT::Unlock(); - } - return lRet; - } - - void LogEventEx(int id, LPCTSTR pszMessage=NULL, WORD type = EVENTLOG_INFORMATION_TYPE) throw() - { - HANDLE hEventSource; - if (m_szServiceName) - { - /* Get a handle to use with ReportEvent(). */ - hEventSource = RegisterEventSource(NULL, m_szServiceName); - if (hEventSource != NULL) - { - /* Write to event log. */ - ReportEvent(hEventSource, - type, - (WORD)0, - id, - NULL, - (WORD)(pszMessage != NULL ? 1 : 0), - 0, - pszMessage != NULL ? &pszMessage : NULL, - NULL); - DeregisterEventSource(hEventSource); - } - } - } - - void __cdecl LogEvent(LPCTSTR pszFormat, ...) throw() - { - TCHAR chMsg[256]; - HANDLE hEventSource; - LPTSTR lpszStrings[1]; - va_list pArg; - - va_start(pArg, pszFormat); - _vstprintf(chMsg, pszFormat, pArg); - va_end(pArg); - - lpszStrings[0] = chMsg; - - if (!m_bService) - { - // Not running as a service, so print out the error message - // to the console if possible - _putts(chMsg); - } - - /* Get a handle to use with ReportEvent(). */ - hEventSource = RegisterEventSource(NULL, m_szServiceName); - if (hEventSource != NULL) - { - /* Write to event log. */ - ReportEvent(hEventSource, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (LPCTSTR*) &lpszStrings[0], NULL); - DeregisterEventSource(hEventSource); - } - } - void SetServiceStatus(DWORD dwState) throw() - { - m_status.dwCurrentState = dwState; - ::SetServiceStatus(m_hServiceStatus, &m_status); - } - -//Implementation -protected: - static void WINAPI _ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv) throw() - { - ((T*)_pAtlModule)->ServiceMain(dwArgc, lpszArgv); - } - static void WINAPI _Handler(DWORD dwOpcode) throw() - { - ((T*)_pAtlModule)->Handler(dwOpcode); - } - -// data members -public: - TCHAR m_szServiceName[256]; - SERVICE_STATUS_HANDLE m_hServiceStatus; - SERVICE_STATUS m_status; - BOOL m_bService; - DWORD m_dwThreadID; -}; - -#endif // _ATL_NO_SERVICE - -#endif // !_AFX - -#ifdef _AFX -class CAtlMfcModule : public ATL::CAtlModuleT -{ -public : - virtual LONG Lock() throw() - { -#ifdef _USRDLL - AFX_MANAGE_STATE(AfxGetStaticModuleState()); -#endif - AfxOleLockApp(); - return AfxGetModuleState()->m_nObjectCount; - } - - virtual LONG Unlock() throw() - { -#ifdef _USRDLL - AFX_MANAGE_STATE(AfxGetStaticModuleState()); -#endif - AfxOleUnlockApp(); - return AfxGetModuleState()->m_nObjectCount; - } - - virtual LONG GetLockCount() throw() - { -#ifdef _USRDLL - AFX_MANAGE_STATE(AfxGetStaticModuleState()); -#endif - return AfxGetModuleState()->m_nObjectCount; - } - - // Obtain a Class Factory (DLL only) - HRESULT GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) - { - return ATL::AtlComModuleGetClassObject(&ATL::_AtlComModule, rclsid, riid, ppv); - } - - // Register/Revoke All Class Factories with the OS (EXE only) - HRESULT RegisterClassObjects(DWORD dwClsContext, DWORD dwFlags) - { - return ATL::AtlComModuleRegisterClassObjects(&ATL::_AtlComModule, dwClsContext, dwFlags); - } - - HRESULT RevokeClassObjects() - { - return ATL::AtlComModuleRevokeClassObjects(&ATL::_AtlComModule); - } -}; - -#endif // _AFX - -///////////////////////////////////////////////////////////////////////////// -// CComModule - Uses the functionality provided by other modules - -#define THREADFLAGS_APARTMENT 0x1 -#define THREADFLAGS_BOTH 0x2 -#define AUTPRXFLAG 0x4 - -#ifndef _ATL_NO_COMMODULE - -class CComModule; -__declspec(selectany) CComModule* _pModule = NULL; -class CComModule : public CAtlModuleT -{ -public : - - CComModule() - { - // Should have only one instance of a class - // derived from CComModule in a project. - ATLASSERT(_pModule == NULL); - _pModule = this; - } - __declspec(property(get = get_m_hInst)) HINSTANCE m_hInst; - HINSTANCE& get_m_hInst() const throw() - { - return _AtlBaseModule.m_hInst; - } - - __declspec(property(get = get_m_hInstResource, put = put_m_hInstResource)) HINSTANCE m_hInstResource; - HINSTANCE& get_m_hInstResource() const throw() - { - return _AtlBaseModule.m_hInstResource; - } - void put_m_hInstResource(HINSTANCE h) throw() - { - _AtlBaseModule.SetResourceInstance(h); - } - HINSTANCE SetResourceInstance(HINSTANCE h) throw() - { - return _AtlBaseModule.SetResourceInstance(h); - } - - HINSTANCE GetModuleInstance() throw() - { - return _AtlBaseModule.m_hInst; - } - HINSTANCE GetResourceInstance() throw() - { - return _AtlBaseModule.m_hInstResource; - } - - __declspec(property(get = get_m_hInstTypeLib, put = put_m_hInstTypeLib)) HINSTANCE m_hInstTypeLib; - HINSTANCE& get_m_hInstTypeLib() const throw() - { - return _AtlComModule.m_hInstTypeLib; - } - void put_m_hInstTypeLib(HINSTANCE h) throw() - { - _AtlComModule.m_hInstTypeLib = h; - } - - HINSTANCE GetTypeLibInstance() const throw() - { - return _AtlComModule.m_hInstTypeLib; - } - - // For Backward compatibility - _ATL_OBJMAP_ENTRY* m_pObjMap; - - __declspec(property(get = get_m_csWindowCreate)) CRITICAL_SECTION m_csWindowCreate; - CRITICAL_SECTION& get_m_csWindowCreate() throw(); - - __declspec(property(get = get_m_csObjMap)) CRITICAL_SECTION m_csObjMap; - CRITICAL_SECTION& get_m_csObjMap() throw(); - - __declspec(property(get = get_m_csStaticDataInit)) CRITICAL_SECTION m_csTypeInfoHolder; - __declspec(property(get = get_m_csStaticDataInit)) CRITICAL_SECTION m_csStaticDataInit; - CRITICAL_SECTION& get_m_csStaticDataInit() throw(); - void EnterStaticDataCriticalSection() throw() - { - EnterCriticalSection(&m_csStaticDataInit); - } - - void LeaveStaticDataCriticalSection() throw() - { - LeaveCriticalSection(&m_csStaticDataInit); - } - - __declspec(property(get = get_dwAtlBuildVer)) DWORD dwAtlBuildVer; - DWORD& get_dwAtlBuildVer() throw() - { - return _AtlBaseModule.dwAtlBuildVer; - } - - __declspec(property(get = get_m_pCreateWndList, put = put_m_pCreateWndList)) _AtlCreateWndData* m_pCreateWndList; - _AtlCreateWndData*& get_m_pCreateWndList() throw(); - void put_m_pCreateWndList(_AtlCreateWndData* p) throw(); - - __declspec(property(get = get_pguidVer)) const GUID* pguidVer; - const GUID*& get_pguidVer() throw() - { - return _AtlBaseModule.pguidVer; - } - -#ifdef _ATL_DEBUG_INTERFACES - - __declspec(property(get = get_m_nIndexQI, put = put_m_nIndexQI)) UINT m_nIndexQI; - UINT& get_m_nIndexQI() throw(); - void put_m_nIndexQI(UINT nIndex) throw(); - - __declspec(property(get = get_m_nIndexBreakAt, put = put_m_nIndexBreakAt)) UINT m_nIndexBreakAt; - UINT& get_m_nIndexBreakAt() throw(); - void put_m_nIndexBreakAt(UINT nIndex) throw(); - - __declspec(property(get = get_m_paThunks)) CSimpleArray<_QIThunk*>* m_paThunks; - CSimpleArray<_QIThunk*>* get_m_paThunks() throw(); - HRESULT AddThunk(IUnknown** pp, LPCTSTR lpsz, REFIID iid) throw(); - - HRESULT AddNonAddRefThunk(IUnknown* p, LPCTSTR lpsz, IUnknown** ppThunkRet) throw(); - void DeleteNonAddRefThunk(IUnknown* pUnk) throw(); - void DeleteThunk(_QIThunk* p) throw(); - bool DumpLeakedThunks() throw(); -#endif // _ATL_DEBUG_INTERFACES - - HRESULT Init(_ATL_OBJMAP_ENTRY* p, HINSTANCE h, const GUID* plibid = NULL) throw(); - void Term() throw(); - - HRESULT GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) throw(); - // Register/Revoke All Class Factories with the OS (EXE only) - HRESULT RegisterClassObjects(DWORD dwClsContext, DWORD dwFlags) throw(); - HRESULT RevokeClassObjects() throw(); - // Registry support (helpers) - HRESULT RegisterTypeLib() throw(); - HRESULT RegisterTypeLib(LPCTSTR lpszIndex) throw(); - HRESULT UnRegisterTypeLib() throw(); - HRESULT UnRegisterTypeLib(LPCTSTR lpszIndex) throw(); - HRESULT RegisterServer(BOOL bRegTypeLib = FALSE, const CLSID* pCLSID = NULL) throw(); - HRESULT UnregisterServer(BOOL bUnRegTypeLib, const CLSID* pCLSID = NULL) throw(); - HRESULT UnregisterServer(const CLSID* pCLSID = NULL) throw(); - - void AddCreateWndData(_AtlCreateWndData* pData, void* pObject) throw() - { - _AtlWinModule.AddCreateWndData(pData, pObject); - } - - void* ExtractCreateWndData() throw() - { - return _AtlWinModule.ExtractCreateWndData(); - } - - // Only used in CComAutoThreadModule - HRESULT CreateInstance(void* /*pfnCreateInstance*/, REFIID /*riid*/, void** /*ppvObj*/) throw() - { - ATLASSERT(0); - ATLTRACENOTIMPL(_T("CComModule::CreateInstance")); - } - - HRESULT RegisterAppId(LPCTSTR pAppId); - HRESULT UnregisterAppId(LPCTSTR pAppId); - - // Resource-based Registration - virtual HRESULT WINAPI UpdateRegistryFromResourceD(LPCTSTR lpszRes, BOOL bRegister, - struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw() - { -#if defined(_ATL_STATIC_REGISTRY) - (lpszRes); - (bRegister); - (pMapEntries); - return E_FAIL; -#else - return CAtlModuleT::UpdateRegistryFromResourceD(lpszRes, bRegister, pMapEntries); -#endif - } - virtual HRESULT WINAPI UpdateRegistryFromResourceD(UINT nResID, BOOL bRegister, - struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw() - { -#if defined(_ATL_STATIC_REGISTRY) - (nResID); - (bRegister); - (pMapEntries); - return E_FAIL; -#else - return CAtlModuleT::UpdateRegistryFromResourceD(nResID, bRegister, pMapEntries); -#endif - } - - - // Statically linking to Registry Ponent - virtual HRESULT WINAPI UpdateRegistryFromResourceS(LPCTSTR lpszRes, BOOL bRegister, - struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw() - { -#ifdef _ATL_STATIC_REGISTRY - return CAtlModuleT::UpdateRegistryFromResourceS(lpszRes, bRegister, pMapEntries); -#else - (lpszRes); - (bRegister); - (pMapEntries); - return E_FAIL; -#endif - } - virtual HRESULT WINAPI UpdateRegistryFromResourceS(UINT nResID, BOOL bRegister, - struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw() - { -#ifdef _ATL_STATIC_REGISTRY - return CAtlModuleT::UpdateRegistryFromResourceS(nResID, bRegister, pMapEntries); -#else - (nResID); - (bRegister); - (pMapEntries); - return E_FAIL; -#endif - } - - - // Use RGS file for registration - - ATL_DEPRECATED static HRESULT RegisterProgID(LPCTSTR lpszCLSID, LPCTSTR lpszProgID, LPCTSTR lpszUserDesc); - // Standard Registration - ATL_DEPRECATED HRESULT WINAPI UpdateRegistryClass(const CLSID& clsid, LPCTSTR lpszProgID, - LPCTSTR lpszVerIndProgID, UINT nDescID, DWORD dwFlags, BOOL bRegister); - ATL_DEPRECATED HRESULT WINAPI UpdateRegistryClass(const CLSID& clsid, LPCTSTR lpszProgID, - LPCTSTR lpszVerIndProgID, LPCTSTR szDesc, DWORD dwFlags, BOOL bRegister); - ATL_DEPRECATED HRESULT WINAPI RegisterClassHelper(const CLSID& clsid, LPCTSTR lpszProgID, - LPCTSTR lpszVerIndProgID, LPCTSTR szDesc, DWORD dwFlags); - ATL_DEPRECATED HRESULT WINAPI UnregisterClassHelper(const CLSID& clsid, LPCTSTR lpszProgID, - LPCTSTR lpszVerIndProgID); - - BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /* lpReserved */, _ATL_OBJMAP_ENTRY* pObjMap, const GUID* pLibID) - { - if (dwReason == DLL_PROCESS_ATTACH) - { - if (CAtlBaseModule::m_bInitFailed) - { - ATLASSERT(0); - return FALSE; - } - - if (FAILED(Init(pObjMap, hInstance, pLibID))) - { - Term(); - return FALSE; - } -#ifdef _ATL_MIN_CRT - DisableThreadLibraryCalls(hInstance); -#endif - } - else if (dwReason == DLL_PROCESS_DETACH) - Term(); - return TRUE; // ok - } - - HRESULT DllCanUnloadNow() throw() - { - return (GetLockCount()==0) ? S_OK : S_FALSE; - } - HRESULT DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) throw() - { - return GetClassObject(rclsid, riid, ppv); - } - - HRESULT DllRegisterServer(BOOL bRegTypeLib = TRUE) throw() - { - // registers object, typelib and all interfaces in typelib - return RegisterServer(bRegTypeLib); - } - - HRESULT DllUnregisterServer(BOOL bUnRegTypeLib = TRUE) throw() - { - return UnregisterServer(bUnRegTypeLib); - } - -}; - -#endif // !_ATL_NO_COMMODULE - -///////////////////////////////////////////////////////////////////////////// -// Thread creation helpers - -#if !defined(_ATL_MIN_CRT) && defined(_MT) -// CRTThreadTraits -// This class is for use with CThreadPool or CWorkerThread -// It should be used if the worker class will use CRT -// functions. -class CRTThreadTraits -{ -public: - static HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpsa, DWORD dwStackSize, LPTHREAD_START_ROUTINE pfnThreadProc, void *pvParam, DWORD dwCreationFlags, DWORD *pdwThreadId) throw() - { - ATLASSERT(sizeof(DWORD) == sizeof(unsigned int)); // sanity check for pdwThreadId - - // _beginthreadex calls CreateThread which will set the last error value before it returns. - return (HANDLE) _beginthreadex(lpsa, dwStackSize, (unsigned int (__stdcall *)(void *)) pfnThreadProc, pvParam, dwCreationFlags, (unsigned int *) pdwThreadId); - } -}; - -#endif - -// Win32ThreadTraits -// This class is for use with CThreadPool or CWorkerThread -// It should be used if the worker class will not use CRT -// functions. -class Win32ThreadTraits -{ -public: - static HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpsa, DWORD dwStackSize, LPTHREAD_START_ROUTINE pfnThreadProc, void *pvParam, DWORD dwCreationFlags, DWORD *pdwThreadId) throw() - { - return ::CreateThread(lpsa, dwStackSize, pfnThreadProc, pvParam, dwCreationFlags, pdwThreadId); - } -}; - -#if !defined(_ATL_MIN_CRT) && defined(_MT) - typedef CRTThreadTraits DefaultThreadTraits; -#else - typedef Win32ThreadTraits DefaultThreadTraits; -#endif - -template -HANDLE CreateThreadT(LPSECURITY_ATTRIBUTES lpsa, DWORD dwStackSize, DWORD (WINAPI * pfn)(T *pparam), - T *pparam, DWORD dwCreationFlags, LPDWORD pdw) -{ - return DefaultThreadTraits::CreateThread(lpsa, - dwStackSize, - (LPTHREAD_START_ROUTINE)pfn, - pparam, - dwCreationFlags, - pdw); -} - -template -HANDLE AtlCreateThread(DWORD (WINAPI* pfn)(T *pparam), T *pparam) -{ - return CreateThreadT(0, 0, pfn, pparam, 0, 0); -} - -///////////////////////////////////////////////////////////////////////////////////////////// -// Thread Pooling classes - -class _AtlAptCreateObjData -{ -public: - _ATL_CREATORFUNC* pfnCreateInstance; - const IID* piid; - HANDLE hEvent; - LPSTREAM pStream; - HRESULT hRes; -}; - -class CComApartment -{ -public: - CComApartment() - { - m_nLockCnt = 0; - m_hThread = NULL; - } - static UINT ATL_CREATE_OBJECT; - static DWORD WINAPI _Apartment(void* pv) - { - ATLASSERT(pv != NULL); - return ((CComApartment*)pv)->Apartment(); - } - DWORD Apartment() - { - CoInitialize(NULL); - MSG msg; - while(GetMessage(&msg, 0, 0, 0) > 0) - { - if (msg.message == ATL_CREATE_OBJECT) - { - _AtlAptCreateObjData* pdata = (_AtlAptCreateObjData*)msg.lParam; - IUnknown* pUnk = NULL; - pdata->hRes = pdata->pfnCreateInstance(NULL, __uuidof(IUnknown), (void**)&pUnk); - if (SUCCEEDED(pdata->hRes)) - pdata->hRes = CoMarshalInterThreadInterfaceInStream(*pdata->piid, pUnk, &pdata->pStream); - if (SUCCEEDED(pdata->hRes)) - { - pUnk->Release(); - ATLTRACE(atlTraceCOM, 2, _T("Object created on thread = %d\n"), GetCurrentThreadId()); - } -#ifdef _DEBUG - else - { - ATLTRACE(atlTraceCOM, 2, _T("Failed to create Object on thread = %d\n"), GetCurrentThreadId()); - } -#endif - SetEvent(pdata->hEvent); - } - DispatchMessage(&msg); - } - CoUninitialize(); - - return 0; - } - LONG Lock() {return CComGlobalsThreadModel::Increment(&m_nLockCnt);} - LONG Unlock(){return CComGlobalsThreadModel::Decrement(&m_nLockCnt); - } - LONG GetLockCount() {return m_nLockCnt;} - - DWORD m_dwThreadID; - HANDLE m_hThread; - LONG m_nLockCnt; -}; - -__declspec(selectany) UINT CComApartment::ATL_CREATE_OBJECT = 0; - -class CComSimpleThreadAllocator -{ -public: - CComSimpleThreadAllocator() - { - m_nThread = 0; - } - int GetThread(CComApartment* /*pApt*/, int nThreads) - { - if (++m_nThread == nThreads) - m_nThread = 0; - return m_nThread; - } - int m_nThread; -}; - -__interface IAtlAutoThreadModule -{ - virtual HRESULT CreateInstance(void* pfnCreateInstance, REFIID riid, void** ppvObj); -}; - -__declspec(selectany) IAtlAutoThreadModule* _pAtlAutoThreadModule; - -template -class ATL_NO_VTABLE CAtlAutoThreadModuleT : public IAtlAutoThreadModule -{ -// This class is not for use in a DLL. -// If this class were used in a DLL, there will be a deadlock when the DLL is unloaded. -// because of dwWait's default value of INFINITE -public: - CAtlAutoThreadModuleT(int nThreads = T::GetDefaultThreads()) - { - ATLASSERT(_pAtlAutoThreadModule == NULL); - _pAtlAutoThreadModule = this; - m_pApartments = NULL; - m_nThreads= 0; - - ATLTRY(m_pApartments = new CComApartment[nThreads]); - ATLASSERT(m_pApartments != NULL); - if(m_pApartments == NULL) - { - CAtlBaseModule::m_bInitFailed = true; - } - - memset(m_pApartments, 0, sizeof(CComApartment) * nThreads); - - m_nThreads = nThreads; - for (int i = 0; i < nThreads; i++) - { - -#if !defined(_ATL_MIN_CRT) && defined(_MT) - typedef unsigned ( __stdcall *pfnThread )( void * ); - m_pApartments[i].m_hThread = (HANDLE)_beginthreadex(NULL, 0, (pfnThread)CComApartment::_Apartment, &m_pApartments[i], 0, (UINT*)&m_pApartments[i].m_dwThreadID); - if (m_pApartments[i].m_hThread == NULL) - { - HRESULT hr = E_FAIL; - switch (errno) - { - case EAGAIN: - hr = HRESULT_FROM_WIN32(ERROR_TOO_MANY_TCBS); - break; - case EINVAL: - hr = E_INVALIDARG; - break; - } - CAtlBaseModule::m_bInitFailed = true; - break; - } - -#else - m_pApartments[i].m_hThread = ::CreateThread(NULL, 0, CComApartment::_Apartment, (void*)&m_pApartments[i], 0, &m_pApartments[i].m_dwThreadID); - // clean up allocated threads - if (m_pApartments[i].m_hThread == NULL) - { - CAtlBaseModule::m_bInitFailed = true; - break; - } - -#endif - - } - if (!CAtlBaseModule::m_bInitFailed) - CComApartment::ATL_CREATE_OBJECT = RegisterWindowMessage(_T("ATL_CREATE_OBJECT")); - } - - virtual ~CAtlAutoThreadModuleT() - { - if (m_pApartments == NULL) - return; - - DWORD dwCurrentThreadId = GetCurrentThreadId(); - int nCurrentThread = -1; - for (int i=0; i < m_nThreads; i++) - { - if (m_pApartments[i].m_hThread == NULL) - continue; - if (m_pApartments[i].m_dwThreadID == dwCurrentThreadId) - { - nCurrentThread = i; - continue; - } - while (::PostThreadMessage(m_pApartments[i].m_dwThreadID, WM_QUIT, 0, 0) == 0) - { - if (GetLastError() == ERROR_INVALID_THREAD_ID) - { - ATLASSERT(FALSE); - break; - } - ::Sleep(100); - } - ::WaitForSingleObject(m_pApartments[i].m_hThread, dwWait); - CloseHandle(m_pApartments[i].m_hThread); - } - if (nCurrentThread != -1) - CloseHandle(m_pApartments[nCurrentThread].m_hThread); - - delete [] m_pApartments; - m_pApartments = NULL; - } - - HRESULT CreateInstance(void* pfnCreateInstance, REFIID riid, void** ppvObj) - { - ATLASSERT(ppvObj != NULL); - if (ppvObj == NULL) - return E_POINTER; - *ppvObj = NULL; - - _ATL_CREATORFUNC* pFunc = (_ATL_CREATORFUNC*) pfnCreateInstance; - _AtlAptCreateObjData data; - data.pfnCreateInstance = pFunc; - data.piid = &riid; - data.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - data.hRes = S_OK; - int nThread = m_Allocator.GetThread(m_pApartments, m_nThreads); - int nIterations = 0; - while(::PostThreadMessage(m_pApartments[nThread].m_dwThreadID, CComApartment::ATL_CREATE_OBJECT, 0, (LPARAM)&data) == 0 && ++nIterations < 100) - { - Sleep(100); - } - if (nIterations < 100) - { - AtlWaitWithMessageLoop(data.hEvent); - } - else - { - data.hRes = AtlHresultFromLastError(); - } - CloseHandle(data.hEvent); - if (SUCCEEDED(data.hRes)) - data.hRes = CoGetInterfaceAndReleaseStream(data.pStream, riid, ppvObj); - return data.hRes; - } - DWORD dwThreadID; - int m_nThreads; - CComApartment* m_pApartments; - ThreadAllocator m_Allocator; - static int GetDefaultThreads() - { - SYSTEM_INFO si; - GetSystemInfo(&si); - return si.dwNumberOfProcessors * 4; - } -}; - -class CAtlAutoThreadModule : public CAtlAutoThreadModuleT -{ -public : -}; - -#ifndef _ATL_NO_COMMODULE - -template -class CComAutoThreadModule : - public CComModule, - public CAtlAutoThreadModuleT -{ -public: - CComAutoThreadModule(int nThreads = GetDefaultThreads()) : - CAtlAutoThreadModuleT(nThreads) - { - } - HRESULT Init(_ATL_OBJMAP_ENTRY* p, HINSTANCE h, const GUID* plibid = NULL, int nThreads = GetDefaultThreads()) - { - ATLASSERT(nThreads == GetDefaultThreads() && _T("Set number of threads through the constructor")); - return CComModule::Init(p, h, plibid); - } -}; - -#endif // !_ATL_NO_COMMODULE - -///////////////////////////////////////////////////////////////////////////// -// GIT Pointer - -template -class CComGITPtr -{ -public: - CComGITPtr() throw() - { - m_dwCookie = 0; - } - CComGITPtr(T* p) - { - m_dwCookie = 0; - HRESULT hr = Attach(p); - - if (FAILED(hr)) - AtlThrow(hr); - } - CComGITPtr(const CComGITPtr& git) - { - m_dwCookie = 0; - CComPtr spT; - - HRESULT hr = git.CopyTo(&spT); - if (SUCCEEDED(hr)) - hr = Attach(spT); - - if (FAILED(hr)) - AtlThrow(hr); - } - explicit CComGITPtr(DWORD dwCookie) throw() - { - ATLASSERT(m_dwCookie != NULL); - m_dwCookie = dwCookie; - -#ifdef _DEBUG - CComPtr spT; - HRESULT hr = CopyTo(&spT); - ATLASSERT(SUCCEEDED(hr)); -#endif - } - - ~CComGITPtr() throw() - { - Revoke(); - } - CComGITPtr& operator=(const CComGITPtr& git) - { - CComPtr spT; - - HRESULT hr = git.CopyTo(&spT); - if (SUCCEEDED(hr)) - hr = Attach(spT); - - if (FAILED(hr)) - AtlThrow(hr); - - return *this; - } - CComGITPtr& operator=(T* p) - { - HRESULT hr = Attach(p); - if (FAILED(hr)) - AtlThrow(hr); - return *this; - } - CComGITPtr& operator=(DWORD dwCookie) - { - HRESULT hr = Attach(dwCookie); - if (FAILED(hr)) - AtlThrow(hr); - - m_dwCookie = dwCookie; - -#ifdef _DEBUG - CComPtr spT; - hr = CopyTo(&spT); - ATLASSERT(SUCCEEDED(hr)); -#endif - - return *this; - } - - // Get the cookie from the class - operator DWORD() const - { - return m_dwCookie; - } - // Get the cookie from the class - DWORD GetCookie() const - { - return m_dwCookie; - } - // Register the passed interface pointer in the GIT - HRESULT Attach(T* p) throw() - { - CComPtr spGIT; - HRESULT hr = E_FAIL; - hr = AtlGetGITPtr(&spGIT); - ATLASSERT(spGIT != NULL); - ATLASSERT(SUCCEEDED(hr)); - if (FAILED(hr)) - return hr; - - if (m_dwCookie != 0) - hr = spGIT->RevokeInterfaceFromGlobal(m_dwCookie); - if (FAILED(hr)) - return hr; - - return spGIT->RegisterInterfaceInGlobal(p, __uuidof(T), &m_dwCookie); - } - - HRESULT Attach(DWORD dwCookie) throw() - { - ATLASSERT(dwCookie != NULL); - HRESULT hr = Revoke(); - if (FAILED(hr)) - return hr; - m_dwCookie = dwCookie; - return S_OK; - } - - // Detach - DWORD Detach() throw() - { - DWORD dwCookie = m_dwCookie; - m_dwCookie = NULL; - return dwCookie; - } - - // Remove the interface from the GIT - HRESULT Revoke() throw() - { - HRESULT hr = S_OK; - if (m_dwCookie != 0) - { - CComPtr spGIT; - HRESULT hr = E_FAIL; - hr = AtlGetGITPtr(&spGIT); - - ATLASSERT(spGIT != NULL); - ATLASSERT(SUCCEEDED(hr)); - if (FAILED(hr)) - return hr; - - hr = spGIT->RevokeInterfaceFromGlobal(m_dwCookie); - if (SUCCEEDED(hr)) - m_dwCookie = 0; - } - return hr; - } - // Get's the interface from the GIT and copies it to the passed pointer. The pointer - // must be released by the caller when finished. - HRESULT CopyTo(T** pp) const throw() - { - CComPtr spGIT; - HRESULT hr = E_FAIL; - hr = AtlGetGITPtr(&spGIT); - - ATLASSERT(spGIT != NULL); - ATLASSERT(SUCCEEDED(hr)); - if (FAILED(hr)) - return hr; - - ATLASSERT(m_dwCookie!=NULL); - return spGIT->GetInterfaceFromGlobal(m_dwCookie, __uuidof(T), (void**)pp); - } - DWORD m_dwCookie; -}; - -///////////////////////////////////////////////////////////////////////////// -// CRegKey - -class CRegKey -{ -public: - CRegKey() throw(); - CRegKey( CRegKey& key ) throw(); - explicit CRegKey(HKEY hKey) throw(); - ~CRegKey() throw(); - - CRegKey& operator=( CRegKey& key ) throw(); - -// Attributes -public: - operator HKEY() const throw(); - HKEY m_hKey; - -// Operations -public: - ATL_DEPRECATED LONG SetValue(DWORD dwValue, LPCTSTR lpszValueName); - ATL_DEPRECATED LONG SetValue(LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL, bool bMulti = false, int nValueLen = -1); - LONG SetValue(LPCTSTR pszValueName, DWORD dwType, const void* pValue, ULONG nBytes) throw(); - LONG SetGUIDValue(LPCTSTR pszValueName, REFGUID guidValue) throw(); - LONG SetBinaryValue(LPCTSTR pszValueName, const void* pValue, ULONG nBytes) throw(); - LONG SetDWORDValue(LPCTSTR pszValueName, DWORD dwValue) throw(); - LONG SetQWORDValue(LPCTSTR pszValueName, ULONGLONG qwValue) throw(); - LONG SetStringValue(LPCTSTR pszValueName, LPCTSTR pszValue, DWORD dwType = REG_SZ) throw(); - LONG SetMultiStringValue(LPCTSTR pszValueName, LPCTSTR pszValue) throw(); - - ATL_DEPRECATED LONG QueryValue(DWORD& dwValue, LPCTSTR lpszValueName); - ATL_DEPRECATED LONG QueryValue(LPTSTR szValue, LPCTSTR lpszValueName, DWORD* pdwCount); - LONG QueryValue(LPCTSTR pszValueName, DWORD* pdwType, void* pData, ULONG* pnBytes) throw(); - LONG QueryGUIDValue(LPCTSTR pszValueName, GUID& guidValue) throw(); - LONG QueryBinaryValue(LPCTSTR pszValueName, void* pValue, ULONG* pnBytes) throw(); - LONG QueryDWORDValue(LPCTSTR pszValueName, DWORD& dwValue) throw(); - LONG QueryQWORDValue(LPCTSTR pszValueName, ULONGLONG& qwValue) throw(); - LONG QueryStringValue(LPCTSTR pszValueName, LPTSTR pszValue, ULONG* pnChars) throw(); - LONG QueryMultiStringValue(LPCTSTR pszValueName, LPTSTR pszValue, ULONG* pnChars) throw(); - - // Get the key's security attributes. - LONG GetKeySecurity(SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR psd, LPDWORD pnBytes) throw(); - // Set the key's security attributes. - LONG SetKeySecurity(SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR psd) throw(); - - LONG SetKeyValue(LPCTSTR lpszKeyName, LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL) throw(); - static LONG WINAPI SetValue(HKEY hKeyParent, LPCTSTR lpszKeyName, - LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL); - - // Create a new registry key (or open an existing one). - LONG Create(HKEY hKeyParent, LPCTSTR lpszKeyName, - LPTSTR lpszClass = REG_NONE, DWORD dwOptions = REG_OPTION_NON_VOLATILE, - REGSAM samDesired = KEY_READ | KEY_WRITE, - LPSECURITY_ATTRIBUTES lpSecAttr = NULL, - LPDWORD lpdwDisposition = NULL) throw(); - // Open an existing registry key. - LONG Open(HKEY hKeyParent, LPCTSTR lpszKeyName, - REGSAM samDesired = KEY_READ | KEY_WRITE) throw(); - // Close the registry key. - LONG Close() throw(); - // Flush the key's data to disk. - LONG Flush() throw(); - - // Detach the CRegKey object from its HKEY. Releases ownership. - HKEY Detach() throw(); - // Attach the CRegKey object to an existing HKEY. Takes ownership. - void Attach(HKEY hKey) throw(); - - // Enumerate the subkeys of the key. - LONG EnumKey(DWORD iIndex, LPTSTR pszName, LPDWORD pnNameLength, FILETIME* pftLastWriteTime = NULL) throw(); - LONG NotifyChangeKeyValue(BOOL bWatchSubtree, DWORD dwNotifyFilter, HANDLE hEvent, BOOL bAsync = TRUE) throw(); - - LONG DeleteSubKey(LPCTSTR lpszSubKey) throw(); - LONG RecurseDeleteKey(LPCTSTR lpszKey) throw(); - LONG DeleteValue(LPCTSTR lpszValue) throw(); -}; - -inline CRegKey::CRegKey() throw() : - m_hKey( NULL ) -{ -} - -inline CRegKey::CRegKey( CRegKey& key ) throw() : - m_hKey( NULL ) -{ - Attach( key.Detach() ); -} - -inline CRegKey::CRegKey(HKEY hKey) throw() : - m_hKey(hKey) -{ -} - -inline CRegKey::~CRegKey() throw() -{Close();} - -inline CRegKey& CRegKey::operator=( CRegKey& key ) throw() -{ - Close(); - Attach( key.Detach() ); - - return( *this ); -} - -inline CRegKey::operator HKEY() const throw() -{return m_hKey;} - -inline HKEY CRegKey::Detach() throw() -{ - HKEY hKey = m_hKey; - m_hKey = NULL; - return hKey; -} - -inline void CRegKey::Attach(HKEY hKey) throw() -{ - ATLASSERT(m_hKey == NULL); - m_hKey = hKey; -} - -inline LONG CRegKey::DeleteSubKey(LPCTSTR lpszSubKey) throw() -{ - ATLASSERT(m_hKey != NULL); - return RegDeleteKey(m_hKey, lpszSubKey); -} - -inline LONG CRegKey::DeleteValue(LPCTSTR lpszValue) throw() -{ - ATLASSERT(m_hKey != NULL); - return RegDeleteValue(m_hKey, (LPTSTR)lpszValue); -} - -inline LONG CRegKey::Close() throw() -{ - LONG lRes = ERROR_SUCCESS; - if (m_hKey != NULL) - { - lRes = RegCloseKey(m_hKey); - m_hKey = NULL; - } - return lRes; -} - -inline LONG CRegKey::Flush() throw() -{ - ATLASSERT(m_hKey != NULL); - - return ::RegFlushKey(m_hKey); -} - -inline LONG CRegKey::EnumKey(DWORD iIndex, LPTSTR pszName, LPDWORD pnNameLength, FILETIME* pftLastWriteTime) throw() -{ - FILETIME ftLastWriteTime; - - ATLASSERT(m_hKey != NULL); - if (pftLastWriteTime == NULL) - { - pftLastWriteTime = &ftLastWriteTime; - } - - return ::RegEnumKeyEx(m_hKey, iIndex, pszName, pnNameLength, NULL, NULL, NULL, pftLastWriteTime); -} - -inline LONG CRegKey::NotifyChangeKeyValue(BOOL bWatchSubtree, DWORD dwNotifyFilter, HANDLE hEvent, BOOL bAsync) throw() -{ - ATLASSERT(m_hKey != NULL); - ATLASSERT((hEvent != NULL) || !bAsync); - - return ::RegNotifyChangeKeyValue(m_hKey, bWatchSubtree, dwNotifyFilter, hEvent, bAsync); -} - -inline LONG CRegKey::Create(HKEY hKeyParent, LPCTSTR lpszKeyName, - LPTSTR lpszClass, DWORD dwOptions, REGSAM samDesired, - LPSECURITY_ATTRIBUTES lpSecAttr, LPDWORD lpdwDisposition) throw() -{ - ATLASSERT(hKeyParent != NULL); - DWORD dw; - HKEY hKey = NULL; - LONG lRes = RegCreateKeyEx(hKeyParent, lpszKeyName, 0, - lpszClass, dwOptions, samDesired, lpSecAttr, &hKey, &dw); - if (lpdwDisposition != NULL) - *lpdwDisposition = dw; - if (lRes == ERROR_SUCCESS) - { - lRes = Close(); - m_hKey = hKey; - } - return lRes; -} - -inline LONG CRegKey::Open(HKEY hKeyParent, LPCTSTR lpszKeyName, REGSAM samDesired) throw() -{ - ATLASSERT(hKeyParent != NULL); - HKEY hKey = NULL; - LONG lRes = RegOpenKeyEx(hKeyParent, lpszKeyName, 0, samDesired, &hKey); - if (lRes == ERROR_SUCCESS) - { - lRes = Close(); - ATLASSERT(lRes == ERROR_SUCCESS); - m_hKey = hKey; - } - return lRes; -} - -#pragma warning(push) -#pragma warning(disable: 4996) -inline LONG CRegKey::QueryValue(DWORD& dwValue, LPCTSTR lpszValueName) -{ - DWORD dwType = NULL; - DWORD dwCount = sizeof(DWORD); - LONG lRes = RegQueryValueEx(m_hKey, lpszValueName, NULL, &dwType, - (LPBYTE)&dwValue, &dwCount); - ATLASSERT((lRes!=ERROR_SUCCESS) || (dwType == REG_DWORD)); - ATLASSERT((lRes!=ERROR_SUCCESS) || (dwCount == sizeof(DWORD))); - if (dwType != REG_DWORD) - return ERROR_INVALID_DATA; - return lRes; -} - -inline LONG CRegKey::QueryValue(LPTSTR pszValue, LPCTSTR lpszValueName, DWORD* pdwCount) -{ - ATLASSERT(pdwCount != NULL); - DWORD dwType = NULL; - LONG lRes = RegQueryValueEx(m_hKey, lpszValueName, NULL, &dwType, - (LPBYTE)pszValue, pdwCount); - ATLASSERT((lRes!=ERROR_SUCCESS) || (dwType == REG_SZ) || - (dwType == REG_MULTI_SZ) || (dwType == REG_EXPAND_SZ)); - if (pszValue != NULL) - { - switch(dwType) - { - case REG_SZ: - case REG_EXPAND_SZ: - if ((*pdwCount) % sizeof(TCHAR) != 0 || pszValue[(*pdwCount) / sizeof(TCHAR) - 1] != 0) - return ERROR_INVALID_DATA; - break; - case REG_MULTI_SZ: - if ((*pdwCount) % sizeof(TCHAR) != 0 || (*pdwCount) / sizeof(TCHAR) < 2 || pszValue[(*pdwCount) / sizeof(TCHAR) -1] != 0 || pszValue[(*pdwCount) / sizeof(TCHAR) - 2] != 0 ) - return ERROR_INVALID_DATA; - break; - default: - return ERROR_INVALID_DATA; - } - } - return lRes; -} -#pragma warning(pop) // 4996 - -inline LONG CRegKey::QueryValue(LPCTSTR pszValueName, DWORD* pdwType, void* pData, ULONG* pnBytes) throw() -{ - ATLASSERT(m_hKey != NULL); - - return( ::RegQueryValueEx(m_hKey, pszValueName, NULL, pdwType, static_cast< LPBYTE >( pData ), pnBytes) ); -} - -inline LONG CRegKey::QueryDWORDValue(LPCTSTR pszValueName, DWORD& dwValue) throw() -{ - LONG lRes; - ULONG nBytes; - DWORD dwType; - - ATLASSERT(m_hKey != NULL); - - nBytes = sizeof(DWORD); - lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast(&dwValue), - &nBytes); - if (lRes != ERROR_SUCCESS) - return lRes; - if (dwType != REG_DWORD) - return ERROR_INVALID_DATA; - - return ERROR_SUCCESS; -} -inline LONG CRegKey::QueryQWORDValue(LPCTSTR pszValueName, ULONGLONG& qwValue) throw() -{ - LONG lRes; - ULONG nBytes; - DWORD dwType; - - ATLASSERT(m_hKey != NULL); - - nBytes = sizeof(ULONGLONG); - lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast(&qwValue), - &nBytes); - if (lRes != ERROR_SUCCESS) - return lRes; - if (dwType != REG_QWORD) - return ERROR_INVALID_DATA; - - return ERROR_SUCCESS; -} - -inline LONG CRegKey::QueryBinaryValue(LPCTSTR pszValueName, void* pValue, ULONG* pnBytes) throw() -{ - LONG lRes; - DWORD dwType; - - ATLASSERT(pnBytes != NULL); - ATLASSERT(m_hKey != NULL); - - lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast(pValue), - pnBytes); - if (lRes != ERROR_SUCCESS) - return lRes; - if (dwType != REG_BINARY) - return ERROR_INVALID_DATA; - - return ERROR_SUCCESS; -} - -inline LONG CRegKey::QueryStringValue(LPCTSTR pszValueName, LPTSTR pszValue, ULONG* pnChars) throw() -{ - LONG lRes; - DWORD dwType; - ULONG nBytes; - - ATLASSERT(m_hKey != NULL); - ATLASSERT(pnChars != NULL); - - nBytes = (*pnChars)*sizeof(TCHAR); - *pnChars = 0; - lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast(pszValue), - &nBytes); - - if (lRes != ERROR_SUCCESS) - return lRes; - if(dwType != REG_SZ && dwType != REG_EXPAND_SZ) - return ERROR_INVALID_DATA; - if (pszValue != NULL && (nBytes % sizeof(TCHAR) != 0 || pszValue[nBytes / sizeof(TCHAR) -1] != 0)) - return ERROR_INVALID_DATA; - - *pnChars = nBytes/sizeof(TCHAR); - - return ERROR_SUCCESS; -} - -inline LONG CRegKey::QueryMultiStringValue(LPCTSTR pszValueName, LPTSTR pszValue, ULONG* pnChars) throw() -{ - LONG lRes; - DWORD dwType; - ULONG nBytes; - - ATLASSERT(m_hKey != NULL); - ATLASSERT(pnChars != NULL); - - if (pszValue != NULL && *pnChars < 2) - return ERROR_INSUFFICIENT_BUFFER; - - nBytes = (*pnChars)*sizeof(TCHAR); - *pnChars = 0; - - lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast(pszValue), - &nBytes); - if (lRes != ERROR_SUCCESS) - return lRes; - if (dwType != REG_MULTI_SZ) - return ERROR_INVALID_DATA; - if (pszValue != NULL && (nBytes % sizeof(TCHAR) != 0 || nBytes / sizeof(TCHAR) < 2 || pszValue[nBytes / sizeof(TCHAR) -1] != 0 || pszValue[nBytes / sizeof(TCHAR) - 2] != 0)) - return ERROR_INVALID_DATA; - - *pnChars = nBytes/sizeof(TCHAR); - - return ERROR_SUCCESS; -} - -inline LONG CRegKey::QueryGUIDValue(LPCTSTR pszValueName, GUID& guidValue) throw() -{ - TCHAR szGUID[64]; - LONG lRes; - ULONG nCount; - HRESULT hr; - - ATLASSERT(m_hKey != NULL); - - guidValue = GUID_NULL; - - nCount = 64; - lRes = QueryStringValue(pszValueName, szGUID, &nCount); - - if (lRes != ERROR_SUCCESS) - return lRes; - - if(szGUID[0] != _T('{')) - return ERROR_INVALID_DATA; - - USES_CONVERSION_EX; - LPOLESTR lpstr = T2OLE_EX(szGUID, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if(lpstr == NULL) - return E_OUTOFMEMORY; -#endif - - hr = ::CLSIDFromString(lpstr, &guidValue); - if (FAILED(hr)) - return ERROR_INVALID_DATA; - - return ERROR_SUCCESS; -} - -inline LONG WINAPI CRegKey::SetValue(HKEY hKeyParent, LPCTSTR lpszKeyName, LPCTSTR lpszValue, LPCTSTR lpszValueName) -{ - ATLASSERT(lpszValue != NULL); - CRegKey key; - LONG lRes = key.Create(hKeyParent, lpszKeyName); - if (lRes == ERROR_SUCCESS) - lRes = key.SetStringValue(lpszValueName, lpszValue); - return lRes; -} - -inline LONG CRegKey::SetKeyValue(LPCTSTR lpszKeyName, LPCTSTR lpszValue, LPCTSTR lpszValueName) throw() -{ - ATLASSERT(lpszValue != NULL); - CRegKey key; - LONG lRes = key.Create(m_hKey, lpszKeyName); - if (lRes == ERROR_SUCCESS) - lRes = key.SetStringValue(lpszValueName, lpszValue); - return lRes; -} - -#pragma warning(push) -#pragma warning(disable: 4996) -inline LONG CRegKey::SetValue(DWORD dwValue, LPCTSTR pszValueName) -{ - ATLASSERT(m_hKey != NULL); - return SetDWORDValue(pszValueName, dwValue); -} - -inline LONG CRegKey::SetValue(LPCTSTR lpszValue, LPCTSTR lpszValueName, bool bMulti, int nValueLen) -{ - ATLASSERT(lpszValue != NULL); - ATLASSERT(m_hKey != NULL); - - if (bMulti && nValueLen == -1) - return ERROR_INVALID_PARAMETER; - - if (nValueLen == -1) - nValueLen = lstrlen(lpszValue) + 1; - - DWORD dwType = bMulti ? REG_MULTI_SZ : REG_SZ; - - return ::RegSetValueEx(m_hKey, lpszValueName, NULL, dwType, - reinterpret_cast(lpszValue), nValueLen*sizeof(TCHAR)); -} -#pragma warning(pop) - -inline LONG CRegKey::SetValue(LPCTSTR pszValueName, DWORD dwType, const void* pValue, ULONG nBytes) throw() -{ - ATLASSERT(m_hKey != NULL); - return ::RegSetValueEx(m_hKey, pszValueName, NULL, dwType, static_cast(pValue), nBytes); -} - -inline LONG CRegKey::SetBinaryValue(LPCTSTR pszValueName, const void* pData, ULONG nBytes) throw() -{ - ATLASSERT(m_hKey != NULL); - return ::RegSetValueEx(m_hKey, pszValueName, NULL, REG_BINARY, reinterpret_cast(pData), nBytes); -} - -inline LONG CRegKey::SetDWORDValue(LPCTSTR pszValueName, DWORD dwValue) throw() -{ - ATLASSERT(m_hKey != NULL); - return ::RegSetValueEx(m_hKey, pszValueName, NULL, REG_DWORD, reinterpret_cast(&dwValue), sizeof(DWORD)); -} - -inline LONG CRegKey::SetQWORDValue(LPCTSTR pszValueName, ULONGLONG qwValue) throw() -{ - ATLASSERT(m_hKey != NULL); - return ::RegSetValueEx(m_hKey, pszValueName, NULL, REG_QWORD, reinterpret_cast(&qwValue), sizeof(ULONGLONG)); -} - -inline LONG CRegKey::SetStringValue(LPCTSTR pszValueName, LPCTSTR pszValue, DWORD dwType) throw() -{ - ATLASSERT(m_hKey != NULL); - ATLASSERT(pszValue != NULL); - ATLASSERT((dwType == REG_SZ) || (dwType == REG_EXPAND_SZ)); - - return ::RegSetValueEx(m_hKey, pszValueName, NULL, dwType, reinterpret_cast(pszValue), (lstrlen(pszValue)+1)*sizeof(TCHAR)); -} - -inline LONG CRegKey::SetMultiStringValue(LPCTSTR pszValueName, LPCTSTR pszValue) throw() -{ - LPCTSTR pszTemp; - ULONG nBytes; - ULONG nLength; - - ATLASSERT(m_hKey != NULL); - ATLASSERT(pszValue != NULL); - - // Find the total length (in bytes) of all of the strings, including the - // terminating '\0' of each string, and the second '\0' that terminates - // the list. - nBytes = 0; - pszTemp = pszValue; - do - { - nLength = lstrlen(pszTemp)+1; - pszTemp += nLength; - nBytes += nLength*sizeof(TCHAR); - } while (nLength != 1); - - return ::RegSetValueEx(m_hKey, pszValueName, NULL, REG_MULTI_SZ, reinterpret_cast(pszValue), - nBytes); -} - -inline LONG CRegKey::SetGUIDValue(LPCTSTR pszValueName, REFGUID guidValue) throw() -{ - OLECHAR szGUID[64]; - - ATLASSERT(m_hKey != NULL); - - ::StringFromGUID2(guidValue, szGUID, 64); - - USES_CONVERSION_EX; - LPCTSTR lpstr = OLE2CT_EX(szGUID, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if(lpstr == NULL) - return E_OUTOFMEMORY; -#endif - return SetStringValue(pszValueName, lpstr); -} - -inline LONG CRegKey::GetKeySecurity(SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR psd, LPDWORD pnBytes) throw() -{ - ATLASSERT(m_hKey != NULL); - ATLASSERT(pnBytes != NULL); - - return ::RegGetKeySecurity(m_hKey, si, psd, pnBytes); -} - -inline LONG CRegKey::SetKeySecurity(SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR psd) throw() -{ - ATLASSERT(m_hKey != NULL); - ATLASSERT(psd != NULL); - - return ::RegSetKeySecurity(m_hKey, si, psd); -} - -inline LONG CRegKey::RecurseDeleteKey(LPCTSTR lpszKey) throw() -{ - CRegKey key; - LONG lRes = key.Open(m_hKey, lpszKey, KEY_READ | KEY_WRITE); - if (lRes != ERROR_SUCCESS) - { - if (lRes != ERROR_FILE_NOT_FOUND && lRes != ERROR_PATH_NOT_FOUND) - { - ATLTRACE(atlTraceCOM, 0, _T("CRegKey::RecurseDeleteKey : Failed to Open Key %s(Error = %d)\n"), lpszKey, lRes); - } - return lRes; - } - FILETIME time; - DWORD dwSize = 256; - TCHAR szBuffer[256]; - while (RegEnumKeyEx(key.m_hKey, 0, szBuffer, &dwSize, NULL, NULL, NULL, - &time)==ERROR_SUCCESS) - { - lRes = key.RecurseDeleteKey(szBuffer); - if (lRes != ERROR_SUCCESS) - return lRes; - dwSize = 256; - } - key.Close(); - return DeleteSubKey(lpszKey); -} - -#ifndef _ATL_NO_COMMODULE - -inline HRESULT CComModule::RegisterProgID(LPCTSTR lpszCLSID, LPCTSTR lpszProgID, LPCTSTR lpszUserDesc) -{ - CRegKey keyProgID; - LONG lRes = keyProgID.Create(HKEY_CLASSES_ROOT, lpszProgID, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE); - if (lRes == ERROR_SUCCESS) - { - lRes = keyProgID.SetStringValue(NULL, lpszUserDesc); - if (lRes == ERROR_SUCCESS) - { - lRes = keyProgID.SetKeyValue(_T("CLSID"), lpszCLSID); - if (lRes == ERROR_SUCCESS) - return S_OK; - } - } - return AtlHresultFromWin32(lRes); -} - -inline HRESULT CComModule::RegisterAppId(LPCTSTR pAppId) -{ - CRegKey keyAppID; - HRESULT hr = S_OK; - LONG lRet; - - if ( (lRet = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_WRITE)) == ERROR_SUCCESS) - { - TCHAR szModule1[MAX_PATH]; - TCHAR szModule2[MAX_PATH]; - TCHAR* pszFileName; - - DWORD dwFLen = ::GetModuleFileName(GetModuleInstance(), szModule1, MAX_PATH); - if ( dwFLen != 0 && dwFLen != MAX_PATH ) - { - if (::GetFullPathName(szModule1, MAX_PATH, szModule2, &pszFileName) != 0) - { - CRegKey keyAppIDEXE; - if ( (lRet = keyAppIDEXE.Create(keyAppID, pszFileName, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE)) == ERROR_SUCCESS) - { - lRet = keyAppIDEXE.SetStringValue(_T("AppID"), pAppId); - if (lRet != ERROR_SUCCESS) - { - ATLTRACE(atlTraceCOM, 0, _T("CComModule::RegisterAppId : Failed to set app id string value\n")); - hr = AtlHresultFromWin32(lRet); - return hr; - } - } - else - { - ATLTRACE(atlTraceCOM, 0, _T("CComModule::RegisterAppId : Failed to create file name key\n")); - hr = AtlHresultFromWin32(lRet); - return hr; - } - if ( (lRet = keyAppIDEXE.Create(keyAppID, pAppId, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE)) == ERROR_SUCCESS) - { - lRet = keyAppIDEXE.SetStringValue(NULL, pszFileName); - if (lRet != ERROR_SUCCESS) - { - ATLTRACE(atlTraceCOM, 0, _T("CComModule::RegisterAppId : Failed to set file name string value\n")); - hr = AtlHresultFromWin32(lRet); - return hr; - } - } - else - { - ATLTRACE(atlTraceCOM, 0, _T("CComModule::RegisterAppId : Failed to create app id key\n")); - hr = AtlHresultFromWin32(lRet); - return hr; - } - } - else - { - ATLTRACE(atlTraceCOM, 0, _T("CComModule::RegisterAppId : Failed to get full path name for file %s\n"), szModule1); - hr = AtlHresultFromLastError(); - } - } - else - { - ATLTRACE(atlTraceCOM, 0, _T("CComModule::RegisterAppId : Failed to get module name\n")); - if( dwFLen == 0 ) - hr = AtlHresultFromLastError(); - else if( dwFLen == MAX_PATH ) - hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - } - } - else - { - ATLTRACE(atlTraceCOM, 0, _T("CComModule::RegisterAppId : Failed to open registry key\n")); - hr = AtlHresultFromWin32(lRet); - } - return hr; -} - -inline HRESULT CComModule::UnregisterAppId(LPCTSTR pAppId) -{ - CRegKey keyAppID; - HRESULT hr = S_OK; - LONG lRet = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_READ | KEY_WRITE); - - if (lRet == ERROR_SUCCESS) - { - TCHAR szModule1[MAX_PATH]; - TCHAR szModule2[MAX_PATH]; - TCHAR* pszFileName; - - DWORD dwFLen = ::GetModuleFileName(GetModuleInstance(), szModule1, MAX_PATH); - if ( dwFLen != 0 && dwFLen != MAX_PATH ) - { - if (::GetFullPathName(szModule1, MAX_PATH, szModule2, &pszFileName) != 0) - { - if ((lRet = keyAppID.RecurseDeleteKey(pAppId)) != ERROR_SUCCESS) - { - if (lRet != ERROR_FILE_NOT_FOUND) - hr = AtlHresultFromWin32(lRet); - } - if ((lRet = keyAppID.RecurseDeleteKey(pszFileName)) != ERROR_SUCCESS) - { - if (lRet != ERROR_FILE_NOT_FOUND) - hr = AtlHresultFromWin32(lRet); - } - } - else - { - ATLTRACE(atlTraceCOM, 0, _T("CComModule::UnregisterAppId : Failed to get full path name for file %s\n"), szModule1); - hr = AtlHresultFromLastError(); - } - } - else - { - ATLTRACE(atlTraceCOM, 0, _T("CComModule::UnregisterAppId : Failed to get module name\n")); - if( dwFLen == 0 ) - hr = AtlHresultFromLastError(); - else if( dwFLen == MAX_PATH ) - hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - } - } - else - { - if (lRet != ERROR_FILE_NOT_FOUND && lRet != ERROR_PATH_NOT_FOUND) - { - ATLTRACE(atlTraceCOM, 0, _T("CComModule::UnregisterAppId : Failed to open registry key\n")); - hr = AtlHresultFromWin32(lRet); - } - } - return hr; -} -#endif // !_ATL_NO_COMMODULE - -#ifdef _ATL_STATIC_REGISTRY -} // namespace ATL - -#include - -namespace ATL -{ - -// Statically linking to Registry Ponent -inline HRESULT WINAPI CAtlModule::UpdateRegistryFromResourceS(LPCTSTR lpszRes, BOOL bRegister, - struct _ATL_REGMAP_ENTRY* pMapEntries /*= NULL*/) throw() -{ - CRegObject ro; - - if (pMapEntries != NULL) - { - while (pMapEntries->szKey != NULL) - { - ATLASSERT(NULL != pMapEntries->szData); - ro.AddReplacement(pMapEntries->szKey, pMapEntries->szData); - pMapEntries++; - } - } - - HRESULT hr = AddCommonRGSReplacements(&ro); - if (FAILED(hr)) - return hr; - - USES_CONVERSION_EX; - TCHAR szModule[MAX_PATH]; - HINSTANCE hInst = _AtlBaseModule.GetModuleInstance(); - DWORD dwFLen = GetModuleFileName(hInst, szModule, MAX_PATH); - if( dwFLen == 0 ) - return AtlHresultFromLastError(); - else if( dwFLen == MAX_PATH ) - return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - - LPOLESTR pszModule; - pszModule = T2OLE_EX(szModule, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if(pszModule == NULL) - return E_OUTOFMEMORY; -#endif - - OLECHAR pszModuleUnquoted[_MAX_PATH * 2]; - EscapeSingleQuote(pszModuleUnquoted, pszModule); - - HRESULT hRes; - if ((hInst == NULL) || (hInst == GetModuleHandle(NULL))) // register as EXE - { - // If Registering as an EXE, then we quote the resultant path. - // We don't do it for a DLL, because LoadLibrary fails if the path is - // quoted - OLECHAR pszModuleQuote[(_MAX_PATH + _ATL_QUOTES_SPACE)*2]; - pszModuleQuote[0] = OLESTR('\"'); - ocscpy(pszModuleQuote + 1, pszModuleUnquoted); - int nLen = ocslen(pszModuleQuote); - pszModuleQuote[nLen] = OLESTR('\"'); - pszModuleQuote[nLen + 1] = 0; - - hRes = ro.AddReplacement(OLESTR("Module"), pszModuleQuote); - } - else - { - hRes = ro.AddReplacement(OLESTR("Module"), pszModuleUnquoted); - } - - if(FAILED(hRes)) - return hRes; - - hRes = ro.AddReplacement(OLESTR("Module_Raw"), pszModuleUnquoted); - if(FAILED(hRes)) - return hRes; - - LPCOLESTR szType = OLESTR("REGISTRY"); - LPCOLESTR pszRes = T2COLE_EX(lpszRes, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if(pszRes == NULL) - return E_OUTOFMEMORY; -#endif - hr = (bRegister) ? ro.ResourceRegisterSz(pszModule, pszRes, szType) : - ro.ResourceUnregisterSz(pszModule, pszRes, szType); - return hr; -} -inline HRESULT WINAPI CAtlModule::UpdateRegistryFromResourceS(UINT nResID, BOOL bRegister, - struct _ATL_REGMAP_ENTRY* pMapEntries /*= NULL*/) throw() -{ - CRegObject ro; - - if (pMapEntries != NULL) - { - while (pMapEntries->szKey != NULL) - { - ATLASSERT(NULL != pMapEntries->szData); - ro.AddReplacement(pMapEntries->szKey, pMapEntries->szData); - pMapEntries++; - } - } - - HRESULT hr = AddCommonRGSReplacements(&ro); - if (FAILED(hr)) - return hr; - - USES_CONVERSION_EX; - TCHAR szModule[MAX_PATH]; - HINSTANCE hInst = _AtlBaseModule.GetModuleInstance(); - DWORD dwFLen = GetModuleFileName(hInst, szModule, MAX_PATH); - if( dwFLen == 0 ) - return AtlHresultFromLastError(); - else if( dwFLen == MAX_PATH ) - return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - - LPOLESTR pszModule; - pszModule = T2OLE_EX(szModule, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if(pszModule == NULL) - return E_OUTOFMEMORY; -#endif - - OLECHAR pszModuleUnquoted[_MAX_PATH * 2]; - EscapeSingleQuote(pszModuleUnquoted, pszModule); - - HRESULT hRes; - if ((hInst == NULL) || (hInst == GetModuleHandle(NULL))) // register as EXE - { - // If Registering as an EXE, then we quote the resultant path. - // We don't do it for a DLL, because LoadLibrary fails if the path is - // quoted - OLECHAR pszModuleQuote[(_MAX_PATH + _ATL_QUOTES_SPACE)*2]; - pszModuleQuote[0] = OLESTR('\"'); - ocscpy(pszModuleQuote + 1, pszModuleUnquoted); - int nLen = ocslen(pszModuleQuote); - pszModuleQuote[nLen] = OLESTR('\"'); - pszModuleQuote[nLen + 1] = 0; - - hRes = ro.AddReplacement(OLESTR("Module"), pszModuleQuote); - } - else - { - hRes = ro.AddReplacement(OLESTR("Module"), pszModuleUnquoted); - } - - if(FAILED(hRes)) - return hRes; - - hRes = ro.AddReplacement(OLESTR("Module_Raw"), pszModuleUnquoted); - if(FAILED(hRes)) - return hRes; - - LPCOLESTR szType = OLESTR("REGISTRY"); - hr = (bRegister) ? ro.ResourceRegister(pszModule, nResID, szType) : - ro.ResourceUnregister(pszModule, nResID, szType); - return hr; -} -#endif //_ATL_STATIC_REGISTRY - -#ifndef _ATL_NO_COMMODULE - -#pragma warning( push ) -#pragma warning( disable: 4996 ) // Disable "deprecated symbol" warning - -inline HRESULT WINAPI CComModule::UpdateRegistryClass(const CLSID& clsid, LPCTSTR lpszProgID, - LPCTSTR lpszVerIndProgID, UINT nDescID, DWORD dwFlags, BOOL bRegister) -{ - if (bRegister) - { - TCHAR szDesc[256]; - LoadString(m_hInst, nDescID, szDesc, 256); - return RegisterClassHelper(clsid, lpszProgID, lpszVerIndProgID, szDesc, dwFlags); - } - return UnregisterClassHelper(clsid, lpszProgID, lpszVerIndProgID); -} - -inline HRESULT WINAPI CComModule::UpdateRegistryClass(const CLSID& clsid, LPCTSTR lpszProgID, - LPCTSTR lpszVerIndProgID, LPCTSTR szDesc, DWORD dwFlags, BOOL bRegister) -{ - if (bRegister) - return RegisterClassHelper(clsid, lpszProgID, lpszVerIndProgID, szDesc, dwFlags); - return UnregisterClassHelper(clsid, lpszProgID, lpszVerIndProgID); -} - -inline HRESULT WINAPI CComModule::RegisterClassHelper(const CLSID& clsid, LPCTSTR lpszProgID, - LPCTSTR lpszVerIndProgID, LPCTSTR szDesc, DWORD dwFlags) -{ - static const TCHAR szProgID[] = _T("ProgID"); - static const TCHAR szVIProgID[] = _T("VersionIndependentProgID"); - static const TCHAR szLS32[] = _T("LocalServer32"); - static const TCHAR szIPS32[] = _T("InprocServer32"); - static const TCHAR szThreadingModel[] = _T("ThreadingModel"); - static const TCHAR szAUTPRX32[] = _T("AUTPRX32.DLL"); - static const TCHAR szApartment[] = _T("Apartment"); - static const TCHAR szBoth[] = _T("both"); - USES_CONVERSION_EX; - TCHAR szModule[_MAX_PATH + _ATL_QUOTES_SPACE]; - - // If the ModuleFileName's length is equal or greater than the 3rd parameter - // (length of the buffer passed),GetModuleFileName fills the buffer (truncates - // if neccessary), but doesn't null terminate it. It returns the same value as - // the 3rd parameter passed. So if the return value is the same as the 3rd param - // then you have a non null terminated buffer (which may or may not be truncated) - // We pass (szModule + 1) because in case it's an EXE we need to quote the PATH - // The quote is done later in this method before the SetKeyValue is called - DWORD dwLen = GetModuleFileName(m_hInst, szModule + 1, MAX_PATH); - if (dwLen == 0) - { - return AtlHresultFromLastError(); - } - else if( dwLen == MAX_PATH ) - { - return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - } - - LPOLESTR lpOleStr; - HRESULT hRes = StringFromCLSID(clsid, &lpOleStr); - if (FAILED(hRes)) - return hRes; - - LPTSTR lpsz = OLE2T_EX(lpOleStr, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if(lpsz == NULL) - { - CoTaskMemFree(lpOleStr); - return E_OUTOFMEMORY; - } -#endif - - hRes = RegisterProgID(lpsz, lpszProgID, szDesc); - if (hRes == S_OK) - hRes = RegisterProgID(lpsz, lpszVerIndProgID, szDesc); - LONG lRes = ERROR_SUCCESS; - if (hRes == S_OK) - { - CRegKey key; - lRes = key.Open(HKEY_CLASSES_ROOT, _T("CLSID"), KEY_READ | KEY_WRITE); - if (lRes == ERROR_SUCCESS) - { - lRes = key.Create(key, lpsz, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE); - if (lRes == ERROR_SUCCESS) - { - lRes = key.SetStringValue(NULL, szDesc); - if (lRes == ERROR_SUCCESS) - { - lRes = key.SetKeyValue(szProgID, lpszProgID); - if (lRes == ERROR_SUCCESS) - { - lRes = key.SetKeyValue(szVIProgID, lpszVerIndProgID); - if (lRes == ERROR_SUCCESS) - { - if ((m_hInst == NULL) || (m_hInst == GetModuleHandle(NULL))) // register as EXE - { - // If Registering as an EXE, then we quote the resultant path. - // We don't do it for a DLL, because LoadLibrary fails if the path is - // quoted - szModule[0] = _T('\"'); - szModule[dwLen + 1] = _T('\"'); - szModule[dwLen + 2] = 0; - - lRes = key.SetKeyValue(szLS32, szModule); - } - else - { - lRes = key.SetKeyValue(szIPS32, (dwFlags & AUTPRXFLAG) ? szAUTPRX32 : szModule + 1); - if (lRes == ERROR_SUCCESS) - { - LPCTSTR lpszModel = (dwFlags & THREADFLAGS_BOTH) ? szBoth : - (dwFlags & THREADFLAGS_APARTMENT) ? szApartment : NULL; - if (lpszModel != NULL) - lRes = key.SetKeyValue(szIPS32, lpszModel, szThreadingModel); - } - } - } - } - } - } - } - } - CoTaskMemFree(lpOleStr); - if (lRes != ERROR_SUCCESS) - hRes = AtlHresultFromWin32(lRes); - return hRes; -} - -inline HRESULT WINAPI CComModule::UnregisterClassHelper(const CLSID& clsid, LPCTSTR lpszProgID, - LPCTSTR lpszVerIndProgID) -{ - USES_CONVERSION_EX; - CRegKey key; - LONG lRet; - - key.Attach(HKEY_CLASSES_ROOT); - if (lpszProgID != NULL && lstrcmpi(lpszProgID, _T(""))) - { - lRet = key.RecurseDeleteKey(lpszProgID); - if (lRet != ERROR_SUCCESS && lRet != ERROR_FILE_NOT_FOUND && lRet != ERROR_PATH_NOT_FOUND) - { - ATLTRACE(atlTraceCOM, 0, _T("Failed to Unregister ProgID : %s\n"), lpszProgID); - key.Detach(); - return AtlHresultFromWin32(lRet); - } - } - if (lpszVerIndProgID != NULL && lstrcmpi(lpszVerIndProgID, _T(""))) - { - lRet = key.RecurseDeleteKey(lpszVerIndProgID); - if (lRet != ERROR_SUCCESS && lRet != ERROR_FILE_NOT_FOUND && lRet != ERROR_PATH_NOT_FOUND) - { - ATLTRACE(atlTraceCOM, 0, _T("Failed to Unregister Version Independent ProgID : %s\n"), lpszVerIndProgID); - key.Detach(); - return AtlHresultFromWin32(lRet); - } - } - LPOLESTR lpOleStr; - HRESULT hr = StringFromCLSID(clsid, &lpOleStr); - if (SUCCEEDED(hr)) - { - LPTSTR lpsz = OLE2T_EX(lpOleStr, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if(lpsz == NULL) - { - CoTaskMemFree(lpOleStr); - return E_OUTOFMEMORY; - } -#endif - - lRet = key.Open(key, _T("CLSID"), KEY_READ | KEY_WRITE); - if (lRet == ERROR_SUCCESS) - lRet = key.RecurseDeleteKey(lpsz); - if (lRet != ERROR_SUCCESS && lRet != ERROR_FILE_NOT_FOUND && lRet != ERROR_PATH_NOT_FOUND) - { - ATLTRACE(atlTraceCOM, 0, _T("Failed to delete CLSID : %s\n"), lpsz); - hr = AtlHresultFromWin32(lRet); - } - CoTaskMemFree(lpOleStr); - } - else - { - ATLTRACE(atlTraceCOM, 0, _T("Failed to delete CLSID : {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"), - clsid.Data1, - clsid.Data2, - clsid.Data3, - clsid.Data4[0], - clsid.Data4[1], - clsid.Data4[2], - clsid.Data4[3], - clsid.Data4[4], - clsid.Data4[5], - clsid.Data4[6], - clsid.Data4[7] - ); - } - key.Detach(); - return hr; -} - -#pragma warning( pop ) // Disable "deprecated symbol" warning - -#endif // !_ATL_NO_COMMODULE - -#ifdef _ATL_DEBUG_INTERFACES - -inline void _QIThunk::Dump() throw() -{ - TCHAR buf[512]; - if (m_dwRef != 0) - { - wsprintf(buf, _T("ATL: QIThunk - %-10d\tLEAK :\tObject = 0x%08x\tRefcount = %d\tMaxRefCount = %d\t"), m_nIndex, m_pUnk, m_dwRef, m_dwMaxRef); - OutputDebugString(buf); - AtlDumpIID(m_iid, m_lpszClassName, S_OK); - } - else - { - wsprintf(buf, _T("ATL: QIThunk - %-10d\tNonAddRef LEAK :\tObject = 0x%08x\t"), m_nIndex, m_pUnk); - OutputDebugString(buf); - AtlDumpIID(m_iid, m_lpszClassName, S_OK); - } -} - -#endif // _ATL_DEBUG_INTERFACES - -#if defined(_ATL_DEBUG_INTERFACES) || defined(_ATL_DEBUG_QI) -__forceinline HRESULT WINAPI AtlDumpIID(REFIID iid, LPCTSTR pszClassName, HRESULT hr) throw() -{ - USES_CONVERSION_EX; - CRegKey key; - TCHAR szName[100]; - DWORD dwType; - DWORD dw = sizeof(szName); - - LPOLESTR pszGUID = NULL; - if (FAILED(StringFromCLSID(iid, &pszGUID))) - return hr; - - OutputDebugString(pszClassName); - OutputDebugString(_T(" - ")); - - LPTSTR lpszGUID = OLE2T_EX(pszGUID, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if(lpszGUID == NULL) - { - CoTaskMemFree(pszGUID); - return hr; - } -#endif - // Attempt to find it in the interfaces section - if (key.Open(HKEY_CLASSES_ROOT, _T("Interface"), KEY_READ) == ERROR_SUCCESS) - { - if (key.Open(key, lpszGUID, KEY_READ) == ERROR_SUCCESS) - { - *szName = 0; - if (RegQueryValueEx(key.m_hKey, (LPTSTR)NULL, NULL, &dwType, (LPBYTE)szName, &dw) == ERROR_SUCCESS) - { - OutputDebugString(szName); - } - } - } - // Attempt to find it in the clsid section - else if (key.Open(HKEY_CLASSES_ROOT, _T("CLSID"), KEY_READ) == ERROR_SUCCESS) - { - if (key.Open(key, lpszGUID, KEY_READ) == ERROR_SUCCESS) - { - *szName = 0; - if (RegQueryValueEx(key.m_hKey, (LPTSTR)NULL, NULL, &dwType, (LPBYTE)szName, &dw) == ERROR_SUCCESS) - { - OutputDebugString(_T("(CLSID\?\?\?) ")); - OutputDebugString(szName); - } - } - } - else - OutputDebugString(lpszGUID); - - if (hr != S_OK) - OutputDebugString(_T(" - failed")); - OutputDebugString(_T("\n")); - CoTaskMemFree(pszGUID); - - return hr; -} -#endif // _ATL_DEBUG_INTERFACES || _ATL_DEBUG_QI - -#pragma pack(pop) - -// WM_FORWARDMSG - used to forward a message to another window for processing -// WPARAM - DWORD dwUserData - defined by user -// LPARAM - LPMSG pMsg - a pointer to the MSG structure -// return value - 0 if the message was not processed, nonzero if it was -#define WM_FORWARDMSG 0x037F - -}; //namespace ATL - -#ifndef _ATL_NO_AUTOMATIC_NAMESPACE -using namespace ATL; -#endif //!_ATL_NO_AUTOMATIC_NAMESPACE - -#ifdef _ATL_ATTRIBUTES -#include -#endif - -namespace ATL -{ - -// All exports go here -// Pull in if building ATL DLL or not linking to ATL DLL -#ifndef _ATL_DLL - -///////////////////////////////////////////////////////////////////////////// -// statics - -static inline UINT WINAPI AtlGetDirLen(LPCOLESTR lpszPathName) throw() -{ - ATLASSERT(lpszPathName != NULL); - if(lpszPathName == NULL) - return 0; - - // always capture the complete file name including extension (if present) - LPCOLESTR lpszTemp = lpszPathName; - for (LPCOLESTR lpsz = lpszPathName; *lpsz != NULL; ) - { - LPCOLESTR lp = CharNextO(lpsz); - // remember last directory/drive separator - if (*lpsz == OLESTR('\\') || *lpsz == OLESTR('/') || *lpsz == OLESTR(':')) - lpszTemp = lp; - lpsz = lp; - } - - return UINT( lpszTemp-lpszPathName ); -} - -///////////////////////////////////////////////////////////////////////////// -// TypeLib registration - -#define _ATL_MAX_PATH_PLUS_INDEX (_MAX_PATH + _ATL_TYPELIB_INDEX_LENGTH) - -ATLINLINE ATLAPI AtlLoadTypeLib(HINSTANCE hInstTypeLib, LPCOLESTR lpszIndex, BSTR* pbstrPath, ITypeLib** ppTypeLib) -{ - ATLASSERT(pbstrPath != NULL && ppTypeLib != NULL); - if (pbstrPath == NULL || ppTypeLib == NULL) - return E_POINTER; - - *pbstrPath = NULL; - *ppTypeLib = NULL; - - USES_CONVERSION_EX; - ATLASSERT(hInstTypeLib != NULL); - TCHAR szModule[_ATL_MAX_PATH_PLUS_INDEX]; - - DWORD dwFLen = GetModuleFileName(hInstTypeLib, szModule, MAX_PATH); - if( dwFLen == 0 ) - return AtlHresultFromLastError(); - else if( dwFLen == MAX_PATH ) - return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - - // get the extension pointer in case of fail - LPTSTR lpszExt = NULL; - - lpszExt = PathFindExtension(szModule); - - if (lpszIndex != NULL) - { - LPCTSTR lpcszIndex = OLE2CT_EX(lpszIndex, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if(lpcszIndex == NULL) - return E_OUTOFMEMORY; -#endif - int nIndexLen = lstrlen(lpcszIndex); - - if( dwFLen + nIndexLen >= _ATL_MAX_PATH_PLUS_INDEX ) - return E_FAIL; - lstrcpy(szModule + dwFLen,lpcszIndex); - } - LPOLESTR lpszModule = T2OLE_EX(szModule, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if(lpszModule == NULL) - return E_OUTOFMEMORY; -#endif - HRESULT hr = LoadTypeLib(lpszModule, ppTypeLib); - if (!SUCCEEDED(hr)) - { - // typelib not in module, try .tlb instead - TCHAR szExt[] = _T(".tlb"); - if ((lpszExt - szModule + sizeof(szExt)/sizeof(TCHAR)) > _MAX_PATH) - return E_FAIL; - - lstrcpy(lpszExt, szExt); - lpszModule = T2OLE_EX(szModule, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if(lpszModule == NULL) - return E_OUTOFMEMORY; -#endif - hr = LoadTypeLib(lpszModule, ppTypeLib); - } - if (SUCCEEDED(hr)) - { - *pbstrPath = ::SysAllocString(lpszModule); - if (*pbstrPath == NULL) - hr = E_OUTOFMEMORY; - } - return hr; -} - -ATLINLINE ATLAPI AtlUnRegisterTypeLib(HINSTANCE hInstTypeLib, LPCOLESTR lpszIndex) -{ - CComBSTR bstrPath; - CComPtr pTypeLib; - HRESULT hr = AtlLoadTypeLib(hInstTypeLib, lpszIndex, &bstrPath, &pTypeLib); - if (SUCCEEDED(hr)) - { - TLIBATTR* ptla; - hr = pTypeLib->GetLibAttr(&ptla); - if (SUCCEEDED(hr)) - { - hr = UnRegisterTypeLib(ptla->guid, ptla->wMajorVerNum, ptla->wMinorVerNum, ptla->lcid, ptla->syskind); - pTypeLib->ReleaseTLibAttr(ptla); - } - } - return hr; -} - -ATLINLINE ATLAPI AtlRegisterTypeLib(HINSTANCE hInstTypeLib, LPCOLESTR lpszIndex) -{ - CComBSTR bstrPath; - CComPtr pTypeLib; - HRESULT hr = AtlLoadTypeLib(hInstTypeLib, lpszIndex, &bstrPath, &pTypeLib); - if (SUCCEEDED(hr)) - { - OLECHAR szDir[MAX_PATH]; - wcsncpy(szDir,bstrPath,MAX_PATH - 1); - szDir[MAX_PATH - 1] = 0; - // If index is specified remove it from the path - if (lpszIndex != NULL) - { - size_t nLenPath = ocslen(szDir); - size_t nLenIndex = ocslen(lpszIndex); - if (memcmp(szDir + nLenPath - nLenIndex, lpszIndex, nLenIndex) == 0) - szDir[nLenPath - nLenIndex] = 0; - } - szDir[AtlGetDirLen(szDir)] = 0; - hr = ::RegisterTypeLib(pTypeLib, bstrPath, szDir); - } - return hr; -} - -///////////////////////////////////////////////////////////////////////////// -// Registration - -// AtlComModuleRegisterServer walks the ATL Autogenerated Object Map and registers each object in the map -// If pCLSID is not NULL then only the object referred to by pCLSID is registered (The default case) -// otherwise all the objects are registered -ATLINLINE ATLAPI AtlComModuleRegisterServer(_ATL_COM_MODULE* pComModule, BOOL bRegTypeLib, const CLSID* pCLSID) -{ - ATLASSERT(pComModule != NULL); - if (pComModule == NULL) - return E_INVALIDARG; - ATLASSERT(pComModule->m_hInstTypeLib != NULL); - - HRESULT hr = S_OK; - - for (_ATL_OBJMAP_ENTRY** ppEntry = pComModule->m_ppAutoObjMapFirst; ppEntry < pComModule->m_ppAutoObjMapLast; ppEntry++) - { - if (*ppEntry != NULL) - { - _ATL_OBJMAP_ENTRY* pEntry = *ppEntry; - if (pCLSID != NULL) - { - if (!IsEqualGUID(*pCLSID, *pEntry->pclsid)) - continue; - } - hr = pEntry->pfnUpdateRegistry(TRUE); - if (FAILED(hr)) - break; - hr = AtlRegisterClassCategoriesHelper( *pEntry->pclsid, - pEntry->pfnGetCategoryMap(), TRUE ); - if (FAILED(hr)) - break; - } - } - - if (SUCCEEDED(hr) && bRegTypeLib) - hr = AtlRegisterTypeLib(pComModule->m_hInstTypeLib, 0); - - return hr; -} - -// AtlComUnregisterServer walks the ATL Object Map and unregisters each object in the map -// If pCLSID is not NULL then only the object referred to by pCLSID is unregistered (The default case) -// otherwise all the objects are unregistered. -ATLINLINE ATLAPI AtlComModuleUnregisterServer(_ATL_COM_MODULE* pComModule, BOOL bUnRegTypeLib, const CLSID* pCLSID) -{ - ATLASSERT(pComModule != NULL); - if (pComModule == NULL) - return E_INVALIDARG; - - HRESULT hr = S_OK; - - for (_ATL_OBJMAP_ENTRY** ppEntry = pComModule->m_ppAutoObjMapFirst; ppEntry < pComModule->m_ppAutoObjMapLast; ppEntry++) - { - if (*ppEntry != NULL) - { - _ATL_OBJMAP_ENTRY* pEntry = *ppEntry; - if (pCLSID != NULL) - { - if (!IsEqualGUID(*pCLSID, *pEntry->pclsid)) - continue; - } - hr = AtlRegisterClassCategoriesHelper( *pEntry->pclsid, pEntry->pfnGetCategoryMap(), FALSE ); - if (FAILED(hr)) - break; - hr = pEntry->pfnUpdateRegistry(FALSE); //unregister - if (FAILED(hr)) - break; - } - } - if (SUCCEEDED(hr) && bUnRegTypeLib) - hr = AtlUnRegisterTypeLib(pComModule->m_hInstTypeLib, 0); - - return hr; -} - -ATLINLINE ATLAPI AtlRegisterClassCategoriesHelper( REFCLSID clsid, - const struct _ATL_CATMAP_ENTRY* pCatMap, BOOL bRegister ) -{ - CComPtr< ICatRegister > pCatRegister; - HRESULT hResult; - const struct _ATL_CATMAP_ENTRY* pEntry; - CATID catid; - - if( pCatMap == NULL ) - { - return( S_OK ); - } - - if (InlineIsEqualGUID(clsid, GUID_NULL)) - { - ATLASSERT(0 && _T("Use OBJECT_ENTRY_NON_CREATEABLE_EX macro if you want to register class categories for non creatable objects.")); - return S_OK; - } - - hResult = CoCreateInstance( CLSID_StdComponentCategoriesMgr, NULL, - CLSCTX_INPROC_SERVER, __uuidof(ICatRegister), (void**)&pCatRegister ); - if( FAILED( hResult ) ) - { - // Since not all systems have the category manager installed, we'll allow - // the registration to succeed even though we didn't register our - // categories. If you really want to register categories on a system - // without the category manager, you can either manually add the - // appropriate entries to your registry script (.rgs), or you can - // redistribute comcat.dll. - return( S_OK ); - } - - hResult = S_OK; - pEntry = pCatMap; - while( pEntry->iType != _ATL_CATMAP_ENTRY_END ) - { - catid = *pEntry->pcatid; - if( bRegister ) - { - if( pEntry->iType == _ATL_CATMAP_ENTRY_IMPLEMENTED ) - { - hResult = pCatRegister->RegisterClassImplCategories( clsid, 1, - &catid ); - } - else - { - ATLASSERT( pEntry->iType == _ATL_CATMAP_ENTRY_REQUIRED ); - hResult = pCatRegister->RegisterClassReqCategories( clsid, 1, - &catid ); - } - if( FAILED( hResult ) ) - { - return( hResult ); - } - } - else - { - if( pEntry->iType == _ATL_CATMAP_ENTRY_IMPLEMENTED ) - { - pCatRegister->UnRegisterClassImplCategories( clsid, 1, &catid ); - } - else - { - ATLASSERT( pEntry->iType == _ATL_CATMAP_ENTRY_REQUIRED ); - pCatRegister->UnRegisterClassReqCategories( clsid, 1, &catid ); - } - } - pEntry++; - } - - // When unregistering remove "Implemented Categories" and "Required Categories" subkeys if they are empty. - if (!bRegister) - { - OLECHAR szGUID[64]; - ::StringFromGUID2(clsid, szGUID, 64); - USES_CONVERSION_EX; - TCHAR* pszGUID = OLE2T_EX(szGUID, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); - if (pszGUID != NULL) - { - TCHAR szKey[128]; - lstrcpy(szKey, _T("CLSID\\")); - lstrcat(szKey, pszGUID); - lstrcat(szKey, _T("\\Required Categories")); - - CRegKey root(HKEY_CLASSES_ROOT); - CRegKey key; - DWORD cbSubKeys = 0; - - LRESULT lRes = key.Open(root, szKey, KEY_READ); - if (lRes == ERROR_SUCCESS) - { - lRes = RegQueryInfoKey(key, NULL, NULL, NULL, &cbSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - key.Close(); - if (lRes == ERROR_SUCCESS && cbSubKeys == 0) - { - root.DeleteSubKey(szKey); - } - } - - lstrcpy(szKey, _T("CLSID\\")); - lstrcat(szKey, pszGUID); - lstrcat(szKey, _T("\\Implemented Categories")); - lRes = key.Open(root, szKey, KEY_READ); - if (lRes == ERROR_SUCCESS) - { - lRes = RegQueryInfoKey(key, NULL, NULL, NULL, &cbSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - key.Close(); - if (lRes == ERROR_SUCCESS && cbSubKeys == 0) - { - root.DeleteSubKey(szKey); - } - } - } - } - return( S_OK ); -} - -ATLINLINE ATLAPI AtlWinModuleTerm(_ATL_WIN_MODULE* pWinModule, HINSTANCE hInst) -{ - if (pWinModule == NULL) - return E_INVALIDARG; - if (pWinModule->cbSize == 0) - return S_OK; - if (pWinModule->cbSize != sizeof(_ATL_WIN_MODULE)) - return E_INVALIDARG; - - for (int i = 0; i < pWinModule->m_rgWindowClassAtoms.GetSize(); i++) - UnregisterClass((LPCTSTR)pWinModule->m_rgWindowClassAtoms[i], hInst); - pWinModule->m_rgWindowClassAtoms.RemoveAll(); - pWinModule->m_csWindowCreate.Term(); - pWinModule->cbSize = 0; - return S_OK; -} - -#endif // _ATL_DLL - -///////////////////////////////////////////////////////////////////////////// -// General DLL Version Helpers - -#pragma warning(push) -#pragma warning(disable : 4191) // 'type cast' : unsafe conversion from 'FARPROC' to 'DLLGETVERSIONPROC' - -inline HRESULT AtlGetDllVersion(HINSTANCE hInstDLL, DLLVERSIONINFO* pDllVersionInfo) -{ - ATLASSERT(!::IsBadWritePtr(pDllVersionInfo, sizeof(DLLVERSIONINFO))); - - // We must get this function explicitly because some DLLs don't implement it. - DLLGETVERSIONPROC pfnDllGetVersion = (DLLGETVERSIONPROC)::GetProcAddress(hInstDLL, "DllGetVersion"); - if(pfnDllGetVersion == NULL) - return E_NOTIMPL; - - return (*pfnDllGetVersion)(pDllVersionInfo); -} - -#pragma warning(pop) - -inline HRESULT AtlGetDllVersion(LPCTSTR lpstrDllName, DLLVERSIONINFO* pDllVersionInfo) -{ - HINSTANCE hInstDLL = ::LoadLibrary(lpstrDllName); - if(hInstDLL == NULL) - return AtlHresultFromLastError(); - HRESULT hRet = AtlGetDllVersion(hInstDLL, pDllVersionInfo); - ::FreeLibrary(hInstDLL); - return hRet; -} - -// Common Control Versions: -// Win95/WinNT 4.0 maj=4 min=00 -// IE 3.x maj=4 min=70 -// IE 4.0 maj=4 min=71 -// IE 5.0 maj=5 min=80 -// Win2000 maj=5 min=81 -inline HRESULT AtlGetCommCtrlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor) -{ - ATLASSERT(!::IsBadWritePtr(pdwMajor, sizeof(DWORD)) && !::IsBadWritePtr(pdwMinor, sizeof(DWORD))); - - DLLVERSIONINFO dvi; - memset(&dvi, 0, sizeof(dvi)); - dvi.cbSize = sizeof(dvi); - - HRESULT hRet = AtlGetDllVersion(_T("comctl32.dll"), &dvi); - - if(SUCCEEDED(hRet)) - { - *pdwMajor = dvi.dwMajorVersion; - *pdwMinor = dvi.dwMinorVersion; - } - else if(hRet == E_NOTIMPL) - { - // If DllGetVersion is not there, then the DLL is a version - // previous to the one shipped with IE 3.x - *pdwMajor = 4; - *pdwMinor = 0; - hRet = S_OK; - } - - return hRet; -} - -// Shell Versions: -// Win95/WinNT 4.0 maj=4 min=00 -// IE 3.x, IE 4.0 without Web Integrated Desktop maj=4 min=00 -// IE 4.0 with Web Integrated Desktop maj=4 min=71 -// IE 4.01 with Web Integrated Desktop maj=4 min=72 -// Win2000 maj=5 min=00 -inline HRESULT AtlGetShellVersion(LPDWORD pdwMajor, LPDWORD pdwMinor) -{ - ATLASSERT(!::IsBadWritePtr(pdwMajor, sizeof(DWORD)) && !::IsBadWritePtr(pdwMinor, sizeof(DWORD))); - - DLLVERSIONINFO dvi; - memset(&dvi, 0, sizeof(dvi)); - dvi.cbSize = sizeof(dvi); - HRESULT hRet = AtlGetDllVersion(_T("shell32.dll"), &dvi); - - if(SUCCEEDED(hRet)) - { - *pdwMajor = dvi.dwMajorVersion; - *pdwMinor = dvi.dwMinorVersion; - } - else if(hRet == E_NOTIMPL) - { - // If DllGetVersion is not there, then the DLL is a version - // previous to the one shipped with IE 4.x - *pdwMajor = 4; - *pdwMinor = 0; - hRet = S_OK; - } - - return hRet; -} - -inline ATL_DEPRECATED HRESULT AtlModuleRegisterClassObjects(_ATL_MODULE* /*pM*/, DWORD dwClsContext, DWORD dwFlags) -{ - return AtlComModuleRegisterClassObjects(&_AtlComModule, dwClsContext, dwFlags); -} - -inline ATL_DEPRECATED HRESULT AtlModuleRevokeClassObjects(_ATL_MODULE* /*pM*/) -{ - return AtlComModuleRevokeClassObjects(&_AtlComModule); -} - -inline ATL_DEPRECATED HRESULT AtlModuleGetClassObject(_ATL_MODULE* /*pM*/, REFCLSID rclsid, REFIID riid, LPVOID* ppv) -{ -#ifndef _ATL_OLEDB_CONFORMANCE_TESTS - ATLASSERT(ppv != NULL); -#endif - - return AtlComModuleGetClassObject(&_AtlComModule, rclsid, riid, ppv); -} - -inline ATL_DEPRECATED HRESULT AtlModuleRegisterServer(_ATL_MODULE* /*pM*/, BOOL bRegTypeLib, const CLSID* pCLSID = NULL) -{ - return AtlComModuleRegisterServer(&_AtlComModule, bRegTypeLib, pCLSID); -} - -inline ATL_DEPRECATED HRESULT AtlModuleUnregisterServer(_ATL_MODULE* /*pM*/, const CLSID* pCLSID = NULL) -{ - return AtlComModuleUnregisterServer(&_AtlComModule, FALSE, pCLSID); -} - -inline ATL_DEPRECATED HRESULT AtlModuleUnregisterServerEx(_ATL_MODULE* /*pM*/, BOOL bUnRegTypeLib, const CLSID* pCLSID = NULL) -{ - return AtlComModuleUnregisterServer(&_AtlComModule, bUnRegTypeLib, pCLSID); -} - -inline ATL_DEPRECATED HRESULT AtlModuleUpdateRegistryFromResourceD(_ATL_MODULE* /*pM*/, LPCOLESTR lpszRes, - BOOL bRegister, struct _ATL_REGMAP_ENTRY* pMapEntries, IRegistrar* pReg = NULL) -{ - return AtlUpdateRegistryFromResourceD(_AtlBaseModule.GetModuleInstance(), lpszRes, bRegister, pMapEntries, pReg); -} - -inline ATL_DEPRECATED HRESULT AtlModuleRegisterTypeLib(_ATL_MODULE* /*pM*/, LPCOLESTR lpszIndex) -{ - return AtlRegisterTypeLib(_AtlComModule.m_hInstTypeLib, lpszIndex); -} - -inline ATL_DEPRECATED HRESULT AtlModuleUnRegisterTypeLib(_ATL_MODULE* /*pM*/, LPCOLESTR lpszIndex) -{ - return AtlUnRegisterTypeLib(_AtlComModule.m_hInstTypeLib, lpszIndex); -} - -inline ATL_DEPRECATED HRESULT AtlModuleLoadTypeLib(_ATL_MODULE* /*pM*/, LPCOLESTR lpszIndex, BSTR* pbstrPath, ITypeLib** ppTypeLib) -{ - return AtlLoadTypeLib(_AtlComModule.m_hInstTypeLib, lpszIndex, pbstrPath, ppTypeLib); -} - -inline ATL_DEPRECATED HRESULT AtlModuleInit(_ATL_MODULE* /*pM*/, _ATL_OBJMAP_ENTRY* /*p*/, HINSTANCE /*h*/) -{ - return S_OK; -} - -inline ATL_DEPRECATED HRESULT AtlModuleTerm(_ATL_MODULE* /*pM*/) -{ - return S_OK; -} - -inline ATL_DEPRECATED void AtlModuleAddCreateWndData(_ATL_MODULE* /*pM*/, _AtlCreateWndData* pData, void* pObject) -{ - AtlWinModuleAddCreateWndData(&_AtlWinModule, pData, pObject); -} - -inline ATL_DEPRECATED void* AtlModuleExtractCreateWndData(_ATL_MODULE* /*pM*/) -{ - return AtlWinModuleExtractCreateWndData(&_AtlWinModule); -} - -#ifndef _ATL_NO_COMMODULE - -inline CRITICAL_SECTION& CComModule::get_m_csWindowCreate() throw() -{ - return _AtlWinModule.m_csWindowCreate.m_sec; -} - -inline CRITICAL_SECTION& CComModule::get_m_csObjMap() throw() -{ - return _AtlComModule.m_csObjMap.m_sec; -} - -inline CRITICAL_SECTION& CComModule::get_m_csStaticDataInit() throw() -{ - return m_csStaticDataInitAndTypeInfo.m_sec; -} - -inline _AtlCreateWndData*& CComModule::get_m_pCreateWndList() throw() -{ - return _AtlWinModule.m_pCreateWndList; -} -inline void CComModule::put_m_pCreateWndList(_AtlCreateWndData* p) throw() -{ - _AtlWinModule.m_pCreateWndList = p; -} -#ifdef _ATL_DEBUG_INTERFACES -inline UINT& CComModule::get_m_nIndexQI() throw() -{ - return _AtlDebugInterfacesModule.m_nIndexQI; -} -inline void CComModule::put_m_nIndexQI(UINT nIndex) throw() -{ - _AtlDebugInterfacesModule.m_nIndexQI = nIndex; -} -inline UINT& CComModule::get_m_nIndexBreakAt() throw() -{ - return _AtlDebugInterfacesModule.m_nIndexBreakAt; -} -inline void CComModule::put_m_nIndexBreakAt(UINT nIndex) throw() -{ - _AtlDebugInterfacesModule.m_nIndexBreakAt = nIndex; -} -inline CSimpleArray<_QIThunk*>* CComModule::get_m_paThunks() throw() -{ - return &_AtlDebugInterfacesModule.m_aThunks; -} -inline HRESULT CComModule::AddThunk(IUnknown** pp, LPCTSTR lpsz, REFIID iid) throw() -{ - return _AtlDebugInterfacesModule.AddThunk(pp, lpsz, iid); -} -inline HRESULT CComModule::AddNonAddRefThunk(IUnknown* p, LPCTSTR lpsz, IUnknown** ppThunkRet) throw() -{ - return _AtlDebugInterfacesModule.AddNonAddRefThunk(p, lpsz, ppThunkRet); -} - -inline void CComModule::DeleteNonAddRefThunk(IUnknown* pUnk) throw() -{ - _AtlDebugInterfacesModule.DeleteNonAddRefThunk(pUnk); -} - -inline void CComModule::DeleteThunk(_QIThunk* p) throw() -{ - _AtlDebugInterfacesModule.DeleteThunk(p); -} - -inline bool CComModule::DumpLeakedThunks() throw() -{ - return _AtlDebugInterfacesModule.DumpLeakedThunks(); -} -#endif // _ATL_DEBUG_INTERFACES - -inline HRESULT CComModule::Init(_ATL_OBJMAP_ENTRY* p, HINSTANCE /*h*/, const GUID* plibid) throw() -{ - if (plibid != NULL) - m_libid = *plibid; - - _ATL_OBJMAP_ENTRY* pEntry; - if (p != (_ATL_OBJMAP_ENTRY*)-1) - { - m_pObjMap = p; - if (m_pObjMap != NULL) - { - pEntry = m_pObjMap; - while (pEntry->pclsid != NULL) - { - pEntry->pfnObjectMain(true); //initialize class resources - pEntry++; - } - } - } - for (_ATL_OBJMAP_ENTRY** ppEntry = _AtlComModule.m_ppAutoObjMapFirst; ppEntry < _AtlComModule.m_ppAutoObjMapLast; ppEntry++) - { - if (*ppEntry != NULL) - (*ppEntry)->pfnObjectMain(true); //initialize class resources - } - return S_OK; -} -inline void CComModule::Term() throw() -{ - _ATL_OBJMAP_ENTRY* pEntry; - if (m_pObjMap != NULL) - { - pEntry = m_pObjMap; - while (pEntry->pclsid != NULL) - { - if (pEntry->pCF != NULL) - pEntry->pCF->Release(); - pEntry->pCF = NULL; - pEntry->pfnObjectMain(false); //cleanup class resources - pEntry++; - } - } - for (_ATL_OBJMAP_ENTRY** ppEntry = _AtlComModule.m_ppAutoObjMapFirst; ppEntry < _AtlComModule.m_ppAutoObjMapLast; ppEntry++) - { - if (*ppEntry != NULL) - (*ppEntry)->pfnObjectMain(false); //cleanup class resources - } -#ifdef _DEBUG - // Prevent false memory leak reporting. ~CAtlWinModule may be too late. - _AtlWinModule.Term(); -#endif // _DEBUG - - CAtlModuleT::Term(); -} - -inline HRESULT CComModule::GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) throw() -{ - if (ppv == NULL) - return E_POINTER; - HRESULT hr = S_OK; - _ATL_OBJMAP_ENTRY* pEntry; - if (m_pObjMap != NULL) - { - pEntry = m_pObjMap; - while (pEntry->pclsid != NULL) - { - if ((pEntry->pfnGetClassObject != NULL) && InlineIsEqualGUID(rclsid, *pEntry->pclsid)) - { - if (pEntry->pCF == NULL) - { - CComCritSecLock lock(_AtlComModule.m_csObjMap, false); - hr = lock.Lock(); - if (FAILED(hr)) - { - ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to lock critical section in CComModule::GetClassObject\n")); - ATLASSERT(0); - break; - } - if (pEntry->pCF == NULL) - hr = pEntry->pfnGetClassObject(pEntry->pfnCreateInstance, __uuidof(IUnknown), (LPVOID*)&pEntry->pCF); - } - if (pEntry->pCF != NULL) - hr = pEntry->pCF->QueryInterface(riid, ppv); - break; - } - pEntry++; - } - } - if (*ppv == NULL && hr == S_OK) - hr = AtlComModuleGetClassObject(&_AtlComModule, rclsid, riid, ppv); - return hr; -} - -// Register/Revoke All Class Factories with the OS (EXE only) -inline HRESULT CComModule::RegisterClassObjects(DWORD dwClsContext, DWORD dwFlags) throw() -{ - HRESULT hr = S_OK; - _ATL_OBJMAP_ENTRY* pEntry; - if (m_pObjMap != NULL) - { - pEntry = m_pObjMap; - while (pEntry->pclsid != NULL && hr == S_OK) - { - hr = pEntry->RegisterClassObject(dwClsContext, dwFlags); - pEntry++; - } - } - if (hr == S_OK) - hr = AtlComModuleRegisterClassObjects(&_AtlComModule, dwClsContext, dwFlags); - return hr; -} -inline HRESULT CComModule::RevokeClassObjects() throw() -{ - HRESULT hr = S_OK; - _ATL_OBJMAP_ENTRY* pEntry; - if (m_pObjMap != NULL) - { - pEntry = m_pObjMap; - while (pEntry->pclsid != NULL && hr == S_OK) - { - hr = pEntry->RevokeClassObject(); - pEntry++; - } - } - if (hr == S_OK) - hr = AtlComModuleRevokeClassObjects(&_AtlComModule); - return hr; -} - -// Registry support (helpers) -inline HRESULT CComModule::RegisterTypeLib() throw() -{ - return _AtlComModule.RegisterTypeLib(); -} -inline HRESULT CComModule::RegisterTypeLib(LPCTSTR lpszIndex) throw() -{ - return _AtlComModule.RegisterTypeLib(lpszIndex); -} -inline HRESULT CComModule::UnRegisterTypeLib() throw() -{ - return _AtlComModule.UnRegisterTypeLib(); -} -inline HRESULT CComModule::UnRegisterTypeLib(LPCTSTR lpszIndex) throw() -{ - return _AtlComModule.UnRegisterTypeLib(lpszIndex); -} - -inline HRESULT CComModule::RegisterServer(BOOL bRegTypeLib /*= FALSE*/, const CLSID* pCLSID /*= NULL*/) throw() -{ - HRESULT hr = S_OK; - _ATL_OBJMAP_ENTRY* pEntry = m_pObjMap; - if (pEntry != NULL) - { - for (;pEntry->pclsid != NULL; pEntry++) - { - if (pCLSID != NULL) - { - if (!IsEqualGUID(*pCLSID, *pEntry->pclsid)) - continue; - } - hr = pEntry->pfnUpdateRegistry(TRUE); - if (FAILED(hr)) - break; - hr = AtlRegisterClassCategoriesHelper( *pEntry->pclsid, - pEntry->pfnGetCategoryMap(), TRUE ); - if (FAILED(hr)) - break; - } - } - if (SUCCEEDED(hr)) - hr = CAtlModuleT::RegisterServer(bRegTypeLib, pCLSID); - return hr; -} - -inline HRESULT CComModule::UnregisterServer(BOOL bUnRegTypeLib, const CLSID* pCLSID /*= NULL*/) throw() -{ - HRESULT hr = S_OK; - _ATL_OBJMAP_ENTRY* pEntry = m_pObjMap; - if (pEntry != NULL) - { - for (;pEntry->pclsid != NULL; pEntry++) - { - if (pCLSID != NULL) - { - if (!IsEqualGUID(*pCLSID, *pEntry->pclsid)) - continue; - } - hr = AtlRegisterClassCategoriesHelper( *pEntry->pclsid, - pEntry->pfnGetCategoryMap(), FALSE ); - if (FAILED(hr)) - break; - hr = pEntry->pfnUpdateRegistry(FALSE); //unregister - if (FAILED(hr)) - break; - } - } - if (SUCCEEDED(hr)) - hr = CAtlModuleT::UnregisterServer(bUnRegTypeLib, pCLSID); - return hr; -} - -inline HRESULT CComModule::UnregisterServer(const CLSID* pCLSID /*= NULL*/) throw() -{ - return UnregisterServer(FALSE, pCLSID); -} - -#endif // !_ATL_NO_COMMODULE - -} // namespace ATL - -#pragma warning( pop ) - -#if !defined(_ATL_DLL) && !defined(_DEBUG) - -#include - -#endif // !_ATL_DLL && !_DEBUG - -#ifdef _ATL_ALL_WARNINGS -#pragma warning( pop ) -#endif - -///////////////////////////////////////////////////////////////////////////// - -#endif // __ATLBASE_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlbase.inl b/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlbase.inl deleted file mode 100644 index 858288861..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlbase.inl +++ /dev/null @@ -1,424 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLBASE_INL__ -#define __ATLBASE_INL__ - -#pragma once - -#ifndef __ATLBASE_H__ - #error atlbase.inl requires atlbase.h to be included first -#endif - -namespace ATL -{ - -///////////////////////////////////////////////////////////////////////////// -// Connection Point Helpers - -ATLINLINE ATLAPI AtlAdvise(IUnknown* pUnkCP, IUnknown* pUnk, const IID& iid, LPDWORD pdw) -{ - if(pUnkCP == NULL) - return E_INVALIDARG; - - CComPtr pCPC; - CComPtr pCP; - HRESULT hRes = pUnkCP->QueryInterface(__uuidof(IConnectionPointContainer), (void**)&pCPC); - if (SUCCEEDED(hRes)) - hRes = pCPC->FindConnectionPoint(iid, &pCP); - if (SUCCEEDED(hRes)) - hRes = pCP->Advise(pUnk, pdw); - return hRes; -} - -ATLINLINE ATLAPI AtlUnadvise(IUnknown* pUnkCP, const IID& iid, DWORD dw) -{ - if(pUnkCP == NULL) - return E_INVALIDARG; - - CComPtr pCPC; - CComPtr pCP; - HRESULT hRes = pUnkCP->QueryInterface(__uuidof(IConnectionPointContainer), (void**)&pCPC); - if (SUCCEEDED(hRes)) - hRes = pCPC->FindConnectionPoint(iid, &pCP); - if (SUCCEEDED(hRes)) - hRes = pCP->Unadvise(dw); - return hRes; -} - -///////////////////////////////////////////////////////////////////////////// -// Inproc Marshaling helpers - -//This API should be called from the same thread that called -//AtlMarshalPtrInProc -ATLINLINE ATLAPI AtlFreeMarshalStream(IStream* pStream) -{ - if (pStream != NULL) - { - LARGE_INTEGER l; - l.QuadPart = 0; - pStream->Seek(l, STREAM_SEEK_SET, NULL); - CoReleaseMarshalData(pStream); - pStream->Release(); - } - return S_OK; -} - -ATLINLINE ATLAPI AtlMarshalPtrInProc(IUnknown* pUnk, const IID& iid, IStream** ppStream) -{ - ATLASSERT(ppStream != NULL); - if (ppStream == NULL) - return E_POINTER; - - HRESULT hRes = CreateStreamOnHGlobal(NULL, TRUE, ppStream); - if (SUCCEEDED(hRes)) - { - hRes = CoMarshalInterface(*ppStream, iid, - pUnk, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLESTRONG); - if (FAILED(hRes)) - { - (*ppStream)->Release(); - *ppStream = NULL; - } - } - return hRes; -} - -ATLINLINE ATLAPI AtlUnmarshalPtr(IStream* pStream, const IID& iid, IUnknown** ppUnk) -{ - ATLASSERT(ppUnk != NULL); - if (ppUnk == NULL) - return E_POINTER; - - *ppUnk = NULL; - HRESULT hRes = E_INVALIDARG; - if (pStream != NULL) - { - LARGE_INTEGER l; - l.QuadPart = 0; - pStream->Seek(l, STREAM_SEEK_SET, NULL); - hRes = CoUnmarshalInterface(pStream, iid, (void**)ppUnk); - } - return hRes; -} - -///////////////////////////////////////////////////////////////////////////// -// Module - -ATLINLINE ATLAPI AtlComModuleGetClassObject(_ATL_COM_MODULE* pComModule, REFCLSID rclsid, REFIID riid, LPVOID* ppv) -{ - ATLASSERT(pComModule != NULL); - if (pComModule == NULL) - return E_INVALIDARG; - if (pComModule->cbSize == 0) // Module hasn't been initialized - return E_UNEXPECTED; - - if (ppv == NULL) - return E_POINTER; - *ppv = NULL; - - HRESULT hr = S_OK; - - for (_ATL_OBJMAP_ENTRY** ppEntry = pComModule->m_ppAutoObjMapFirst; ppEntry < pComModule->m_ppAutoObjMapLast; ppEntry++) - { - if (*ppEntry != NULL) - { - _ATL_OBJMAP_ENTRY* pEntry = *ppEntry; - if ((pEntry->pfnGetClassObject != NULL) && InlineIsEqualGUID(rclsid, *pEntry->pclsid)) - { - if (pEntry->pCF == NULL) - { - CComCritSecLock lock(pComModule->m_csObjMap, false); - hr = lock.Lock(); - if (FAILED(hr)) - { - ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to lock critical section in AtlComModuleGetClassObject\n")); - ATLASSERT(0); - break; - } - if (pEntry->pCF == NULL) - hr = pEntry->pfnGetClassObject(pEntry->pfnCreateInstance, __uuidof(IUnknown), (LPVOID*)&pEntry->pCF); - } - if (pEntry->pCF != NULL) - hr = pEntry->pCF->QueryInterface(riid, ppv); - break; - } - } - } - - if (*ppv == NULL && hr == S_OK) - hr = CLASS_E_CLASSNOTAVAILABLE; - return hr; -} - -ATLINLINE ATLAPI AtlComModuleRegisterClassObjects(_ATL_COM_MODULE* pComModule, DWORD dwClsContext, DWORD dwFlags) -{ - ATLASSERT(pComModule != NULL); - if (pComModule == NULL) - return E_INVALIDARG; - - HRESULT hr = S_FALSE; - for (_ATL_OBJMAP_ENTRY** ppEntry = pComModule->m_ppAutoObjMapFirst; ppEntry < pComModule->m_ppAutoObjMapLast && SUCCEEDED(hr); ppEntry++) - { - if (*ppEntry != NULL) - hr = (*ppEntry)->RegisterClassObject(dwClsContext, dwFlags); - } - return hr; -} - -ATLINLINE ATLAPI AtlComModuleRevokeClassObjects(_ATL_COM_MODULE* pComModule) -{ - ATLASSERT(pComModule != NULL); - if (pComModule == NULL) - return E_INVALIDARG; - - HRESULT hr = S_OK; - for (_ATL_OBJMAP_ENTRY** ppEntry = pComModule->m_ppAutoObjMapFirst; ppEntry < pComModule->m_ppAutoObjMapLast && hr == S_OK; ppEntry++) - { - if (*ppEntry != NULL) - hr = (*ppEntry)->RevokeClassObject(); - } - return hr; -} - -ATLINLINE ATLAPI_(BOOL) AtlWaitWithMessageLoop(HANDLE hEvent) -{ - DWORD dwRet; - MSG msg; - - while(1) - { - dwRet = MsgWaitForMultipleObjects(1, &hEvent, FALSE, INFINITE, QS_ALLINPUT); - - if (dwRet == WAIT_OBJECT_0) - return TRUE; // The event was signaled - - if (dwRet != WAIT_OBJECT_0 + 1) - break; // Something else happened - - // There is one or more window message available. Dispatch them - while(PeekMessage(&msg,0,0,0,PM_NOREMOVE)) - { - // check for unicode window so we call the appropriate functions - BOOL bUnicode = ::IsWindowUnicode(msg.hwnd); - BOOL bRet; - - if (bUnicode) - bRet = ::GetMessageW(&msg, NULL, 0, 0); - else - bRet = ::GetMessageA(&msg, NULL, 0, 0); - - if (bRet > 0) - { - ::TranslateMessage(&msg); - - if (bUnicode) - ::DispatchMessageW(&msg); - else - ::DispatchMessageA(&msg); - } - - if (WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0) - return TRUE; // Event is now signaled. - } - } - return FALSE; -} - -///////////////////////////////////////////////////////////////////////////// -// QI support - -ATLINLINE ATLAPI AtlInternalQueryInterface(void* pThis, - const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject) -{ - ATLASSERT(pThis != NULL); - ATLASSERT(pEntries!= NULL); - - if(pThis == NULL || pEntries == NULL) - return E_INVALIDARG ; - - // First entry in the com map should be a simple map entry - ATLASSERT(pEntries->pFunc == _ATL_SIMPLEMAPENTRY); - if (ppvObject == NULL) - return E_POINTER; - *ppvObject = NULL; - if (InlineIsEqualUnknown(iid)) // use first interface - { - IUnknown* pUnk = (IUnknown*)((INT_PTR)pThis+pEntries->dw); - pUnk->AddRef(); - *ppvObject = pUnk; - return S_OK; - } - while (pEntries->pFunc != NULL) - { - BOOL bBlind = (pEntries->piid == NULL); - if (bBlind || InlineIsEqualGUID(*(pEntries->piid), iid)) - { - if (pEntries->pFunc == _ATL_SIMPLEMAPENTRY) //offset - { - ATLASSERT(!bBlind); - IUnknown* pUnk = (IUnknown*)((INT_PTR)pThis+pEntries->dw); - pUnk->AddRef(); - *ppvObject = pUnk; - return S_OK; - } - else //actual function call - { - HRESULT hRes = pEntries->pFunc(pThis, - iid, ppvObject, pEntries->dw); - if (hRes == S_OK || (!bBlind && FAILED(hRes))) - return hRes; - } - } - pEntries++; - } - return E_NOINTERFACE; -} - -ATLINLINE ATLAPI_(DWORD) AtlGetVersion(void* /* pReserved */) -{ - return _ATL_VER; -} - -///////////////////////////////////////////////////////////////////////////// -// Windowing - -ATLINLINE ATLAPI_(void) AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE* pWinModule, _AtlCreateWndData* pData, void* pObject) -{ - if (pWinModule == NULL) - _AtlRaiseException(EXCEPTION_ACCESS_VIOLATION); - - ATLASSERT(pData != NULL && pObject != NULL); - if(pData == NULL || pObject == NULL) - _AtlRaiseException(EXCEPTION_ACCESS_VIOLATION); - - pData->m_pThis = pObject; - pData->m_dwThreadID = ::GetCurrentThreadId(); - CComCritSecLock lock(pWinModule->m_csWindowCreate, false); - if (FAILED(lock.Lock())) - { - ATLTRACE(atlTraceWindowing, 0, _T("ERROR : Unable to lock critical section in AtlWinModuleAddCreateWndData\n")); - ATLASSERT(0); - return; - } - pData->m_pNext = pWinModule->m_pCreateWndList; - pWinModule->m_pCreateWndList = pData; -} - -ATLINLINE ATLAPI_(void*) AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE* pWinModule) -{ - if (pWinModule == NULL) - return NULL; - - void* pv = NULL; - CComCritSecLock lock(pWinModule->m_csWindowCreate, false); - if (FAILED(lock.Lock())) - { - ATLTRACE(atlTraceWindowing, 0, _T("ERROR : Unable to lock critical section in AtlWinModuleExtractCreateWndData\n")); - ATLASSERT(0); - return pv; - } - _AtlCreateWndData* pEntry = pWinModule->m_pCreateWndList; - if(pEntry != NULL) - { - DWORD dwThreadID = ::GetCurrentThreadId(); - _AtlCreateWndData* pPrev = NULL; - while(pEntry != NULL) - { - if(pEntry->m_dwThreadID == dwThreadID) - { - if(pPrev == NULL) - pWinModule->m_pCreateWndList = pEntry->m_pNext; - else - pPrev->m_pNext = pEntry->m_pNext; - pv = pEntry->m_pThis; - break; - } - pPrev = pEntry; - pEntry = pEntry->m_pNext; - } - } - return pv; -} - -ATLINLINE ATLAPI AtlWinModuleInit(_ATL_WIN_MODULE* pWinModule) -{ - if (pWinModule == NULL) - return E_INVALIDARG; - - // check only in the DLL - if (pWinModule->cbSize != sizeof(_ATL_WIN_MODULE)) - return E_INVALIDARG; - - pWinModule->m_pCreateWndList = NULL; - - HRESULT hr = pWinModule->m_csWindowCreate.Init(); - if (FAILED(hr)) - { - ATLTRACE(atlTraceWindowing, 0, _T("ERROR : Unable to initialize critical section in AtlWinModuleInit\n")); - ATLASSERT(0); - } - return hr; -} - -///////////////////////////////////////////////////////////////////////////// -// Module - -ATLINLINE ATLAPI AtlModuleAddTermFunc(_ATL_MODULE* pModule, _ATL_TERMFUNC* pFunc, DWORD_PTR dw) -{ - if (pModule == NULL) - return E_INVALIDARG; - - HRESULT hr = S_OK; - _ATL_TERMFUNC_ELEM* pNew = NULL; - ATLTRY(pNew = new _ATL_TERMFUNC_ELEM); - if (pNew == NULL) - hr = E_OUTOFMEMORY; - else - { - pNew->pFunc = pFunc; - pNew->dw = dw; - CComCritSecLock lock(pModule->m_csStaticDataInitAndTypeInfo, false); - hr = lock.Lock(); - if (SUCCEEDED(hr)) - { - pNew->pNext = pModule->m_pTermFuncs; - pModule->m_pTermFuncs = pNew; - } - else - { - delete pNew; - ATLTRACE(atlTraceGeneral, 0, _T("ERROR : Unable to lock critical section in AtlModuleAddTermFunc\n")); - ATLASSERT(0); - } - } - return hr; -} - -ATLINLINE ATLAPI_(void) AtlCallTermFunc(_ATL_MODULE* pModule) -{ - if (pModule == NULL) - _AtlRaiseException(EXCEPTION_ACCESS_VIOLATION); - - _ATL_TERMFUNC_ELEM* pElem = pModule->m_pTermFuncs; - _ATL_TERMFUNC_ELEM* pNext = NULL; - while (pElem != NULL) - { - pElem->pFunc(pElem->dw); - pNext = pElem->pNext; - delete pElem; - pElem = pNext; - } - pModule->m_pTermFuncs = NULL; -} - -} // namespace ATL - -#endif // __ATLBASE_INL__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlcom.h b/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlcom.h deleted file mode 100644 index b147b814f..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlcom.h +++ /dev/null @@ -1,6215 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLCOM_H__ -#define __ATLCOM_H__ - -#pragma once - -#ifndef _ATL_NO_PRAGMA_WARNINGS -#pragma warning (push) -#pragma warning(disable: 4702) // unreachable code -#pragma warning(disable: 4355) // 'this' used in initializer list -#pragma warning(disable: 4511) // copy constructor could not be generated -#pragma warning(disable: 4512) // assignment operator could not be generated -#pragma warning(disable : 4668) // is not defined as a preprocessor macro, replacing with '0' for '#if/#elif -#pragma warning(disable : 4820) // padding added after member -#endif //!_ATL_NO_PRAGMA_WARNINGS - -#ifdef _ATL_ALL_WARNINGS -#pragma warning( push ) -#endif -#pragma warning(disable: 4127) // constant expression -#pragma warning(disable: 4786) // avoid 255-character limit warnings - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#ifndef __ATLBASE_H__ - #error atlcom.h requires atlbase.h to be included first -#endif - -#pragma pack(push, _ATL_PACKING) - -EXTERN_C const IID IID_ITargetFrame; - -#include - -namespace ATL -{ - -#define CComConnectionPointContainerImpl ATL::IConnectionPointContainerImpl -#define CComISupportErrorInfoImpl ATL::ISupportErrorInfoImpl -#define CComProvideClassInfo2Impl ATL::IProvideClassInfoImpl -#define CComDualImpl ATL::IDispatchImpl - -#ifdef _ATL_DEBUG_QI -#ifndef _ATL_DEBUG -#define _ATL_DEBUG -#endif // _ATL_DEBUG -#endif // _ATL_DEBUG_QI - -#ifdef _ATL_DEBUG_QI -#define _ATLDUMPIID(iid, name, hr) AtlDumpIID(iid, name, hr) -#else -#define _ATLDUMPIID(iid, name, hr) hr -#endif - -#define _ATL_DEBUG_ADDREF_RELEASE_IMPL(className)\ - virtual ULONG STDMETHODCALLTYPE AddRef(void) = 0;\ - virtual ULONG STDMETHODCALLTYPE Release(void) = 0; - -///////////////////////////////////////////////////////////////////////////// -// AtlReportError - -inline HRESULT WINAPI AtlReportError(const CLSID& clsid, UINT nID, const IID& iid = GUID_NULL, - HRESULT hRes = 0, HINSTANCE hInst = _AtlBaseModule.GetResourceInstance()) -{ - return AtlSetErrorInfo(clsid, (LPCOLESTR)MAKEINTRESOURCE(nID), 0, NULL, iid, hRes, hInst); -} - -inline HRESULT WINAPI AtlReportError(const CLSID& clsid, UINT nID, DWORD dwHelpID, - LPCOLESTR lpszHelpFile, const IID& iid = GUID_NULL, HRESULT hRes = 0, - HINSTANCE hInst = _AtlBaseModule.GetResourceInstance()) -{ - return AtlSetErrorInfo(clsid, (LPCOLESTR)MAKEINTRESOURCE(nID), dwHelpID, - lpszHelpFile, iid, hRes, hInst); -} - -inline HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCSTR lpszDesc, - DWORD dwHelpID, LPCSTR lpszHelpFile, const IID& iid = GUID_NULL, HRESULT hRes = 0) -{ - ATLASSERT(lpszDesc != NULL); - if (lpszDesc == NULL) - return E_POINTER; - USES_CONVERSION_EX; - LPCOLESTR pwszDesc = A2COLE_EX(lpszDesc, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); - if(pwszDesc == NULL) - return E_OUTOFMEMORY; - - LPCWSTR pwzHelpFile = NULL; - if(lpszHelpFile != NULL) - { - pwzHelpFile = A2CW_EX(lpszHelpFile, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); - if(pwzHelpFile == NULL) - return E_OUTOFMEMORY; - } - - return AtlSetErrorInfo(clsid, pwszDesc, dwHelpID, pwzHelpFile, iid, hRes, NULL); -} - -inline HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCSTR lpszDesc, - const IID& iid = GUID_NULL, HRESULT hRes = 0) -{ - return AtlReportError(clsid, lpszDesc, 0, NULL, iid, hRes); -} - -inline HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCOLESTR lpszDesc, - const IID& iid = GUID_NULL, HRESULT hRes = 0) -{ - return AtlSetErrorInfo(clsid, lpszDesc, 0, NULL, iid, hRes, NULL); -} - -inline HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCOLESTR lpszDesc, DWORD dwHelpID, - LPCOLESTR lpszHelpFile, const IID& iid = GUID_NULL, HRESULT hRes = 0) -{ - return AtlSetErrorInfo(clsid, lpszDesc, dwHelpID, lpszHelpFile, iid, hRes, NULL); -} - -// Returns the apartment type that the current thread is in. false is returned -// if the thread isn't in an apartment. -inline bool AtlGetApartmentType(DWORD* pApartmentType) -{ - HRESULT hr = CoInitialize(NULL); - if (SUCCEEDED(hr)) - CoUninitialize(); - - if (hr == S_FALSE) - { - *pApartmentType = COINIT_APARTMENTTHREADED; - return true; - } -#if ((_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM)) - else - if (hr == RPC_E_CHANGED_MODE) - { - *pApartmentType = COINIT_MULTITHREADED; - return true; - } -#endif - return false; -} - -///////////////////////////////////////////////////////////////////////////// -// CComTypeAttr - -class CComTypeAttr -{ -// Construction -public: - CComTypeAttr( ITypeInfo* pTypeInfo ) throw() : - m_pTypeAttr( NULL ), - m_pTypeInfo( pTypeInfo ) - { - } - ~CComTypeAttr() throw() - { - Release(); - } - -// Operators -public: - TYPEATTR* operator->() throw() - { - ATLASSERT( m_pTypeAttr != NULL ); - - return m_pTypeAttr; - } - TYPEATTR** operator&() throw() - { - ATLASSERT( m_pTypeAttr == NULL ); - - return &m_pTypeAttr; - } - - operator const TYPEATTR*() const throw() - { - return m_pTypeAttr; - } - -// Operations -public: - void Release() throw() - { - if( m_pTypeAttr != NULL ) - { - ATLASSERT( m_pTypeInfo != NULL ); - m_pTypeInfo->ReleaseTypeAttr( m_pTypeAttr ); - m_pTypeAttr = NULL; - } - } - -public: - TYPEATTR* m_pTypeAttr; - CComPtr< ITypeInfo > m_pTypeInfo; -}; - - -///////////////////////////////////////////////////////////////////////////// -// CComVarDesc - -class CComVarDesc -{ -// Construction -public: - CComVarDesc( ITypeInfo* pTypeInfo ) throw() : - m_pVarDesc( NULL ), - m_pTypeInfo( pTypeInfo ) - { - } - ~CComVarDesc() throw() - { - Release(); - } - -// Operators -public: - VARDESC* operator->() throw() - { - ATLASSERT( m_pVarDesc != NULL ); - - return m_pVarDesc; - } - VARDESC** operator&() throw() - { - ATLASSERT( m_pVarDesc == NULL ); - - return &m_pVarDesc; - } - - operator const VARDESC*() const throw() - { - return m_pVarDesc; - } - -// Operations -public: - void Release() throw() - { - if( m_pVarDesc != NULL ) - { - ATLASSERT( m_pTypeInfo != NULL ); - m_pTypeInfo->ReleaseVarDesc( m_pVarDesc ); - m_pVarDesc = NULL; - } - } - -public: - VARDESC* m_pVarDesc; - CComPtr< ITypeInfo > m_pTypeInfo; -}; - - -///////////////////////////////////////////////////////////////////////////// -// CComFuncDesc - -class CComFuncDesc -{ -// Construction -public: - CComFuncDesc( ITypeInfo* pTypeInfo ) throw() : - m_pFuncDesc( NULL ), - m_pTypeInfo( pTypeInfo ) - { - } - ~CComFuncDesc() throw() - { - Release(); - } - -// Operators -public: - FUNCDESC* operator->() throw() - { - ATLASSERT( m_pFuncDesc != NULL ); - - return m_pFuncDesc; - } - FUNCDESC** operator&() throw() - { - ATLASSERT( m_pFuncDesc == NULL ); - - return &m_pFuncDesc; - } - - operator const FUNCDESC*() const throw() - { - return m_pFuncDesc; - } - -// Operations -public: - void Release() throw() - { - if( m_pFuncDesc != NULL ) - { - ATLASSERT( m_pTypeInfo != NULL ); - m_pTypeInfo->ReleaseFuncDesc( m_pFuncDesc ); - m_pFuncDesc = NULL; - } - } - -public: - FUNCDESC* m_pFuncDesc; - CComPtr< ITypeInfo > m_pTypeInfo; -}; - - -///////////////////////////////////////////////////////////////////////////// -// CComExcepInfo - -class CComExcepInfo : - public EXCEPINFO -{ -// Construction -public: - CComExcepInfo() - { - memset( this, 0, sizeof( *this ) ); - } - ~CComExcepInfo() - { - Clear(); - } - -// Operations -public: - void Clear() - { - if (bstrSource != NULL) - ::SysFreeString(bstrSource); - - if (bstrDescription != NULL) - ::SysFreeString(bstrDescription); - - if (bstrHelpFile != NULL) - ::SysFreeString(bstrHelpFile); - - memset(this, 0, sizeof(*this)); - } -}; - - -////////////////////////////////////////////////////////////////////////////// -// IPersistImpl -template -class ATL_NO_VTABLE IPersistImpl : public IPersist -{ -public: - STDMETHOD(GetClassID)(CLSID *pClassID) - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistImpl::GetClassID\n")); - if (pClassID == NULL) - return E_FAIL; - *pClassID = T::GetObjectCLSID(); - return S_OK; - } -}; - -////////////////////////////////////////////////////////////////////////////// -// CFakeFirePropNotifyEvent -class CFakeFirePropNotifyEvent -{ -public: - static HRESULT FireOnRequestEdit(IUnknown* /*pUnk*/, DISPID /*dispID*/) - { - return S_OK; - } - static HRESULT FireOnChanged(IUnknown* /*pUnk*/, DISPID /*dispID*/) - { - return S_OK; - } -}; -typedef CFakeFirePropNotifyEvent _ATL_PROP_NOTIFY_EVENT_CLASS; - - -////////////////////////////////////////////////////////////////////////////// -// ALT_PROP_VAL_MAP - -struct ATL_PROPVALMAP_ENTRY -{ - DISPID dispid; - VARIANT val; - LPCOLESTR szDesc; -}; - -#define BEGIN_PROP_VAL_MAP(theClass) \ - static ATL::ATL_PROPVALMAP_ENTRY* GetPropValMap(int *cnt)\ - {\ - static ATL::ATL_PROPVALMAP_ENTRY pPropMap[] = \ - { - -#define PROP_VAL_INT(dispid, ival, str) \ - {dispid, {VT_I4, 0, 0, 0, ival}, OLESTR(str)}, - - -#define END_PROP_VAL_MAP() \ - }; \ - if (cnt) \ - *cnt = sizeof(pPropMap)/sizeof(pPropMap[0]); \ - return pPropMap; \ - } - -#define DECLARE_EMPTY_PROP_VAL_MAP() \ -public: \ - static ATL::ATL_PROPVALMAP_ENTRY* GetPropValMap(int *cnt)\ - { \ - if (cnt) \ - *cnt = 0; \ - return NULL; \ - } - -////////////////////////////////////////////////////////////////////////////// -// ATL Persistence - -struct ATL_PROPMAP_ENTRY -{ - LPCOLESTR szDesc; - DISPID dispid; - const CLSID* pclsidPropPage; - const IID* piidDispatch; - DWORD dwOffsetData; - DWORD dwSizeData; - VARTYPE vt; -}; - -// This one is DEPRECATED and is used for ATL 2.X controls -// it includes an implicit m_sizeExtent -#define BEGIN_PROPERTY_MAP(theClass) \ - __if_not_exists(__ATL_PROP_NOTIFY_EVENT_CLASS) \ - { \ - typedef ATL::_ATL_PROP_NOTIFY_EVENT_CLASS __ATL_PROP_NOTIFY_EVENT_CLASS; \ - } \ - typedef theClass _PropMapClass; \ - static ATL::ATL_PROPMAP_ENTRY* GetPropertyMap()\ - {\ - static ATL::ATL_PROPMAP_ENTRY pPropMap[] = \ - { \ - {OLESTR("_cx"), 0, &CLSID_NULL, NULL, offsetof(_PropMapClass, m_sizeExtent.cx), sizeof(long), VT_UI4}, \ - {OLESTR("_cy"), 0, &CLSID_NULL, NULL, offsetof(_PropMapClass, m_sizeExtent.cy), sizeof(long), VT_UI4}, - -// This one can be used on any type of object, but does not -// include the implicit m_sizeExtent -#define BEGIN_PROP_MAP(theClass) \ - __if_not_exists(__ATL_PROP_NOTIFY_EVENT_CLASS) \ - { \ - typedef ATL::_ATL_PROP_NOTIFY_EVENT_CLASS __ATL_PROP_NOTIFY_EVENT_CLASS; \ - } \ - typedef theClass _PropMapClass; \ - static ATL::ATL_PROPMAP_ENTRY* GetPropertyMap()\ - {\ - static ATL::ATL_PROPMAP_ENTRY pPropMap[] = \ - { - -#define PROP_ENTRY(szDesc, dispid, clsid) \ - {OLESTR(szDesc), dispid, &clsid, &__uuidof(IDispatch), 0, 0, 0}, - -#define PROP_ENTRY_EX(szDesc, dispid, clsid, iidDispatch) \ - {OLESTR(szDesc), dispid, &clsid, &iidDispatch, 0, 0, 0}, - -#define PROP_PAGE(clsid) \ - {NULL, NULL, &clsid, &IID_NULL, 0, 0, 0}, - -#define PROP_DATA_ENTRY(szDesc, member, vt) \ - {OLESTR(szDesc), 0, &CLSID_NULL, NULL, offsetof(_PropMapClass, member), sizeof(((_PropMapClass*)0)->member), vt}, - -#define END_PROPERTY_MAP() \ - {NULL, 0, NULL, &IID_NULL, 0, 0, 0} \ - }; \ - return pPropMap; \ - } - -#define END_PROP_MAP() \ - {NULL, 0, NULL, &IID_NULL, 0, 0, 0} \ - }; \ - return pPropMap; \ - } - -////////////////////////////////////////////////////////////////////////////// -// IPersist* Helpers - -ATLAPI AtlIPersistStreamInit_Load(LPSTREAM pStm, ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk); -ATLAPI AtlIPersistStreamInit_Save(LPSTREAM pStm, BOOL fClearDirty, ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk); -ATLAPI AtlIPersistPropertyBag_Load(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog, ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk); -ATLAPI AtlIPersistPropertyBag_Save(LPPROPERTYBAG pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties, ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk); - -////////////////////////////////////////////////////////////////////////////// -// IPersistStreamInitImpl -template -class ATL_NO_VTABLE IPersistStreamInitImpl : public IPersistStreamInit -{ -public: - // IPersist - STDMETHOD(GetClassID)(CLSID *pClassID) - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistStreamInitImpl::GetClassID\n")); - if (pClassID == NULL) - return E_POINTER; - *pClassID = T::GetObjectCLSID(); - return S_OK; - } - - // IPersistStream - STDMETHOD(IsDirty)() - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistStreamInitImpl::IsDirty\n")); - T* pT = static_cast(this); - return (pT->m_bRequiresSave) ? S_OK : S_FALSE; - } - STDMETHOD(Load)(LPSTREAM pStm) - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistStreamInitImpl::Load\n")); - - T* pT = static_cast(this); - return pT->IPersistStreamInit_Load(pStm, T::GetPropertyMap()); - } - STDMETHOD(Save)(LPSTREAM pStm, BOOL fClearDirty) - { - T* pT = static_cast(this); - ATLTRACE(atlTraceCOM, 2, _T("IPersistStreamInitImpl::Save\n")); - return pT->IPersistStreamInit_Save(pStm, fClearDirty, T::GetPropertyMap()); - } - STDMETHOD(GetSizeMax)(ULARGE_INTEGER* pcbSize) - { - HRESULT hr = S_OK; - T* pT = static_cast(this); - ATLTRACE(atlTraceCOM, 2, _T("IPersistStreamInitImpl::GetSizeMax\n")); - - if (pcbSize == NULL) - return E_POINTER; - - ATL_PROPMAP_ENTRY* pMap = T::GetPropertyMap(); - ATLASSERT(pMap != NULL); - - // Start the size with the size of the ATL version we write out. - ULARGE_INTEGER nSize; - nSize.HighPart = 0; - nSize.LowPart = sizeof(DWORD); - - CComPtr pDispatch; - const IID* piidOld = NULL; - for (int i = 0; pMap[i].pclsidPropPage != NULL; i++) - { - if (pMap[i].szDesc == NULL) - continue; - - // check if raw data entry - if (pMap[i].dwSizeData != 0) - { - nSize.QuadPart += pMap[i].dwSizeData; - continue; - } - - CComVariant var; - if (pMap[i].piidDispatch != piidOld) - { - pDispatch.Release(); - if (FAILED(pT->GetUnknown()->QueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch))) - { - ATLTRACE(atlTraceCOM, 0, _T("Failed to get a dispatch pointer for property #%i\n"), i); - hr = E_FAIL; - break; - } - piidOld = pMap[i].piidDispatch; - } - - if (FAILED(pDispatch.GetProperty(pMap[i].dispid, &var))) - { - ATLTRACE(atlTraceCOM, 0, _T("Invoked failed on DISPID %x\n"), pMap[i].dispid); - hr = E_FAIL; - break; - } - nSize.QuadPart += var.GetSize(); - } - *pcbSize = nSize; - return hr; - } - - // IPersistStreamInit - STDMETHOD(InitNew)() - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistStreamInitImpl::InitNew\n")); - T* pT = static_cast(this); - pT->m_bRequiresSave = TRUE; - return S_OK; - } - - HRESULT IPersistStreamInit_Load(LPSTREAM pStm, ATL_PROPMAP_ENTRY* pMap) - { - T* pT = static_cast(this); - HRESULT hr = AtlIPersistStreamInit_Load(pStm, pMap, pT, pT->GetUnknown()); - if (SUCCEEDED(hr)) - pT->m_bRequiresSave = FALSE; - return hr; - - } - HRESULT IPersistStreamInit_Save(LPSTREAM pStm, BOOL fClearDirty, ATL_PROPMAP_ENTRY* pMap) - { - T* pT = static_cast(this); - return AtlIPersistStreamInit_Save(pStm, fClearDirty, pMap, pT, pT->GetUnknown()); - } -}; - -////////////////////////////////////////////////////////////////////////////// -// IPersistStorageImpl -template -class ATL_NO_VTABLE IPersistStorageImpl : public IPersistStorage -{ -public: - // IPersist - STDMETHOD(GetClassID)(CLSID *pClassID) - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistStorageImpl::GetClassID\n")); - if (pClassID == NULL) - return E_POINTER; - *pClassID = T::GetObjectCLSID(); - return S_OK; - } - - // IPersistStorage - STDMETHOD(IsDirty)(void) - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistStorageImpl::IsDirty\n")); - CComPtr p; - p.p = IPSI_GetIPersistStreamInit(); - return (p != NULL) ? p->IsDirty() : E_FAIL; - } - STDMETHOD(InitNew)(IStorage*) - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistStorageImpl::InitNew\n")); - CComPtr p; - p.p = IPSI_GetIPersistStreamInit(); - return (p != NULL) ? p->InitNew() : E_FAIL; - } - STDMETHOD(Load)(IStorage* pStorage) - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistStorageImpl::Load\n")); - if (pStorage == NULL) - return E_INVALIDARG; - CComPtr p; - p.p = IPSI_GetIPersistStreamInit(); - HRESULT hr = E_FAIL; - if (p != NULL) - { - CComPtr spStream; - hr = pStorage->OpenStream(OLESTR("Contents"), NULL, - STGM_DIRECT | STGM_SHARE_EXCLUSIVE, 0, &spStream); - if (SUCCEEDED(hr)) - hr = p->Load(spStream); - } - return hr; - } - STDMETHOD(Save)(IStorage* pStorage, BOOL fSameAsLoad) - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistStorageImpl::Save\n")); - if (pStorage == NULL) - return E_INVALIDARG; - CComPtr p; - p.p = IPSI_GetIPersistStreamInit(); - HRESULT hr = E_FAIL; - if (p != NULL) - { - CComPtr spStream; - static LPCOLESTR vszContents = OLESTR("Contents"); - hr = pStorage->CreateStream(vszContents, - STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, - 0, 0, &spStream); - if (SUCCEEDED(hr)) - hr = p->Save(spStream, fSameAsLoad); - } - return hr; - } - STDMETHOD(SaveCompleted)(IStorage* /* pStorage */) - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistStorageImpl::SaveCompleted\n")); - return S_OK; - } - STDMETHOD(HandsOffStorage)(void) - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistStorageImpl::HandsOffStorage\n")); - return S_OK; - } -private: - IPersistStreamInit* IPSI_GetIPersistStreamInit(); -}; - -template -IPersistStreamInit* IPersistStorageImpl::IPSI_GetIPersistStreamInit() -{ - T* pT = static_cast(this); - IPersistStreamInit* p; - if (FAILED(pT->GetUnknown()->QueryInterface(__uuidof(IPersistStreamInit), (void**)&p))) - pT->_InternalQueryInterface(__uuidof(IPersistStreamInit), (void**)&p); - return p; -} - - -////////////////////////////////////////////////////////////////////////////// -// IPersistPropertyBagImpl -template -class ATL_NO_VTABLE IPersistPropertyBagImpl : public IPersistPropertyBag -{ -public: - // IPersist - STDMETHOD(GetClassID)(CLSID *pClassID) - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistPropertyBagImpl::GetClassID\n")); - if (pClassID == NULL) - return E_POINTER; - *pClassID = T::GetObjectCLSID(); - return S_OK; - } - - // IPersistPropertyBag - // - STDMETHOD(InitNew)() - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistPropertyBagImpl::InitNew\n")); - T* pT = static_cast(this); - pT->m_bRequiresSave = TRUE; - return S_OK; - } - STDMETHOD(Load)(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog) - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistPropertyBagImpl::Load\n")); - T* pT = static_cast(this); - ATL_PROPMAP_ENTRY* pMap = T::GetPropertyMap(); - ATLASSERT(pMap != NULL); - return pT->IPersistPropertyBag_Load(pPropBag, pErrorLog, pMap); - } - STDMETHOD(Save)(LPPROPERTYBAG pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties) - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistPropertyBagImpl::Save\n")); - T* pT = static_cast(this); - ATL_PROPMAP_ENTRY* pMap = T::GetPropertyMap(); - ATLASSERT(pMap != NULL); - return pT->IPersistPropertyBag_Save(pPropBag, fClearDirty, fSaveAllProperties, pMap); - } - HRESULT IPersistPropertyBag_Load(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog, ATL_PROPMAP_ENTRY* pMap) - { - T* pT = static_cast(this); - HRESULT hr = AtlIPersistPropertyBag_Load(pPropBag, pErrorLog, pMap, pT, pT->GetUnknown()); - if (SUCCEEDED(hr)) - pT->m_bRequiresSave = FALSE; - return hr; - } - HRESULT IPersistPropertyBag_Save(LPPROPERTYBAG pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties, ATL_PROPMAP_ENTRY* pMap) - { - T* pT = static_cast(this); - return AtlIPersistPropertyBag_Save(pPropBag, fClearDirty, fSaveAllProperties, pMap, pT, pT->GetUnknown()); - } -}; - -////////////////////////////////////////////////////////////////////////////// -// CSecurityDescriptor -__declspec(deprecated) class CSecurityDescriptor -{ -public: - CSecurityDescriptor(); - ~CSecurityDescriptor(); - -public: - HRESULT Attach(PSECURITY_DESCRIPTOR pSelfRelativeSD); - HRESULT AttachObject(HANDLE hObject); - HRESULT Initialize(); - HRESULT InitializeFromProcessToken(BOOL bDefaulted = FALSE); - HRESULT InitializeFromThreadToken(BOOL bDefaulted = FALSE, BOOL bRevertToProcessToken = TRUE); - HRESULT SetOwner(PSID pOwnerSid, BOOL bDefaulted = FALSE); - HRESULT SetGroup(PSID pGroupSid, BOOL bDefaulted = FALSE); - HRESULT Allow(LPCTSTR pszPrincipal, DWORD dwAccessMask); - HRESULT Deny(LPCTSTR pszPrincipal, DWORD dwAccessMask); - HRESULT Revoke(LPCTSTR pszPrincipal); - HRESULT Allow(PSID pSid, DWORD dwAccessMask); - HRESULT Deny(PSID pSid, DWORD dwAccessMask); - HRESULT Revoke(PSID pSid); - - // utility functions - // Any PSID you get from these functions should be free()ed - static HRESULT SetPrivilege(LPCTSTR Privilege, BOOL bEnable = TRUE, HANDLE hToken = NULL); - static HRESULT GetTokenSids(HANDLE hToken, PSID* ppUserSid, PSID* ppGroupSid); - static HRESULT GetProcessSids(PSID* ppUserSid, PSID* ppGroupSid = NULL); - static HRESULT GetThreadSids(PSID* ppUserSid, PSID* ppGroupSid = NULL, BOOL bOpenAsSelf = FALSE); - static HRESULT CopyACL(PACL pDest, PACL pSrc); - static HRESULT GetCurrentUserSID(PSID *ppSid); - static HRESULT GetPrincipalSID(LPCTSTR pszPrincipal, PSID *ppSid); - static HRESULT AddAccessAllowedACEToACL(PACL *Acl, PSID pSid, DWORD dwAccessMask); - static HRESULT AddAccessDeniedACEToACL(PACL *Acl, PSID pSid, DWORD dwAccessMask); - static HRESULT RemovePrincipalFromACL(PACL Acl, PSID pSid); - static HRESULT CloneSID(PSID *ppSIDDest, PSID pSIDSrc) - { - HRESULT hr = S_OK; - if (ppSIDDest == NULL) - return E_POINTER; - - if (*ppSIDDest != NULL) - return E_INVALIDARG; - *ppSIDDest = NULL; - - if (!IsValidSid(pSIDSrc)) - return E_INVALIDARG; - - DWORD dwSize = GetLengthSid(pSIDSrc); - - *ppSIDDest = (PSID) malloc(dwSize); - if (*ppSIDDest == NULL) - return E_OUTOFMEMORY; - if (!CopySid(dwSize, *ppSIDDest, pSIDSrc)) - { - hr = AtlHresultFromLastError(); - ATLASSERT(FALSE); - free(*ppSIDDest); - *ppSIDDest = NULL; - } - return hr; - } - operator PSECURITY_DESCRIPTOR() - { - return m_pSD; - } - -public: - PSECURITY_DESCRIPTOR m_pSD; - PSID m_pOwner; - PSID m_pGroup; - PACL m_pDACL; - PACL m_pSACL; -}; - -inline CSecurityDescriptor::CSecurityDescriptor() -{ - m_pSD = NULL; - m_pOwner = NULL; - m_pGroup = NULL; - m_pDACL = NULL; - m_pSACL= NULL; -} - -inline CSecurityDescriptor::~CSecurityDescriptor() -{ - delete m_pSD; - free(m_pOwner); - free(m_pGroup); - free(m_pDACL); - free(m_pSACL); -} - -inline HRESULT CSecurityDescriptor::Initialize() -{ - delete m_pSD; - m_pSD = NULL; - - free(m_pOwner); - m_pOwner = NULL; - - free(m_pGroup); - m_pGroup = NULL; - - free(m_pDACL); - m_pDACL = NULL; - - free(m_pSACL); - m_pSACL = NULL; - - ATLTRY(m_pSD = new SECURITY_DESCRIPTOR); - if (m_pSD != NULL) - { - if (InitializeSecurityDescriptor(m_pSD, SECURITY_DESCRIPTOR_REVISION)) - return S_OK; - - HRESULT hr = AtlHresultFromLastError(); - delete m_pSD; - m_pSD = NULL; - ATLASSERT(FALSE); - return hr; - } - - return E_OUTOFMEMORY; -} - -inline HRESULT CSecurityDescriptor::InitializeFromProcessToken(BOOL bDefaulted) -{ - HRESULT hr = Initialize(); - if (SUCCEEDED(hr)) - { - PSID pUserSid = NULL; - PSID pGroupSid = NULL; - hr = GetProcessSids(&pUserSid, &pGroupSid); - if (SUCCEEDED(hr)) - { - hr = SetOwner(pUserSid, bDefaulted); - if (SUCCEEDED(hr)) - { - hr = SetGroup(pGroupSid, bDefaulted); - } - free(pUserSid); - free(pGroupSid); - // If something failed reinitialize the object - if (FAILED(hr)) - Initialize(); - } - } - return hr; -} - -inline HRESULT CSecurityDescriptor::InitializeFromThreadToken(BOOL bDefaulted, BOOL bRevertToProcessToken) -{ - HRESULT hr = Initialize(); - if (SUCCEEDED(hr)) - { - PSID pUserSid = NULL; - PSID pGroupSid = NULL; - - hr = GetThreadSids(&pUserSid, &pGroupSid); - if (HRESULT_CODE(hr) == ERROR_NO_TOKEN && bRevertToProcessToken) - hr = GetProcessSids(&pUserSid, &pGroupSid); - if (SUCCEEDED(hr)) - { - hr = SetOwner(pUserSid, bDefaulted); - if (SUCCEEDED(hr)) - hr = SetGroup(pGroupSid, bDefaulted); - free(pUserSid); - free(pGroupSid); - // If something failed reinitialize the object - if (FAILED(hr)) - Initialize(); - } - } - return hr; -} - -inline HRESULT CSecurityDescriptor::SetOwner(PSID pOwnerSid, BOOL bDefaulted) -{ - ATLASSERT(m_pSD); - HRESULT hr = S_OK; - - // Mark the SD as having no owner - if (SetSecurityDescriptorOwner(m_pSD, NULL, bDefaulted)) - { - free(m_pOwner); - m_pOwner = NULL; - - // If they asked for no owner don't do the copy - if (pOwnerSid == NULL) - return S_OK; - - // Make a copy of the Sid for the return value - hr = CloneSID(&m_pOwner, pOwnerSid); - if (SUCCEEDED(hr)) - { - ATLASSERT(IsValidSid(m_pOwner)); - - if (!SetSecurityDescriptorOwner(m_pSD, m_pOwner, bDefaulted)) - { - hr = AtlHresultFromLastError(); - ATLASSERT(FALSE); - free(m_pOwner); - m_pOwner = NULL; - } - } - } - else - { - hr = AtlHresultFromLastError(); - ATLASSERT(FALSE); - } - - return hr; -} - -inline HRESULT CSecurityDescriptor::SetGroup(PSID pGroupSid, BOOL bDefaulted) -{ - ATLASSERT(m_pSD); - HRESULT hr = S_OK; - - // Mark the SD as having no Group - if (SetSecurityDescriptorGroup(m_pSD, NULL, bDefaulted)) - { - free(m_pGroup); - m_pGroup = NULL; - - // If they asked for no Group don't do the copy - if (pGroupSid == NULL) - return S_OK; - - // Make a copy of the Sid for the return value - hr = CloneSID(&m_pGroup, pGroupSid); - if (SUCCEEDED(hr)) - { - ATLASSERT(IsValidSid(m_pGroup)); - - if (!SetSecurityDescriptorGroup(m_pSD, m_pGroup, bDefaulted)) - { - hr = AtlHresultFromLastError(); - ATLASSERT(FALSE); - free(m_pGroup); - m_pGroup = NULL; - } - } - } - else - { - hr = AtlHresultFromLastError(); - ATLASSERT(FALSE); - } - - return hr; -} - -inline HRESULT CSecurityDescriptor::Allow(LPCTSTR pszPrincipal, DWORD dwAccessMask) -{ - PSID pSid; - HRESULT hr = GetPrincipalSID(pszPrincipal, &pSid); - if (SUCCEEDED(hr)) - { - hr = Allow(pSid, dwAccessMask); - free(pSid); - } - return hr; -} - -inline HRESULT CSecurityDescriptor::Deny(LPCTSTR pszPrincipal, DWORD dwAccessMask) -{ - PSID pSid; - HRESULT hr = GetPrincipalSID(pszPrincipal, &pSid); - if (SUCCEEDED(hr)) - { - hr = Deny(pSid, dwAccessMask); - free(pSid); - } - return hr; -} - -inline HRESULT CSecurityDescriptor::Revoke(LPCTSTR pszPrincipal) -{ - PSID pSid; - HRESULT hr = GetPrincipalSID(pszPrincipal, &pSid); - if (SUCCEEDED(hr)) - { - hr = Revoke(pSid); - free(pSid); - } - return hr; -} - -inline HRESULT CSecurityDescriptor::Allow(PSID pSid, DWORD dwAccessMask) -{ - HRESULT hr = AddAccessAllowedACEToACL(&m_pDACL, pSid, dwAccessMask); - if (SUCCEEDED(hr)) - { - if (!SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE)) - hr = AtlHresultFromLastError(); - } - return hr; -} - -inline HRESULT CSecurityDescriptor::Deny(PSID pSid, DWORD dwAccessMask) -{ - HRESULT hr = AddAccessDeniedACEToACL(&m_pDACL, pSid, dwAccessMask); - if (SUCCEEDED(hr)) - { - if (!SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE)) - hr = AtlHresultFromLastError(); - } - return hr; -} - -inline HRESULT CSecurityDescriptor::Revoke(PSID pSid) -{ - HRESULT hr = RemovePrincipalFromACL(m_pDACL, pSid); - if (SUCCEEDED(hr)) - { - if (!SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE)) - hr = AtlHresultFromLastError(); - } - return hr; -} - -inline HRESULT CSecurityDescriptor::GetProcessSids(PSID* ppUserSid, PSID* ppGroupSid) -{ - HRESULT hr = S_OK; - HANDLE hToken = NULL; - if (ppUserSid) - *ppUserSid = NULL; - if (ppGroupSid) - *ppGroupSid = NULL; - if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) - { - hr = GetTokenSids(hToken, ppUserSid, ppGroupSid); - CloseHandle(hToken); - } - else - { - // Couldn't open process token - hr = AtlHresultFromLastError(); - ATLASSERT(FALSE); - } - - return hr; -} - -inline HRESULT CSecurityDescriptor::GetThreadSids(PSID* ppUserSid, PSID* ppGroupSid, BOOL bOpenAsSelf) -{ - HRESULT hr = S_OK; - HANDLE hToken = NULL; - if (ppUserSid) - *ppUserSid = NULL; - if (ppGroupSid) - *ppGroupSid = NULL; - if(OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, bOpenAsSelf, &hToken)) - { - hr = GetTokenSids(hToken, ppUserSid, ppGroupSid); - CloseHandle(hToken); - } - else - // Couldn't open thread token - hr = AtlHresultFromLastError(); - - return hr; -} - -inline HRESULT CSecurityDescriptor::GetTokenSids(HANDLE hToken, PSID* ppUserSid, PSID* ppGroupSid) -{ - DWORD dwSize = 0; - HRESULT hr = S_OK; - if (ppUserSid != NULL) - *ppUserSid = NULL; - if (ppGroupSid != NULL) - *ppGroupSid = NULL; - - if (ppUserSid != NULL) - { - PTOKEN_USER ptkUser = NULL; - - // Get length required for TokenUser by specifying buffer length of 0 - GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize); - // Expected ERROR_INSUFFICIENT_BUFFER - DWORD dwError = GetLastError(); - if (dwError == ERROR_INSUFFICIENT_BUFFER) - { - ptkUser = (TOKEN_USER*) malloc(dwSize); - if (ptkUser != NULL) - { - // Get Sid of process token. - if (GetTokenInformation(hToken, TokenUser, ptkUser, dwSize, &dwSize)) - { - // Make a copy of the Sid for the return value - hr = CloneSID(ppUserSid, ptkUser->User.Sid); - -#ifdef _DEBUG - if (SUCCEEDED(hr)) - { - ATLASSERT(IsValidSid(*ppUserSid)); - } -#endif - } - else - // Couldn't get user info - hr = AtlHresultFromLastError(); - - free(ptkUser); - ptkUser = NULL; - } - else - hr = E_OUTOFMEMORY; - } - else - { - ATLASSERT(FALSE); - hr = AtlHresultFromWin32(dwError); - } - } - if (SUCCEEDED(hr) && ppGroupSid != NULL) - { - PTOKEN_PRIMARY_GROUP ptkGroup = NULL; - - // Get length required for TokenPrimaryGroup by specifying buffer length of 0 - GetTokenInformation(hToken, TokenPrimaryGroup, NULL, 0, &dwSize); - DWORD dwError = GetLastError(); - // Expected ERROR_INSUFFICIENT_BUFFER - if (dwError == ERROR_INSUFFICIENT_BUFFER) - { - ptkGroup = (TOKEN_PRIMARY_GROUP*) malloc(dwSize); - if (ptkGroup != NULL) - { - // Get Sid of process token. - if (GetTokenInformation(hToken, TokenPrimaryGroup, ptkGroup, dwSize, &dwSize)) - { - // Make a copy of the Sid for the return value - hr = CloneSID(ppGroupSid, ptkGroup->PrimaryGroup); - -#ifdef _DEBUG - if (SUCCEEDED(hr)) - { - ATLASSERT(IsValidSid(*ppGroupSid)); - } -#endif - } - else - // Couldn't get user info - hr = AtlHresultFromLastError(); - - free(ptkGroup); - ptkGroup = NULL; - } - else - hr = E_OUTOFMEMORY; - } - else - hr = AtlHresultFromWin32(dwError); - } - if (FAILED(hr)) - { - if (ppUserSid != NULL) - { - free (*ppUserSid); - *ppUserSid = NULL; - } - if (ppGroupSid != NULL) - { - free (*ppGroupSid); - *ppGroupSid = NULL; - } - } - - return hr; -} - - -inline HRESULT CSecurityDescriptor::GetCurrentUserSID(PSID *ppSid) -{ - if (ppSid == NULL) - return E_POINTER; - *ppSid = NULL; - - HANDLE tkHandle; - HRESULT hr = S_OK; - - if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &tkHandle)) - { - TOKEN_USER *tkUser = NULL; - DWORD tkSize; - - // Get length required for TokenPrimaryGroup by specifying buffer length of 0 - GetTokenInformation(tkHandle, TokenUser, NULL, 0, &tkSize); - DWORD dwError = GetLastError(); - // Expected ERROR_INSUFFICIENT_BUFFER - if (dwError == ERROR_INSUFFICIENT_BUFFER) - { - tkUser = (TOKEN_USER *) malloc(tkSize); - if (tkUser != NULL) - { - // Now make the real call - if (GetTokenInformation(tkHandle, TokenUser, tkUser, tkSize, &tkSize)) - { - hr = CloneSID(ppSid, tkUser->User.Sid); - -#ifdef _DEBUG - if (SUCCEEDED(hr)) - { - ATLASSERT(IsValidSid(*ppSid)); - } -#endif - } - else - hr = AtlHresultFromLastError(); - - free (tkUser); - tkUser = NULL; - } - else - hr = E_OUTOFMEMORY; - } - else - { - hr = AtlHresultFromWin32(dwError); - ATLASSERT(FALSE); - } - CloseHandle(tkHandle); - } - else - hr = AtlHresultFromLastError(); - - return hr; -} - - -inline HRESULT CSecurityDescriptor::GetPrincipalSID(LPCTSTR pszPrincipal, PSID *ppSid) -{ - if (ppSid == NULL) - return E_POINTER; - if (pszPrincipal == NULL) - return E_INVALIDARG; - *ppSid = NULL; - - HRESULT hr; - LPTSTR pszRefDomain = NULL; - DWORD dwDomainSize = 0; - DWORD dwSidSize = 0; - SID_NAME_USE snu; - DWORD dwError; - - // Call to get size info for alloc - LookupAccountName(NULL, pszPrincipal, NULL, &dwSidSize, NULL, &dwDomainSize, &snu); - - dwError = GetLastError(); - if (dwError == ERROR_INSUFFICIENT_BUFFER) - { - ATLTRY(pszRefDomain = new TCHAR[dwDomainSize]); - if (pszRefDomain != NULL) - { - *ppSid = (PSID) malloc(dwSidSize); - if (*ppSid != NULL) - { - if (LookupAccountName(NULL, pszPrincipal, *ppSid, &dwSidSize, pszRefDomain, &dwDomainSize, &snu)) - { - hr = S_OK; - } - else - { - hr = AtlHresultFromLastError(); - free(*ppSid); - *ppSid = NULL; - } - } - else - hr = E_OUTOFMEMORY; - delete[] pszRefDomain; - } - else - hr = E_OUTOFMEMORY; - } - else - hr = AtlHresultFromWin32(dwError); - - return hr; -} - -inline HRESULT CSecurityDescriptor::Attach(PSECURITY_DESCRIPTOR pSelfRelativeSD) -{ - PACL pDACL = NULL; - PACL pSACL = NULL; - BOOL bDACLPresent, bSACLPresent; - BOOL bDefaulted; - HRESULT hr; - PSID pUserSid; - PSID pGroupSid; - - if (pSelfRelativeSD == NULL || !IsValidSecurityDescriptor(pSelfRelativeSD)) - return E_INVALIDARG; - - hr = Initialize(); - if(FAILED(hr)) - return hr; - - // get the existing DACL. - if (GetSecurityDescriptorDacl(pSelfRelativeSD, &bDACLPresent, &pDACL, &bDefaulted)) - { - if (bDACLPresent) - { - // pDACL should be valid if bDACLPresent is true - ATLASSERT(pDACL != NULL); - // allocate new DACL. - m_pDACL = (PACL) malloc(pDACL->AclSize); - if (m_pDACL != NULL) - { - // initialize the DACL - if (InitializeAcl(m_pDACL, pDACL->AclSize, ACL_REVISION)) - { - // copy the ACL - hr = CopyACL(m_pDACL, pDACL); - if (SUCCEEDED(hr) && !IsValidAcl(m_pDACL)) - hr = E_FAIL; - } - else - hr = AtlHresultFromLastError(); - } - else - hr = E_OUTOFMEMORY; - } - // set the DACL - if (SUCCEEDED(hr) && !SetSecurityDescriptorDacl(m_pSD, bDACLPresent, m_pDACL, bDefaulted)) - hr = AtlHresultFromLastError(); - } - else - hr = AtlHresultFromLastError(); - - // get the existing SACL. - if (SUCCEEDED(hr) && GetSecurityDescriptorSacl(pSelfRelativeSD, &bSACLPresent, &pSACL, &bDefaulted)) - { - if (bSACLPresent) - { - // pSACL should be valid if bSACLPresent is true - ATLASSERT(pSACL != NULL); - // allocate new SACL. - m_pSACL = (PACL) malloc(pSACL->AclSize); - if (m_pSACL != NULL) - { - // initialize the SACL - if (InitializeAcl(m_pSACL, pSACL->AclSize, ACL_REVISION)) - { - // copy the ACL - hr = CopyACL(m_pSACL, pSACL); - if (SUCCEEDED(hr) && !IsValidAcl(m_pSACL)) - hr = E_FAIL; - } - else - hr = AtlHresultFromLastError(); - } - else - hr = E_OUTOFMEMORY; - } - // set the SACL - if (SUCCEEDED(hr) && !SetSecurityDescriptorSacl(m_pSD, bSACLPresent, m_pSACL, bDefaulted)) - hr = AtlHresultFromLastError(); - } - else if (SUCCEEDED(hr)) - hr = AtlHresultFromLastError(); - - if (SUCCEEDED(hr)) - { - if (GetSecurityDescriptorOwner(pSelfRelativeSD, &pUserSid, &bDefaulted)) - { - if (SUCCEEDED(hr = SetOwner(pUserSid, bDefaulted))) - { - if (GetSecurityDescriptorGroup(pSelfRelativeSD, &pGroupSid, &bDefaulted)) - { - if (SUCCEEDED(hr = SetGroup(pGroupSid, bDefaulted))) - { - if (!IsValidSecurityDescriptor(m_pSD)) - hr = E_FAIL; - } - } - else - hr = AtlHresultFromLastError(); - } - } - else - hr = AtlHresultFromLastError(); - } - - if (FAILED(hr)) - { - free(m_pDACL); - m_pDACL = NULL; - - free(m_pSACL); - m_pSACL = NULL; - - free(m_pSD); - m_pSD = NULL; - } - - return hr; -} - -inline HRESULT CSecurityDescriptor::AttachObject(HANDLE hObject) -{ - HRESULT hr; - DWORD dwError; - DWORD dwSize = 0; - PSECURITY_DESCRIPTOR pSD = NULL; - - GetKernelObjectSecurity(hObject, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | - DACL_SECURITY_INFORMATION, NULL, 0, &dwSize); - - dwError = GetLastError(); - if (dwError != ERROR_INSUFFICIENT_BUFFER) - return AtlHresultFromWin32(dwError); - - pSD = (PSECURITY_DESCRIPTOR) malloc(dwSize); - if (pSD != NULL) - { - if (GetKernelObjectSecurity(hObject, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | - DACL_SECURITY_INFORMATION, pSD, dwSize, &dwSize)) - - hr = Attach(pSD); - else - hr = AtlHresultFromLastError(); - free(pSD); - } - else - hr = E_OUTOFMEMORY; - - return hr; -} - - -inline HRESULT CSecurityDescriptor::CopyACL(PACL pDest, PACL pSrc) -{ - ACL_SIZE_INFORMATION aclSizeInfo; - LPVOID pAce; - ACE_HEADER *aceHeader; - - if (pDest == NULL) - return E_POINTER; - - if (pSrc == NULL) - return S_OK; - - if (!GetAclInformation(pSrc, (LPVOID) &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) - return AtlHresultFromLastError(); - - // Copy all of the ACEs to the new ACL - for (UINT i = 0; i < aclSizeInfo.AceCount; i++) - { - if (!GetAce(pSrc, i, &pAce)) - return AtlHresultFromLastError(); - - aceHeader = (ACE_HEADER *) pAce; - - if (!AddAce(pDest, ACL_REVISION, 0xffffffff, pAce, aceHeader->AceSize)) - return AtlHresultFromLastError(); - } - - return S_OK; -} - -inline HRESULT CSecurityDescriptor::AddAccessDeniedACEToACL(PACL *ppAcl, PSID pSid, DWORD dwAccessMask) -{ - ACL_SIZE_INFORMATION aclSizeInfo; - int aclSize; - PACL oldACL, newACL = NULL; - HRESULT hr = S_OK; - - if (ppAcl == NULL) - return E_POINTER; - - oldACL = *ppAcl; - - if (pSid == NULL || !IsValidSid(pSid)) - return E_INVALIDARG; - - aclSizeInfo.AclBytesInUse = 0; - if (*ppAcl != NULL && !GetAclInformation(oldACL, (LPVOID) &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) - hr = AtlHresultFromLastError(); - - if (SUCCEEDED(hr)) - { - aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_DENIED_ACE) + GetLengthSid(pSid) - sizeof(DWORD); - newACL = (PACL) malloc(aclSize); - if (newACL != NULL) - { - if (InitializeAcl(newACL, aclSize, ACL_REVISION)) - { - // access denied ACEs should be before access allowed ACEs - if (AddAccessDeniedAce(newACL, ACL_REVISION2, dwAccessMask, pSid)) - { - // Copy existing ACEs to the new ACL - hr = CopyACL(newACL, oldACL); - if (SUCCEEDED(hr)) - { - *ppAcl = newACL; - free(oldACL); - } - } - else - hr = AtlHresultFromLastError(); - } - else - hr = AtlHresultFromLastError(); - - if (FAILED(hr)) - free(newACL); - } - else - hr = E_OUTOFMEMORY; - } - return hr; -} - - -inline HRESULT CSecurityDescriptor::AddAccessAllowedACEToACL(PACL *ppAcl, PSID pSid, DWORD dwAccessMask) -{ - ACL_SIZE_INFORMATION aclSizeInfo; - int aclSize; - HRESULT hr = S_OK; - PACL oldACL, newACL = NULL; - - if (ppAcl == NULL) - return E_POINTER; - - oldACL = *ppAcl; - - if (pSid == NULL || !IsValidSid(pSid)) - return E_INVALIDARG; - - aclSizeInfo.AclBytesInUse = 0; - if (*ppAcl != NULL && !GetAclInformation(oldACL, (LPVOID) &aclSizeInfo, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) - hr = AtlHresultFromLastError(); - - if (SUCCEEDED(hr)) - { - aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pSid) - sizeof(DWORD); - newACL = (PACL) malloc(aclSize); - if (newACL != NULL) - { - if (InitializeAcl(newACL, aclSize, ACL_REVISION)) - { - // Copy existing ACEs - hr = CopyACL(newACL, oldACL); - if (SUCCEEDED(hr)) - { - // Add access Allowed ACEs after all other existing ACEs (possibly access denied ACEs) - if (AddAccessAllowedAce(newACL, ACL_REVISION2, dwAccessMask, pSid)) - { - *ppAcl = newACL; - free(oldACL); - } - else - hr = AtlHresultFromLastError(); - } - } - else - hr = AtlHresultFromLastError(); - - if (FAILED(hr)) - free(newACL); - } - else - hr = E_OUTOFMEMORY; - } - return hr; -} - -inline HRESULT CSecurityDescriptor::RemovePrincipalFromACL(PACL pAcl, PSID principalSID) -{ - if (pAcl == NULL || principalSID == NULL || !IsValidSid(principalSID)) - return E_INVALIDARG; - - HRESULT hr = S_OK; - ACL_SIZE_INFORMATION aclSizeInfo; - if (!GetAclInformation(pAcl, (LPVOID) &aclSizeInfo, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) - { - hr = AtlHresultFromLastError(); - aclSizeInfo.AceCount = 0; - } - - for (ULONG i = aclSizeInfo.AceCount; i > 0; i--) - { - ULONG uIndex = i - 1; - LPVOID ace; - if (!GetAce(pAcl, uIndex, &ace)) - { - hr = AtlHresultFromLastError(); - break; - } - - ACE_HEADER *aceHeader = (ACE_HEADER *) ace; - - if (aceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE) - { - ACCESS_ALLOWED_ACE *accessAllowedAce = (ACCESS_ALLOWED_ACE *) ace; - if (EqualSid(principalSID, (PSID) &accessAllowedAce->SidStart)) - { - DeleteAce(pAcl, uIndex); - } - } - else if (aceHeader->AceType == ACCESS_DENIED_ACE_TYPE) - { - ACCESS_DENIED_ACE *accessDeniedAce = (ACCESS_DENIED_ACE *) ace; - if (EqualSid(principalSID, (PSID) &accessDeniedAce->SidStart)) - { - DeleteAce(pAcl, uIndex); - } - } - else if (aceHeader->AceType == SYSTEM_AUDIT_ACE_TYPE) - { - SYSTEM_AUDIT_ACE *systemAuditAce = (SYSTEM_AUDIT_ACE *) ace; - if (EqualSid(principalSID, (PSID) &systemAuditAce->SidStart)) - { - DeleteAce(pAcl, uIndex); - } - } - } - return hr; -} - -inline HRESULT CSecurityDescriptor::SetPrivilege(LPCTSTR privilege, BOOL bEnable, HANDLE hToken) -{ - TOKEN_PRIVILEGES tpPrevious; - TOKEN_PRIVILEGES tp; - DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES); - LUID luid; - HANDLE hTokenUsed; - - if (!LookupPrivilegeValue(NULL, privilege, &luid )) - goto _Error; - - // if no token specified open process token - if (hToken != 0) - hTokenUsed = hToken; - else - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hTokenUsed)) - goto _Error; - - tp.PrivilegeCount = 1; - tp.Privileges[0].Luid = luid; - tp.Privileges[0].Attributes = 0; - - if (!AdjustTokenPrivileges(hTokenUsed, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &tpPrevious, &cbPrevious)) - goto _Error_CloseHandle; - - tpPrevious.PrivilegeCount = 1; - tpPrevious.Privileges[0].Luid = luid; - - if (bEnable) - tpPrevious.Privileges[0].Attributes |= SE_PRIVILEGE_ENABLED; - else - tpPrevious.Privileges[0].Attributes &= ~SE_PRIVILEGE_ENABLED; - - if (!AdjustTokenPrivileges(hTokenUsed, FALSE, &tpPrevious, cbPrevious, NULL, NULL)) - goto _Error_CloseHandle; - - if(hToken == 0) - CloseHandle(hTokenUsed); - - return S_OK; - - HRESULT hr; - -_Error: - hr = AtlHresultFromLastError(); - return hr; - -_Error_CloseHandle: - hr = AtlHresultFromLastError(); - if (hToken == 0) - CloseHandle(hTokenUsed); - return hr; -} - -///////////////////////////////////////////////////////////////////////////// -// COM Objects - -#define DECLARE_PROTECT_FINAL_CONSTRUCT()\ - void InternalFinalConstructAddRef() {InternalAddRef();}\ - void InternalFinalConstructRelease() {InternalRelease();} - -template -class CComCreator -{ -public: - static HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv) - { - ATLASSERT(ppv != NULL); - if (ppv == NULL) - return E_POINTER; - *ppv = NULL; - - HRESULT hRes = E_OUTOFMEMORY; - T1* p = NULL; - ATLTRY(p = new T1(pv)) - if (p != NULL) - { - p->SetVoid(pv); - p->InternalFinalConstructAddRef(); - hRes = p->FinalConstruct(); - if (SUCCEEDED(hRes)) - hRes = p->_AtlFinalConstruct(); - p->InternalFinalConstructRelease(); - if (hRes == S_OK) - hRes = p->QueryInterface(riid, ppv); - if (hRes != S_OK) - delete p; - } - return hRes; - } -}; - -template -class CComInternalCreator -{ -public: - static HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv) - { - ATLASSERT(ppv != NULL); - if (ppv == NULL) - return E_POINTER; - *ppv = NULL; - - HRESULT hRes = E_OUTOFMEMORY; - T1* p = NULL; - ATLTRY(p = new T1(pv)) - if (p != NULL) - { - p->SetVoid(pv); - p->InternalFinalConstructAddRef(); - hRes = p->FinalConstruct(); - if (SUCCEEDED(hRes)) - hRes = p->_AtlFinalConstruct(); - p->InternalFinalConstructRelease(); - if (hRes == S_OK) - hRes = p->_InternalQueryInterface(riid, ppv); - if (hRes != S_OK) - delete p; - } - return hRes; - } -}; - -template -class CComFailCreator -{ -public: - static HRESULT WINAPI CreateInstance(void*, REFIID, LPVOID* ppv) - { - if (ppv == NULL) - return E_POINTER; - *ppv = NULL; - - return hr; - } -}; - -template -class CComCreator2 -{ -public: - static HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv) - { - ATLASSERT(ppv != NULL); - - return (pv == NULL) ? - T1::CreateInstance(NULL, riid, ppv) : - T2::CreateInstance(pv, riid, ppv); - } -}; - -#define DECLARE_NOT_AGGREGATABLE(x) public:\ - typedef ATL::CComCreator2< ATL::CComCreator< ATL::CComObject< x > >, ATL::CComFailCreator > _CreatorClass; -#define DECLARE_AGGREGATABLE(x) public:\ - typedef ATL::CComCreator2< ATL::CComCreator< ATL::CComObject< x > >, ATL::CComCreator< ATL::CComAggObject< x > > > _CreatorClass; -#define DECLARE_ONLY_AGGREGATABLE(x) public:\ - typedef ATL::CComCreator2< ATL::CComFailCreator, ATL::CComCreator< ATL::CComAggObject< x > > > _CreatorClass; -#define DECLARE_POLY_AGGREGATABLE(x) public:\ - typedef ATL::CComCreator< ATL::CComPolyObject< x > > _CreatorClass; - -struct _ATL_CREATORDATA -{ - _ATL_CREATORFUNC* pFunc; -}; - -template -class _CComCreatorData -{ -public: - static _ATL_CREATORDATA data; -}; - -template -_ATL_CREATORDATA _CComCreatorData::data = {Creator::CreateInstance}; - -struct _ATL_CACHEDATA -{ - DWORD dwOffsetVar; - _ATL_CREATORFUNC* pFunc; -}; - -template -class _CComCacheData -{ -public: - static _ATL_CACHEDATA data; -}; - -template -_ATL_CACHEDATA _CComCacheData::data = {dwVar, Creator::CreateInstance}; - -struct _ATL_CHAINDATA -{ - DWORD_PTR dwOffset; - const _ATL_INTMAP_ENTRY* (WINAPI *pFunc)(); -}; - -template -class _CComChainData -{ -public: - static _ATL_CHAINDATA data; -}; - -template -_ATL_CHAINDATA _CComChainData::data = - {offsetofclass(base, derived), base::_GetEntries}; - -template -class CComAggregateCreator -{ -public: - static HRESULT WINAPI CreateInstance(void* pv, REFIID/*riid*/, LPVOID* ppv) throw() - { - // Only Assert here. CoCreateInstance will return the correct HRESULT if ppv == NULL - ATLASSERT(ppv != NULL && *ppv == NULL); - - ATLASSERT(pv != NULL); - if (pv == NULL) - return E_INVALIDARG; - - T* p = (T*) pv; - // Add the following line to your object if you get a message about - // GetControllingUnknown() being undefined - // DECLARE_GET_CONTROLLING_UNKNOWN() - return CoCreateInstance(*pclsid, p->GetControllingUnknown(), CLSCTX_INPROC, __uuidof(IUnknown), ppv); - } -}; - -#ifdef _ATL_DEBUG -#define DEBUG_QI_ENTRY(x) \ - {NULL, \ - (DWORD_PTR)_T(#x), \ - (ATL::_ATL_CREATORARGFUNC*)0}, -#else -#define DEBUG_QI_ENTRY(x) -#endif //_ATL_DEBUG - -#ifdef _ATL_DEBUG_INTERFACES -#define _ATL_DECLARE_GET_UNKNOWN(x)\ - IUnknown* GetUnknown() throw() \ - { \ - IUnknown* p; \ - _AtlDebugInterfacesModule.AddNonAddRefThunk(_GetRawUnknown(), _T(#x), &p); \ - return p; \ - } -#else -#define _ATL_DECLARE_GET_UNKNOWN(x) IUnknown* GetUnknown() throw() {return _GetRawUnknown();} -#endif - -//If you get a message that FinalConstruct is ambiguous then you need to -// override it in your class and call each base class' version of this -#define BEGIN_COM_MAP(x) public: \ - typedef x _ComMapClass; \ - static HRESULT WINAPI _Cache(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw) throw()\ - {\ - _ComMapClass* p = (_ComMapClass*)pv;\ - p->Lock();\ - HRESULT hRes = E_FAIL; \ - __try \ - { \ - hRes = CComObjectRootBase::_Cache(pv, iid, ppvObject, dw);\ - } \ - __finally \ - { \ - p->Unlock();\ - } \ - return hRes;\ - }\ - IUnknown* _GetRawUnknown() throw() \ - { ATLASSERT(_GetEntries()[0].pFunc == _ATL_SIMPLEMAPENTRY); return (IUnknown*)((INT_PTR)this+_GetEntries()->dw); } \ - _ATL_DECLARE_GET_UNKNOWN(x)\ - HRESULT _InternalQueryInterface(REFIID iid, void** ppvObject) throw() \ - { return InternalQueryInterface(this, _GetEntries(), iid, ppvObject); } \ - const static ATL::_ATL_INTMAP_ENTRY* WINAPI _GetEntries() throw() { \ - static const ATL::_ATL_INTMAP_ENTRY _entries[] = { DEBUG_QI_ENTRY(x) - -// For use by attributes for chaining to existing COM_MAP -#define BEGIN_ATTRCOM_MAP(x) public: \ - typedef x _AttrComMapClass; \ - const static ATL::_ATL_INTMAP_ENTRY* WINAPI _GetAttrEntries() throw() { \ - static const ATL::_ATL_INTMAP_ENTRY _entries[] = { - -#define DECLARE_GET_CONTROLLING_UNKNOWN() public:\ - virtual IUnknown* GetControllingUnknown() throw() {return GetUnknown();} - -#define COM_INTERFACE_ENTRY_BREAK(x)\ - {&_ATL_IIDOF(x), \ - NULL, \ - _Break}, - -#define COM_INTERFACE_ENTRY_NOINTERFACE(x)\ - {&_ATL_IIDOF(x), \ - NULL, \ - _NoInterface}, - -#define COM_INTERFACE_ENTRY(x)\ - {&_ATL_IIDOF(x), \ - offsetofclass(x, _ComMapClass), \ - _ATL_SIMPLEMAPENTRY}, - -#define COM_INTERFACE_ENTRY_IID(iid, x)\ - {&iid,\ - offsetofclass(x, _ComMapClass),\ - _ATL_SIMPLEMAPENTRY}, - -// The impl macros are now obsolete -#define COM_INTERFACE_ENTRY_IMPL(x)\ - COM_INTERFACE_ENTRY_IID(_ATL_IIDOF(x), x##Impl<_ComMapClass>) - -#define COM_INTERFACE_ENTRY_IMPL_IID(iid, x)\ - COM_INTERFACE_ENTRY_IID(iid, x##Impl<_ComMapClass>) -// - -#define COM_INTERFACE_ENTRY2(x, x2)\ - {&_ATL_IIDOF(x),\ - reinterpret_cast(static_cast(static_cast(reinterpret_cast<_ComMapClass*>(8))))-8,\ - _ATL_SIMPLEMAPENTRY}, - -#define COM_INTERFACE_ENTRY2_IID(iid, x, x2)\ - {&iid,\ - reinterpret_cast(static_cast(static_cast(reinterpret_cast<_ComMapClass*>(8))))-8,\ - _ATL_SIMPLEMAPENTRY}, - -#define COM_INTERFACE_ENTRY_FUNC(iid, dw, func)\ - {&iid, \ - dw, \ - func}, - -#define COM_INTERFACE_ENTRY_FUNC_BLIND(dw, func)\ - {NULL, \ - dw, \ - func}, - -#define COM_INTERFACE_ENTRY_TEAR_OFF(iid, x)\ - {&iid,\ - (DWORD_PTR)&ATL::_CComCreatorData<\ - ATL::CComInternalCreator< ATL::CComTearOffObject< x > >\ - >::data,\ - _Creator}, - -#define COM_INTERFACE_ENTRY_CACHED_TEAR_OFF(iid, x, punk)\ - {&iid,\ - (DWORD_PTR)&ATL::_CComCacheData<\ - ATL::CComCreator< ATL::CComCachedTearOffObject< x > >,\ - (DWORD_PTR)offsetof(_ComMapClass, punk)\ - >::data,\ - _Cache}, - -#define COM_INTERFACE_ENTRY_AGGREGATE(iid, punk)\ - {&iid,\ - (DWORD_PTR)offsetof(_ComMapClass, punk),\ - _Delegate}, - -#define COM_INTERFACE_ENTRY_AGGREGATE_BLIND(punk)\ - {NULL,\ - (DWORD_PTR)offsetof(_ComMapClass, punk),\ - _Delegate}, - -#define COM_INTERFACE_ENTRY_AUTOAGGREGATE(iid, punk, clsid)\ - {&iid,\ - (DWORD_PTR)&ATL::_CComCacheData<\ - ATL::CComAggregateCreator<_ComMapClass, &clsid>,\ - (DWORD_PTR)offsetof(_ComMapClass, punk)\ - >::data,\ - _Cache}, - -#define COM_INTERFACE_ENTRY_AUTOAGGREGATE_BLIND(punk, clsid)\ - {NULL,\ - (DWORD_PTR)&ATL::_CComCacheData<\ - ATL::CComAggregateCreator<_ComMapClass, &clsid>,\ - (DWORD_PTR)offsetof(_ComMapClass, punk)\ - >::data,\ - _Cache}, - -#define COM_INTERFACE_ENTRY_CHAIN(classname)\ - {NULL,\ - (DWORD_PTR)&ATL::_CComChainData::data,\ - _Chain}, - -#ifdef _ATL_DEBUG -#define END_COM_MAP() \ - __if_exists(_GetAttrEntries) {{NULL, (DWORD_PTR)_GetAttrEntries, _ChainAttr }, }\ - {NULL, 0, 0}}; return &_entries[1];} \ - virtual ULONG STDMETHODCALLTYPE AddRef( void) throw() = 0; \ - virtual ULONG STDMETHODCALLTYPE Release( void) throw() = 0; \ - STDMETHOD(QueryInterface)(REFIID, void**) throw() = 0; -#else -#define END_COM_MAP() \ - __if_exists(_GetAttrEntries) {{NULL, (DWORD_PTR)_GetAttrEntries, _ChainAttr }, }\ - {NULL, 0, 0}}; return _entries;} \ - virtual ULONG STDMETHODCALLTYPE AddRef( void) throw() = 0; \ - virtual ULONG STDMETHODCALLTYPE Release( void) throw() = 0; \ - STDMETHOD(QueryInterface)(REFIID, void**) throw() = 0; -#endif // _ATL_DEBUG - -#define END_ATTRCOM_MAP() \ - {NULL, 0, 0}}; return _entries;} - - -#define BEGIN_CATEGORY_MAP(x)\ - static const struct ATL::_ATL_CATMAP_ENTRY* GetCategoryMap() throw() {\ - static const struct ATL::_ATL_CATMAP_ENTRY pMap[] = { -#define IMPLEMENTED_CATEGORY( catid ) { _ATL_CATMAP_ENTRY_IMPLEMENTED, &catid }, -#define REQUIRED_CATEGORY( catid ) { _ATL_CATMAP_ENTRY_REQUIRED, &catid }, -#define END_CATEGORY_MAP()\ - { _ATL_CATMAP_ENTRY_END, NULL } };\ - return( pMap ); } - -#define BEGIN_OBJECT_MAP(x) static ATL::_ATL_OBJMAP_ENTRY x[] = { -#define END_OBJECT_MAP() {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}}; -#define OBJECT_ENTRY(clsid, class) {&clsid, class::UpdateRegistry, class::_ClassFactoryCreatorClass::CreateInstance, class::_CreatorClass::CreateInstance, NULL, 0, class::GetObjectDescription, class::GetCategoryMap, class::ObjectMain }, -#define OBJECT_ENTRY_NON_CREATEABLE(class) {&CLSID_NULL, class::UpdateRegistry, NULL, NULL, NULL, 0, NULL, class::GetCategoryMap, class::ObjectMain }, -#define OBJECT_ENTRY_NON_CREATEABLE_EX(clsid, class) {&clsid, class::UpdateRegistry, NULL, NULL, NULL, 0, NULL, class::GetCategoryMap, class::ObjectMain }, - -#ifndef OBJECT_ENTRY_PRAGMA - -#if defined(_M_IX86) -#define OBJECT_ENTRY_PRAGMA(class) __pragma(comment(linker, "/include:___pobjMap_" #class)); -#elif defined(_M_IA64) -#define OBJECT_ENTRY_PRAGMA(class) __pragma(comment(linker, "/include:__pobjMap_" #class)); -#else -#error Unknown Platform. define OBJECT_ENTRY_PRAGMA -#endif - -#endif //OBJECT_ENTRY_PRAGMA - -#define OBJECT_ENTRY_AUTO(clsid, class) \ - __declspec(selectany) ATL::_ATL_OBJMAP_ENTRY __objMap_##class = {&clsid, class::UpdateRegistry, class::_ClassFactoryCreatorClass::CreateInstance, class::_CreatorClass::CreateInstance, NULL, 0, class::GetObjectDescription, class::GetCategoryMap, class::ObjectMain }; \ - extern "C" __declspec(allocate("ATL$__m")) __declspec(selectany) ATL::_ATL_OBJMAP_ENTRY* const __pobjMap_##class = &__objMap_##class; \ - OBJECT_ENTRY_PRAGMA(class) - - -#define OBJECT_ENTRY_NON_CREATEABLE_EX_AUTO(clsid, class) \ - __declspec(selectany) ATL::_ATL_OBJMAP_ENTRY __objMap_##class = {&clsid, class::UpdateRegistry, NULL, NULL, NULL, 0, NULL, class::GetCategoryMap, class::ObjectMain }; \ - extern "C" __declspec(allocate("ATL$__m")) __declspec(selectany) ATL::_ATL_OBJMAP_ENTRY* const __pobjMap_##class = &__objMap_##class; \ - OBJECT_ENTRY_PRAGMA(class) - -// the functions in this class don't need to be virtual because -// they are called from CComObject -class CComObjectRootBase -{ -public: - CComObjectRootBase() - { - m_dwRef = 0L; - } - HRESULT FinalConstruct() - { - return S_OK; - } - // For library initialization only - HRESULT _AtlFinalConstruct() - { - return S_OK; - } - void FinalRelease() {} - void _AtlFinalRelease() {} // temp - - void _HRPass(HRESULT hr) // temp - { - (hr); - } - - void _HRFail(HRESULT hr) // temp... - { - (hr); - } - - //ObjectMain is called during Module::Init and Module::Term - static void WINAPI ObjectMain(bool /* bStarting */) {} - - static const struct _ATL_CATMAP_ENTRY* GetCategoryMap() {return NULL;}; - static HRESULT WINAPI InternalQueryInterface(void* pThis, - const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject) - { - // Only Assert here. AtlInternalQueryInterface will return the correct HRESULT if ppvObject == NULL -#ifndef _ATL_OLEDB_CONFORMANCE_TESTS - ATLASSERT(ppvObject != NULL); -#endif - ATLASSERT(pThis != NULL); - // First entry in the com map should be a simple map entry - ATLASSERT(pEntries->pFunc == _ATL_SIMPLEMAPENTRY); - #if defined(_ATL_DEBUG_INTERFACES) || defined(_ATL_DEBUG_QI) - LPCTSTR pszClassName = (LPCTSTR) pEntries[-1].dw; - #endif // _ATL_DEBUG_INTERFACES - HRESULT hRes = AtlInternalQueryInterface(pThis, pEntries, iid, ppvObject); - #ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.AddThunk((IUnknown**)ppvObject, pszClassName, iid); - #endif // _ATL_DEBUG_INTERFACES - return _ATLDUMPIID(iid, pszClassName, hRes); - } - -//Outer funcs - ULONG OuterAddRef() - { - return m_pOuterUnknown->AddRef(); - } - ULONG OuterRelease() - { - return m_pOuterUnknown->Release(); - } - HRESULT OuterQueryInterface(REFIID iid, void ** ppvObject) - { - return m_pOuterUnknown->QueryInterface(iid, ppvObject); - } - - void SetVoid(void*) {} - void InternalFinalConstructAddRef() {} - void InternalFinalConstructRelease() - { - ATLASSERT(m_dwRef == 0); - } - // If this assert occurs, your object has probably been deleted - // Try using DECLARE_PROTECT_FINAL_CONSTRUCT() - - - static HRESULT WINAPI _Break(void* /* pv */, REFIID iid, void** /* ppvObject */, DWORD_PTR /* dw */) - { - (iid); - _ATLDUMPIID(iid, _T("Break due to QI for interface "), S_OK); - DebugBreak(); - return S_FALSE; - } - static HRESULT WINAPI _NoInterface(void* /* pv */, REFIID /* iid */, void** /* ppvObject */, DWORD_PTR /* dw */) - { - return E_NOINTERFACE; - } - static HRESULT WINAPI _Creator(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw) - { - _ATL_CREATORDATA* pcd = (_ATL_CREATORDATA*)dw; - return pcd->pFunc(pv, iid, ppvObject); - } - static HRESULT WINAPI _Delegate(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw) - { - HRESULT hRes = E_NOINTERFACE; - IUnknown* p = *(IUnknown**)((DWORD_PTR)pv + dw); - if (p != NULL) - hRes = p->QueryInterface(iid, ppvObject); - return hRes; - } - static HRESULT WINAPI _Chain(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw) - { - _ATL_CHAINDATA* pcd = (_ATL_CHAINDATA*)dw; - void* p = (void*)((DWORD_PTR)pv + pcd->dwOffset); - return InternalQueryInterface(p, pcd->pFunc(), iid, ppvObject); - } - static HRESULT WINAPI _ChainAttr(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw) - { - const _ATL_INTMAP_ENTRY* (WINAPI *pFunc)() = (const _ATL_INTMAP_ENTRY* (WINAPI *)())dw; - const _ATL_INTMAP_ENTRY *pEntries = pFunc(); - if (pEntries == NULL) - return S_OK; - return InternalQueryInterface(pv, pEntries, iid, ppvObject); - } - static HRESULT WINAPI _Cache(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw) - { - HRESULT hRes = E_NOINTERFACE; - _ATL_CACHEDATA* pcd = (_ATL_CACHEDATA*)dw; - IUnknown** pp = (IUnknown**)((DWORD_PTR)pv + pcd->dwOffsetVar); - if (*pp == NULL) - hRes = pcd->pFunc(pv, __uuidof(IUnknown), (void**)pp); - if (*pp != NULL) - hRes = (*pp)->QueryInterface(iid, ppvObject); - return hRes; - } - - union - { - long m_dwRef; - IUnknown* m_pOuterUnknown; - }; -}; - -//foward declaration -template -class CComObjectRootEx; - -template -class CComObjectLockT -{ -public: - CComObjectLockT(CComObjectRootEx* p) - { - if (p) - p->Lock(); - m_p = p; - } - - ~CComObjectLockT() - { - if (m_p) - m_p->Unlock(); - } - CComObjectRootEx* m_p; -}; - -template <> class CComObjectLockT; - -template -class CComObjectRootEx : public CComObjectRootBase -{ -public: - typedef ThreadModel _ThreadModel; - typedef typename _ThreadModel::AutoCriticalSection _CritSec; - typedef CComObjectLockT<_ThreadModel> ObjectLock; - - ULONG InternalAddRef() - { - ATLASSERT(m_dwRef != -1L); - return _ThreadModel::Increment(&m_dwRef); - } - ULONG InternalRelease() - { -#ifdef _DEBUG - LONG nRef = _ThreadModel::Decrement(&m_dwRef); - if (nRef < -(LONG_MAX / 2)) - { - ATLASSERT(0 && _T("Release called on a pointer that has already been released")); - } - return nRef; -#else - return _ThreadModel::Decrement(&m_dwRef); -#endif - } - - void Lock() {m_critsec.Lock();} - void Unlock() {m_critsec.Unlock();} -private: - _CritSec m_critsec; -}; - -template <> -class CComObjectRootEx : public CComObjectRootBase -{ -public: - typedef CComSingleThreadModel _ThreadModel; - typedef _ThreadModel::AutoCriticalSection _CritSec; - typedef CComObjectLockT<_ThreadModel> ObjectLock; - - ULONG InternalAddRef() - { - ATLASSERT(m_dwRef != -1L); - return _ThreadModel::Increment(&m_dwRef); - } - ULONG InternalRelease() - { -#ifdef _DEBUG - long nRef = _ThreadModel::Decrement(&m_dwRef); - if (nRef < -(LONG_MAX / 2)) - { - ATLASSERT(0 && _T("Release called on a pointer that has already been released")); - } - return nRef; -#else - return _ThreadModel::Decrement(&m_dwRef); -#endif - } - - void Lock() {} - void Unlock() {} -}; - -template <> -class CComObjectLockT -{ -public: - CComObjectLockT(CComObjectRootEx*) {} - ~CComObjectLockT() {} -}; - -typedef CComObjectRootEx CComObjectRoot; - -#if defined(_WINDLL) | defined(_USRDLL) -#define DECLARE_CLASSFACTORY_EX(cf) typedef ATL::CComCreator< ATL::CComObjectCached< cf > > _ClassFactoryCreatorClass; -#else -// don't let class factory refcount influence lock count -#define DECLARE_CLASSFACTORY_EX(cf) typedef ATL::CComCreator< ATL::CComObjectNoLock< cf > > _ClassFactoryCreatorClass; -#endif -#define DECLARE_CLASSFACTORY() DECLARE_CLASSFACTORY_EX(ATL::CComClassFactory) -#define DECLARE_CLASSFACTORY2(lic) DECLARE_CLASSFACTORY_EX(ATL::CComClassFactory2) -#define DECLARE_CLASSFACTORY_AUTO_THREAD() DECLARE_CLASSFACTORY_EX(ATL::CComClassFactoryAutoThread) -#define DECLARE_CLASSFACTORY_SINGLETON(obj) DECLARE_CLASSFACTORY_EX(ATL::CComClassFactorySingleton) - -#define DECLARE_OBJECT_DESCRIPTION(x)\ - static LPCTSTR WINAPI GetObjectDescription() throw()\ - {\ - return _T(x);\ - } - -#define DECLARE_NO_REGISTRY()\ - static HRESULT WINAPI UpdateRegistry(BOOL /*bRegister*/) throw()\ - {return S_OK;} - -#define DECLARE_REGISTRY(class, pid, vpid, nid, flags)\ - static HRESULT WINAPI UpdateRegistry(BOOL bRegister) throw()\ - {\ - return _Module.UpdateRegistryClass(GetObjectCLSID(), pid, vpid, nid,\ - flags, bRegister);\ - } - -#define DECLARE_REGISTRY_RESOURCE(x)\ - static HRESULT WINAPI UpdateRegistry(BOOL bRegister) throw()\ - {\ - __if_exists(_GetMiscStatus) \ - { \ - ATL::_ATL_REGMAP_ENTRY regMapEntries[2]; \ - memset(®MapEntries[1], 0, sizeof(ATL::_ATL_REGMAP_ENTRY)); \ - regMapEntries[0].szKey = L"OLEMISC"; \ - TCHAR szOleMisc[32]; \ - wsprintf(szOleMisc, _T("%d"), _GetMiscStatus()); \ - USES_CONVERSION_EX; \ - regMapEntries[0].szData = T2OLE_EX(szOleMisc, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); \ - if (regMapEntries[0].szData == NULL) \ - return E_OUTOFMEMORY; \ - __if_exists(_Module) \ - { \ - return _Module.UpdateRegistryFromResource(_T(#x), bRegister, regMapEntries); \ - } \ - __if_not_exists(_Module) \ - { \ - return ATL::_pAtlModule->UpdateRegistryFromResource(_T(#x), bRegister, regMapEntries); \ - } \ - } \ - __if_not_exists(_GetMiscStatus) \ - { \ - __if_exists(_Module) \ - { \ - return _Module.UpdateRegistryFromResource(_T(#x), bRegister); \ - } \ - __if_not_exists(_Module) \ - { \ - return ATL::_pAtlModule->UpdateRegistryFromResource(_T(#x), bRegister); \ - } \ - } \ - } - -#define DECLARE_REGISTRY_RESOURCEID(x)\ - static HRESULT WINAPI UpdateRegistry(BOOL bRegister) throw()\ - {\ - __if_exists(_GetMiscStatus) \ - { \ - ATL::_ATL_REGMAP_ENTRY regMapEntries[2]; \ - memset(®MapEntries[1], 0, sizeof(ATL::_ATL_REGMAP_ENTRY)); \ - regMapEntries[0].szKey = L"OLEMISC"; \ - TCHAR szOleMisc[32]; \ - wsprintf(szOleMisc, _T("%d"), _GetMiscStatus()); \ - USES_CONVERSION_EX; \ - regMapEntries[0].szData = T2OLE_EX(szOleMisc, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); \ - if (regMapEntries[0].szData == NULL) \ - return E_OUTOFMEMORY; \ - __if_exists(_Module) \ - { \ - return _Module.UpdateRegistryFromResource(x, bRegister, regMapEntries); \ - } \ - __if_not_exists(_Module) \ - { \ - return ATL::_pAtlModule->UpdateRegistryFromResource(x, bRegister, regMapEntries); \ - } \ - } \ - __if_not_exists(_GetMiscStatus) \ - { \ - __if_exists(_Module) \ - { \ - return _Module.UpdateRegistryFromResource(x, bRegister); \ - } \ - __if_not_exists(_Module) \ - { \ - return ATL::_pAtlModule->UpdateRegistryFromResource(x, bRegister); \ - } \ - } \ - } - -//DECLARE_STATIC_* provided for backward compatibility -#ifdef _ATL_STATIC_REGISTRY -#define DECLARE_STATIC_REGISTRY_RESOURCE(x) DECLARE_REGISTRY_RESOURCE(x) -#define DECLARE_STATIC_REGISTRY_RESOURCEID(x) DECLARE_REGISTRY_RESOURCEID(x) -#endif //_ATL_STATIC_REGISTRY - -#define DECLARE_OLEMISC_STATUS(x) \ - static DWORD _GetMiscStatus() throw() \ - { \ - static DWORD m_dwOleMisc = x; \ - return m_dwOleMisc; \ - } - -template class CComObject; // fwd decl - -template -class CComTearOffObjectBase : public CComObjectRootEx -{ -public: - typedef Owner _OwnerClass; - Owner* m_pOwner; - CComTearOffObjectBase() {m_pOwner = NULL;} -}; - -//Base is the user's class that derives from CComObjectRoot and whatever -//interfaces the user wants to support on the object -template -class CComObject : public Base -{ -public: - typedef Base _BaseClass; - CComObject(void* = NULL) throw() - { - _pAtlModule->Lock(); - } - // Set refcount to -(LONG_MAX/2) to protect destruction and - // also catch mismatched Release in debug builds - virtual ~CComObject() throw() - { - m_dwRef = -(LONG_MAX/2); - FinalRelease(); -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.DeleteNonAddRefThunk(_GetRawUnknown()); -#endif - _pAtlModule->Unlock(); - } - //If InternalAddRef or InternalRelease is undefined then your class - //doesn't derive from CComObjectRoot - STDMETHOD_(ULONG, AddRef)() {return InternalAddRef();} - STDMETHOD_(ULONG, Release)() - { - ULONG l = InternalRelease(); - if (l == 0) - delete this; - return l; - } - //if _InternalQueryInterface is undefined then you forgot BEGIN_COM_MAP - STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) throw() - {return _InternalQueryInterface(iid, ppvObject);} - template - HRESULT STDMETHODCALLTYPE QueryInterface(Q** pp) throw() - { - return QueryInterface(__uuidof(Q), (void**)pp); - } - - static HRESULT WINAPI CreateInstance(CComObject** pp) throw(); -}; - -template -HRESULT WINAPI CComObject::CreateInstance(CComObject** pp) throw() -{ - ATLASSERT(pp != NULL); - if (pp == NULL) - return E_POINTER; - *pp = NULL; - - HRESULT hRes = E_OUTOFMEMORY; - CComObject* p = NULL; - ATLTRY(p = new CComObject()) - if (p != NULL) - { - p->SetVoid(NULL); - p->InternalFinalConstructAddRef(); - hRes = p->FinalConstruct(); - if (SUCCEEDED(hRes)) - hRes = p->_AtlFinalConstruct(); - p->InternalFinalConstructRelease(); - if (hRes != S_OK) - { - delete p; - p = NULL; - } - } - *pp = p; - return hRes; -} - -//Base is the user's class that derives from CComObjectRoot and whatever -//interfaces the user wants to support on the object -// CComObjectCached is used primarily for class factories in DLL's -// but it is useful anytime you want to cache an object -template -class CComObjectCached : public Base -{ -public: - typedef Base _BaseClass; - CComObjectCached(void* = NULL){} - // Set refcount to -(LONG_MAX/2) to protect destruction and - // also catch mismatched Release in debug builds - virtual ~CComObjectCached() - { - m_dwRef = -(LONG_MAX/2); - FinalRelease(); -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.DeleteNonAddRefThunk(_GetRawUnknown()); -#endif - } - //If InternalAddRef or InternalRelease is undefined then your class - //doesn't derive from CComObjectRoot - STDMETHOD_(ULONG, AddRef)() throw() - { - m_csCached.Lock(); - ULONG l = InternalAddRef(); - if (m_dwRef == 2) - _pAtlModule->Lock(); - m_csCached.Unlock(); - return l; - } - STDMETHOD_(ULONG, Release)() throw() - { - m_csCached.Lock(); - InternalRelease(); - ULONG l = m_dwRef; - m_csCached.Unlock(); - if (l == 0) - delete this; - else if (l == 1) - _pAtlModule->Unlock(); - return l; - } - //if _InternalQueryInterface is undefined then you forgot BEGIN_COM_MAP - STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) throw() - {return _InternalQueryInterface(iid, ppvObject);} - CComGlobalsThreadModel::AutoCriticalSection m_csCached; - static HRESULT WINAPI CreateInstance(CComObjectCached** pp) throw(); -}; - -template -HRESULT WINAPI CComObjectCached::CreateInstance(CComObjectCached** pp) throw() -{ - ATLASSERT(pp != NULL); - if (pp == NULL) - return E_POINTER; - *pp = NULL; - - HRESULT hRes = E_OUTOFMEMORY; - CComObjectCached* p = NULL; - ATLTRY(p = new CComObjectCached()) - if (p != NULL) - { - p->SetVoid(NULL); - p->InternalFinalConstructAddRef(); - hRes = p->FinalConstruct(); - if (SUCCEEDED(hRes)) - hRes = p->_AtlFinalConstruct(); - p->InternalFinalConstructRelease(); - if (hRes != S_OK) - { - delete p; - p = NULL; - } - } - *pp = p; - return hRes; -} - - -//Base is the user's class that derives from CComObjectRoot and whatever -//interfaces the user wants to support on the object -template -class CComObjectNoLock : public Base -{ -public: - typedef Base _BaseClass; - CComObjectNoLock(void* = NULL){} - // Set refcount to -(LONG_MAX/2) to protect destruction and - // also catch mismatched Release in debug builds - virtual ~CComObjectNoLock() - { - m_dwRef = -(LONG_MAX/2); - FinalRelease(); -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.DeleteNonAddRefThunk(_GetRawUnknown()); -#endif - } - - //If InternalAddRef or InternalRelease is undefined then your class - //doesn't derive from CComObjectRoot - STDMETHOD_(ULONG, AddRef)() throw() {return InternalAddRef();} - STDMETHOD_(ULONG, Release)() throw() - { - ULONG l = InternalRelease(); - if (l == 0) - delete this; - return l; - } - //if _InternalQueryInterface is undefined then you forgot BEGIN_COM_MAP - STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) throw() - {return _InternalQueryInterface(iid, ppvObject);} -}; - -// It is possible for Base not to derive from CComObjectRoot -// However, you will need to provide _InternalQueryInterface -template -class CComObjectGlobal : public Base -{ -public: - typedef Base _BaseClass; - CComObjectGlobal(void* = NULL) - { - m_hResFinalConstruct = S_OK; - __if_exists(FinalConstruct) - { - __if_exists(InternalFinalConstructAddRef) - { - InternalFinalConstructAddRef(); - } - m_hResFinalConstruct = FinalConstruct(); - __if_exists(InternalFinalConstructRelease) - { - InternalFinalConstructRelease(); - } - } - } - virtual ~CComObjectGlobal() - { - __if_exists(FinalRelease) - { - FinalRelease(); - } -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.DeleteNonAddRefThunk(_GetRawUnknown()); -#endif - } - - STDMETHOD_(ULONG, AddRef)() throw() - { - return _pAtlModule->Lock(); - } - STDMETHOD_(ULONG, Release)() throw() - { - return _pAtlModule->Unlock(); - } - STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) throw() - { - return _InternalQueryInterface(iid, ppvObject); - } - HRESULT m_hResFinalConstruct; -}; - -// It is possible for Base not to derive from CComObjectRoot -// However, you will need to provide FinalConstruct and InternalQueryInterface -template -class CComObjectStack : public Base -{ -public: - typedef Base _BaseClass; - CComObjectStack(void* = NULL){m_hResFinalConstruct = FinalConstruct();} - virtual ~CComObjectStack() - { - FinalRelease(); -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.DeleteNonAddRefThunk(_GetRawUnknown()); -#endif - } - - - STDMETHOD_(ULONG, AddRef)() {ATLASSERT(FALSE);return 0;} - STDMETHOD_(ULONG, Release)(){ATLASSERT(FALSE);return 0;} - STDMETHOD(QueryInterface)(REFIID, void**) - {ATLASSERT(FALSE);return E_NOINTERFACE;} - HRESULT m_hResFinalConstruct; -}; - -// Base must be derived from CComObjectRoot -template -class CComObjectStackEx : public Base -{ -public: - typedef Base _BaseClass; - - CComObjectStackEx(void* = NULL) - { -#ifdef _DEBUG - m_dwRef = 0; -#endif - - m_hResFinalConstruct = FinalConstruct(); - } - - virtual ~CComObjectStackEx() - { - // This assert indicates mismatched ref counts. - // - // The ref count has no control over the - // lifetime of this object, so you must ensure - // by some other means that the object remains - // alive while clients have references to its interfaces. - ATLASSERT(m_dwRef == 0); - FinalRelease(); -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.DeleteNonAddRefThunk(_GetRawUnknown()); -#endif - } - - STDMETHOD_(ULONG, AddRef)() - { -#ifdef _DEBUG - return InternalAddRef(); -#else - return 0; -#endif - } - - STDMETHOD_(ULONG, Release)() - { -#ifdef _DEBUG - return InternalRelease(); -#else - return 0; -#endif - } - - STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) - { - return _InternalQueryInterface(iid, ppvObject); - } - - HRESULT m_hResFinalConstruct; -}; - -template //Base must be derived from CComObjectRoot -class CComContainedObject : public Base -{ -public: - typedef Base _BaseClass; - CComContainedObject(void* pv) {m_pOuterUnknown = (IUnknown*)pv;} -#ifdef _ATL_DEBUG_INTERFACES - virtual ~CComContainedObject() - { - _AtlDebugInterfacesModule.DeleteNonAddRefThunk(_GetRawUnknown()); - _AtlDebugInterfacesModule.DeleteNonAddRefThunk(m_pOuterUnknown); - } -#endif - - STDMETHOD_(ULONG, AddRef)() throw() {return OuterAddRef();} - STDMETHOD_(ULONG, Release)() throw() {return OuterRelease();} - STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) throw() - { - return OuterQueryInterface(iid, ppvObject); - } - template - HRESULT STDMETHODCALLTYPE QueryInterface(Q** pp) - { - return QueryInterface(__uuidof(Q), (void**)pp); - } - //GetControllingUnknown may be virtual if the Base class has declared - //DECLARE_GET_CONTROLLING_UNKNOWN() - IUnknown* GetControllingUnknown() throw() - { -#ifdef _ATL_DEBUG_INTERFACES - IUnknown* p; - _AtlDebugInterfacesModule.AddNonAddRefThunk(m_pOuterUnknown, _T("CComContainedObject"), &p); - return p; -#else - return m_pOuterUnknown; -#endif - } -}; - -//contained is the user's class that derives from CComObjectRoot and whatever -//interfaces the user wants to support on the object -template -class CComAggObject : - public IUnknown, - public CComObjectRootEx< typename contained::_ThreadModel::ThreadModelNoCS > -{ -public: - typedef contained _BaseClass; - CComAggObject(void* pv) : m_contained(pv) - { - _pAtlModule->Lock(); - } - //If you get a message that this call is ambiguous then you need to - // override it in your class and call each base class' version of this - HRESULT FinalConstruct() - { - CComObjectRootEx::FinalConstruct(); - return m_contained.FinalConstruct(); - } - void FinalRelease() - { - CComObjectRootEx::FinalRelease(); - m_contained.FinalRelease(); - } - // Set refcount to -(LONG_MAX/2) to protect destruction and - // also catch mismatched Release in debug builds - virtual ~CComAggObject() - { - m_dwRef = -(LONG_MAX/2); - FinalRelease(); -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.DeleteNonAddRefThunk(this); -#endif - _pAtlModule->Unlock(); - } - - STDMETHOD_(ULONG, AddRef)() {return InternalAddRef();} - STDMETHOD_(ULONG, Release)() - { - ULONG l = InternalRelease(); - if (l == 0) - delete this; - return l; - } - STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) - { - ATLASSERT(ppvObject != NULL); - if (ppvObject == NULL) - return E_POINTER; - *ppvObject = NULL; - - HRESULT hRes = S_OK; - if (InlineIsEqualUnknown(iid)) - { - *ppvObject = (void*)(IUnknown*)this; - AddRef(); -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.AddThunk((IUnknown**)ppvObject, (LPCTSTR)contained::_GetEntries()[-1].dw, iid); -#endif // _ATL_DEBUG_INTERFACES - } - else - hRes = m_contained._InternalQueryInterface(iid, ppvObject); - return hRes; - } - template - HRESULT STDMETHODCALLTYPE QueryInterface(Q** pp) - { - return QueryInterface(__uuidof(Q), (void**)pp); - } - static HRESULT WINAPI CreateInstance(LPUNKNOWN pUnkOuter, CComAggObject** pp) - { - ATLASSERT(pp != NULL); - if (pp == NULL) - return E_POINTER; - *pp = NULL; - - HRESULT hRes = E_OUTOFMEMORY; - CComAggObject* p = NULL; - ATLTRY(p = new CComAggObject(pUnkOuter)) - if (p != NULL) - { - p->SetVoid(NULL); - p->InternalFinalConstructAddRef(); - hRes = p->FinalConstruct(); - if (SUCCEEDED(hRes)) - hRes = p->_AtlFinalConstruct(); - p->InternalFinalConstructRelease(); - if (hRes != S_OK) - { - delete p; - p = NULL; - } - } - *pp = p; - return hRes; - } - - CComContainedObject m_contained; -}; - -/////////////////////////////////////////////////////////////////////////////// -// CComPolyObject can be either aggregated or not aggregated - -template -class CComPolyObject : - public IUnknown, - public CComObjectRootEx< typename contained::_ThreadModel::ThreadModelNoCS > -{ -public: - typedef contained _BaseClass; - CComPolyObject(void* pv) : m_contained(pv ? pv : this) - { - _pAtlModule->Lock(); - } - //If you get a message that this call is ambiguous then you need to - // override it in your class and call each base class' version of this - HRESULT FinalConstruct() - { - InternalAddRef(); - CComObjectRootEx::FinalConstruct(); - HRESULT hr = m_contained.FinalConstruct(); - InternalRelease(); - return hr; - } - void FinalRelease() - { - CComObjectRootEx::FinalRelease(); - m_contained.FinalRelease(); - } - // Set refcount to -(LONG_MAX/2) to protect destruction and - // also catch mismatched Release in debug builds - virtual ~CComPolyObject() - { - m_dwRef = -(LONG_MAX/2); - FinalRelease(); -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.DeleteNonAddRefThunk(this); -#endif - _pAtlModule->Unlock(); - } - - STDMETHOD_(ULONG, AddRef)() {return InternalAddRef();} - STDMETHOD_(ULONG, Release)() - { - ULONG l = InternalRelease(); - if (l == 0) - delete this; - return l; - } - STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) - { -#ifndef _ATL_OLEDB_CONFORMANCE_TESTS - ATLASSERT(ppvObject != NULL); -#endif - if (ppvObject == NULL) - return E_POINTER; - *ppvObject = NULL; - - HRESULT hRes = S_OK; - if (InlineIsEqualUnknown(iid)) - { - *ppvObject = (void*)(IUnknown*)this; - AddRef(); -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.AddThunk((IUnknown**)ppvObject, (LPCTSTR)contained::_GetEntries()[-1].dw, iid); -#endif // _ATL_DEBUG_INTERFACES - } - else - hRes = m_contained._InternalQueryInterface(iid, ppvObject); - return hRes; - } - template - HRESULT STDMETHODCALLTYPE QueryInterface(Q** pp) - { - return QueryInterface(__uuidof(Q), (void**)pp); - } - static HRESULT WINAPI CreateInstance(LPUNKNOWN pUnkOuter, CComPolyObject** pp) - { - ATLASSERT(pp != NULL); - if (pp == NULL) - return E_POINTER; - *pp = NULL; - - - HRESULT hRes = E_OUTOFMEMORY; - CComPolyObject* p = NULL; - ATLTRY(p = new CComPolyObject(pUnkOuter)) - if (p != NULL) - { - p->SetVoid(NULL); - p->InternalFinalConstructAddRef(); - hRes = p->FinalConstruct(); - if (SUCCEEDED(hRes)) - hRes = p->_AtlFinalConstruct(); - p->InternalFinalConstructRelease(); - if (hRes != S_OK) - { - delete p; - p = NULL; - } - } - *pp = p; - return hRes; - } - - CComContainedObject m_contained; -}; - -template -class CComTearOffObject : public Base -{ -public: - CComTearOffObject(void* pv) - { - ATLASSERT(m_pOwner == NULL); - m_pOwner = reinterpret_cast(pv); - m_pOwner->AddRef(); - } - // Set refcount to -(LONG_MAX/2) to protect destruction and - // also catch mismatched Release in debug builds - ~CComTearOffObject() - { - m_dwRef = -(LONG_MAX/2); - FinalRelease(); -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.DeleteNonAddRefThunk(_GetRawUnknown()); -#endif - m_pOwner->Release(); - } - - STDMETHOD_(ULONG, AddRef)() throw() {return InternalAddRef();} - STDMETHOD_(ULONG, Release)() throw() - { - ULONG l = InternalRelease(); - if (l == 0) - delete this; - return l; - } - STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) throw() - { - return m_pOwner->QueryInterface(iid, ppvObject); - } -}; - -template -class CComCachedTearOffObject : - public IUnknown, - public CComObjectRootEx -{ -public: - typedef contained _BaseClass; - CComCachedTearOffObject(void* pv) : - m_contained(((contained::_OwnerClass*)pv)->GetControllingUnknown()) - { - ATLASSERT(m_contained.m_pOwner == NULL); - m_contained.m_pOwner = reinterpret_cast(pv); - } - //If you get a message that this call is ambiguous then you need to - // override it in your class and call each base class' version of this - HRESULT FinalConstruct() - { - CComObjectRootEx::FinalConstruct(); - return m_contained.FinalConstruct(); - } - void FinalRelease() - { - CComObjectRootEx::FinalRelease(); - m_contained.FinalRelease(); - } - // Set refcount to -(LONG_MAX/2) to protect destruction and - // also catch mismatched Release in debug builds - ~CComCachedTearOffObject() - { - m_dwRef = -(LONG_MAX/2); - FinalRelease(); -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.DeleteNonAddRefThunk(this); -#endif - } - - - STDMETHOD_(ULONG, AddRef)() {return InternalAddRef();} - STDMETHOD_(ULONG, Release)() - { - ULONG l = InternalRelease(); - if (l == 0) - delete this; - return l; - } - STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) - { - ATLASSERT(ppvObject != NULL); - if (ppvObject == NULL) - return E_POINTER; - *ppvObject = NULL; - - HRESULT hRes = S_OK; - if (InlineIsEqualUnknown(iid)) - { - *ppvObject = (void*)(IUnknown*)this; - AddRef(); -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.AddThunk((IUnknown**)ppvObject, (LPCTSTR)contained::_GetEntries()[-1].dw, iid); -#endif // _ATL_DEBUG_INTERFACES - } - else - hRes = m_contained._InternalQueryInterface(iid, ppvObject); - return hRes; - } - CComContainedObject m_contained; -}; - -class CComClassFactory : - public IClassFactory, - public CComObjectRootEx -{ -public: - BEGIN_COM_MAP(CComClassFactory) - COM_INTERFACE_ENTRY(IClassFactory) - END_COM_MAP() - - virtual ~CComClassFactory() - { - } - - // IClassFactory - STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj) - { - ATLASSERT(m_pfnCreateInstance != NULL); - HRESULT hRes = E_POINTER; - if (ppvObj != NULL) - { - *ppvObj = NULL; - // can't ask for anything other than IUnknown when aggregating - - if ((pUnkOuter != NULL) && !InlineIsEqualUnknown(riid)) - { - ATLTRACE(atlTraceCOM, 0, _T("CComClassFactory: asked for non IUnknown interface while creating an aggregated object")); - hRes = CLASS_E_NOAGGREGATION; - } - else - hRes = m_pfnCreateInstance(pUnkOuter, riid, ppvObj); - } - return hRes; - } - - STDMETHOD(LockServer)(BOOL fLock) - { - if (fLock) - _pAtlModule->Lock(); - else - _pAtlModule->Unlock(); - return S_OK; - } - // helper - void SetVoid(void* pv) - { - m_pfnCreateInstance = (_ATL_CREATORFUNC*)pv; - } - _ATL_CREATORFUNC* m_pfnCreateInstance; -}; - -template -class CComClassFactory2 : - public IClassFactory2, - public CComObjectRootEx, - public license -{ -public: - typedef license _LicenseClass; - typedef CComClassFactory2 _ComMapClass; -BEGIN_COM_MAP(CComClassFactory2) - COM_INTERFACE_ENTRY(IClassFactory) - COM_INTERFACE_ENTRY(IClassFactory2) -END_COM_MAP() - // IClassFactory - STDMETHOD(LockServer)(BOOL fLock) - { - if (fLock) - _pAtlModule->Lock(); - else - _pAtlModule->Unlock(); - return S_OK; - } - STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, - REFIID riid, void** ppvObj) - { - ATLASSERT(m_pfnCreateInstance != NULL); - if (ppvObj == NULL) - return E_POINTER; - *ppvObj = NULL; - if (!IsLicenseValid()) - return CLASS_E_NOTLICENSED; - - if ((pUnkOuter != NULL) && !InlineIsEqualUnknown(riid)) - return CLASS_E_NOAGGREGATION; - else - return m_pfnCreateInstance(pUnkOuter, riid, ppvObj); - } - // IClassFactory2 - STDMETHOD(CreateInstanceLic)(IUnknown* pUnkOuter, - IUnknown* /* pUnkReserved */, REFIID riid, BSTR bstrKey, - void** ppvObject) - { - ATLASSERT(m_pfnCreateInstance != NULL); - if (ppvObject == NULL) - return E_POINTER; - *ppvObject = NULL; - if ( ((bstrKey != NULL) && !VerifyLicenseKey(bstrKey)) || - ((bstrKey == NULL) && !IsLicenseValid()) ) - return CLASS_E_NOTLICENSED; - if ((pUnkOuter != NULL) && !InlineIsEqualUnknown(riid)) - return CLASS_E_NOAGGREGATION; - else - return m_pfnCreateInstance(pUnkOuter, riid, ppvObject); - } - STDMETHOD(RequestLicKey)(DWORD dwReserved, BSTR* pbstrKey) - { - if (pbstrKey == NULL) - return E_POINTER; - *pbstrKey = NULL; - - if (!IsLicenseValid()) - return CLASS_E_NOTLICENSED; - return GetLicenseKey(dwReserved,pbstrKey) ? S_OK : E_FAIL; - } - STDMETHOD(GetLicInfo)(LICINFO* pLicInfo) - { - if (pLicInfo == NULL) - return E_POINTER; - pLicInfo->cbLicInfo = sizeof(LICINFO); - pLicInfo->fLicVerified = IsLicenseValid(); - BSTR bstr = NULL; - pLicInfo->fRuntimeKeyAvail = GetLicenseKey(0,&bstr); - ::SysFreeString(bstr); - return S_OK; - } - void SetVoid(void* pv) - { - m_pfnCreateInstance = (_ATL_CREATORFUNC*)pv; - } - _ATL_CREATORFUNC* m_pfnCreateInstance; -}; - -///////////////////////////////////////////////////////////////////////////////////////////// -// Thread Pooling class factory -class CComClassFactoryAutoThread : - public IClassFactory, - public CComObjectRootEx -{ -public: - BEGIN_COM_MAP(CComClassFactoryAutoThread) - COM_INTERFACE_ENTRY(IClassFactory) - END_COM_MAP() - - virtual ~CComClassFactoryAutoThread() - { - } - - // helper - void SetVoid(void* pv) - { - m_pfnCreateInstance = (_ATL_CREATORFUNC*)pv; - } - STDMETHODIMP CreateInstance(LPUNKNOWN pUnkOuter, - REFIID riid, void** ppvObj) - { - ATLASSERT(m_pfnCreateInstance != NULL); - HRESULT hRes = E_POINTER; - if (ppvObj != NULL) - { - *ppvObj = NULL; - // cannot aggregate across apartments - ATLASSERT(pUnkOuter == NULL); - if (pUnkOuter != NULL) - hRes = CLASS_E_NOAGGREGATION; - else - { - ATLASSERT(_pAtlAutoThreadModule && _T("Global instance of CAtlAutoThreadModule not declared")); - if (_pAtlAutoThreadModule == NULL) - return E_FAIL; - - hRes = _pAtlAutoThreadModule->CreateInstance(m_pfnCreateInstance, riid, ppvObj); - } - } - return hRes; - } - STDMETHODIMP LockServer(BOOL fLock) - { - if (fLock) - _pAtlModule->Lock(); - else - _pAtlModule->Unlock(); - return S_OK; - } - _ATL_CREATORFUNC* m_pfnCreateInstance; -}; - - -///////////////////////////////////////////////////////////////////////////////////////////// -// Singleton Class Factory -template -class CComClassFactorySingleton : public CComClassFactory -{ -public: - CComClassFactorySingleton() : m_hrCreate(S_OK) - { - } - virtual ~CComClassFactorySingleton() - { - } - // IClassFactory - STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj) - { - HRESULT hRes = E_POINTER; - if (ppvObj != NULL) - { - *ppvObj = NULL; - // aggregation is not supported in Singletons - ATLASSERT(pUnkOuter == NULL); - if (pUnkOuter != NULL) - hRes = CLASS_E_NOAGGREGATION; - else - { - if (m_hrCreate == S_OK && m_spObj == NULL) - { - Lock(); - // Did another thread got here first - if (m_hrCreate == S_OK && m_spObj == NULL) - { - __try - { - CComObjectCached *p; - m_hrCreate = CComObjectCached::CreateInstance(&p); - if (SUCCEEDED(m_hrCreate)) - { - m_hrCreate = p->QueryInterface(IID_IUnknown, (void**)&m_spObj); - if (FAILED(m_hrCreate)) - { - delete p; - } - } - } - __finally - { - Unlock(); - } - } - } - if (m_hrCreate == S_OK) - { - hRes = m_spObj->QueryInterface(riid, ppvObj); - } - else - { - hRes = m_hrCreate; - } - } - } - return hRes; - } - HRESULT m_hrCreate; - CComPtr m_spObj; -}; - -template -class CComCoClass -{ -public: - DECLARE_CLASSFACTORY() - DECLARE_AGGREGATABLE(T) - typedef T _CoClass; - static const CLSID& WINAPI GetObjectCLSID() {return *pclsid;} - static LPCTSTR WINAPI GetObjectDescription() {return NULL;} - static HRESULT WINAPI Error(LPCOLESTR lpszDesc, - const IID& iid = GUID_NULL, HRESULT hRes = 0) - { - return AtlReportError(GetObjectCLSID(), lpszDesc, iid, hRes); - } - static HRESULT WINAPI Error(LPCOLESTR lpszDesc, DWORD dwHelpID, - LPCOLESTR lpszHelpFile, const IID& iid = GUID_NULL, HRESULT hRes = 0) - { - return AtlReportError(GetObjectCLSID(), lpszDesc, dwHelpID, lpszHelpFile, - iid, hRes); - } - static HRESULT WINAPI Error(UINT nID, const IID& iid = GUID_NULL, - HRESULT hRes = 0, HINSTANCE hInst = _AtlBaseModule.GetResourceInstance()) - { - return AtlReportError(GetObjectCLSID(), nID, iid, hRes, hInst); - } - static HRESULT WINAPI Error(UINT nID, DWORD dwHelpID, - LPCOLESTR lpszHelpFile, const IID& iid = GUID_NULL, - HRESULT hRes = 0, HINSTANCE hInst = _AtlBaseModule.GetResourceInstance()) - { - return AtlReportError(GetObjectCLSID(), nID, dwHelpID, lpszHelpFile, - iid, hRes, hInst); - } - static HRESULT WINAPI Error(LPCSTR lpszDesc, - const IID& iid = GUID_NULL, HRESULT hRes = 0) - { - return AtlReportError(GetObjectCLSID(), lpszDesc, iid, hRes); - } - static HRESULT WINAPI Error(LPCSTR lpszDesc, DWORD dwHelpID, - LPCSTR lpszHelpFile, const IID& iid = GUID_NULL, HRESULT hRes = 0) - { - return AtlReportError(GetObjectCLSID(), lpszDesc, dwHelpID, - lpszHelpFile, iid, hRes); - } - template - static HRESULT CreateInstance(IUnknown* punkOuter, Q** pp) - { - return T::_CreatorClass::CreateInstance(punkOuter, __uuidof(Q), (void**) pp); - } - template - static HRESULT CreateInstance(Q** pp) - { - return T::_CreatorClass::CreateInstance(NULL, __uuidof(Q), (void**) pp); - } -}; - -// ATL doesn't support multiple LCID's at the same time -// Whatever LCID is queried for first is the one that is used. -class CComTypeInfoHolder -{ -// Should be 'protected' but can cause compiler to generate fat code. -public: - const GUID* m_pguid; - const GUID* m_plibid; - WORD m_wMajor; - WORD m_wMinor; - - ITypeInfo* m_pInfo; - long m_dwRef; - struct stringdispid - { - CComBSTR bstr; - int nLen; - DISPID id; - stringdispid() : nLen(0), id(DISPID_UNKNOWN){} - }; - stringdispid* m_pMap; - int m_nCount; - -public: - -#ifdef _ATL_DLL_IMPL - CComTypeInfoHolder(const GUID* pguid, const GUID* plibid, WORD wMajor, WORD wMinor) : - m_pguid(pguid), m_plibid(plibid), m_wMajor(wMajor), m_wMinor(wMinor), - m_pInfo(NULL), m_dwRef(0), m_pMap(NULL), m_nCount(0) - { - } - - ~CComTypeInfoHolder() - { - if (m_pInfo != NULL) - m_pInfo->Release(); - m_pInfo = NULL; - delete [] m_pMap; - m_pMap = NULL; - } -#endif - - HRESULT GetTI(LCID lcid, ITypeInfo** ppInfo) - { - ATLASSERT(ppInfo != NULL); - if (ppInfo == NULL) - return E_POINTER; - - HRESULT hr = S_OK; - if (m_pInfo == NULL) - hr = GetTI(lcid); - *ppInfo = m_pInfo; - if (m_pInfo != NULL) - { - m_pInfo->AddRef(); - hr = S_OK; - } - return hr; - } - HRESULT GetTI(LCID lcid); - HRESULT EnsureTI(LCID lcid) - { - HRESULT hr = S_OK; - if (m_pInfo == NULL || m_pMap == NULL) - hr = GetTI(lcid); - return hr; - } - - // This function is called by the module on exit - // It is registered through _pAtlModule->AddTermFunc() - static void __stdcall Cleanup(DWORD_PTR dw) - { - ATLASSERT(dw != 0); - if (dw == 0) - return; - - CComTypeInfoHolder* p = (CComTypeInfoHolder*) dw; - if (p->m_pInfo != NULL) - p->m_pInfo->Release(); - p->m_pInfo = NULL; - delete [] p->m_pMap; - p->m_pMap = NULL; - } - - HRESULT GetTypeInfo(UINT /* itinfo */, LCID lcid, ITypeInfo** pptinfo) - { - return GetTI(lcid, pptinfo); - } - HRESULT GetIDsOfNames(REFIID /* riid */, LPOLESTR* rgszNames, UINT cNames, - LCID lcid, DISPID* rgdispid) - { - HRESULT hRes = EnsureTI(lcid); - if (m_pInfo != NULL) - { - hRes = E_FAIL; - // Look in cache if - // cache is populated - // parameter names are not requested - if (m_pMap != NULL && cNames == 1) - { - int n = int( ocslen(rgszNames[0]) ); - for (int j=m_nCount-1; j>=0; j--) - { - if ((n == m_pMap[j].nLen) && - (memcmp(m_pMap[j].bstr, rgszNames[0], m_pMap[j].nLen * sizeof(OLECHAR)) == 0)) - { - rgdispid[0] = m_pMap[j].id; - hRes = S_OK; - break; - } - } - } - // if cache is empty or name not in cache or parameter names are requested, - // delegate to ITypeInfo::GetIDsOfNames - if (FAILED(hRes)) - { - hRes = m_pInfo->GetIDsOfNames(rgszNames, cNames, rgdispid); - } - } - return hRes; - } - - HRESULT Invoke(IDispatch* p, DISPID dispidMember, REFIID /* riid */, - LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, - EXCEPINFO* pexcepinfo, UINT* puArgErr) - { - HRESULT hRes = EnsureTI(lcid); - if (m_pInfo != NULL) - hRes = m_pInfo->Invoke(p, dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr); - return hRes; - } - HRESULT LoadNameCache(ITypeInfo* pTypeInfo) - { - TYPEATTR* pta; - HRESULT hr = pTypeInfo->GetTypeAttr(&pta); - if (SUCCEEDED(hr)) - { - stringdispid* pMap = NULL; - m_nCount = pta->cFuncs; - m_pMap = NULL; - if (m_nCount != 0) - { - ATLTRY(pMap = new stringdispid[m_nCount]); - if (pMap == NULL) - { - pTypeInfo->ReleaseTypeAttr(pta); - return E_OUTOFMEMORY; - } - } - for (int i=0; iGetFuncDesc(i, &pfd))) - { - CComBSTR bstrName; - if (SUCCEEDED(pTypeInfo->GetDocumentation(pfd->memid, &bstrName, NULL, NULL, NULL))) - { - pMap[i].bstr.Attach(bstrName.Detach()); - pMap[i].nLen = SysStringLen(pMap[i].bstr); - pMap[i].id = pfd->memid; - } - pTypeInfo->ReleaseFuncDesc(pfd); - } - } - m_pMap = pMap; - pTypeInfo->ReleaseTypeAttr(pta); - } - return S_OK; - } -}; - - -inline HRESULT CComTypeInfoHolder::GetTI(LCID lcid) -{ - //If this assert occurs then most likely didn't initialize properly - ATLASSERT(m_plibid != NULL && m_pguid != NULL); - ATLASSERT(!InlineIsEqualGUID(*m_plibid, GUID_NULL) && "Did you forget to pass the LIBID to CComModule::Init?"); - - if (m_pInfo != NULL && m_pMap != NULL) - return S_OK; - - CComCritSecLock lock(_pAtlModule->m_csStaticDataInitAndTypeInfo, false); - HRESULT hRes = lock.Lock(); - if (FAILED(hRes)) - { - ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to lock critical section in CComTypeInfoHolder::GetTI\n")); - ATLASSERT(0); - return hRes; - } - hRes = E_FAIL; - if (m_pInfo == NULL) - { - ITypeLib* pTypeLib = NULL; - if (InlineIsEqualGUID(CAtlModule::m_libid, *m_plibid) && m_wMajor == 0xFFFF && m_wMinor == 0xFFFF) - { - TCHAR szFilePath[MAX_PATH]; - DWORD dwFLen = ::GetModuleFileName(_AtlBaseModule.GetModuleInstance(), szFilePath, MAX_PATH); - if( dwFLen != 0 && dwFLen != MAX_PATH ) - { - USES_CONVERSION_EX; - LPOLESTR pszFile = T2OLE_EX(szFilePath, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if (pszFile == NULL) - return E_OUTOFMEMORY; -#endif - hRes = LoadTypeLib(pszFile, &pTypeLib); - } - } - else - { - hRes = LoadRegTypeLib(*m_plibid, m_wMajor, m_wMinor, lcid, &pTypeLib); -#ifdef _DEBUG - if (SUCCEEDED(hRes)) - { - // Trace out an warning if the requested TypelibID is the same as the modules TypelibID - // and versions do not match. - // - // In most cases it is due to wrong version template parameters to IDispatchImpl, - // IProvideClassInfoImpl or IProvideClassInfo2Impl. - // Set major and minor versions to 0xFFFF if the modules type lib has to be loaded - // irrespective of its version. - // - // Get the module's file path - TCHAR szFilePath[MAX_PATH]; - DWORD dwFLen = ::GetModuleFileName(_AtlBaseModule.GetModuleInstance(), szFilePath, MAX_PATH); - if( dwFLen != 0 && dwFLen != MAX_PATH ) - { - USES_CONVERSION_EX; - CComPtr spTypeLibModule; - HRESULT hRes2 = S_OK; - LPOLESTR pszFile = T2OLE_EX(szFilePath, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); - if (pszFile == NULL) - hRes2 = E_OUTOFMEMORY; - else - hRes2 = LoadTypeLib(pszFile, &spTypeLibModule); - if (SUCCEEDED(hRes2)) - { - TLIBATTR* pLibAttr; - hRes2 = spTypeLibModule->GetLibAttr(&pLibAttr); - if (SUCCEEDED(hRes2)) - { - if (InlineIsEqualGUID(pLibAttr->guid, *m_plibid) && - (pLibAttr->wMajorVerNum != m_wMajor || - pLibAttr->wMinorVerNum != m_wMinor)) - { - ATLTRACE(atlTraceCOM, 0, _T("Warning : CComTypeInfoHolder::GetTI : Loaded typelib does not match the typelib in the module : %s\n"), szFilePath); - ATLTRACE(atlTraceCOM, 0, _T("\tSee IDispatchImpl overview help topic for more information\n"), szFilePath); - } - spTypeLibModule->ReleaseTLibAttr(pLibAttr); - } - } - } - } - else - { - ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to load Typelibrary. (HRESULT = 0x%x)\n"), hRes); - ATLTRACE(atlTraceCOM, 0, _T("\tVerify TypelibID and major version specified with\n")); - ATLTRACE(atlTraceCOM, 0, _T("\tIDispatchImpl, CStockPropImpl, IProvideClassInfoImpl or IProvideCLassInfo2Impl\n")); - } -#endif - } - if (SUCCEEDED(hRes)) - { - CComPtr spTypeInfo; - hRes = pTypeLib->GetTypeInfoOfGuid(*m_pguid, &spTypeInfo); - if (SUCCEEDED(hRes)) - { - CComPtr spInfo(spTypeInfo); - CComPtr spTypeInfo2; - if (SUCCEEDED(spTypeInfo->QueryInterface(&spTypeInfo2))) - spInfo = spTypeInfo2; - - m_pInfo = spInfo.Detach(); -#ifndef _ATL_DLL_IMPL - _pAtlModule->AddTermFunc(Cleanup, (DWORD_PTR)this); -#endif - } - pTypeLib->Release(); - } - } - else - { - // Another thread has loaded the typeinfo so we're OK. - hRes = S_OK; - } - - if (m_pInfo != NULL && m_pMap == NULL) - LoadNameCache(m_pInfo); - - return hRes; -} - -////////////////////////////////////////////////////////////////////////////// -// IObjectWithSite -// -template -class ATL_NO_VTABLE IObjectWithSiteImpl : public IObjectWithSite -{ -public: - virtual ~IObjectWithSiteImpl() - { - } - - STDMETHOD(SetSite)(IUnknown *pUnkSite) - { - ATLTRACE(atlTraceCOM, 2, _T("IObjectWithSiteImpl::SetSite\n")); - T* pT = static_cast(this); - pT->m_spUnkSite = pUnkSite; - return S_OK; - } - STDMETHOD(GetSite)(REFIID riid, void **ppvSite) - { - ATLTRACE(atlTraceCOM, 2, _T("IObjectWithSiteImpl::GetSite\n")); - T* pT = static_cast(this); - ATLASSERT(ppvSite); - HRESULT hRes = E_POINTER; - if (ppvSite != NULL) - { - if (pT->m_spUnkSite) - hRes = pT->m_spUnkSite->QueryInterface(riid, ppvSite); - else - { - *ppvSite = NULL; - hRes = E_FAIL; - } - } - return hRes; - } - - HRESULT SetChildSite(IUnknown* punkChild) - { - if (punkChild == NULL) - return E_POINTER; - - HRESULT hr; - CComPtr spChildSite; - hr = punkChild->QueryInterface(__uuidof(IObjectWithSite), (void**)&spChildSite); - if (SUCCEEDED(hr)) - hr = spChildSite->SetSite((IUnknown*)this); - - return hr; - } - - static HRESULT SetChildSite(IUnknown* punkChild, IUnknown* punkParent) - { - return AtlSetChildSite(punkChild, punkParent); - } - - CComPtr m_spUnkSite; -}; - -////////////////////////////////////////////////////////////////////////////// -// IServiceProvider -// -template -class ATL_NO_VTABLE IServiceProviderImpl : public IServiceProvider -{ -public: - STDMETHOD(QueryService)(REFGUID guidService, REFIID riid, void** ppvObject) - { - ATLTRACE(atlTraceCOM, 2, _T("IServiceProviderImpl::QueryService\n")); - - T* pT = static_cast(this); - return pT->_InternalQueryService(guidService, riid, ppvObject); - } -}; - -#define BEGIN_SERVICE_MAP(x) public: \ - HRESULT _InternalQueryService(REFGUID guidService, REFIID riid, void** ppvObject) \ - { \ - ATLASSERT(ppvObject != NULL); \ - if (ppvObject == NULL) \ - return E_POINTER; \ - *ppvObject = NULL; - -#define SERVICE_ENTRY(x) \ - if (InlineIsEqualGUID(guidService, x)) \ - return QueryInterface(riid, ppvObject); - -#define SERVICE_ENTRY_CHAIN(x) \ - ATL::CComQIPtr spProvider(x); \ - if (spProvider != NULL) \ - return spProvider->QueryService(guidService, riid, ppvObject); - -#define END_SERVICE_MAP() \ - return E_NOINTERFACE; \ - } - - -///////////////////////////////////////////////////////////////////////////// -// IDispEventImpl - -ATLAPI AtlGetObjectSourceInterface(IUnknown* punkObj, GUID* plibid, IID* piid, unsigned short* pdwMajor, unsigned short* pdwMinor); - -#ifndef _M_IX86 -template -class CComStdCallThunk -{ -public: - typedef void (__stdcall T::*TMFP)(); - void* pVtable; - void* pFunc; - _stdcallthunk thunk; - void Init(TMFP dw, void* pThis) - { - pVtable = &pFunc; - pFunc = &thunk; - union { - DWORD_PTR dwFunc; - TMFP pfn; - } pfn; - pfn.pfn = dw; - thunk.Init(pfn.dwFunc, pThis); - } -}; - -#else - -// used for _M_IX86 -void __stdcall CComStdCallThunkHelper(); - -template -class CComStdCallThunk -{ -public: - typedef void (__stdcall T::*TMFP)(); - void *pVTable; // pointer to artificial VTABLE - void *pThis; // pointer to the class - TMFP pfn; // Pointer to member function to call - void (__stdcall *pfnHelper)(); // Artificial VTABLE entry. Points to CComStdCallThunkHelper - // which modifies the stack and jumps to pfn - - void Init(TMFP pf, void *p) - { - pfnHelper = CComStdCallThunkHelper; - pVTable = &pfnHelper; - pThis = p; - pfn = pf; - } -}; - -#endif // _M_IX86 - -#ifndef _ATL_MAX_VARTYPES -#define _ATL_MAX_VARTYPES 8 -#endif - -struct _ATL_FUNC_INFO -{ - CALLCONV cc; - VARTYPE vtReturn; - SHORT nParams; - VARTYPE pVarTypes[_ATL_MAX_VARTYPES]; -}; - -class ATL_NO_VTABLE _IDispEvent -{ -public: - _IDispEvent() : m_libid(GUID_NULL), m_iid(IID_NULL), m_wMajorVerNum(0), m_wMinorVerNum(0), m_dwEventCookie(0xFEFEFEFE) { } - //this method needs a different name than QueryInterface - STDMETHOD(_LocDEQueryInterface)(REFIID riid, void ** ppvObject) = 0; - virtual ULONG STDMETHODCALLTYPE AddRef(void) = 0; - virtual ULONG STDMETHODCALLTYPE Release(void) = 0; - GUID m_libid; // used for dynamic case - IID m_iid; // used for dynamic case - unsigned short m_wMajorVerNum; // Major version number. used for dynamic case - unsigned short m_wMinorVerNum; // Minor version number. used for dynamic case - DWORD m_dwEventCookie; - HRESULT DispEventAdvise(IUnknown* pUnk, const IID* piid) - { - ATLASSERT(m_dwEventCookie == 0xFEFEFEFE); - return AtlAdvise(pUnk, (IUnknown*)this, *piid, &m_dwEventCookie); - } - HRESULT DispEventUnadvise(IUnknown* pUnk, const IID* piid) - { - HRESULT hr = AtlUnadvise(pUnk, *piid, m_dwEventCookie); - m_dwEventCookie = 0xFEFEFEFE; - return hr; - } - //---- add Advise & Unadvise for ease of calling from attribute code ---- - HRESULT Advise(IUnknown *punk) - { - HRESULT hr = AtlGetObjectSourceInterface(punk, &m_libid, &m_iid, &m_wMajorVerNum, &m_wMinorVerNum); - if (FAILED(hr)) - return hr; - return DispEventAdvise(punk, &m_iid); - } - HRESULT Unadvise(IUnknown *punk) - { - HRESULT hr = AtlGetObjectSourceInterface(punk, &m_libid, &m_iid, &m_wMajorVerNum, &m_wMinorVerNum); - if (FAILED(hr)) - return hr; - return DispEventUnadvise(punk, &m_iid); - } -}; - -template -class ATL_NO_VTABLE _IDispEventLocator : public _IDispEvent -{ -public: -}; - -template -class ATL_NO_VTABLE IDispEventSimpleImpl : public _IDispEventLocator -{ -public: - STDMETHOD(_LocDEQueryInterface)(REFIID riid, void ** ppvObject) - { - ATLASSERT(ppvObject != NULL); - if (ppvObject == NULL) - return E_POINTER; - *ppvObject = NULL; - - if (InlineIsEqualGUID(riid, IID_NULL)) - return E_NOINTERFACE; - - if (InlineIsEqualGUID(riid, *pdiid) || - InlineIsEqualUnknown(riid) || - InlineIsEqualGUID(riid, __uuidof(IDispatch)) || - InlineIsEqualGUID(riid, m_iid)) - { - *ppvObject = this; - AddRef(); -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.AddThunk((IUnknown**)ppvObject, _T("IDispEventImpl"), riid); -#endif // _ATL_DEBUG_INTERFACES - return S_OK; - } - else - return E_NOINTERFACE; - } - - // These are here only to support use in non-COM objects - virtual ULONG STDMETHODCALLTYPE AddRef() - { - return 1; - } - virtual ULONG STDMETHODCALLTYPE Release() - { - return 1; - } - - STDMETHOD(GetTypeInfoCount)(UINT* /*pctinfo*/) - {ATLTRACENOTIMPL(_T("IDispEventSimpleImpl::GetTypeInfoCount"));} - - STDMETHOD(GetTypeInfo)(UINT /*itinfo*/, LCID /*lcid*/, ITypeInfo** /*pptinfo*/) - {ATLTRACENOTIMPL(_T("IDispEventSimpleImpl::GetTypeInfo"));} - - STDMETHOD(GetIDsOfNames)(REFIID /*riid*/, LPOLESTR* /*rgszNames*/, UINT /*cNames*/, - LCID /*lcid*/, DISPID* /*rgdispid*/) - {ATLTRACENOTIMPL(_T("IDispEventSimpleImpl::GetIDsOfNames"));} - - STDMETHOD(Invoke)(DISPID dispidMember, REFIID /*riid*/, - LCID lcid, WORD /*wFlags*/, DISPPARAMS* pdispparams, VARIANT* pvarResult, - EXCEPINFO* /*pexcepinfo*/, UINT* /*puArgErr*/) - { - const _ATL_EVENT_ENTRY* pMap = T::_GetSinkMap(); - const _ATL_EVENT_ENTRY* pFound = NULL; - while (pMap->piid != NULL) - { - if ((pMap->nControlID == nID) && (pMap->dispid == dispidMember) && - (IsEqualIID(*(pMap->piid), *pdiid))) - { - pFound = pMap; - break; - } - pMap++; - } - if (pFound == NULL) - return S_OK; - - - _ATL_FUNC_INFO info; - _ATL_FUNC_INFO* pInfo; - if (pFound->pInfo != NULL) - pInfo = pFound->pInfo; - else - { - pInfo = &info; - HRESULT hr = GetFuncInfoFromId(*pdiid, dispidMember, lcid, info); - if (FAILED(hr)) - return S_OK; - } - return InvokeFromFuncInfo(pFound->pfn, *pInfo, pdispparams, pvarResult); - } - - //Helper for invoking the event - HRESULT InvokeFromFuncInfo(void (__stdcall T::*pEvent)(), _ATL_FUNC_INFO& info, DISPPARAMS* pdispparams, VARIANT* pvarResult) - { - ATLASSERT(pdispparams->cArgs == (UINT)info.nParams); - - T* pT = static_cast(this); - - // If this assert occurs, then add - // #define _ATL_MAX_VARTYPES nnnn - // before including atlcom.h - ATLASSERT(info.nParams <= _ATL_MAX_VARTYPES); - if (info.nParams > _ATL_MAX_VARTYPES) - { - return E_FAIL; - } - VARIANTARG* rgVarArgs[_ATL_MAX_VARTYPES]; - VARIANTARG** pVarArgs = info.nParams ? rgVarArgs : 0; - - UINT nIndex = 0; - -#ifndef _ATL_IGNORE_NAMED_ARGS - for (nIndex; nIndex < pdispparams->cNamedArgs; nIndex++) - pVarArgs[pdispparams->rgdispidNamedArgs[nIndex]] = &pdispparams->rgvarg[nIndex]; -#endif - - for (; nIndex < pdispparams->cArgs; nIndex++) - pVarArgs[info.nParams-nIndex-1] = &pdispparams->rgvarg[nIndex]; - - CComStdCallThunk thunk; - thunk.Init(pEvent, pT); - - CComVariant tmpResult; - if (pvarResult == NULL) - pvarResult = &tmpResult; - - HRESULT hr = DispCallFunc( - &thunk, - 0, - info.cc, - info.vtReturn, - info.nParams, - info.pVarTypes, - pVarArgs, - pvarResult); - ATLASSERT(SUCCEEDED(hr)); - return hr; - } - - //Helper for finding the function index for a DISPID - virtual HRESULT GetFuncInfoFromId(const IID& /*iid*/, DISPID /*dispidMember*/, LCID /*lcid*/, _ATL_FUNC_INFO& /*info*/) - { - ATLTRACE(_T("TODO: Classes using IDispEventSimpleImpl should override this method\n")); - ATLASSERT(0); - ATLTRACENOTIMPL(_T("IDispEventSimpleImpl::GetFuncInfoFromId")); - } - //Helpers for sinking events on random IUnknown* - HRESULT DispEventAdvise(IUnknown* pUnk, const IID* piid) - { - ATLASSERT(m_dwEventCookie == 0xFEFEFEFE); - if (m_dwEventCookie != 0xFEFEFEFE) - return E_UNEXPECTED; - return AtlAdvise(pUnk, (IUnknown*)this, *piid, &m_dwEventCookie); - } - HRESULT DispEventUnadvise(IUnknown* pUnk, const IID* piid) - { - HRESULT hr = AtlUnadvise(pUnk, *piid, m_dwEventCookie); - m_dwEventCookie = 0xFEFEFEFE; - return hr; - } - HRESULT DispEventAdvise(IUnknown* pUnk) - { - return _IDispEvent::DispEventAdvise(pUnk, pdiid); - } - HRESULT DispEventUnadvise(IUnknown* pUnk) - { - return _IDispEvent::DispEventUnadvise(pUnk, pdiid); - } -}; - -//Helper for advising connections points from a sink map -template -inline HRESULT AtlAdviseSinkMap(T* pT, bool bAdvise) -{ - ATLASSERT(::IsWindow(pT->m_hWnd)); - const _ATL_EVENT_ENTRY* pEntries = T::_GetSinkMap(); - if (pEntries == NULL) - return S_OK; - HRESULT hr = S_OK; - while (pEntries->piid != NULL) - { - _IDispEvent* pDE = (_IDispEvent*)((DWORD_PTR)pT+pEntries->nOffset); - bool bNotAdvised = pDE->m_dwEventCookie == 0xFEFEFEFE; - if (bAdvise ^ bNotAdvised) - { - pEntries++; - continue; - } - hr = E_FAIL; - HWND h = pT->GetDlgItem(pEntries->nControlID); - ATLASSERT(h != NULL); - if (h != NULL) - { - CComPtr spUnk; - AtlAxGetControl(h, &spUnk); - ATLASSERT(spUnk != NULL); - if (spUnk != NULL) - { - if (bAdvise) - { - if (!InlineIsEqualGUID(IID_NULL, *pEntries->piid)) - hr = pDE->DispEventAdvise(spUnk, pEntries->piid); - else - { - hr = AtlGetObjectSourceInterface(spUnk, &pDE->m_libid, &pDE->m_iid, &pDE->m_wMajorVerNum, &pDE->m_wMinorVerNum); - if (FAILED(hr)) - return hr; - hr = pDE->DispEventAdvise(spUnk, &pDE->m_iid); - } - } - else - { - if (!InlineIsEqualGUID(IID_NULL, *pEntries->piid)) - hr = pDE->DispEventUnadvise(spUnk, pEntries->piid); - else - hr = pDE->DispEventUnadvise(spUnk, &pDE->m_iid); - } - ATLASSERT(hr == S_OK); - } - } - if (FAILED(hr)) - break; - pEntries++; - } - return hr; -} - -#pragma warning(push) -#pragma warning(disable: 4061) // enumerate XXX not explicitly handled by a case label -inline VARTYPE AtlGetUserDefinedType(ITypeInfo *pTI, HREFTYPE hrt) -{ - if (pTI == NULL) - E_INVALIDARG; - - CComPtr spTypeInfo; - VARTYPE vt = VT_USERDEFINED; - HRESULT hr = E_FAIL; - hr = pTI->GetRefTypeInfo(hrt, &spTypeInfo); - if(FAILED(hr)) - return vt; - TYPEATTR *pta = NULL; - - hr = spTypeInfo->GetTypeAttr(&pta); - if(SUCCEEDED(hr) && pta && (pta->typekind == TKIND_ALIAS || pta->typekind == TKIND_ENUM)) - { - if (pta->tdescAlias.vt == VT_USERDEFINED) - vt = AtlGetUserDefinedType(spTypeInfo, pta->tdescAlias.hreftype); - else - { - switch (pta->typekind) - { - case TKIND_ENUM : - vt = VT_I4; - break; - case TKIND_INTERFACE : - vt = VT_UNKNOWN; - break; - case TKIND_DISPATCH : - vt = VT_DISPATCH; - break; - default: - vt = pta->tdescAlias.vt; - } - } - } - - if(pta) - spTypeInfo->ReleaseTypeAttr(pta); - return vt; - -} -#pragma warning(pop) - -inline HRESULT AtlGetFuncInfoFromId(ITypeInfo* pTypeInfo, const IID& /*iid*/, DISPID dispidMember, LCID /*lcid*/, _ATL_FUNC_INFO& info) -{ - if (pTypeInfo == NULL) - return E_INVALIDARG; - - HRESULT hr = S_OK; - FUNCDESC* pFuncDesc = NULL; - TYPEATTR* pAttr; - hr = pTypeInfo->GetTypeAttr(&pAttr); - if (FAILED(hr)) - return hr; - int i; - for (i=0;icFuncs;i++) - { - hr = pTypeInfo->GetFuncDesc(i, &pFuncDesc); - if (FAILED(hr)) - return hr; - if (pFuncDesc->memid == dispidMember) - break; - pTypeInfo->ReleaseFuncDesc(pFuncDesc); - pFuncDesc = NULL; - } - pTypeInfo->ReleaseTypeAttr(pAttr); - if (pFuncDesc == NULL) - return E_FAIL; - - // If this assert occurs, then add a #define _ATL_MAX_VARTYPES nnnn - // before including atlcom.h - ATLASSERT(pFuncDesc->cParams <= _ATL_MAX_VARTYPES); - if (pFuncDesc->cParams > _ATL_MAX_VARTYPES) - return E_FAIL; - - for (i = 0; i < pFuncDesc->cParams; i++) - { - info.pVarTypes[i] = pFuncDesc->lprgelemdescParam[i].tdesc.vt; - if (info.pVarTypes[i] == VT_PTR) - info.pVarTypes[i] = (VARTYPE)(pFuncDesc->lprgelemdescParam[i].tdesc.lptdesc->vt | VT_BYREF); - if (info.pVarTypes[i] == VT_USERDEFINED) - info.pVarTypes[i] = AtlGetUserDefinedType(pTypeInfo, pFuncDesc->lprgelemdescParam[i].tdesc.hreftype); - } - - VARTYPE vtReturn = pFuncDesc->elemdescFunc.tdesc.vt; - switch(vtReturn) - { - case VT_INT: - vtReturn = VT_I4; - break; - case VT_UINT: - vtReturn = VT_UI4; - break; - case VT_VOID: - vtReturn = VT_EMPTY; // this is how DispCallFunc() represents void - break; - case VT_HRESULT: - vtReturn = VT_ERROR; - break; - } - info.vtReturn = vtReturn; - info.cc = pFuncDesc->callconv; - info.nParams = pFuncDesc->cParams; - pTypeInfo->ReleaseFuncDesc(pFuncDesc); - return S_OK; -} - -template -class ATL_NO_VTABLE IDispEventImpl : public IDispEventSimpleImpl -{ -public: - typedef tihclass _tihclass; - - IDispEventImpl() - { - m_libid = *plibid; - m_iid = *pdiid; - m_wMajorVerNum = wMajor; - m_wMinorVerNum = wMinor; - } - - STDMETHOD(GetTypeInfoCount)(UINT* pctinfo) - { - if (pctinfo == NULL) - return E_POINTER; - *pctinfo = 1; - return S_OK; - } - - STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo** pptinfo) - {return _tih.GetTypeInfo(itinfo, lcid, pptinfo);} - - STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames, - LCID lcid, DISPID* rgdispid) - {return _tih.GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);} - - //Helper for finding the function index for a DISPID - HRESULT GetFuncInfoFromId(const IID& iid, DISPID dispidMember, LCID lcid, _ATL_FUNC_INFO& info) - { - CComPtr spTypeInfo; - if (InlineIsEqualGUID(*_tih.m_plibid, GUID_NULL)) - { - _tih.m_plibid = &m_libid; - _tih.m_pguid = &m_iid; - _tih.m_wMajor = m_wMajorVerNum; - _tih.m_wMinor = m_wMinorVerNum; - } - HRESULT hr = _tih.GetTI(lcid, &spTypeInfo); - if (FAILED(hr)) - return hr; - return AtlGetFuncInfoFromId(spTypeInfo, iid, dispidMember, lcid, info); - } - VARTYPE GetUserDefinedType(ITypeInfo *pTI, HREFTYPE hrt) - { - return AtlGetUserDefinedType(pTI, hrt); - } -protected: - static _tihclass _tih; - static HRESULT GetTI(LCID lcid, ITypeInfo** ppInfo) - {return _tih.GetTI(lcid, ppInfo);} -}; - - -template -typename IDispEventImpl::_tihclass -IDispEventImpl::_tih = - {piid, plibid, wMajor, wMinor, NULL, 0, NULL, 0}; - -template -struct _ATL_EVENT_ENTRY -{ - UINT nControlID; //ID identifying object instance - const IID* piid; //dispinterface IID - int nOffset; //offset of dispinterface from this pointer - DISPID dispid; //DISPID of method/property - void (__stdcall T::*pfn)(); //method to invoke - _ATL_FUNC_INFO* pInfo; -}; - - - -//Sink map is used to set up event handling -#define BEGIN_SINK_MAP(_class)\ - typedef _class _GetSinkMapFinder;\ - static const ATL::_ATL_EVENT_ENTRY<_class>* _GetSinkMap()\ - {\ - typedef _class _atl_event_classtype;\ - static const ATL::_ATL_EVENT_ENTRY<_class> map[] = { - - -#define SINK_ENTRY_INFO(id, iid, dispid, fn, info) {id, &iid, (int)(INT_PTR)(static_cast*>((_atl_event_classtype*)8))-8, dispid, (void (__stdcall _atl_event_classtype::*)())fn, info}, -#define SINK_ENTRY_EX(id, iid, dispid, fn) SINK_ENTRY_INFO(id, iid, dispid, fn, NULL) -#define SINK_ENTRY(id, dispid, fn) SINK_ENTRY_EX(id, IID_NULL, dispid, fn) -#define END_SINK_MAP() {0, NULL, 0, 0, NULL, NULL} }; return map;} - -///////////////////////////////////////////////////////////////////////////// -// IDispatchImpl - -template -class ATL_NO_VTABLE IDispatchImpl : public T -{ -public: - typedef tihclass _tihclass; -// IDispatch - STDMETHOD(GetTypeInfoCount)(UINT* pctinfo) - { - if (pctinfo == NULL) - return E_POINTER; - *pctinfo = 1; - return S_OK; - } - STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo** pptinfo) - { - return _tih.GetTypeInfo(itinfo, lcid, pptinfo); - } - STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames, - LCID lcid, DISPID* rgdispid) - { - return _tih.GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid); - } - STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid, - LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, - EXCEPINFO* pexcepinfo, UINT* puArgErr) - { - return _tih.Invoke((IDispatch*)this, dispidMember, riid, lcid, - wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr); - } - -#ifdef _ATL_DLL_IMPL - // Do not cache type info if it is used in atl71.dll - IDispatchImpl() : _tih(piid, plibid, wMajor, wMinor) - { - } - virtual ~IDispatchImpl() - { - } - -protected: - _tihclass _tih; - HRESULT GetTI(LCID lcid, ITypeInfo** ppInfo) - { - return _tih.GetTI(lcid, ppInfo); - } - -#else - -protected: - static _tihclass _tih; - static HRESULT GetTI(LCID lcid, ITypeInfo** ppInfo) - { - return _tih.GetTI(lcid, ppInfo); - } - -#endif - -}; - -#ifndef _ATL_DLL_IMPL - -template -typename IDispatchImpl::_tihclass -IDispatchImpl::_tih = -{piid, plibid, wMajor, wMinor, NULL, 0, NULL, 0}; - -#endif - -///////////////////////////////////////////////////////////////////////////// -// IProvideClassInfoImpl -template -class ATL_NO_VTABLE IProvideClassInfoImpl : public IProvideClassInfo -{ -public: - typedef tihclass _tihclass; - - STDMETHOD(GetClassInfo)(ITypeInfo** pptinfo) - { - return _tih.GetTypeInfo(0, LANG_NEUTRAL, pptinfo); - } - -protected: - static _tihclass _tih; -}; - -template -typename IProvideClassInfoImpl::_tihclass -IProvideClassInfoImpl::_tih = -{pcoclsid,plibid, wMajor, wMinor, NULL, 0, NULL, 0}; - -///////////////////////////////////////////////////////////////////////////// -// IProvideClassInfo2Impl -template -class ATL_NO_VTABLE IProvideClassInfo2Impl : public IProvideClassInfo2 -{ -public: - typedef tihclass _tihclass; - - STDMETHOD(GetClassInfo)(ITypeInfo** pptinfo) - { - return _tih.GetTypeInfo(0, LANG_NEUTRAL, pptinfo); - } - STDMETHOD(GetGUID)(DWORD dwGuidKind, GUID* pGUID) - { - if (pGUID == NULL) - return E_POINTER; - - if (dwGuidKind == GUIDKIND_DEFAULT_SOURCE_DISP_IID && psrcid != NULL) - { - *pGUID = *psrcid; - return S_OK; - } - *pGUID = GUID_NULL; - return E_FAIL; - } - -protected: - static _tihclass _tih; -}; - - -template -typename IProvideClassInfo2Impl::_tihclass -IProvideClassInfo2Impl::_tih = -{pcoclsid,plibid, wMajor, wMinor, NULL, 0, NULL, 0}; - - -///////////////////////////////////////////////////////////////////////////// -// ISupportErrorInfoImpl - -template -class ATL_NO_VTABLE ISupportErrorInfoImpl : public ISupportErrorInfo -{ -public: - STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid) - { - return (InlineIsEqualGUID(riid,*piid)) ? S_OK : S_FALSE; - } -}; - - -///////////////////////////////////////////////////////////////////////////// -// CComEnumImpl - -// These _CopyXXX classes are used with enumerators in order to control -// how enumerated items are initialized, copied, and deleted - -// Default is shallow copy with no special init or cleanup -template -class _Copy -{ -public: - static HRESULT copy(T* p1, T* p2) {memcpy(p1, p2, sizeof(T)); return S_OK;} - static void init(T*) {} - static void destroy(T*) {} -}; - -template<> -class _Copy -{ -public: - static HRESULT copy(VARIANT* p1, VARIANT* p2) {p1->vt = VT_EMPTY; return VariantCopy(p1, p2);} - static void init(VARIANT* p) {p->vt = VT_EMPTY;} - static void destroy(VARIANT* p) {VariantClear(p);} -}; - -template<> -class _Copy -{ -public: - static HRESULT copy(LPOLESTR* p1, LPOLESTR* p2) - { - HRESULT hr = S_OK; - (*p1) = (LPOLESTR)CoTaskMemAlloc(sizeof(OLECHAR)*(ocslen(*p2)+1)); - if (*p1 == NULL) - hr = E_OUTOFMEMORY; - else - ocscpy(*p1,*p2); - return hr; - } - static void init(LPOLESTR* p) {*p = NULL;} - static void destroy(LPOLESTR* p) { CoTaskMemFree(*p);} -}; - -template<> -class _Copy -{ -public: - static HRESULT copy(OLEVERB* p1, OLEVERB* p2) - { - HRESULT hr = S_OK; - *p1 = *p2; - if (p2->lpszVerbName == NULL) - return S_OK; - p1->lpszVerbName = (LPOLESTR)CoTaskMemAlloc(sizeof(OLECHAR)*(ocslen(p2->lpszVerbName)+1)); - if (p1->lpszVerbName == NULL) - hr = E_OUTOFMEMORY; - else - ocscpy(p1->lpszVerbName,p2->lpszVerbName); - return hr; - } - static void init(OLEVERB* p) { p->lpszVerbName = NULL;} - static void destroy(OLEVERB* p) { if (p->lpszVerbName) CoTaskMemFree(p->lpszVerbName);} -}; - -template<> -class _Copy -{ -public: - static HRESULT copy(CONNECTDATA* p1, CONNECTDATA* p2) - { - *p1 = *p2; - if (p1->pUnk) - p1->pUnk->AddRef(); - return S_OK; - } - static void init(CONNECTDATA* ) {} - static void destroy(CONNECTDATA* p) {if (p->pUnk) p->pUnk->Release();} -}; - -template -class _CopyInterface -{ -public: - static HRESULT copy(T** p1, T** p2) - { - *p1 = *p2; - if (*p1) - (*p1)->AddRef(); - return S_OK; - } - static void init(T** ) {} - static void destroy(T** p) {if (*p) (*p)->Release();} -}; - -template -class ATL_NO_VTABLE CComIEnum : public IUnknown -{ -public: - STDMETHOD(Next)(ULONG celt, T* rgelt, ULONG* pceltFetched) = 0; - STDMETHOD(Skip)(ULONG celt) = 0; - STDMETHOD(Reset)(void) = 0; - STDMETHOD(Clone)(CComIEnum** ppEnum) = 0; -}; - - -enum CComEnumFlags -{ - //see FlagBits in CComEnumImpl - AtlFlagNoCopy = 0, - AtlFlagTakeOwnership = 2, - AtlFlagCopy = 3 // copy implies ownership -}; - -template -class ATL_NO_VTABLE CComEnumImpl : public Base -{ -public: - CComEnumImpl() {m_begin = m_end = m_iter = NULL; m_dwFlags = 0;} - virtual ~CComEnumImpl(); - STDMETHOD(Next)(ULONG celt, T* rgelt, ULONG* pceltFetched); - STDMETHOD(Skip)(ULONG celt); - STDMETHOD(Reset)(void){m_iter = m_begin;return S_OK;} - STDMETHOD(Clone)(Base** ppEnum); - HRESULT Init(T* begin, T* end, IUnknown* pUnk, - CComEnumFlags flags = AtlFlagNoCopy); - CComPtr m_spUnk; - T* m_begin; - T* m_end; - T* m_iter; - DWORD m_dwFlags; -protected: - enum FlagBits - { - BitCopy=1, - BitOwn=2 - }; -}; - -template -CComEnumImpl::~CComEnumImpl() -{ - if (m_dwFlags & BitOwn) - { - for (T* p = m_begin; p != m_end; p++) - Copy::destroy(p); - delete [] m_begin; - } -} - -template -STDMETHODIMP CComEnumImpl::Next(ULONG celt, T* rgelt, - ULONG* pceltFetched) -{ - if (pceltFetched != NULL) - *pceltFetched = 0; - if (celt == 0) - return E_INVALIDARG; - if (rgelt == NULL || (celt != 1 && pceltFetched == NULL)) - return E_POINTER; - if (m_begin == NULL || m_end == NULL || m_iter == NULL) - return E_FAIL; - ULONG nRem = (ULONG)(m_end - m_iter); - HRESULT hRes = S_OK; - if (nRem < celt) - hRes = S_FALSE; - ULONG nMin = celt < nRem ? celt : nRem ; - if (pceltFetched != NULL) - *pceltFetched = nMin; - T* pelt = rgelt; - while(nMin--) - { - HRESULT hr = Copy::copy(pelt, m_iter); - if (FAILED(hr)) - { - while (rgelt < pelt) - Copy::destroy(rgelt++); - if (pceltFetched != NULL) - *pceltFetched = 0; - return hr; - } - pelt++; - m_iter++; - } - return hRes; -} - -template -STDMETHODIMP CComEnumImpl::Skip(ULONG celt) -{ - if (celt == 0) - return E_INVALIDARG; - - ULONG nRem = ULONG(m_end - m_iter); - ULONG nSkip = (celt > nRem) ? nRem : celt; - m_iter += nSkip; - return (celt == nSkip) ? S_OK : S_FALSE; -} - -template -STDMETHODIMP CComEnumImpl::Clone(Base** ppEnum) -{ - typedef CComObject > _class; - HRESULT hRes = E_POINTER; - if (ppEnum != NULL) - { - *ppEnum = NULL; - _class* p; - hRes = _class::CreateInstance(&p); - if (SUCCEEDED(hRes)) - { - // If this object has ownership of the data then we need to keep it around - hRes = p->Init(m_begin, m_end, (m_dwFlags & BitOwn) ? this : m_spUnk); - if (SUCCEEDED(hRes)) - { - p->m_iter = m_iter; - hRes = p->_InternalQueryInterface(*piid, (void**)ppEnum); - } - if (FAILED(hRes)) - delete p; - } - } - return hRes; -} - -template -HRESULT CComEnumImpl::Init(T* begin, T* end, IUnknown* pUnk, - CComEnumFlags flags) -{ - if (flags == AtlFlagCopy) - { - ATLASSERT(m_begin == NULL); //Init called twice? - ATLTRY(m_begin = new T[end-begin]) - m_iter = m_begin; - if (m_begin == NULL) - return E_OUTOFMEMORY; - for (T* i=begin; i != end; i++) - { - Copy::init(m_iter); - HRESULT hr = Copy::copy(m_iter, i); - if (FAILED(hr)) - { - T* p = m_begin; - while (p < m_iter) - Copy::destroy(p++); - delete [] m_begin; - m_begin = m_end = m_iter = NULL; - return hr; - } - m_iter++; - } - m_end = m_begin + (end-begin); - } - else - { - m_begin = begin; - m_end = end; - } - m_spUnk = pUnk; - m_iter = m_begin; - m_dwFlags = flags; - return S_OK; -} - -template -class ATL_NO_VTABLE CComEnum : - public CComEnumImpl, - public CComObjectRootEx< ThreadModel > -{ -public: - typedef CComEnum _CComEnum; - typedef CComEnumImpl _CComEnumBase; - BEGIN_COM_MAP(_CComEnum) - COM_INTERFACE_ENTRY_IID(*piid, _CComEnumBase) - END_COM_MAP() -}; - -template -class ATL_NO_VTABLE IEnumOnSTLImpl : public Base -{ -public: - HRESULT Init(IUnknown *pUnkForRelease, CollType& collection) - { - m_spUnk = pUnkForRelease; - m_pcollection = &collection; - m_iter = m_pcollection->begin(); - return S_OK; - } - STDMETHOD(Next)(ULONG celt, T* rgelt, ULONG* pceltFetched); - STDMETHOD(Skip)(ULONG celt); - STDMETHOD(Reset)(void) - { - if (m_pcollection == NULL) - return E_FAIL; - m_iter = m_pcollection->begin(); - return S_OK; - } - STDMETHOD(Clone)(Base** ppEnum); -//Data - CComPtr m_spUnk; - CollType* m_pcollection; - typename CollType::iterator m_iter; -}; - -template -STDMETHODIMP IEnumOnSTLImpl::Next(ULONG celt, T* rgelt, - ULONG* pceltFetched) -{ - if (rgelt == NULL || (celt != 1 && pceltFetched == NULL)) - return E_POINTER; - if (pceltFetched != NULL) - *pceltFetched = 0; - if (m_pcollection == NULL) - return E_FAIL; - - ULONG nActual = 0; - HRESULT hr = S_OK; - T* pelt = rgelt; - while (SUCCEEDED(hr) && m_iter != m_pcollection->end() && nActual < celt) - { - hr = Copy::copy(pelt, &*m_iter); - if (FAILED(hr)) - { - while (rgelt < pelt) - Copy::destroy(rgelt++); - nActual = 0; - } - else - { - pelt++; - m_iter++; - nActual++; - } - } - if (SUCCEEDED(hr)) - { - if (pceltFetched) - *pceltFetched = nActual; - if (nActual < celt) - hr = S_FALSE; - } - return hr; -} - -template -STDMETHODIMP IEnumOnSTLImpl::Skip(ULONG celt) -{ - HRESULT hr = S_OK; - while (celt--) - { - if (m_iter != m_pcollection->end()) - m_iter++; - else - { - hr = S_FALSE; - break; - } - } - return hr; -} - -template -STDMETHODIMP IEnumOnSTLImpl::Clone(Base** ppEnum) -{ - typedef CComObject > _class; - HRESULT hRes = E_POINTER; - if (ppEnum != NULL) - { - *ppEnum = NULL; - _class* p; - hRes = _class::CreateInstance(&p); - if (SUCCEEDED(hRes)) - { - hRes = p->Init(m_spUnk, *m_pcollection); - if (SUCCEEDED(hRes)) - { - p->m_iter = m_iter; - hRes = p->_InternalQueryInterface(*piid, (void**)ppEnum); - } - if (FAILED(hRes)) - delete p; - } - } - return hRes; -} - -template -class ATL_NO_VTABLE CComEnumOnSTL : - public IEnumOnSTLImpl, - public CComObjectRootEx< ThreadModel > -{ -public: - typedef CComEnumOnSTL _CComEnum; - typedef IEnumOnSTLImpl _CComEnumBase; - BEGIN_COM_MAP(_CComEnum) - COM_INTERFACE_ENTRY_IID(*piid, _CComEnumBase) - END_COM_MAP() -}; - -template -class ICollectionOnSTLImpl : public T -{ -public: - STDMETHOD(get_Count)(long* pcount) - { - if (pcount == NULL) - return E_POINTER; - ATLASSERT(m_coll.size()<=LONG_MAX); - - *pcount = (long)m_coll.size(); - - return S_OK; - } - STDMETHOD(get_Item)(long Index, ItemType* pvar) - { - //Index is 1-based - if (pvar == NULL) - return E_POINTER; - if (Index < 1) - return E_INVALIDARG; - HRESULT hr = E_FAIL; - Index--; - CollType::iterator iter = m_coll.begin(); - while (iter != m_coll.end() && Index > 0) - { - iter++; - Index--; - } - if (iter != m_coll.end()) - hr = CopyItem::copy(pvar, &*iter); - return hr; - } - STDMETHOD(get__NewEnum)(IUnknown** ppUnk) - { - if (ppUnk == NULL) - return E_POINTER; - *ppUnk = NULL; - HRESULT hRes = S_OK; - CComObject* p; - hRes = CComObject::CreateInstance(&p); - if (SUCCEEDED(hRes)) - { - hRes = p->Init(this, m_coll); - if (hRes == S_OK) - hRes = p->QueryInterface(__uuidof(IUnknown), (void**)ppUnk); - } - if (hRes != S_OK) - delete p; - return hRes; - } - CollType m_coll; -}; - -////////////////////////////////////////////////////////////////////////////// -// ISpecifyPropertyPagesImpl -template -class ATL_NO_VTABLE ISpecifyPropertyPagesImpl : public ISpecifyPropertyPages -{ -public: - // ISpecifyPropertyPages - // - STDMETHOD(GetPages)(CAUUID* pPages) - { - ATLTRACE(atlTraceCOM, 2, _T("ISpecifyPropertyPagesImpl::GetPages\n")); - ATL_PROPMAP_ENTRY* pMap = T::GetPropertyMap(); - return GetPagesHelper(pPages, pMap); - } -protected: - HRESULT GetPagesHelper(CAUUID* pPages, ATL_PROPMAP_ENTRY* pMap) - { - if (pPages == NULL) - return E_POINTER; - ATLASSERT(pMap != NULL); - if (pMap == NULL) - return E_POINTER; - - int nCnt = 0; - int i; - // Get count of unique pages to alloc the array - for (i = 0; pMap[i].pclsidPropPage != NULL; i++) - { - // only allow non data entry types - if (pMap[i].vt == 0) - { - // Does this property have a page? CLSID_NULL means it does not - if (!InlineIsEqualGUID(*pMap[i].pclsidPropPage, CLSID_NULL)) - nCnt++; - } - } - pPages->pElems = (GUID*) CoTaskMemAlloc(sizeof(CLSID)*nCnt); - if (pPages->pElems == NULL) - return E_OUTOFMEMORY; - // reset count of items we have added to the array - nCnt = 0; - for (i = 0; pMap[i].pclsidPropPage != NULL; i++) - { - // only allow non data entry types - if (pMap[i].vt == 0) - { - // Does this property have a page? CLSID_NULL means it does not - if (!InlineIsEqualGUID(*pMap[i].pclsidPropPage, CLSID_NULL)) - { - BOOL bFound = FALSE; - // Search through array we are building up to see - // if it is already in there - for (int j=0; jpElems[j])) - { - // It's already there, so no need to add it again - bFound = TRUE; - break; - } - } - // If we didn't find it in there then add it - if (!bFound) - pPages->pElems[nCnt++] = *pMap[i].pclsidPropPage; - } - } - } - pPages->cElems = nCnt; - return S_OK; - } - -}; - -#ifndef _ATL_NO_CONNECTION_POINTS -///////////////////////////////////////////////////////////////////////////// -// Connection Points - -struct _ATL_CONNMAP_ENTRY -{ - DWORD_PTR dwOffset; -}; - - -// We want the offset of the connection point relative to the connection -// point container base class -#define BEGIN_CONNECTION_POINT_MAP(x)\ - __if_not_exists(_atl_conn_classtype) \ - { \ - typedef x _atl_conn_classtype;\ - } \ - static const ATL::_ATL_CONNMAP_ENTRY* GetConnMap(int* pnEntries) {\ - static const ATL::_ATL_CONNMAP_ENTRY _entries[] = { -#define BEGIN_ATTRCONNECTION_POINT_MAP(x)\ - __if_not_exists(_atl_conn_classtype) \ - { \ - typedef x _atl_conn_classtype;\ - } \ - static const ATL::_ATL_CONNMAP_ENTRY* GetAttrConnMap(int* pnEntries) {\ - static const ATL::_ATL_CONNMAP_ENTRY _entries[] = { - -// CONNECTION_POINT_ENTRY computes the offset of the connection point to the -// IConnectionPointContainer interface -#define CONNECTION_POINT_ENTRY(iid){offsetofclass(ATL::_ICPLocator<&iid>, _atl_conn_classtype)-\ - offsetofclass(ATL::IConnectionPointContainerImpl<_atl_conn_classtype>, _atl_conn_classtype)}, -#define END_CONNECTION_POINT_MAP() \ - __if_exists(GetAttrConnMap) \ - { \ - {(DWORD_PTR) -2}, \ - {(DWORD_PTR) GetAttrConnMap }, \ - } \ - {(DWORD_PTR)-1} }; \ - if (pnEntries) \ - { \ - __if_exists(GetAttrConnMap) \ - { \ - GetAttrConnMap(pnEntries); \ - *pnEntries += sizeof(_entries)/sizeof(ATL::_ATL_CONNMAP_ENTRY) - 3; \ - } \ - __if_not_exists(GetAttrConnMap) \ - { \ - *pnEntries = sizeof(_entries)/sizeof(ATL::_ATL_CONNMAP_ENTRY) - 1; \ - } \ - } \ - return _entries;} -#define END_ATTRCONNECTION_POINT_MAP() \ - {(DWORD_PTR)-1} }; \ - if (pnEntries) \ - { \ - *pnEntries = sizeof(_entries)/sizeof(ATL::_ATL_CONNMAP_ENTRY) - 1; \ - } \ - return _entries;} - - -#ifndef _DEFAULT_VECTORLENGTH -#define _DEFAULT_VECTORLENGTH 4 -#endif - -template -class CComUnkArray -{ -public: - CComUnkArray() - { - memset(m_arr, 0, sizeof(IUnknown*)*nMaxSize); - } - DWORD Add(IUnknown* pUnk); - BOOL Remove(DWORD dwCookie); - // If there is more than one instance of the same IUnknown*, - // this function returns the cookie for the first one. - DWORD WINAPI GetCookie(IUnknown** ppFind) - { - ATLASSERT(ppFind && *ppFind); - if (ppFind && *ppFind) - { - // find IUnknown* in array - for (DWORD dwCookie = 0; dwCookie < nMaxSize; dwCookie++) - { - if (m_arr[dwCookie] == *ppFind) - return dwCookie+1; // cookie minus one is an index into the array - } - } - return 0; - } - IUnknown* WINAPI GetUnknown(DWORD dwCookie) - { - ATLASSERT(dwCookie != 0 && dwCookie <= nMaxSize); - if (dwCookie != 0 && dwCookie <= nMaxSize) - return m_arr[dwCookie-1]; // cookie minus one is an index into the array - else - return NULL; - } - IUnknown** begin() - { - return &m_arr[0]; - } - IUnknown** end() - { - return &m_arr[nMaxSize]; - } -protected: - IUnknown* m_arr[nMaxSize]; -}; - -template -inline DWORD CComUnkArray::Add(IUnknown* pUnk) -{ - DWORD dwCookie = 1; - for (IUnknown** pp = begin(); pp < end(); pp++) - { - if (*pp == NULL) - { - *pp = pUnk; - return dwCookie; - } - dwCookie++; - } - // If this fires then you need a larger array - ATLASSERT(0); - return 0; -} - -template -inline BOOL CComUnkArray::Remove(DWORD dwCookie) -{ - ATLASSERT(dwCookie != 0 && dwCookie <= nMaxSize); - if (dwCookie != 0 && dwCookie <= nMaxSize && m_arr[dwCookie-1] != NULL) - { - m_arr[dwCookie-1] = NULL; - return TRUE; - } - else - return FALSE; -} - -template<> -class CComUnkArray<1> -{ -public: - CComUnkArray() - { - m_arr[0] = NULL; - } - DWORD Add(IUnknown* pUnk) - { - if (m_arr[0] != NULL) - { - // If this fires then you need a larger array - ATLASSERT(0); - return 0; - } - m_arr[0] = pUnk; - return 1; - } - BOOL Remove(DWORD dwCookie) - { - ATLASSERT(dwCookie == 1); - if (dwCookie == 1 && m_arr[0] != NULL) - { - m_arr[0] = NULL; - return TRUE; - } - else - return FALSE; - } - DWORD WINAPI GetCookie(IUnknown** /* pp */) - { - return 1; - } - IUnknown* WINAPI GetUnknown(DWORD dwCookie) - { - ATLASSERT(dwCookie == 1); - if (dwCookie == 1) - return m_arr[0]; - else - return NULL; - } - IUnknown** begin() - { - return &m_arr[0]; - } - IUnknown** end() - { - return (&m_arr[0])+1; - } -protected: - IUnknown* m_arr[1]; -}; - -class CComDynamicUnkArray -{ -public: - CComDynamicUnkArray() - { - m_nSize = 0; - m_ppUnk = NULL; - } - - ~CComDynamicUnkArray() - { - if (m_nSize > 1) - free(m_ppUnk); - } - DWORD Add(IUnknown* pUnk); - BOOL Remove(DWORD dwCookie); - // If there is more than one instance of the same IUnknown*, - // this function returns the cookie for the first one. - DWORD WINAPI GetCookie(IUnknown** ppFind) - { - ATLASSERT(ppFind && *ppFind); - if (ppFind && *ppFind) - { - IUnknown** ppUnk = NULL; - DWORD dwCookie = 1; - // find IUnknown* in array - for (ppUnk = begin(); ppUnk < end(); ppUnk++) - { - if (*ppUnk == *ppFind) - return dwCookie; // cookie minus one is an index into the array - dwCookie++; - } - } - return 0; - } - IUnknown* WINAPI GetUnknown(DWORD dwCookie) - { -#ifndef _ATL_OLEDB_CONFORMANCE_TESTS - ATLASSERT(dwCookie != 0 && dwCookie <= (DWORD)m_nSize); -#endif - if (dwCookie != 0 && dwCookie <= (DWORD)m_nSize) - return GetAt(dwCookie-1); // cookie minus one is an index into the array - else - return NULL; - } - IUnknown** begin() - { - return (m_nSize < 2) ? &m_pUnk : m_ppUnk; - } - IUnknown** end() - { - return (m_nSize < 2) ? (&m_pUnk)+m_nSize : &m_ppUnk[m_nSize]; - } - - IUnknown* GetAt(int nIndex) - { - ATLASSERT(nIndex >= 0 && nIndex < m_nSize); - if (nIndex >= 0 && nIndex < m_nSize) - return (m_nSize < 2) ? m_pUnk : m_ppUnk[nIndex]; - else - return NULL; - - } - int GetSize() const - { - return m_nSize; - } - void clear() - { - if (m_nSize > 1) - free(m_ppUnk); - m_nSize = 0; - } -protected: - union - { - IUnknown** m_ppUnk; - IUnknown* m_pUnk; - }; - int m_nSize; -}; - -inline DWORD CComDynamicUnkArray::Add(IUnknown* pUnk) -{ - IUnknown** pp = NULL; - // Use m_pUnk for first item. No need to allocate array. - if (m_nSize == 0) - { - m_pUnk = pUnk; - m_nSize = 1; - return 1; - } - else if (m_nSize == 1) - { - // Create array with _DEFAULT_VECTORLENGTH number of items. - ATLTRY(pp = (IUnknown**)malloc(sizeof(IUnknown*)*_DEFAULT_VECTORLENGTH)); - if (pp == NULL) - return 0; - memset(pp, 0, sizeof(IUnknown*)*_DEFAULT_VECTORLENGTH); - *pp = m_pUnk; - m_ppUnk = pp; - m_nSize = _DEFAULT_VECTORLENGTH; - } - // Walk array and use empty slots if any. - DWORD dwCookie = 1; - for (pp = begin(); pp < end(); pp++) - { - if (*pp == NULL) - { - *pp = pUnk; - return dwCookie; // cookie minus one is index into array - } - dwCookie++; - } - // No empty slots so resize array. - // # of new slots is double of current size. - int nAlloc = m_nSize*2; - pp = (IUnknown**)realloc(m_ppUnk, sizeof(IUnknown*)*nAlloc); - if (pp == NULL) - return 0; - m_ppUnk = pp; - memset(&m_ppUnk[m_nSize], 0, sizeof(IUnknown*)*m_nSize); - m_ppUnk[m_nSize] = pUnk; - dwCookie = m_nSize+1; - m_nSize = nAlloc; - return dwCookie; // cookie minus one is index into array -} - -inline BOOL CComDynamicUnkArray::Remove(DWORD dwCookie) -{ -#ifndef _ATL_OLEDB_CONFORMANCE_TESTS - ATLASSERT(dwCookie != 0 && dwCookie <= (DWORD)m_nSize); -#endif - if (dwCookie != 0 && dwCookie <= (DWORD)m_nSize) - { - if (m_nSize == 1) - { - if (m_pUnk == NULL) - return FALSE; - m_nSize = 0; - m_pUnk = NULL; - } - else - { - // cookie minus one is index into array - if (m_ppUnk[dwCookie-1] == NULL) - return FALSE; - m_ppUnk[dwCookie-1] = NULL; - } - return TRUE; - } - else - return FALSE; -} - -template -class ATL_NO_VTABLE _ICPLocator -{ -public: - //this method needs a different name than QueryInterface - STDMETHOD(_LocCPQueryInterface)(REFIID riid, void ** ppvObject) = 0; - virtual ULONG STDMETHODCALLTYPE AddRef(void) = 0; - virtual ULONG STDMETHODCALLTYPE Release(void) = 0; -}; - -template -class ATL_NO_VTABLE IConnectionPointImpl : public _ICPLocator -{ - typedef CComEnum > CComEnumConnections; - typedef CDV _CDV; -public: - ~IConnectionPointImpl(); - STDMETHOD(_LocCPQueryInterface)(REFIID riid, void ** ppvObject) - { -#ifndef _ATL_OLEDB_CONFORMANCE_TESTS - ATLASSERT(ppvObject != NULL); -#endif - if (ppvObject == NULL) - return E_POINTER; - *ppvObject = NULL; - - if (InlineIsEqualGUID(riid, __uuidof(IConnectionPoint)) || InlineIsEqualUnknown(riid)) - { - *ppvObject = this; - AddRef(); -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.AddThunk((IUnknown**)ppvObject, _T("IConnectionPointImpl"), riid); -#endif // _ATL_DEBUG_INTERFACES - return S_OK; - } - else - return E_NOINTERFACE; - } - - STDMETHOD(GetConnectionInterface)(IID* piid2) - { - if (piid2 == NULL) - return E_POINTER; - *piid2 = *piid; - return S_OK; - } - STDMETHOD(GetConnectionPointContainer)(IConnectionPointContainer** ppCPC) - { - T* pT = static_cast(this); - // No need to check ppCPC for NULL since QI will do that for us - return pT->QueryInterface(__uuidof(IConnectionPointContainer), (void**)ppCPC); - } - STDMETHOD(Advise)(IUnknown* pUnkSink, DWORD* pdwCookie); - STDMETHOD(Unadvise)(DWORD dwCookie); - STDMETHOD(EnumConnections)(IEnumConnections** ppEnum); - CDV m_vec; -}; - -template -IConnectionPointImpl::~IConnectionPointImpl() -{ - IUnknown** pp = m_vec.begin(); - while (pp < m_vec.end()) - { - if (*pp != NULL) - (*pp)->Release(); - pp++; - } -} - -template -STDMETHODIMP IConnectionPointImpl::Advise(IUnknown* pUnkSink, - DWORD* pdwCookie) -{ - T* pT = static_cast(this); - IUnknown* p; - HRESULT hRes = S_OK; - if (pdwCookie != NULL) - *pdwCookie = 0; - if (pUnkSink == NULL || pdwCookie == NULL) - return E_POINTER; - IID iid; - GetConnectionInterface(&iid); - hRes = pUnkSink->QueryInterface(iid, (void**)&p); - if (SUCCEEDED(hRes)) - { - pT->Lock(); - *pdwCookie = m_vec.Add(p); - hRes = (*pdwCookie != NULL) ? S_OK : CONNECT_E_ADVISELIMIT; - pT->Unlock(); - if (hRes != S_OK) - p->Release(); - } - else if (hRes == E_NOINTERFACE) - hRes = CONNECT_E_CANNOTCONNECT; - if (FAILED(hRes)) - *pdwCookie = 0; - return hRes; -} - -template -STDMETHODIMP IConnectionPointImpl::Unadvise(DWORD dwCookie) -{ - T* pT = static_cast(this); - pT->Lock(); - IUnknown* p = m_vec.GetUnknown(dwCookie); - HRESULT hRes = m_vec.Remove(dwCookie) ? S_OK : CONNECT_E_NOCONNECTION; - pT->Unlock(); - if (hRes == S_OK && p != NULL) - p->Release(); - return hRes; -} - -template -STDMETHODIMP IConnectionPointImpl::EnumConnections( - IEnumConnections** ppEnum) -{ - if (ppEnum == NULL) - return E_POINTER; - *ppEnum = NULL; - CComObject* pEnum = NULL; - ATLTRY(pEnum = new CComObject) - if (pEnum == NULL) - return E_OUTOFMEMORY; - T* pT = static_cast(this); - pT->Lock(); - CONNECTDATA* pcd = NULL; - ATLTRY(pcd = new CONNECTDATA[m_vec.end()-m_vec.begin()]) - if (pcd == NULL) - { - delete pEnum; - pT->Unlock(); - return E_OUTOFMEMORY; - } - CONNECTDATA* pend = pcd; - // Copy the valid CONNECTDATA's - for (IUnknown** pp = m_vec.begin();ppAddRef(); - pend->pUnk = *pp; - pend->dwCookie = m_vec.GetCookie(pp); - pend++; - } - } - // don't copy the data, but transfer ownership to it - pEnum->Init(pcd, pend, NULL, AtlFlagTakeOwnership); - pT->Unlock(); - HRESULT hRes = pEnum->_InternalQueryInterface(__uuidof(IEnumConnections), (void**)ppEnum); - if (FAILED(hRes)) - delete pEnum; - return hRes; -} - -///////////////////////////////////////////////////////////////////////////// -// IConnectionPointContainerImpl - -template -class ATL_NO_VTABLE IConnectionPointContainerImpl : public IConnectionPointContainer -{ - typedef CComEnum > - CComEnumConnectionPoints; -public: - STDMETHOD(EnumConnectionPoints)(IEnumConnectionPoints** ppEnum) - { - if (ppEnum == NULL) - return E_POINTER; - *ppEnum = NULL; - CComEnumConnectionPoints* pEnum = NULL; - ATLTRY(pEnum = new CComObject) - if (pEnum == NULL) - return E_OUTOFMEMORY; - - int nCPCount; - const _ATL_CONNMAP_ENTRY* pEntry = T::GetConnMap(&nCPCount); - - // allocate an initialize a vector of connection point object pointers - USES_ATL_SAFE_ALLOCA; - IConnectionPoint** ppCP = (IConnectionPoint**)_ATL_SAFE_ALLOCA(sizeof(IConnectionPoint*)*nCPCount, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); - if (ppCP == NULL) - { - delete pEnum; - return E_OUTOFMEMORY; - } - - int i = 0; - while (pEntry->dwOffset != (DWORD_PTR)-1) - { - if (pEntry->dwOffset == (DWORD_PTR)-2) - { - pEntry++; - const _ATL_CONNMAP_ENTRY* (*pFunc)(int*) = (const _ATL_CONNMAP_ENTRY* (*)(int*))(pEntry->dwOffset); - pEntry = pFunc(NULL); - continue; - } - ppCP[i++] = (IConnectionPoint*)((INT_PTR)this+pEntry->dwOffset); - pEntry++; - } - - // copy the pointers: they will AddRef this object - HRESULT hRes = pEnum->Init((IConnectionPoint**)&ppCP[0], - (IConnectionPoint**)&ppCP[nCPCount], - reinterpret_cast(this), AtlFlagCopy); - if (FAILED(hRes)) - { - delete pEnum; - return hRes; - } - hRes = pEnum->QueryInterface(__uuidof(IEnumConnectionPoints), (void**)ppEnum); - if (FAILED(hRes)) - delete pEnum; - return hRes; - } - STDMETHOD(FindConnectionPoint)(REFIID riid, IConnectionPoint** ppCP) - { - if (ppCP == NULL) - return E_POINTER; - *ppCP = NULL; - HRESULT hRes = CONNECT_E_NOCONNECTION; - const _ATL_CONNMAP_ENTRY* pEntry = T::GetConnMap(NULL); - IID iid; - while (pEntry->dwOffset != (DWORD_PTR)-1) - { - if (pEntry->dwOffset == (DWORD_PTR)-2) - { - pEntry++; - const _ATL_CONNMAP_ENTRY* (*pFunc)(int*) = (const _ATL_CONNMAP_ENTRY* (*)(int*))(pEntry->dwOffset); - pEntry = pFunc(NULL); - continue; - } - IConnectionPoint* pCP = - (IConnectionPoint*)((INT_PTR)this+pEntry->dwOffset); - if (SUCCEEDED(pCP->GetConnectionInterface(&iid)) && - InlineIsEqualGUID(riid, iid)) - { - *ppCP = pCP; - pCP->AddRef(); - hRes = S_OK; - break; - } - pEntry++; - } - return hRes; - } -}; - -#endif //!_ATL_NO_CONNECTION_POINTS - -///////////////////////////////////////////////////////////////////////////// -// IExternalConnectionImpl - -// An object that implements IExternalConnection should explicitly call -// CoDisconnectObject on itself when its external reference count drops to 0. -// This call will cause the stub manager to call Release on the object so the -// object can destroy itself. - -template -class IExternalConnectionImpl : public IExternalConnection -{ -public: - IExternalConnectionImpl(void) : m_nStrongLocks(0) {} - STDMETHODIMP_(DWORD) AddConnection(DWORD extconn, DWORD /*dwReserved*/) - { - DWORD dw = 0; - if (extconn & EXTCONN_STRONG) - { - dw = T::_ThreadModel::Increment(&m_nStrongLocks); - static_cast(this)->OnAddConnection(dw == 1); - } - return dw; - } - STDMETHODIMP_(DWORD) ReleaseConnection(DWORD extconn, DWORD /*dwReserved*/, BOOL bLastUnlockReleases) - { - DWORD dw = 0; - if (extconn & EXTCONN_STRONG) - { - dw = T::_ThreadModel::Decrement(&m_nStrongLocks); - static_cast(this)->OnReleaseConnection(dw == 0, !!bLastUnlockReleases); - } - return dw; - } - - // Services provided by this class - bool DoIHaveAStub() { return m_nStrongLocks != 0; } - LONG GetStrongConnectionCount() { return m_nStrongLocks; } - // Extensibility points provided by this class - void OnAddConnection(bool bThisIsFirstLock) {} - void OnReleaseConnection(bool bThisIsLastUnlock, bool bLastUnlockReleases) - { - if (bThisIsLastUnlock && bLastUnlockReleases) - CoDisconnectObject(static_cast(this)->GetUnknown(), 0); - } - // Implementation - LONG m_nStrongLocks; -}; - -#pragma pack(pop) - -// All exports go here -#ifndef _ATL_DLL - -///////////////////////////////////////////////////////////////////////////// -// IDispatch Error handling - -ATLINLINE ATLAPI AtlSetErrorInfo(const CLSID& clsid, LPCOLESTR lpszDesc, DWORD dwHelpID, - LPCOLESTR lpszHelpFile, const IID& iid, HRESULT hRes, HINSTANCE hInst) -{ - USES_CONVERSION_EX; - TCHAR szDesc[1024]; - szDesc[0] = NULL; - // For a valid HRESULT the id should be in the range [0x0200, 0xffff] - if (IS_INTRESOURCE(lpszDesc)) //id - { - UINT nID = LOWORD((DWORD_PTR)lpszDesc); - ATLASSERT((nID >= 0x0200 && nID <= 0xffff) || hRes != 0); - if (LoadString(hInst, nID, szDesc, 1024) == 0) - { - ATLASSERT(FALSE); - lstrcpy(szDesc, _T("Unknown Error")); - } - lpszDesc = T2OLE_EX(szDesc, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if(lpszDesc == NULL) - return E_OUTOFMEMORY; -#endif - if (hRes == 0) - hRes = MAKE_HRESULT(3, FACILITY_ITF, nID); - } - - CComPtr pICEI; - if (SUCCEEDED(CreateErrorInfo(&pICEI))) - { - CComPtr pErrorInfo; - pICEI->SetGUID(iid); - LPOLESTR lpsz; - ProgIDFromCLSID(clsid, &lpsz); - if (lpsz != NULL) - pICEI->SetSource(lpsz); - if (dwHelpID != 0 && lpszHelpFile != NULL) - { - pICEI->SetHelpContext(dwHelpID); - pICEI->SetHelpFile(const_cast(lpszHelpFile)); - } - CoTaskMemFree(lpsz); - pICEI->SetDescription((LPOLESTR)lpszDesc); - if (SUCCEEDED(pICEI->QueryInterface(__uuidof(IErrorInfo), (void**)&pErrorInfo))) - SetErrorInfo(0, pErrorInfo); - } - return (hRes == 0) ? DISP_E_EXCEPTION : hRes; -} - -///////////////////////////////////////////////////////////////////////////// -// IPersist* helpers. - -ATLINLINE ATLAPI AtlIPersistStreamInit_Load(LPSTREAM pStm, ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk) -{ - ATLASSERT(pMap != NULL); - if (pStm == NULL || pMap == NULL || pThis == NULL || pUnk == NULL) - return E_INVALIDARG; - - HRESULT hr = S_OK; - DWORD dwVer; - hr = pStm->Read(&dwVer, sizeof(DWORD), NULL); - if (FAILED(hr)) - return hr; - if (dwVer > _ATL_VER) - return E_FAIL; - - CComPtr pDispatch; - const IID* piidOld = NULL; - for (int i = 0; pMap[i].pclsidPropPage != NULL; i++) - { - if (pMap[i].szDesc == NULL) - continue; - - // check if raw data entry - if (pMap[i].dwSizeData != 0) - { - void* pData = (void*) (pMap[i].dwOffsetData + (DWORD_PTR)pThis); - // call CComBSTR::ReadFromStream for BSTRs - if (pMap[i].vt == VT_BSTR) - { - CComBSTR bstrRead; - hr = bstrRead.ReadFromStream(pStm); - (*(BSTR*)pData) = bstrRead.Detach(); - } - else - hr = pStm->Read(pData, pMap[i].dwSizeData, NULL); - if (FAILED(hr)) - return hr; - continue; - } - - CComVariant var; - - hr = var.ReadFromStream(pStm); - if (FAILED(hr)) - break; - - if (pMap[i].piidDispatch != piidOld) - { - pDispatch.Release(); - if (FAILED(pUnk->QueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch))) - { - ATLTRACE(atlTraceCOM, 0, _T("Failed to get a dispatch pointer for property #%i\n"), i); - hr = E_FAIL; - break; - } - piidOld = pMap[i].piidDispatch; - } - - if (FAILED(pDispatch.PutProperty(pMap[i].dispid, &var))) - { - ATLTRACE(atlTraceCOM, 0, _T("Invoked failed on DISPID %x\n"), pMap[i].dispid); - hr = E_FAIL; - break; - } - } - return hr; -} - -ATLINLINE ATLAPI AtlIPersistStreamInit_Save(LPSTREAM pStm, - BOOL /* fClearDirty */, ATL_PROPMAP_ENTRY* pMap, - void* pThis, IUnknown* pUnk) -{ - ATLASSERT(pMap != NULL); - if (pStm == NULL || pMap == NULL || pThis == NULL || pUnk == NULL) - return E_INVALIDARG; - - DWORD dw = _ATL_VER; - HRESULT hr = pStm->Write(&dw, sizeof(DWORD), NULL); - if (FAILED(hr)) - return hr; - - CComPtr pDispatch; - const IID* piidOld = NULL; - for (int i = 0; pMap[i].pclsidPropPage != NULL; i++) - { - if (pMap[i].szDesc == NULL) - continue; - - // check if raw data entry - if (pMap[i].dwSizeData != 0) - { - void* pData = (void*) (pMap[i].dwOffsetData + (DWORD_PTR)pThis); - // call CComBSTR::WriteToStream for BSTRs - if (pMap[i].vt == VT_BSTR) - { - CComBSTR bstrWrite; - bstrWrite.Attach(*(BSTR*)pData); - hr = bstrWrite.WriteToStream(pStm); - bstrWrite.Detach(); - } - else - hr = pStm->Write(pData, pMap[i].dwSizeData, NULL); - if (FAILED(hr)) - return hr; - continue; - } - - CComVariant var; - if (pMap[i].piidDispatch != piidOld) - { - pDispatch.Release(); - if (FAILED(pUnk->QueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch))) - { - ATLTRACE(atlTraceCOM, 0, _T("Failed to get a dispatch pointer for property #%i\n"), i); - hr = E_FAIL; - break; - } - piidOld = pMap[i].piidDispatch; - } - - if (FAILED(pDispatch.GetProperty(pMap[i].dispid, &var))) - { - ATLTRACE(atlTraceCOM, 0, _T("Invoked failed on DISPID %x\n"), pMap[i].dispid); - hr = E_FAIL; - break; - } - - hr = var.WriteToStream(pStm); - if (FAILED(hr)) - break; - } - return hr; -} -ATLINLINE ATLAPI AtlIPersistPropertyBag_Load(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog, ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk) -{ - if (pPropBag == NULL || pMap == NULL || pThis == NULL || pUnk == NULL) - return E_INVALIDARG; - - CComPtr pDispatch; - const IID* piidOld = NULL; - for (int i = 0; pMap[i].pclsidPropPage != NULL; i++) - { - if (pMap[i].szDesc == NULL) - continue; - - CComVariant var; - - // If raw entry skip it - we don't handle it for property bags just yet - if (pMap[i].dwSizeData != 0) - { - var.vt = pMap[i].vt; - void* pData = (void*) (pMap[i].dwOffsetData + (DWORD_PTR)pThis); - HRESULT hr = pPropBag->Read(pMap[i].szDesc, &var, pErrorLog); - if (SUCCEEDED(hr)) - { - // check the type - we only deal with limited set - switch (pMap[i].vt) - { - case VT_UI1: - case VT_I1: - *((BYTE*)pData) = var.bVal; - break; - case VT_BOOL: - *((VARIANT_BOOL*)pData) = var.boolVal; - break; - case VT_I2: - case VT_UI2: - *((short*)pData) = var.iVal; - break; - case VT_I4: - case VT_UI4: - case VT_INT: - case VT_UINT: - *((long*)pData) = var.lVal; - break; - case VT_BSTR: - *((BSTR*)pData) = ::SysAllocString(var.bstrVal); - if (*((BSTR*)pData) == NULL && var.bstrVal != NULL) - return E_OUTOFMEMORY; - break; - } - } - continue; - } - - if (pMap[i].piidDispatch != piidOld) - { - pDispatch.Release(); - if (FAILED(pUnk->QueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch))) - { - ATLTRACE(atlTraceCOM, 0, _T("Failed to get a dispatch pointer for property #%i\n"), i); - return E_FAIL; - } - piidOld = pMap[i].piidDispatch; - } - - if (FAILED(pDispatch.GetProperty(pMap[i].dispid, &var))) - { - ATLTRACE(atlTraceCOM, 0, _T("Invoked failed on DISPID %x\n"), pMap[i].dispid); - return E_FAIL; - } - - HRESULT hr = pPropBag->Read(pMap[i].szDesc, &var, pErrorLog); - if (FAILED(hr)) - { -#ifdef _DEBUG - USES_CONVERSION_EX; - LPCTSTR lp = OLE2CT_EX(pMap[i].szDesc, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); - - if (hr == E_INVALIDARG) - { - if (lp == NULL) - ATLTRACE(atlTraceCOM, 0, _T("Property not in Bag\n")); - else - ATLTRACE(atlTraceCOM, 0, _T("Property %s not in Bag\n"), lp); - } - else - { - // Many containers return different ERROR values for Member not found - if (lp == NULL) - ATLTRACE(atlTraceCOM, 0, _T("Error attempting to read Property from PropertyBag \n")); - else - ATLTRACE(atlTraceCOM, 0, _T("Error attempting to read Property %s from PropertyBag \n"), lp); - } -#endif - continue; - } - - if (FAILED(pDispatch.PutProperty(pMap[i].dispid, &var))) - { - ATLTRACE(atlTraceCOM, 0, _T("Invoked failed on DISPID %x\n"), pMap[i].dispid); - return E_FAIL; - } - } - return S_OK; -} -ATLINLINE ATLAPI AtlIPersistPropertyBag_Save(LPPROPERTYBAG pPropBag, - BOOL /* fClearDirty */, BOOL /* fSaveAllProperties */, - ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk) -{ - if (pPropBag == NULL) - { - ATLTRACE(atlTraceCOM, 0, _T("PropBag pointer passed in was invalid\n")); - return E_INVALIDARG; - } - if (pMap == NULL || pThis == NULL || pUnk == NULL) - return E_INVALIDARG; - - CComPtr pDispatch; - const IID* piidOld = NULL; - for (int i = 0; pMap[i].pclsidPropPage != NULL; i++) - { - if (pMap[i].szDesc == NULL) - continue; - - CComVariant var; - - // If raw entry skip it - we don't handle it for property bags just yet - if (pMap[i].dwSizeData != 0) - { - void* pData = (void*) (pMap[i].dwOffsetData + (DWORD_PTR)pThis); - // check the type - we only deal with limited set - bool bTypeOK = false; - switch (pMap[i].vt) - { - case VT_UI1: - case VT_I1: - var.bVal = *((BYTE*)pData); - bTypeOK = true; - break; - case VT_BOOL: - var.boolVal = *((VARIANT_BOOL*)pData); - bTypeOK = true; - break; - case VT_UI2: - var.iVal = *((short*)pData); - bTypeOK = true; - break; - case VT_UI4: - case VT_INT: - case VT_UINT: - var.lVal = *((long*)pData); - bTypeOK = true; - break; - case VT_BSTR: - var.bstrVal = ::SysAllocString(*((BSTR*)pData)); - if (var.bstrVal == NULL && *((BSTR*)pData) != NULL) - return E_OUTOFMEMORY; - bTypeOK = true; - break; - } - if (bTypeOK) - { - var.vt = pMap[i].vt; - HRESULT hr = pPropBag->Write(pMap[i].szDesc, &var); - if (FAILED(hr)) - return hr; - } - continue; - } - - if (pMap[i].piidDispatch != piidOld) - { - pDispatch.Release(); - if (FAILED(pUnk->QueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch))) - { - ATLTRACE(atlTraceCOM, 0, _T("Failed to get a dispatch pointer for property #%i\n"), i); - return E_FAIL; - } - piidOld = pMap[i].piidDispatch; - } - - if (FAILED(pDispatch.GetProperty(pMap[i].dispid, &var))) - { - ATLTRACE(atlTraceCOM, 0, _T("Invoked failed on DISPID %x\n"), pMap[i].dispid); - return E_FAIL; - } - - if (var.vt == VT_UNKNOWN || var.vt == VT_DISPATCH) - { - if (var.punkVal == NULL) - { - ATLTRACE(atlTraceCOM, 2, _T("Warning skipping empty IUnknown in Save\n")); - continue; - } - } - - HRESULT hr = pPropBag->Write(pMap[i].szDesc, &var); - if (FAILED(hr)) - return hr; - } - return S_OK; -} - -///////////////////////////////////////////////////////////////////////////// -// Connection Point Sink Helper - -ATLINLINE ATLAPI AtlGetObjectSourceInterface(IUnknown* punkObj, GUID* plibid, IID* piid, unsigned short* pdwMajor, unsigned short* pdwMinor) -{ - if (plibid == NULL || piid == NULL || pdwMajor == NULL || pdwMinor == NULL) - return E_POINTER; - - *plibid = GUID_NULL; - *piid = IID_NULL; - *pdwMajor = 0; - *pdwMinor = 0; - - - HRESULT hr = E_FAIL; - if (punkObj != NULL) - { - CComPtr spDispatch; - hr = punkObj->QueryInterface(__uuidof(IDispatch), (void**)&spDispatch); - if (SUCCEEDED(hr)) - { - CComPtr spTypeInfo; - hr = spDispatch->GetTypeInfo(0, 0, &spTypeInfo); - if (SUCCEEDED(hr)) - { - CComPtr spTypeLib; - hr = spTypeInfo->GetContainingTypeLib(&spTypeLib, 0); - if (SUCCEEDED(hr)) - { - TLIBATTR* plibAttr; - hr = spTypeLib->GetLibAttr(&plibAttr); - if (SUCCEEDED(hr)) - { - memcpy(plibid, &plibAttr->guid, sizeof(GUID)); - *pdwMajor = plibAttr->wMajorVerNum; - *pdwMinor = plibAttr->wMinorVerNum; - spTypeLib->ReleaseTLibAttr(plibAttr); - // First see if the object is willing to tell us about the - // default source interface via IProvideClassInfo2 - CComPtr spProvideClassInfo; - hr = punkObj->QueryInterface(__uuidof(IProvideClassInfo2), (void**)&spProvideClassInfo); - if (SUCCEEDED(hr) && spProvideClassInfo != NULL) - hr = spProvideClassInfo->GetGUID(GUIDKIND_DEFAULT_SOURCE_DISP_IID, piid); - else - { - // No, we have to go hunt for it - CComPtr spInfoCoClass; - // If we have a clsid, use that - // Otherwise, try to locate the clsid from IPersist - CComPtr spPersist; - CLSID clsid; - hr = punkObj->QueryInterface(__uuidof(IPersist), (void**)&spPersist); - if (SUCCEEDED(hr)) - { - hr = spPersist->GetClassID(&clsid); - if (SUCCEEDED(hr)) - { - hr = spTypeLib->GetTypeInfoOfGuid(clsid, &spInfoCoClass); - if (SUCCEEDED(hr)) - { - TYPEATTR* pAttr=NULL; - spInfoCoClass->GetTypeAttr(&pAttr); - if (pAttr != NULL) - { - HREFTYPE hRef; - for (int i = 0; i < pAttr->cImplTypes; i++) - { - int nType; - hr = spInfoCoClass->GetImplTypeFlags(i, &nType); - if (SUCCEEDED(hr)) - { - if (nType == (IMPLTYPEFLAG_FDEFAULT | IMPLTYPEFLAG_FSOURCE)) - { - // we found it - hr = spInfoCoClass->GetRefTypeOfImplType(i, &hRef); - if (SUCCEEDED(hr)) - { - CComPtr spInfo; - hr = spInfoCoClass->GetRefTypeInfo(hRef, &spInfo); - if (SUCCEEDED(hr)) - { - TYPEATTR* pAttrIF; - spInfo->GetTypeAttr(&pAttrIF); - if (pAttrIF != NULL) - { - memcpy(piid, &pAttrIF->guid, sizeof(GUID)); - spInfo->ReleaseTypeAttr(pAttrIF); - } - } - } - break; - } - } - } - spInfoCoClass->ReleaseTypeAttr(pAttr); - } - } - } - } - } - } - } - } - } - } - return hr; -} - -#endif // !_ATL_DLL - -} // namespace ATL - -#ifdef _ATL_ALL_WARNINGS -#pragma warning( pop ) -#endif - -#ifndef _ATL_NO_PRAGMA_WARNINGS -#pragma warning (pop) -#endif - -#endif // __ATLCOM_H__ - -///////////////////////////////////////////////////////////////////////////// diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlcomcli.h b/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlcomcli.h deleted file mode 100644 index 608bf125a..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlcomcli.h +++ /dev/null @@ -1,2467 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLCOMCLI_H__ -#define __ATLCOMCLI_H__ - -#pragma once - -#include -#include -#include - -namespace ATL -{ -///////////////////////////////////////////////////////////////////////////// -// Error to HRESULT helpers - -ATL_NOINLINE inline HRESULT AtlHresultFromLastError() throw() -{ - DWORD dwErr = ::GetLastError(); - return HRESULT_FROM_WIN32(dwErr); -} - -ATL_NOINLINE inline HRESULT AtlHresultFromWin32(DWORD nError) throw() -{ - return( HRESULT_FROM_WIN32( nError ) ); -} - -///////////////////////////////////////////////////////////////////////////// -// Smart Pointer helpers - -ATLAPI_(IUnknown*) AtlComPtrAssign(IUnknown** pp, IUnknown* lp); -ATLAPI_(IUnknown*) AtlComQIPtrAssign(IUnknown** pp, IUnknown* lp, REFIID riid); - -#ifndef _ATL_DLL - -ATLINLINE ATLAPI_(IUnknown*) AtlComPtrAssign(IUnknown** pp, IUnknown* lp) -{ - if (pp == NULL) - return NULL; - - if (lp != NULL) - lp->AddRef(); - if (*pp) - (*pp)->Release(); - *pp = lp; - return lp; -} - -ATLINLINE ATLAPI_(IUnknown*) AtlComQIPtrAssign(IUnknown** pp, IUnknown* lp, REFIID riid) -{ - if (pp == NULL) - return NULL; - - IUnknown* pTemp = *pp; - *pp = NULL; - if (lp != NULL) - lp->QueryInterface(riid, (void**)pp); - if (pTemp) - pTemp->Release(); - return *pp; -} - -#endif // _ATL_DLL - -///////////////////////////////////////////////////////////////////////////// -// COM Smart pointers - -template -class _NoAddRefReleaseOnCComPtr : public T -{ - private: - STDMETHOD_(ULONG, AddRef)()=0; - STDMETHOD_(ULONG, Release)()=0; -}; - -inline HRESULT AtlSetChildSite(IUnknown* punkChild, IUnknown* punkParent) -{ - if (punkChild == NULL) - return E_POINTER; - - HRESULT hr; - IObjectWithSite* pChildSite = NULL; - hr = punkChild->QueryInterface(__uuidof(IObjectWithSite), (void**)&pChildSite); - if (SUCCEEDED(hr) && pChildSite != NULL) - { - hr = pChildSite->SetSite(punkParent); - pChildSite->Release(); - } - return hr; -} - - -//CComPtrBase provides the basis for all other smart pointers -//The other smartpointers add their own constructors and operators -template -class CComPtrBase -{ -protected: - CComPtrBase() throw() - { - p = NULL; - } - CComPtrBase(int nNull) throw() - { - ATLASSERT(nNull == 0); - (void)nNull; - p = NULL; - } - CComPtrBase(T* lp) throw() - { - p = lp; - if (p != NULL) - p->AddRef(); - } -public: - typedef T _PtrClass; - ~CComPtrBase() throw() - { - if (p) - p->Release(); - } - operator T*() const throw() - { - return p; - } - T& operator*() const throw() - { - ATLASSERT(p!=NULL); - return *p; - } - //The assert on operator& usually indicates a bug. If this is really - //what is needed, however, take the address of the p member explicitly. - T** operator&() throw() - { - ATLASSERT(p==NULL); - return &p; - } - _NoAddRefReleaseOnCComPtr* operator->() const throw() - { - ATLASSERT(p!=NULL); - return (_NoAddRefReleaseOnCComPtr*)p; - } - bool operator!() const throw() - { - return (p == NULL); - } - bool operator<(T* pT) const throw() - { - return p < pT; - } - bool operator==(T* pT) const throw() - { - return p == pT; - } - - // Release the interface and set to NULL - void Release() throw() - { - T* pTemp = p; - if (pTemp) - { - p = NULL; - pTemp->Release(); - } - } - // Compare two objects for equivalence - bool IsEqualObject(IUnknown* pOther) throw() - { - if (p == NULL && pOther == NULL) - return true; // They are both NULL objects - - if (p == NULL || pOther == NULL) - return false; // One is NULL the other is not - - CComPtr punk1; - CComPtr punk2; - p->QueryInterface(__uuidof(IUnknown), (void**)&punk1); - pOther->QueryInterface(__uuidof(IUnknown), (void**)&punk2); - return punk1 == punk2; - } - // Attach to an existing interface (does not AddRef) - void Attach(T* p2) throw() - { - if (p) - p->Release(); - p = p2; - } - // Detach the interface (does not Release) - T* Detach() throw() - { - T* pt = p; - p = NULL; - return pt; - } - HRESULT CopyTo(T** ppT) throw() - { - ATLASSERT(ppT != NULL); - if (ppT == NULL) - return E_POINTER; - *ppT = p; - if (p) - p->AddRef(); - return S_OK; - } - HRESULT SetSite(IUnknown* punkParent) throw() - { - return AtlSetChildSite(p, punkParent); - } - HRESULT Advise(IUnknown* pUnk, const IID& iid, LPDWORD pdw) throw() - { - return AtlAdvise(p, pUnk, iid, pdw); - } - HRESULT CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) throw() - { - ATLASSERT(p == NULL); - return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&p); - } - HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) throw() - { - CLSID clsid; - HRESULT hr = CLSIDFromProgID(szProgID, &clsid); - ATLASSERT(p == NULL); - if (SUCCEEDED(hr)) - hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&p); - return hr; - } - template - HRESULT QueryInterface(Q** pp) const throw() - { - ATLASSERT(pp != NULL); - return p->QueryInterface(__uuidof(Q), (void**)pp); - } - T* p; -}; - -template -class CComPtr : public CComPtrBase -{ -public: - CComPtr() throw() - { - } - CComPtr(int nNull) throw() : - CComPtrBase(nNull) - { - } - /* - template - CComPtr(Q* lp) - { - if (lp != NULL) - lp->QueryInterface(__uuidof(Q), (void**)&p); - else - p = NULL; - } - template <> - */ - CComPtr(T* lp) throw() : - CComPtrBase(lp) - - { - } - CComPtr(const CComPtr& lp) throw() : - CComPtrBase(lp.p) - { - } -// template<> - /* - T* operator=(void* lp) - { - return (T*)AtlComPtrAssign((IUnknown**)&p, (T*)lp); - } - */ - /* - template - T* operator=(Q* lp) - { - return (T*)AtlComQIPtrAssign((IUnknown**)&p, lp, __uuidof(T)); - } - template <> - */ - T* operator=(T* lp) throw() - { - return static_cast(AtlComPtrAssign((IUnknown**)&p, lp)); - } - template - T* operator=(const CComPtr& lp) throw() - { - return static_cast(AtlComQIPtrAssign((IUnknown**)&p, lp, __uuidof(T))); - } - template <> - T* operator=(const CComPtr& lp) throw() - { - return static_cast(AtlComPtrAssign((IUnknown**)&p, lp)); - } -}; - -//specialization for IDispatch -template <> -class CComPtr : public CComPtrBase -{ -public: - CComPtr() throw() - { - } - CComPtr(IDispatch* lp) throw() : - CComPtrBase(lp) - { - } - CComPtr(const CComPtr& lp) throw() : - CComPtrBase(lp.p) - { - } - IDispatch* operator=(IDispatch* lp) throw() - { - return static_cast(AtlComPtrAssign((IUnknown**)&p, lp)); - } - IDispatch* operator=(const CComPtr& lp) throw() - { - return static_cast(AtlComPtrAssign((IUnknown**)&p, lp.p)); - } - -// IDispatch specific stuff - HRESULT GetPropertyByName(LPCOLESTR lpsz, VARIANT* pVar) throw() - { - ATLASSERT(p); - ATLASSERT(pVar); - DISPID dwDispID; - HRESULT hr = GetIDOfName(lpsz, &dwDispID); - if (SUCCEEDED(hr)) - hr = GetProperty(dwDispID, pVar); - return hr; - } - HRESULT GetProperty(DISPID dwDispID, VARIANT* pVar) throw() - { - return GetProperty(p, dwDispID, pVar); - } - HRESULT PutPropertyByName(LPCOLESTR lpsz, VARIANT* pVar) throw() - { - ATLASSERT(p); - ATLASSERT(pVar); - DISPID dwDispID; - HRESULT hr = GetIDOfName(lpsz, &dwDispID); - if (SUCCEEDED(hr)) - hr = PutProperty(dwDispID, pVar); - return hr; - } - HRESULT PutProperty(DISPID dwDispID, VARIANT* pVar) throw() - { - return PutProperty(p, dwDispID, pVar); - } - HRESULT GetIDOfName(LPCOLESTR lpsz, DISPID* pdispid) throw() - { - return p->GetIDsOfNames(IID_NULL, const_cast(&lpsz), 1, LOCALE_USER_DEFAULT, pdispid); - } - // Invoke a method by DISPID with no parameters - HRESULT Invoke0(DISPID dispid, VARIANT* pvarRet = NULL) throw() - { - DISPPARAMS dispparams = { NULL, NULL, 0, 0}; - return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL); - } - // Invoke a method by name with no parameters - HRESULT Invoke0(LPCOLESTR lpszName, VARIANT* pvarRet = NULL) throw() - { - HRESULT hr; - DISPID dispid; - hr = GetIDOfName(lpszName, &dispid); - if (SUCCEEDED(hr)) - hr = Invoke0(dispid, pvarRet); - return hr; - } - // Invoke a method by DISPID with a single parameter - HRESULT Invoke1(DISPID dispid, VARIANT* pvarParam1, VARIANT* pvarRet = NULL) throw() - { - DISPPARAMS dispparams = { pvarParam1, NULL, 1, 0}; - return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL); - } - // Invoke a method by name with a single parameter - HRESULT Invoke1(LPCOLESTR lpszName, VARIANT* pvarParam1, VARIANT* pvarRet = NULL) throw() - { - HRESULT hr; - DISPID dispid; - hr = GetIDOfName(lpszName, &dispid); - if (SUCCEEDED(hr)) - hr = Invoke1(dispid, pvarParam1, pvarRet); - return hr; - } - // Invoke a method by DISPID with two parameters - HRESULT Invoke2(DISPID dispid, VARIANT* pvarParam1, VARIANT* pvarParam2, VARIANT* pvarRet = NULL) throw(); - // Invoke a method by name with two parameters - HRESULT Invoke2(LPCOLESTR lpszName, VARIANT* pvarParam1, VARIANT* pvarParam2, VARIANT* pvarRet = NULL) throw() - { - HRESULT hr; - DISPID dispid; - hr = GetIDOfName(lpszName, &dispid); - if (SUCCEEDED(hr)) - hr = Invoke2(dispid, pvarParam1, pvarParam2, pvarRet); - return hr; - } - // Invoke a method by DISPID with N parameters - HRESULT InvokeN(DISPID dispid, VARIANT* pvarParams, int nParams, VARIANT* pvarRet = NULL) throw() - { - DISPPARAMS dispparams = { pvarParams, NULL, nParams, 0}; - return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL); - } - // Invoke a method by name with Nparameters - HRESULT InvokeN(LPCOLESTR lpszName, VARIANT* pvarParams, int nParams, VARIANT* pvarRet = NULL) throw() - { - HRESULT hr; - DISPID dispid; - hr = GetIDOfName(lpszName, &dispid); - if (SUCCEEDED(hr)) - hr = InvokeN(dispid, pvarParams, nParams, pvarRet); - return hr; - } - static HRESULT PutProperty(IDispatch* p, DISPID dwDispID, VARIANT* pVar) throw() - { - ATLASSERT(p); - ATLASSERT(pVar != NULL); - if (pVar == NULL) - return E_POINTER; - - if(p == NULL) - return E_INVALIDARG; - - ATLTRACE(atlTraceCOM, 2, _T("CPropertyHelper::PutProperty\n")); - DISPPARAMS dispparams = {NULL, NULL, 1, 1}; - dispparams.rgvarg = pVar; - DISPID dispidPut = DISPID_PROPERTYPUT; - dispparams.rgdispidNamedArgs = &dispidPut; - - if (pVar->vt == VT_UNKNOWN || pVar->vt == VT_DISPATCH || - (pVar->vt & VT_ARRAY) || (pVar->vt & VT_BYREF)) - { - HRESULT hr = p->Invoke(dwDispID, IID_NULL, - LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF, - &dispparams, NULL, NULL, NULL); - if (SUCCEEDED(hr)) - return hr; - } - return p->Invoke(dwDispID, IID_NULL, - LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, - &dispparams, NULL, NULL, NULL); - } - static HRESULT GetProperty(IDispatch* p, DISPID dwDispID, VARIANT* pVar) throw() - { - ATLASSERT(p); - ATLASSERT(pVar != NULL); - if (pVar == NULL) - return E_POINTER; - - if(p == NULL) - return E_INVALIDARG; - - ATLTRACE(atlTraceCOM, 2, _T("CPropertyHelper::GetProperty\n")); - DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0}; - return p->Invoke(dwDispID, IID_NULL, - LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, - &dispparamsNoArgs, pVar, NULL, NULL); - } -}; - -template -class CComQIPtr : public CComPtr -{ -public: - CComQIPtr() throw() - { - } - CComQIPtr(T* lp) throw() : - CComPtr(lp) - { - } - CComQIPtr(const CComQIPtr& lp) throw() : - CComPtr(lp.p) - { - } - CComQIPtr(IUnknown* lp) throw() - { - if (lp != NULL) - lp->QueryInterface(*piid, (void **)&p); - } - T* operator=(T* lp) throw() - { - return static_cast(AtlComPtrAssign((IUnknown**)&p, lp)); - } - T* operator=(const CComQIPtr& lp) throw() - { - return static_cast(AtlComPtrAssign((IUnknown**)&p, lp.p)); - } - T* operator=(IUnknown* lp) throw() - { - return static_cast(AtlComQIPtrAssign((IUnknown**)&p, lp, *piid)); - } -}; - -//Specialization to make it work -template<> -class CComQIPtr : public CComPtr -{ -public: - CComQIPtr() throw() - { - } - CComQIPtr(IUnknown* lp) throw() - { - //Actually do a QI to get identity - if (lp != NULL) - lp->QueryInterface(__uuidof(IUnknown), (void **)&p); - } - CComQIPtr(const CComQIPtr& lp) throw() : - CComPtr(lp.p) - { - } - IUnknown* operator=(IUnknown* lp) throw() - { - //Actually do a QI to get identity - return AtlComQIPtrAssign((IUnknown**)&p, lp, __uuidof(IUnknown)); - } - IUnknown* operator=(const CComQIPtr& lp) throw() - { - return AtlComPtrAssign((IUnknown**)&p, lp.p); - } -}; - -typedef CComQIPtr CComDispatchDriver; - -#define com_cast ATL::CComQIPtr - -///////////////////////////////////////////////////////////////////////////// -// CComBSTR - -class CComBSTR -{ -public: - BSTR m_str; - CComBSTR() throw() - { - m_str = NULL; - } - CComBSTR(int nSize) - { - if (nSize == 0) - m_str = NULL; - else - { - m_str = ::SysAllocStringLen(NULL, nSize); - if (m_str == NULL) - AtlThrow(E_OUTOFMEMORY); - } - } - CComBSTR(int nSize, LPCOLESTR sz) - { - if (nSize == 0) - m_str = NULL; - else - { - m_str = ::SysAllocStringLen(sz, nSize); - if (m_str == NULL) - AtlThrow(E_OUTOFMEMORY); - } - } - CComBSTR(LPCOLESTR pSrc) - { - if (pSrc == NULL) - m_str = NULL; - else - { - m_str = ::SysAllocString(pSrc); - if (m_str == NULL) - AtlThrow(E_OUTOFMEMORY); - } - } - CComBSTR(const CComBSTR& src) - { - m_str = src.Copy(); - if (!!src && m_str == NULL) - AtlThrow(E_OUTOFMEMORY); - - } - CComBSTR(REFGUID guid) - { - OLECHAR szGUID[64]; - ::StringFromGUID2(guid, szGUID, 64); - m_str = ::SysAllocString(szGUID); - if (m_str == NULL) - AtlThrow(E_OUTOFMEMORY); - } - - CComBSTR& operator=(const CComBSTR& src) - { - if (m_str != src.m_str) - { - ::SysFreeString(m_str); - m_str = src.Copy(); - if (!!src && m_str == NULL) - AtlThrow(E_OUTOFMEMORY); - } - return *this; - } - - CComBSTR& operator=(LPCOLESTR pSrc) - { - if (pSrc != m_str) - { - ::SysFreeString(m_str); - if (pSrc != NULL) - { - m_str = ::SysAllocString(pSrc); - if (m_str == NULL) - AtlThrow(E_OUTOFMEMORY); - } - else - m_str = NULL; - } - return *this; - } - - ~CComBSTR() throw() - { - ::SysFreeString(m_str); - } - unsigned int Length() const throw() - { - return (m_str == NULL)? 0 : SysStringLen(m_str); - } - unsigned int ByteLength() const throw() - { - return (m_str == NULL)? 0 : SysStringByteLen(m_str); - } - operator BSTR() const throw() - { - return m_str; - } - BSTR* operator&() throw() - { - return &m_str; - } - BSTR Copy() const throw() - { - if (m_str == NULL) - return NULL; - return ::SysAllocStringByteLen((char*)m_str, ::SysStringByteLen(m_str)); - } - HRESULT CopyTo(BSTR* pbstr) throw() - { - ATLASSERT(pbstr != NULL); - if (pbstr == NULL) - return E_POINTER; - *pbstr = Copy(); - if ((*pbstr == NULL) && (m_str != NULL)) - return E_OUTOFMEMORY; - return S_OK; - } - // copy BSTR to VARIANT - HRESULT CopyTo(VARIANT *pvarDest) throw() - { - ATLASSERT(pvarDest != NULL); - HRESULT hRes = E_POINTER; - if (pvarDest != NULL) - { - pvarDest->vt = VT_BSTR; - pvarDest->bstrVal = Copy(); - if (pvarDest->bstrVal == NULL && m_str != NULL) - hRes = E_OUTOFMEMORY; - else - hRes = S_OK; - } - return hRes; - } - void Attach(BSTR src) throw() - { - if (m_str != src) - { - ::SysFreeString(m_str); - m_str = src; - } - } - BSTR Detach() throw() - { - BSTR s = m_str; - m_str = NULL; - return s; - } - void Empty() throw() - { - ::SysFreeString(m_str); - m_str = NULL; - } - bool operator!() const throw() - { - return (m_str == NULL); - } - HRESULT Append(const CComBSTR& bstrSrc) throw() - { - return AppendBSTR(bstrSrc.m_str); - } - HRESULT Append(LPCOLESTR lpsz) throw() - { - return Append(lpsz, UINT(ocslen(lpsz))); - } - // a BSTR is just a LPCOLESTR so we need a special version to signify - // that we are appending a BSTR - HRESULT AppendBSTR(BSTR p) throw() - { - if (p == NULL) - return S_OK; - BSTR bstrNew = NULL; - HRESULT hr; - hr = VarBstrCat(m_str, p, &bstrNew); - if (SUCCEEDED(hr)) - { - ::SysFreeString(m_str); - m_str = bstrNew; - } - return hr; - } - HRESULT Append(LPCOLESTR lpsz, int nLen) throw() - { - if (lpsz == NULL || (m_str != NULL && nLen == 0)) - return S_OK; - int n1 = Length(); - BSTR b; - b = ::SysAllocStringLen(NULL, n1+nLen); - if (b == NULL) - return E_OUTOFMEMORY; - if(m_str != NULL) - memcpy(b, m_str, n1*sizeof(OLECHAR)); - memcpy(b+n1, lpsz, nLen*sizeof(OLECHAR)); - b[n1+nLen] = NULL; - SysFreeString(m_str); - m_str = b; - return S_OK; - } - HRESULT Append(char ch) throw() - { - OLECHAR chO = ch; - - return( Append( &chO, 1 ) ); - } - HRESULT Append(wchar_t ch) throw() - { - return( Append( &ch, 1 ) ); - } - HRESULT AppendBytes(const char* lpsz, int nLen) throw() - { - if (lpsz == NULL || nLen == 0) - return S_OK; - int n1 = ByteLength(); - BSTR b; - b = ::SysAllocStringByteLen(NULL, n1+nLen); - if (b == NULL) - return E_OUTOFMEMORY; - memcpy(b, m_str, n1); - memcpy(((char*)b)+n1, lpsz, nLen); - *((OLECHAR*)(((char*)b)+n1+nLen)) = NULL; - SysFreeString(m_str); - m_str = b; - return S_OK; - } - HRESULT AssignBSTR(const BSTR bstrSrc) throw() - { - HRESULT hr = S_OK; - if (m_str != bstrSrc) - { - ::SysFreeString(m_str); - if (bstrSrc != NULL) - { - m_str = ::SysAllocStringByteLen((char*)bstrSrc, ::SysStringByteLen(bstrSrc)); - if (m_str == NULL) - hr = E_OUTOFMEMORY; - } - else - m_str = NULL; - } - - return hr; - } - HRESULT ToLower() throw() - { - if (m_str != NULL) - { -#ifdef _UNICODE - // Convert in place - CharLowerBuff(m_str, Length()); -#else - // Cannot use conversion macros due to possible embedded NULLs - UINT _acp = _AtlGetConversionACP(); - int _convert = WideCharToMultiByte(_acp, 0, m_str, Length(), NULL, 0, NULL, NULL); - CTempBuffer pszA; - ATLTRY(pszA.Allocate(_convert)); - if (pszA == NULL) - return E_OUTOFMEMORY; - - int nRet = WideCharToMultiByte(_acp, 0, m_str, Length(), pszA, _convert, NULL, NULL); - if (nRet == 0) - { - ATLASSERT(0); - return AtlHresultFromLastError(); - } - - CharLowerBuff(pszA, nRet); - - _convert = MultiByteToWideChar(_acp, 0, pszA, nRet, NULL, 0); - - CTempBuffer pszW; - ATLTRY(pszW.Allocate(_convert)); - if (pszW == NULL) - return E_OUTOFMEMORY; - - nRet = MultiByteToWideChar(_acp, 0, pszA, nRet, pszW, _convert); - if (nRet == 0) - { - ATLASSERT(0); - return AtlHresultFromLastError(); - } - - BSTR b = ::SysAllocStringByteLen((LPCSTR) (LPWSTR) pszW, nRet * sizeof(OLECHAR)); - if (b == NULL) - return E_OUTOFMEMORY; - SysFreeString(m_str); - m_str = b; -#endif - } - return S_OK; - } - HRESULT ToUpper() throw() - { - if (m_str != NULL) - { -#ifdef _UNICODE - // Convert in place - CharUpperBuff(m_str, Length()); -#else - // Cannot use conversion macros due to possible embedded NULLs - UINT _acp = _AtlGetConversionACP(); - int _convert = WideCharToMultiByte(_acp, 0, m_str, Length(), NULL, 0, NULL, NULL); - CTempBuffer pszA; - ATLTRY(pszA.Allocate(_convert)); - if (pszA == NULL) - return E_OUTOFMEMORY; - - int nRet = WideCharToMultiByte(_acp, 0, m_str, Length(), pszA, _convert, NULL, NULL); - if (nRet == 0) - { - ATLASSERT(0); - return AtlHresultFromLastError(); - } - - CharUpperBuff(pszA, nRet); - - _convert = MultiByteToWideChar(_acp, 0, pszA, nRet, NULL, 0); - - CTempBuffer pszW; - ATLTRY(pszW.Allocate(_convert)); - if (pszW == NULL) - return E_OUTOFMEMORY; - - nRet = MultiByteToWideChar(_acp, 0, pszA, nRet, pszW, _convert); - if (nRet == 0) - { - ATLASSERT(0); - return AtlHresultFromLastError(); - } - - BSTR b = ::SysAllocStringByteLen((LPCSTR) (LPWSTR) pszW, nRet * sizeof(OLECHAR)); - if (b == NULL) - return E_OUTOFMEMORY; - SysFreeString(m_str); - m_str = b; -#endif - } - return S_OK; - } - bool LoadString(HINSTANCE hInst, UINT nID) throw() - { - ::SysFreeString(m_str); - m_str = NULL; - return LoadStringResource(hInst, nID, m_str); - } - bool LoadString(UINT nID) throw() - { - ::SysFreeString(m_str); - m_str = NULL; - return LoadStringResource(nID, m_str); - } - - CComBSTR& operator+=(const CComBSTR& bstrSrc) - { - HRESULT hr; - hr = AppendBSTR(bstrSrc.m_str); - if (FAILED(hr)) - AtlThrow(hr); - return *this; - } - CComBSTR& operator+=(LPCOLESTR pszSrc) - { - HRESULT hr; - hr = Append(pszSrc); - if (FAILED(hr)) - AtlThrow(hr); - return *this; - } - - bool operator<(const CComBSTR& bstrSrc) const throw() - { - return VarBstrCmp(m_str, bstrSrc.m_str, LOCALE_USER_DEFAULT, 0) == VARCMP_LT; - } - bool operator<(LPCOLESTR pszSrc) const - { - CComBSTR bstr2(pszSrc); - return operator<(bstr2); - } - bool operator<(LPOLESTR pszSrc) const - { - return operator<((LPCOLESTR)pszSrc); - } - - bool operator>(const CComBSTR& bstrSrc) const throw() - { - return VarBstrCmp(m_str, bstrSrc.m_str, LOCALE_USER_DEFAULT, 0) == VARCMP_GT; - } - bool operator>(LPCOLESTR pszSrc) const - { - CComBSTR bstr2(pszSrc); - return operator>(bstr2); - } - bool operator>(LPOLESTR pszSrc) const - { - return operator>((LPCOLESTR)pszSrc); - } - - bool operator!=(const CComBSTR& bstrSrc) const throw() - { - return !operator==(bstrSrc); - } - bool operator!=(LPCOLESTR pszSrc) const - { - return !operator==(pszSrc); - } - bool operator!=(int nNull) const throw() - { - return !operator==(nNull); - } - bool operator!=(LPOLESTR pszSrc) const - { - return operator!=((LPCOLESTR)pszSrc); - } - - bool operator==(const CComBSTR& bstrSrc) const throw() - { - return VarBstrCmp(m_str, bstrSrc.m_str, LOCALE_USER_DEFAULT, 0) == VARCMP_EQ; - } - bool operator==(LPCOLESTR pszSrc) const - { - CComBSTR bstr2(pszSrc); - return operator==(bstr2); - } - bool operator==(LPOLESTR pszSrc) const - { - return operator==((LPCOLESTR)pszSrc); - } - - bool operator==(int nNull) const throw() - { - ATLASSERT(nNull == NULL); - (void)nNull; - return (m_str == NULL); - } - CComBSTR(LPCSTR pSrc) - { - if (pSrc != NULL) - { - m_str = A2WBSTR(pSrc); - if (m_str == NULL) - AtlThrow(E_OUTOFMEMORY); - } - else - m_str = NULL; - } - - CComBSTR(int nSize, LPCSTR sz) - { - if (nSize != 0 && sz == NULL) - { - m_str = ::SysAllocStringLen(NULL, nSize); - if (m_str == NULL) - AtlThrow(E_OUTOFMEMORY); - return; - } - - m_str = A2WBSTR(sz, nSize); - if (m_str == NULL && nSize != 0) - AtlThrow(E_OUTOFMEMORY); - } - - HRESULT Append(LPCSTR lpsz) throw() - { - if (lpsz == NULL) - return S_OK; - - CComBSTR bstrTemp; - ATLTRY(bstrTemp = lpsz); - if (bstrTemp.m_str == NULL) - return E_OUTOFMEMORY; - return Append(bstrTemp); - } - - CComBSTR& operator=(LPCSTR pSrc) - { - ::SysFreeString(m_str); - m_str = A2WBSTR(pSrc); - if (m_str == NULL && pSrc != NULL) - AtlThrow(E_OUTOFMEMORY); - return *this; - } - bool operator<(LPCSTR pszSrc) const - { - CComBSTR bstr2(pszSrc); - return operator<(bstr2); - } - bool operator>(LPCSTR pszSrc) const - { - CComBSTR bstr2(pszSrc); - return operator>(bstr2); - } - bool operator!=(LPCSTR pszSrc) const - { - return !operator==(pszSrc); - } - bool operator==(LPCSTR pszSrc) const - { - CComBSTR bstr2(pszSrc); - return operator==(bstr2); - } - HRESULT WriteToStream(IStream* pStream) throw() - { - ATLASSERT(pStream != NULL); - if(pStream == NULL) - return E_INVALIDARG; - - ULONG cb; - ULONG cbStrLen = ULONG(m_str ? SysStringByteLen(m_str)+sizeof(OLECHAR) : 0); - HRESULT hr = pStream->Write((void*) &cbStrLen, sizeof(cbStrLen), &cb); - if (FAILED(hr)) - return hr; - return cbStrLen ? pStream->Write((void*) m_str, cbStrLen, &cb) : S_OK; - } - HRESULT ReadFromStream(IStream* pStream) throw() - { - ATLASSERT(pStream != NULL); - if(pStream == NULL) - return E_INVALIDARG; - - ATLASSERT(m_str == NULL); // should be empty - Empty(); - - ULONG cbStrLen = 0; - HRESULT hr = pStream->Read((void*) &cbStrLen, sizeof(cbStrLen), NULL); - if ((hr == S_OK) && (cbStrLen != 0)) - { - //subtract size for terminating NULL which we wrote out - //since SysAllocStringByteLen overallocates for the NULL - m_str = SysAllocStringByteLen(NULL, cbStrLen-sizeof(OLECHAR)); - if (m_str == NULL) - hr = E_OUTOFMEMORY; - else - hr = pStream->Read((void*) m_str, cbStrLen, NULL); - // If SysAllocStringByteLen or IStream::Read failed, reset seek - // pointer to start of BSTR size. - if (hr != S_OK) - { - LARGE_INTEGER nOffset; - nOffset.QuadPart = -(static_cast(sizeof(cbStrLen))); - pStream->Seek(nOffset, STREAM_SEEK_CUR, NULL); - } - } - if (hr == S_FALSE) - hr = E_FAIL; - return hr; - } - static bool LoadStringResource(HINSTANCE hInstance, UINT uID, BSTR& bstrText) throw() - { - const ATLSTRINGRESOURCEIMAGE* pImage; - - ATLASSERT(bstrText == NULL); - - pImage = AtlGetStringResourceImage(hInstance, uID); - if (pImage != NULL) - { - bstrText = ::SysAllocStringLen(pImage->achString, pImage->nLength); - } - - return (bstrText != NULL) ? true : false; - } - - static bool LoadStringResource(UINT uID, BSTR& bstrText) throw() - { - const ATLSTRINGRESOURCEIMAGE* pImage; - - ATLASSERT(bstrText == NULL); - - pImage = AtlGetStringResourceImage(uID); - if (pImage != NULL) - { - bstrText = ::SysAllocStringLen(pImage->achString, pImage->nLength); - } - - return (bstrText != NULL) ? true : false; - } - - - - // each character in BSTR is copied to each element in SAFEARRAY - HRESULT BSTRToArray(LPSAFEARRAY *ppArray) throw() - { - return VectorFromBstr(m_str, ppArray); - } - - // first character of each element in SAFEARRAY is copied to BSTR - HRESULT ArrayToBSTR(const SAFEARRAY *pSrc) throw() - { - ::SysFreeString(m_str); - return BstrFromVector((LPSAFEARRAY)pSrc, &m_str); - } -}; - -///////////////////////////////////////////////////////////// -// Class to Adapt CComBSTR and CComPtr for use with STL containers -// the syntax to use it is -// std::vector< CAdapt > vect; - -template -class CAdapt -{ -public: - CAdapt() - { - } - CAdapt(const T& rSrc) : - m_T( rSrc ) - { - } - - CAdapt(const CAdapt& rSrCA) : - m_T( rSrCA.m_T ) - { - } - - CAdapt& operator=(const T& rSrc) - { - m_T = rSrc; - return *this; - } - bool operator<(const T& rSrc) const - { - return m_T < rSrc; - } - bool operator==(const T& rSrc) const - { - return m_T == rSrc; - } - operator T&() - { - return m_T; - } - - operator const T&() const - { - return m_T; - } - - T m_T; -}; - -///////////////////////////////////////////////////////////////////////////// -// CComVariant - - -#define ATL_VARIANT_TRUE VARIANT_BOOL( -1 ) -#define ATL_VARIANT_FALSE VARIANT_BOOL( 0 ) - -template< typename T > -class CVarTypeInfo -{ -// static const VARTYPE VT; // VARTYPE corresponding to type T -// static T VARIANT::* const pmField; // Pointer-to-member of corresponding field in VARIANT struct -}; - -template<> -class CVarTypeInfo< char > -{ -public: - static const VARTYPE VT = VT_I1; - static char VARIANT::* const pmField; -}; - -__declspec( selectany ) char VARIANT::* const CVarTypeInfo< char >::pmField = &VARIANT::cVal; - -template<> -class CVarTypeInfo< unsigned char > -{ -public: - static const VARTYPE VT = VT_UI1; - static unsigned char VARIANT::* const pmField; -}; - -__declspec( selectany ) unsigned char VARIANT::* const CVarTypeInfo< unsigned char >::pmField = &VARIANT::bVal; - -template<> -class CVarTypeInfo< char* > -{ -public: - static const VARTYPE VT = VT_I1|VT_BYREF; - static char* VARIANT::* const pmField; -}; - -__declspec( selectany ) char* VARIANT::* const CVarTypeInfo< char* >::pmField = &VARIANT::pcVal; - -template<> -class CVarTypeInfo< unsigned char* > -{ -public: - static const VARTYPE VT = VT_UI1|VT_BYREF; - static unsigned char* VARIANT::* const pmField; -}; - -__declspec( selectany ) unsigned char* VARIANT::* const CVarTypeInfo< unsigned char* >::pmField = &VARIANT::pbVal; - -template<> -class CVarTypeInfo< short > -{ -public: - static const VARTYPE VT = VT_I2; - static short VARIANT::* const pmField; -}; - -__declspec( selectany ) short VARIANT::* const CVarTypeInfo< short >::pmField = &VARIANT::iVal; - -template<> -class CVarTypeInfo< short* > -{ -public: - static const VARTYPE VT = VT_I2|VT_BYREF; - static short* VARIANT::* const pmField; -}; - -__declspec( selectany ) short* VARIANT::* const CVarTypeInfo< short* >::pmField = &VARIANT::piVal; - -template<> -class CVarTypeInfo< unsigned short > -{ -public: - static const VARTYPE VT = VT_UI2; - static unsigned short VARIANT::* const pmField; -}; - -__declspec( selectany ) unsigned short VARIANT::* const CVarTypeInfo< unsigned short >::pmField = &VARIANT::uiVal; - -#ifdef _NATIVE_WCHAR_T_DEFINED // Only treat unsigned short* as VT_UI2|VT_BYREF if BSTR isn't the same as unsigned short* -template<> -class CVarTypeInfo< unsigned short* > -{ -public: - static const VARTYPE VT = VT_UI2|VT_BYREF; - static unsigned short* VARIANT::* const pmField; -}; - -__declspec( selectany ) unsigned short* VARIANT::* const CVarTypeInfo< unsigned short* >::pmField = &VARIANT::puiVal; -#endif // _NATIVE_WCHAR_T_DEFINED - -template<> -class CVarTypeInfo< int > -{ -public: - static const VARTYPE VT = VT_I4; - static int VARIANT::* const pmField; -}; - -__declspec( selectany ) int VARIANT::* const CVarTypeInfo< int >::pmField = &VARIANT::intVal; - -template<> -class CVarTypeInfo< int* > -{ -public: - static const VARTYPE VT = VT_I4|VT_BYREF; - static int* VARIANT::* const pmField; -}; - -__declspec( selectany ) int* VARIANT::* const CVarTypeInfo< int* >::pmField = &VARIANT::pintVal; - -template<> -class CVarTypeInfo< unsigned int > -{ -public: - static const VARTYPE VT = VT_UI4; - static unsigned int VARIANT::* const pmField; -}; - -__declspec( selectany ) unsigned int VARIANT::* const CVarTypeInfo< unsigned int >::pmField = &VARIANT::uintVal; - -template<> -class CVarTypeInfo< unsigned int* > -{ -public: - static const VARTYPE VT = VT_UI4|VT_BYREF; - static unsigned int* VARIANT::* const pmField; -}; - -__declspec( selectany ) unsigned int* VARIANT::* const CVarTypeInfo< unsigned int* >::pmField = &VARIANT::puintVal; - -template<> -class CVarTypeInfo< long > -{ -public: - static const VARTYPE VT = VT_I4; - static long VARIANT::* const pmField; -}; - -__declspec( selectany ) long VARIANT::* const CVarTypeInfo< long >::pmField = &VARIANT::lVal; - -template<> -class CVarTypeInfo< long* > -{ -public: - static const VARTYPE VT = VT_I4|VT_BYREF; - static long* VARIANT::* const pmField; -}; - -__declspec( selectany ) long* VARIANT::* const CVarTypeInfo< long* >::pmField = &VARIANT::plVal; - -template<> -class CVarTypeInfo< unsigned long > -{ -public: - static const VARTYPE VT = VT_UI4; - static unsigned long VARIANT::* const pmField; -}; - -__declspec( selectany ) unsigned long VARIANT::* const CVarTypeInfo< unsigned long >::pmField = &VARIANT::ulVal; - -template<> -class CVarTypeInfo< unsigned long* > -{ -public: - static const VARTYPE VT = VT_UI4|VT_BYREF; - static unsigned long* VARIANT::* const pmField; -}; - -__declspec( selectany ) unsigned long* VARIANT::* const CVarTypeInfo< unsigned long* >::pmField = &VARIANT::pulVal; - -template<> -class CVarTypeInfo< __int64 > -{ -public: - static const VARTYPE VT = VT_I8; - static __int64 VARIANT::* const pmField; -}; - -__declspec( selectany ) __int64 VARIANT::* const CVarTypeInfo< __int64 >::pmField = &VARIANT::llVal; - -template<> -class CVarTypeInfo< __int64* > -{ -public: - static const VARTYPE VT = VT_I8|VT_BYREF; - static __int64* VARIANT::* const pmField; -}; - -__declspec( selectany ) __int64* VARIANT::* const CVarTypeInfo< __int64* >::pmField = &VARIANT::pllVal; - -template<> -class CVarTypeInfo< unsigned __int64 > -{ -public: - static const VARTYPE VT = VT_UI8; - static unsigned __int64 VARIANT::* const pmField; -}; - -__declspec( selectany ) unsigned __int64 VARIANT::* const CVarTypeInfo< unsigned __int64 >::pmField = &VARIANT::ullVal; - -template<> -class CVarTypeInfo< unsigned __int64* > -{ -public: - static const VARTYPE VT = VT_UI8|VT_BYREF; - static unsigned __int64* VARIANT::* const pmField; -}; - -__declspec( selectany ) unsigned __int64* VARIANT::* const CVarTypeInfo< unsigned __int64* >::pmField = &VARIANT::pullVal; - -template<> -class CVarTypeInfo< float > -{ -public: - static const VARTYPE VT = VT_R4; - static float VARIANT::* const pmField; -}; - -__declspec( selectany ) float VARIANT::* const CVarTypeInfo< float >::pmField = &VARIANT::fltVal; - -template<> -class CVarTypeInfo< float* > -{ -public: - static const VARTYPE VT = VT_R4|VT_BYREF; - static float* VARIANT::* const pmField; -}; - -__declspec( selectany ) float* VARIANT::* const CVarTypeInfo< float* >::pmField = &VARIANT::pfltVal; - -template<> -class CVarTypeInfo< double > -{ -public: - static const VARTYPE VT = VT_R8; - static double VARIANT::* const pmField; -}; - -__declspec( selectany ) double VARIANT::* const CVarTypeInfo< double >::pmField = &VARIANT::dblVal; - -template<> -class CVarTypeInfo< double* > -{ -public: - static const VARTYPE VT = VT_R8|VT_BYREF; - static double* VARIANT::* const pmField; -}; - -__declspec( selectany ) double* VARIANT::* const CVarTypeInfo< double* >::pmField = &VARIANT::pdblVal; - -template<> -class CVarTypeInfo< VARIANT > -{ -public: - static const VARTYPE VT = VT_VARIANT; -}; - -template<> -class CVarTypeInfo< BSTR > -{ -public: - static const VARTYPE VT = VT_BSTR; - static BSTR VARIANT::* const pmField; -}; - -__declspec( selectany ) BSTR VARIANT::* const CVarTypeInfo< BSTR >::pmField = &VARIANT::bstrVal; - -template<> -class CVarTypeInfo< BSTR* > -{ -public: - static const VARTYPE VT = VT_BSTR|VT_BYREF; - static BSTR* VARIANT::* const pmField; -}; - -__declspec( selectany ) BSTR* VARIANT::* const CVarTypeInfo< BSTR* >::pmField = &VARIANT::pbstrVal; - -template<> -class CVarTypeInfo< IUnknown* > -{ -public: - static const VARTYPE VT = VT_UNKNOWN; - static IUnknown* VARIANT::* const pmField; -}; - -__declspec( selectany ) IUnknown* VARIANT::* const CVarTypeInfo< IUnknown* >::pmField = &VARIANT::punkVal; - -template<> -class CVarTypeInfo< IUnknown** > -{ -public: - static const VARTYPE VT = VT_UNKNOWN|VT_BYREF; - static IUnknown** VARIANT::* const pmField; -}; - -__declspec( selectany ) IUnknown** VARIANT::* const CVarTypeInfo< IUnknown** >::pmField = &VARIANT::ppunkVal; - -template<> -class CVarTypeInfo< IDispatch* > -{ -public: - static const VARTYPE VT = VT_DISPATCH; - static IDispatch* VARIANT::* const pmField; -}; - -__declspec( selectany ) IDispatch* VARIANT::* const CVarTypeInfo< IDispatch* >::pmField = &VARIANT::pdispVal; - -template<> -class CVarTypeInfo< IDispatch** > -{ -public: - static const VARTYPE VT = VT_DISPATCH|VT_BYREF; - static IDispatch** VARIANT::* const pmField; -}; - -__declspec( selectany ) IDispatch** VARIANT::* const CVarTypeInfo< IDispatch** >::pmField = &VARIANT::ppdispVal; - -template<> -class CVarTypeInfo< CY > -{ -public: - static const VARTYPE VT = VT_CY; - static CY VARIANT::* const pmField; -}; - -__declspec( selectany ) CY VARIANT::* const CVarTypeInfo< CY >::pmField = &VARIANT::cyVal; - -template<> -class CVarTypeInfo< CY* > -{ -public: - static const VARTYPE VT = VT_CY|VT_BYREF; - static CY* VARIANT::* const pmField; -}; - -__declspec( selectany ) CY* VARIANT::* const CVarTypeInfo< CY* >::pmField = &VARIANT::pcyVal; - -class CComVariant : public tagVARIANT -{ -// Constructors -public: - CComVariant() throw() - { - ::VariantInit(this); - } - ~CComVariant() throw() - { - Clear(); - } - - CComVariant(const VARIANT& varSrc) - { - vt = VT_EMPTY; - InternalCopy(&varSrc); - } - - CComVariant(const CComVariant& varSrc) - { - vt = VT_EMPTY; - InternalCopy(&varSrc); - } - CComVariant(LPCOLESTR lpszSrc) - { - vt = VT_EMPTY; - *this = lpszSrc; - } - - CComVariant(LPCSTR lpszSrc) - { - vt = VT_EMPTY; - *this = lpszSrc; - } - - CComVariant(bool bSrc) - { - vt = VT_BOOL; - boolVal = bSrc ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE; - } - - CComVariant(int nSrc, VARTYPE vtSrc = VT_I4) throw() - { - ATLASSERT(vtSrc == VT_I4 || vtSrc == VT_INT); - vt = vtSrc; - intVal = nSrc; - } - CComVariant(BYTE nSrc) throw() - { - vt = VT_UI1; - bVal = nSrc; - } - CComVariant(short nSrc) throw() - { - vt = VT_I2; - iVal = nSrc; - } - CComVariant(long nSrc, VARTYPE vtSrc = VT_I4) throw() - { - ATLASSERT(vtSrc == VT_I4 || vtSrc == VT_ERROR); - vt = vtSrc; - lVal = nSrc; - } - CComVariant(float fltSrc) throw() - { - vt = VT_R4; - fltVal = fltSrc; - } - CComVariant(double dblSrc, VARTYPE vtSrc = VT_R8) throw() - { - ATLASSERT(vtSrc == VT_R8 || vtSrc == VT_DATE); - vt = vtSrc; - dblVal = dblSrc; - } -#if (_WIN32_WINNT >= 0x0501) || defined(_ATL_SUPPORT_VT_I8) - CComVariant(LONGLONG nSrc) throw() - { - vt = VT_I8; - llVal = nSrc; - } - CComVariant(ULONGLONG nSrc) throw() - { - vt = VT_UI8; - ullVal = nSrc; - } -#endif - CComVariant(CY cySrc) throw() - { - vt = VT_CY; - cyVal.Hi = cySrc.Hi; - cyVal.Lo = cySrc.Lo; - } - CComVariant(IDispatch* pSrc) throw() - { - vt = VT_DISPATCH; - pdispVal = pSrc; - // Need to AddRef as VariantClear will Release - if (pdispVal != NULL) - pdispVal->AddRef(); - } - CComVariant(IUnknown* pSrc) throw() - { - vt = VT_UNKNOWN; - punkVal = pSrc; - // Need to AddRef as VariantClear will Release - if (punkVal != NULL) - punkVal->AddRef(); - } - CComVariant(char cSrc) throw() - { - vt = VT_I1; - cVal = cSrc; - } - CComVariant(unsigned short nSrc) throw() - { - vt = VT_UI2; - uiVal = nSrc; - } - CComVariant(unsigned long nSrc) throw() - { - vt = VT_UI4; - ulVal = nSrc; - } - CComVariant(unsigned int nSrc, VARTYPE vtSrc = VT_UI4) throw() - { - ATLASSERT(vtSrc == VT_UI4 || vtSrc == VT_UINT); - vt = vtSrc; - uintVal= nSrc; - } - CComVariant(const CComBSTR& bstrSrc) - { - vt = VT_EMPTY; - *this = bstrSrc; - } - CComVariant(const SAFEARRAY *pSrc) - { - LPSAFEARRAY pCopy; - if (pSrc != NULL) - { - HRESULT hRes = ::SafeArrayCopy((LPSAFEARRAY)pSrc, &pCopy); - if (SUCCEEDED(hRes) && pCopy != NULL) - { - ::SafeArrayGetVartype((LPSAFEARRAY)pSrc, &vt); - vt |= VT_ARRAY; - parray = pCopy; - } - else - { - vt = VT_ERROR; - scode = hRes; - } - } - } -// Assignment Operators -public: - CComVariant& operator=(const CComVariant& varSrc) - { - InternalCopy(&varSrc); - return *this; - } - CComVariant& operator=(const VARIANT& varSrc) - { - InternalCopy(&varSrc); - return *this; - } - - CComVariant& operator=(const CComBSTR& bstrSrc) - { - Clear(); - vt = VT_BSTR; - bstrVal = bstrSrc.Copy(); - if (bstrVal == NULL && bstrSrc.m_str != NULL) - { - vt = VT_ERROR; - scode = E_OUTOFMEMORY; - } - return *this; - } - - CComVariant& operator=(LPCOLESTR lpszSrc) - { - Clear(); - vt = VT_BSTR; - bstrVal = ::SysAllocString(lpszSrc); - - if (bstrVal == NULL && lpszSrc != NULL) - { - vt = VT_ERROR; - scode = E_OUTOFMEMORY; - } - return *this; - } - - CComVariant& operator=(LPCSTR lpszSrc) - { - USES_CONVERSION_EX; - Clear(); - vt = VT_BSTR; - bstrVal = ::SysAllocString(A2COLE_EX(lpszSrc, _ATL_SAFE_ALLOCA_DEF_THRESHOLD)); - - if (bstrVal == NULL && lpszSrc != NULL) - { - vt = VT_ERROR; - scode = E_OUTOFMEMORY; - } - return *this; - } - - CComVariant& operator=(bool bSrc) - { - if (vt != VT_BOOL) - { - Clear(); - vt = VT_BOOL; - } - boolVal = bSrc ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE; - return *this; - } - - CComVariant& operator=(int nSrc) throw() - { - if (vt != VT_I4) - { - Clear(); - vt = VT_I4; - } - intVal = nSrc; - - return *this; - } - - CComVariant& operator=(BYTE nSrc) throw() - { - if (vt != VT_UI1) - { - Clear(); - vt = VT_UI1; - } - bVal = nSrc; - return *this; - } - - CComVariant& operator=(short nSrc) throw() - { - if (vt != VT_I2) - { - Clear(); - vt = VT_I2; - } - iVal = nSrc; - return *this; - } - - CComVariant& operator=(long nSrc) throw() - { - if (vt != VT_I4) - { - Clear(); - vt = VT_I4; - } - lVal = nSrc; - return *this; - } - - CComVariant& operator=(float fltSrc) throw() - { - if (vt != VT_R4) - { - Clear(); - vt = VT_R4; - } - fltVal = fltSrc; - return *this; - } - - CComVariant& operator=(double dblSrc) throw() - { - if (vt != VT_R8) - { - Clear(); - vt = VT_R8; - } - dblVal = dblSrc; - return *this; - } - - CComVariant& operator=(CY cySrc) throw() - { - if (vt != VT_CY) - { - Clear(); - vt = VT_CY; - } - cyVal.Hi = cySrc.Hi; - cyVal.Lo = cySrc.Lo; - return *this; - } - - CComVariant& operator=(IDispatch* pSrc) throw() - { - Clear(); - vt = VT_DISPATCH; - pdispVal = pSrc; - // Need to AddRef as VariantClear will Release - if (pdispVal != NULL) - pdispVal->AddRef(); - return *this; - } - - CComVariant& operator=(IUnknown* pSrc) throw() - { - Clear(); - vt = VT_UNKNOWN; - punkVal = pSrc; - - // Need to AddRef as VariantClear will Release - if (punkVal != NULL) - punkVal->AddRef(); - return *this; - } - - CComVariant& operator=(char cSrc) throw() - { - if (vt != VT_I1) - { - Clear(); - vt = VT_I1; - } - cVal = cSrc; - return *this; - } - - CComVariant& operator=(unsigned short nSrc) throw() - { - if (vt != VT_UI2) - { - Clear(); - vt = VT_UI2; - } - uiVal = nSrc; - return *this; - } - - CComVariant& operator=(unsigned long nSrc) throw() - { - if (vt != VT_UI4) - { - Clear(); - vt = VT_UI4; - } - ulVal = nSrc; - return *this; - } - - CComVariant& operator=(unsigned int nSrc) throw() - { - if (vt != VT_UI4) - { - Clear(); - vt = VT_UI4; - } - uintVal= nSrc; - return *this; - } - - CComVariant& operator=(BYTE* pbSrc) throw() - { - if (vt != (VT_UI1|VT_BYREF)) - { - Clear(); - vt = VT_UI1|VT_BYREF; - } - pbVal = pbSrc; - return *this; - } - - CComVariant& operator=(short* pnSrc) throw() - { - if (vt != (VT_I2|VT_BYREF)) - { - Clear(); - vt = VT_I2|VT_BYREF; - } - piVal = pnSrc; - return *this; - } - -#ifdef _NATIVE_WCHAR_T_DEFINED - CComVariant& operator=(USHORT* pnSrc) throw() - { - if (vt != (VT_UI2|VT_BYREF)) - { - Clear(); - vt = VT_UI2|VT_BYREF; - } - puiVal = pnSrc; - return *this; - } -#endif - - CComVariant& operator=(int* pnSrc) throw() - { - if (vt != (VT_I4|VT_BYREF)) - { - Clear(); - vt = VT_I4|VT_BYREF; - } - pintVal = pnSrc; - return *this; - } - - CComVariant& operator=(UINT* pnSrc) throw() - { - if (vt != (VT_UI4|VT_BYREF)) - { - Clear(); - vt = VT_UI4|VT_BYREF; - } - puintVal = pnSrc; - return *this; - } - - CComVariant& operator=(long* pnSrc) throw() - { - if (vt != (VT_I4|VT_BYREF)) - { - Clear(); - vt = VT_I4|VT_BYREF; - } - plVal = pnSrc; - return *this; - } - - CComVariant& operator=(ULONG* pnSrc) throw() - { - if (vt != (VT_UI4|VT_BYREF)) - { - Clear(); - vt = VT_UI4|VT_BYREF; - } - pulVal = pnSrc; - return *this; - } - -#if (_WIN32_WINNT >= 0x0501) || defined(_ATL_SUPPORT_VT_I8) - CComVariant& operator=(LONGLONG nSrc) throw() - { - if (vt != VT_I8) - { - Clear(); - vt = VT_I8; - } - llVal = nSrc; - - return *this; - } - - CComVariant& operator=(LONGLONG* pnSrc) throw() - { - if (vt != (VT_I8|VT_BYREF)) - { - Clear(); - vt = VT_I8|VT_BYREF; - } - pllVal = pnSrc; - return *this; - } - - CComVariant& operator=(ULONGLONG nSrc) throw() - { - if (vt != VT_UI8) - { - Clear(); - vt = VT_UI8; - } - ullVal = nSrc; - - return *this; - } - - CComVariant& operator=(ULONGLONG* pnSrc) throw() - { - if (vt != (VT_UI8|VT_BYREF)) - { - Clear(); - vt = VT_UI8|VT_BYREF; - } - pullVal = pnSrc; - return *this; - } -#endif - - CComVariant& operator=(float* pfSrc) throw() - { - if (vt != (VT_R4|VT_BYREF)) - { - Clear(); - vt = VT_R4|VT_BYREF; - } - pfltVal = pfSrc; - return *this; - } - - CComVariant& operator=(double* pfSrc) throw() - { - if (vt != (VT_R8|VT_BYREF)) - { - Clear(); - vt = VT_R8|VT_BYREF; - } - pdblVal = pfSrc; - return *this; - } - - CComVariant& operator=(const SAFEARRAY *pSrc) - { - Clear(); - LPSAFEARRAY pCopy; - if (pSrc != NULL) - { - HRESULT hRes = ::SafeArrayCopy((LPSAFEARRAY)pSrc, &pCopy); - if (SUCCEEDED(hRes) && pCopy != NULL) - { - ::SafeArrayGetVartype((LPSAFEARRAY)pSrc, &vt); - vt |= VT_ARRAY; - parray = pCopy; - } - else - { - vt = VT_ERROR; - scode = hRes; - } - } - return *this; - } - -// Comparison Operators -public: - bool operator==(const VARIANT& varSrc) const throw() - { - // For backwards compatibility - if (vt == VT_NULL && varSrc.vt == VT_NULL) - return true; - return VarCmp((VARIANT*)this, (VARIANT*)&varSrc, LOCALE_USER_DEFAULT, 0) == VARCMP_EQ; - } - - bool operator!=(const VARIANT& varSrc) const throw() - { - return !operator==(varSrc); - } - - bool operator<(const VARIANT& varSrc) const throw() - { - if (vt == VT_NULL && varSrc.vt == VT_NULL) - return false; - return VarCmp((VARIANT*)this, (VARIANT*)&varSrc, LOCALE_USER_DEFAULT, 0)==VARCMP_LT; - } - - bool operator>(const VARIANT& varSrc) const throw() - { - if (vt == VT_NULL && varSrc.vt == VT_NULL) - return false; - return VarCmp((VARIANT*)this, (VARIANT*)&varSrc, LOCALE_USER_DEFAULT, 0)==VARCMP_GT; - } - -// Operations -public: - HRESULT Clear() { return ::VariantClear(this); } - HRESULT Copy(const VARIANT* pSrc) { return ::VariantCopy(this, const_cast(pSrc)); } - // copy VARIANT to BSTR - HRESULT CopyTo(BSTR *pstrDest) - { - ATLASSERT(pstrDest != NULL && vt == VT_BSTR); - HRESULT hRes = E_POINTER; - if (pstrDest != NULL && vt == VT_BSTR) - { - *pstrDest = ::SysAllocStringByteLen((char*)bstrVal, ::SysStringByteLen(bstrVal)); - if (*pstrDest == NULL) - hRes = E_OUTOFMEMORY; - else - hRes = S_OK; - } - else if (vt != VT_BSTR) - hRes = DISP_E_TYPEMISMATCH; - return hRes; - } - HRESULT Attach(VARIANT* pSrc) - { - if(pSrc == NULL) - return E_INVALIDARG; - - // Clear out the variant - HRESULT hr = Clear(); - if (!FAILED(hr)) - { - // Copy the contents and give control to CComVariant - memcpy(this, pSrc, sizeof(VARIANT)); - pSrc->vt = VT_EMPTY; - hr = S_OK; - } - return hr; - } - - HRESULT Detach(VARIANT* pDest) - { - ATLASSERT(pDest != NULL); - if(pDest == NULL) - return E_POINTER; - - // Clear out the variant - HRESULT hr = ::VariantClear(pDest); - if (!FAILED(hr)) - { - // Copy the contents and remove control from CComVariant - memcpy(pDest, this, sizeof(VARIANT)); - vt = VT_EMPTY; - hr = S_OK; - } - return hr; - } - - HRESULT ChangeType(VARTYPE vtNew, const VARIANT* pSrc = NULL) - { - VARIANT* pVar = const_cast(pSrc); - // Convert in place if pSrc is NULL - if (pVar == NULL) - pVar = this; - // Do nothing if doing in place convert and vts not different - return ::VariantChangeType(this, pVar, 0, vtNew); - } - - template< typename T > - void SetByRef( T* pT ) throw() - { - Clear(); - vt = CVarTypeInfo< T >::VT|VT_BYREF; - byref = pT; - } - - HRESULT WriteToStream(IStream* pStream); - HRESULT ReadFromStream(IStream* pStream); - - // Return the size in bytes of the current contents - ULONG GetSize() const; - -// Implementation -public: - HRESULT InternalClear() - { - HRESULT hr = Clear(); - ATLASSERT(SUCCEEDED(hr)); - if (FAILED(hr)) - { - vt = VT_ERROR; - scode = hr; - } - return hr; - } - - void InternalCopy(const VARIANT* pSrc) - { - HRESULT hr = Copy(pSrc); - if (FAILED(hr)) - { - vt = VT_ERROR; - scode = hr; - } - } -}; - -#pragma warning(push) -#pragma warning(disable: 4702) -inline HRESULT CComVariant::WriteToStream(IStream* pStream) -{ - if(pStream == NULL) - return E_INVALIDARG; - - HRESULT hr = pStream->Write(&vt, sizeof(VARTYPE), NULL); - if (FAILED(hr)) - return hr; - - int cbWrite = 0; - switch (vt) - { - case VT_UNKNOWN: - case VT_DISPATCH: - { - CComPtr spStream; - if (punkVal != NULL) - { - hr = punkVal->QueryInterface(__uuidof(IPersistStream), (void**)&spStream); - if (FAILED(hr)) - { - hr = punkVal->QueryInterface(__uuidof(IPersistStreamInit), (void**)&spStream); - if (FAILED(hr)) - return hr; - } - } - if (spStream != NULL) - return OleSaveToStream(spStream, pStream); - return WriteClassStm(pStream, CLSID_NULL); - } - case VT_UI1: - case VT_I1: - cbWrite = sizeof(BYTE); - break; - case VT_I2: - case VT_UI2: - case VT_BOOL: - cbWrite = sizeof(short); - break; - case VT_I4: - case VT_UI4: - case VT_R4: - case VT_INT: - case VT_UINT: - case VT_ERROR: - cbWrite = sizeof(long); - break; - case VT_I8: - case VT_UI8: - cbWrite = sizeof(LONGLONG); - break; - case VT_R8: - case VT_CY: - case VT_DATE: - cbWrite = sizeof(double); - break; - default: - break; - } - if (cbWrite != 0) - return pStream->Write((void*) &bVal, cbWrite, NULL); - - CComBSTR bstrWrite; - CComVariant varBSTR; - if (vt != VT_BSTR) - { - hr = VariantChangeType(&varBSTR, this, VARIANT_NOVALUEPROP, VT_BSTR); - if (FAILED(hr)) - return hr; - bstrWrite.Attach(varBSTR.bstrVal); - } - else - bstrWrite.Attach(bstrVal); - - hr = bstrWrite.WriteToStream(pStream); - bstrWrite.Detach(); - return hr; -} -#pragma warning(pop) // C4702 - -inline HRESULT CComVariant::ReadFromStream(IStream* pStream) -{ - ATLASSERT(pStream != NULL); - if(pStream == NULL) - return E_INVALIDARG; - - HRESULT hr; - hr = VariantClear(this); - if (FAILED(hr)) - return hr; - VARTYPE vtRead = VT_EMPTY; - ULONG cbRead = 0; - hr = pStream->Read(&vtRead, sizeof(VARTYPE), &cbRead); - if (hr == S_FALSE || (cbRead != sizeof(VARTYPE) && hr == S_OK)) - hr = E_FAIL; - if (FAILED(hr)) - return hr; - - vt = vtRead; - cbRead = 0; - switch (vtRead) - { - case VT_UNKNOWN: - case VT_DISPATCH: - { - punkVal = NULL; - hr = OleLoadFromStream(pStream, - (vtRead == VT_UNKNOWN) ? __uuidof(IUnknown) : __uuidof(IDispatch), - (void**)&punkVal); - // If IPictureDisp or IFontDisp property is not set, - // OleLoadFromStream() will return REGDB_E_CLASSNOTREG. - if (hr == REGDB_E_CLASSNOTREG) - hr = S_OK; - return hr; - } - case VT_UI1: - case VT_I1: - cbRead = sizeof(BYTE); - break; - case VT_I2: - case VT_UI2: - case VT_BOOL: - cbRead = sizeof(short); - break; - case VT_I4: - case VT_UI4: - case VT_R4: - case VT_INT: - case VT_UINT: - case VT_ERROR: - cbRead = sizeof(long); - break; - case VT_I8: - case VT_UI8: - cbRead = sizeof(LONGLONG); - break; - case VT_R8: - case VT_CY: - case VT_DATE: - cbRead = sizeof(double); - break; - default: - break; - } - if (cbRead != 0) - { - hr = pStream->Read((void*) &bVal, cbRead, NULL); - if (hr == S_FALSE) - hr = E_FAIL; - return hr; - } - CComBSTR bstrRead; - - hr = bstrRead.ReadFromStream(pStream); - if (FAILED(hr)) - { - // If CComBSTR::ReadFromStream failed, reset seek pointer to start of - // variant type. - LARGE_INTEGER nOffset; - nOffset.QuadPart = -(static_cast(sizeof(VARTYPE))); - pStream->Seek(nOffset, STREAM_SEEK_CUR, NULL); - return hr; - } - vt = VT_BSTR; - bstrVal = bstrRead.Detach(); - if (vtRead != VT_BSTR) - hr = ChangeType(vtRead); - return hr; -} - -inline ULONG CComVariant::GetSize() const -{ - ULONG nSize = sizeof(VARTYPE); - HRESULT hr; - - switch (vt) - { - case VT_UNKNOWN: - case VT_DISPATCH: - { - CComPtr spStream; - if (punkVal != NULL) - { - hr = punkVal->QueryInterface(__uuidof(IPersistStream), (void**)&spStream); - if (FAILED(hr)) - { - hr = punkVal->QueryInterface(__uuidof(IPersistStreamInit), (void**)&spStream); - if (FAILED(hr)) - break; - } - } - if (spStream != NULL) - { - ULARGE_INTEGER nPersistSize; - nPersistSize.QuadPart = 0; - spStream->GetSizeMax(&nPersistSize); - nSize += nPersistSize.LowPart + sizeof(CLSID); - } - else - nSize += sizeof(CLSID); - } - break; - case VT_UI1: - case VT_I1: - nSize += sizeof(BYTE); - break; - case VT_I2: - case VT_UI2: - case VT_BOOL: - nSize += sizeof(short); - break; - case VT_I4: - case VT_UI4: - case VT_R4: - case VT_INT: - case VT_UINT: - case VT_ERROR: - nSize += sizeof(long); - break; - case VT_I8: - case VT_UI8: - nSize += sizeof(LONGLONG); - break; - case VT_R8: - case VT_CY: - case VT_DATE: - nSize += sizeof(double); - break; - default: - break; - } - if (nSize == sizeof(VARTYPE)) - { - BSTR bstr = NULL; - CComVariant varBSTR; - if (vt != VT_BSTR) - { - hr = VariantChangeType(&varBSTR, const_cast((const VARIANT*)this), VARIANT_NOVALUEPROP, VT_BSTR); - if (SUCCEEDED(hr)) - bstr = varBSTR.bstrVal; - } - else - bstr = bstrVal; - - // Add the size of the length, the string itself and the NULL character - if (bstr != NULL) - nSize += sizeof(ULONG) + SysStringByteLen(bstr) + sizeof(OLECHAR); - } - return nSize; -} - -inline HRESULT CComPtr::Invoke2(DISPID dispid, VARIANT* pvarParam1, VARIANT* pvarParam2, VARIANT* pvarRet) throw() -{ - if(pvarParam1 == NULL || pvarParam2 == NULL) - return E_INVALIDARG; - - CComVariant varArgs[2] = { *pvarParam2, *pvarParam1 }; - DISPPARAMS dispparams = { &varArgs[0], NULL, 2, 0}; - return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL); -} - -} // namespace ATL - -#ifndef _ATL_NO_AUTOMATIC_NAMESPACE -using namespace ATL; -#endif //!_ATL_NO_AUTOMATIC_NAMESPACE - -#endif // __ATLCOMCLI_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlconv.h b/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlconv.h deleted file mode 100644 index 4b0f72f36..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlconv.h +++ /dev/null @@ -1,1023 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLCONV_H__ -#define __ATLCONV_H__ - -#pragma once - -#ifndef _ATL_NO_PRAGMA_WARNINGS -#pragma warning (push) -#pragma warning(disable: 4127) // unreachable code -#endif //!_ATL_NO_PRAGMA_WARNINGS - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#include -#include -#include - -#ifndef __wtypes_h__ - -#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_IX86) -#define _X86_ -#endif - -#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_AMD64) -#define _AMD64_ -#endif - -#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_M68K) -#define _68K_ -#endif - -#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_MPPC) -#define _MPPC_ -#endif - -#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_M_IX86) && !defined(_AMD64_) && defined(_M_IA64) -#if !defined(_IA64_) -#define _IA64_ -#endif // !_IA64_ -#endif - -#include -#include -#include -#include - -#if defined(_WIN32) && !defined(OLE2ANSI) - -typedef WCHAR OLECHAR; -typedef OLECHAR *LPOLESTR; -typedef const OLECHAR *LPCOLESTR; -#define OLESTR(str) L##str - -#else - -typedef char OLECHAR; -typedef LPSTR LPOLESTR; -typedef LPCSTR LPCOLESTR; -#define OLESTR(str) str - -#endif // _WIN32 && !OLE2ANSI -#endif // __wtypes_h__ - -#ifndef _OLEAUTO_H_ -typedef LPWSTR BSTR;// must (semantically) match typedef in oleauto.h - -extern "C" -{ -__declspec(dllimport) BSTR __stdcall SysAllocString(const OLECHAR *); -__declspec(dllimport) BSTR __stdcall SysAllocStringLen(const OLECHAR *, UINT); -__declspec(dllimport) INT __stdcall SysReAllocStringLen(BSTR *, const OLECHAR *, UINT); -__declspec(dllimport) void __stdcall SysFreeString(BSTR); -} -#endif - -// we use our own implementation of InterlockedExchangePointer because of problems with the one in system headers -#ifdef _M_IX86 -#undef InterlockedExchangePointer -inline void* WINAPI InterlockedExchangePointer(void** pp, void* pNew) throw() -{ - return( reinterpret_cast(static_cast(::InterlockedExchange(reinterpret_cast(pp), static_cast(reinterpret_cast(pNew))))) ); -} -#endif -namespace ATL -{ -#ifndef _CONVERSION_DONT_USE_THREAD_LOCALE -typedef UINT (WINAPI *ATLGETTHREADACP)(); - -inline UINT WINAPI _AtlGetThreadACPFake() throw() -{ - UINT nACP = 0; - - LCID lcidThread = ::GetThreadLocale(); - - char szACP[7]; - // GetLocaleInfoA will fail for a Unicode-only LCID, but those are only supported on - // Windows 2000. Since Windows 2000 supports CP_THREAD_ACP, this code path is never - // executed on Windows 2000. - if (::GetLocaleInfoA(lcidThread, LOCALE_IDEFAULTANSICODEPAGE, szACP, 7) != 0) - { - char* pch = szACP; - while (*pch != '\0') - { - nACP *= 10; - nACP += *pch++ - '0'; - } - } - // Use the Default ANSI Code Page if we were unable to get the thread ACP or if one does not exist. - if (nACP == 0) - nACP = ::GetACP(); - - return nACP; -} - -inline UINT WINAPI _AtlGetThreadACPReal() throw() -{ - return( CP_THREAD_ACP ); -} - -extern ATLGETTHREADACP g_pfnGetThreadACP; - -inline UINT WINAPI _AtlGetThreadACPThunk() throw() -{ - OSVERSIONINFO ver; - ATLGETTHREADACP pfnGetThreadACP; - - ver.dwOSVersionInfoSize = sizeof( ver ); - ::GetVersionEx( &ver ); - if( (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) && (ver.dwMajorVersion >= 5) ) - { - // On Win2K, CP_THREAD_ACP is supported - pfnGetThreadACP = _AtlGetThreadACPReal; - } - else - { - pfnGetThreadACP = _AtlGetThreadACPFake; - } - InterlockedExchangePointer( reinterpret_cast< void** >(&g_pfnGetThreadACP), pfnGetThreadACP ); - - return( g_pfnGetThreadACP() ); -} - -__declspec( selectany ) ATLGETTHREADACP g_pfnGetThreadACP = _AtlGetThreadACPThunk; - -inline UINT WINAPI _AtlGetConversionACP() throw() -{ - return( g_pfnGetThreadACP() ); -} - -#else - -inline UINT WINAPI _AtlGetConversionACP() throw() -{ - return( CP_ACP ); -} - -#endif // _CONVERSION_DONT_USE_THREAD_LOCALE - -template< int t_nBufferLength = 128 > -class CW2WEX -{ -public: - CW2WEX( LPCWSTR psz ) throw(...) : - m_psz( m_szBuffer ) - { - Init( psz ); - } - CW2WEX( LPCWSTR psz, UINT nCodePage ) throw(...) : - m_psz( m_szBuffer ) - { - (void)nCodePage; // Code page doesn't matter - - Init( psz ); - } - ~CW2WEX() throw() - { - if( m_psz != m_szBuffer ) - { - free( m_psz ); - } - } - - operator LPWSTR() const throw() - { - return( m_psz ); - } - -private: - void Init( LPCWSTR psz ) throw(...) - { - if (psz == NULL) - { - m_psz = NULL; - return; - } - int nLength = lstrlenW( psz )+1; - if( nLength > t_nBufferLength ) - { - m_psz = static_cast< LPWSTR >( malloc( nLength*sizeof( wchar_t ) ) ); - if( m_psz == NULL ) - { - AtlThrow( E_OUTOFMEMORY ); - } - } - memcpy( m_psz, psz, nLength*sizeof( wchar_t ) ); - } - -public: - LPWSTR m_psz; - wchar_t m_szBuffer[t_nBufferLength]; - -private: - CW2WEX( const CW2WEX& ) throw(); - CW2WEX& operator=( const CW2WEX& ) throw(); -}; -typedef CW2WEX<> CW2W; - -template< int t_nBufferLength = 128 > -class CA2AEX -{ -public: - CA2AEX( LPCSTR psz ) throw(...) : - m_psz( m_szBuffer ) - { - Init( psz ); - } - CA2AEX( LPCSTR psz, UINT nCodePage ) throw(...) : - m_psz( m_szBuffer ) - { - (void)nCodePage; // Code page doesn't matter - - Init( psz ); - } - ~CA2AEX() throw() - { - if( m_psz != m_szBuffer ) - { - free( m_psz ); - } - } - - operator LPSTR() const throw() - { - return( m_psz ); - } - -private: - void Init( LPCSTR psz ) throw(...) - { - if (psz == NULL) - { - m_psz = NULL; - return; - } - int nLength = lstrlenA( psz )+1; - if( nLength > t_nBufferLength ) - { - m_psz = static_cast< LPSTR >( malloc( nLength*sizeof( char ) ) ); - if( m_psz == NULL ) - { - AtlThrow( E_OUTOFMEMORY ); - } - } - memcpy( m_psz, psz, nLength*sizeof( char ) ); - } - -public: - LPSTR m_psz; - char m_szBuffer[t_nBufferLength]; - -private: - CA2AEX( const CA2AEX& ) throw(); - CA2AEX& operator=( const CA2AEX& ) throw(); -}; -typedef CA2AEX<> CA2A; - -template< int t_nBufferLength = 128 > -class CA2CAEX -{ -public: - CA2CAEX( LPCSTR psz ) throw(...) : - m_psz( psz ) - { - } - CA2CAEX( LPCSTR psz, UINT nCodePage ) throw(...) : - m_psz( psz ) - { - (void)nCodePage; - } - ~CA2CAEX() throw() - { - } - - operator LPCSTR() const throw() - { - return( m_psz ); - } - -public: - LPCSTR m_psz; - -private: - CA2CAEX( const CA2CAEX& ) throw(); - CA2CAEX& operator=( const CA2CAEX& ) throw(); -}; -typedef CA2CAEX<> CA2CA; - -template< int t_nBufferLength = 128 > -class CW2CWEX -{ -public: - CW2CWEX( LPCWSTR psz ) throw(...) : - m_psz( psz ) - { - } - CW2CWEX( LPCWSTR psz, UINT nCodePage ) throw(...) : - m_psz( psz ) - { - (void)nCodePage; - } - ~CW2CWEX() throw() - { - } - - operator LPCWSTR() const throw() - { - return( m_psz ); - } - -public: - LPCWSTR m_psz; - -private: - CW2CWEX( const CW2CWEX& ) throw(); - CW2CWEX& operator=( const CW2CWEX& ) throw(); -}; -typedef CW2CWEX<> CW2CW; - -template< int t_nBufferLength = 128 > -class CA2WEX -{ -public: - CA2WEX( LPCSTR psz ) throw(...) : - m_psz( m_szBuffer ) - { - Init( psz, _AtlGetConversionACP() ); - } - CA2WEX( LPCSTR psz, UINT nCodePage ) throw(...) : - m_psz( m_szBuffer ) - { - Init( psz, nCodePage ); - } - ~CA2WEX() throw() - { - if( m_psz != m_szBuffer ) - { - free( m_psz ); - } - } - - operator LPWSTR() const throw() - { - return( m_psz ); - } - -private: - void Init( LPCSTR psz, UINT nCodePage ) throw(...) - { - if (psz == NULL) - { - m_psz = NULL; - return; - } - int nLengthA = lstrlenA( psz )+1; - int nLengthW = nLengthA; - - if( nLengthW > t_nBufferLength ) - { - m_psz = static_cast< LPWSTR >( malloc( nLengthW*sizeof( wchar_t ) ) ); - if (m_psz == NULL) - { - AtlThrow( E_OUTOFMEMORY ); - } - } - - if (::MultiByteToWideChar( nCodePage, 0, psz, nLengthA, m_psz, nLengthW ) == 0) - { - AtlThrowLastWin32(); - } - } - -public: - LPWSTR m_psz; - wchar_t m_szBuffer[t_nBufferLength]; - -private: - CA2WEX( const CA2WEX& ) throw(); - CA2WEX& operator=( const CA2WEX& ) throw(); -}; -typedef CA2WEX<> CA2W; - -template< int t_nBufferLength = 128 > -class CW2AEX -{ -public: - CW2AEX( LPCWSTR psz ) throw(...) : - m_psz( m_szBuffer ) - { - Init( psz, _AtlGetConversionACP() ); - } - CW2AEX( LPCWSTR psz, UINT nCodePage ) throw(...) : - m_psz( m_szBuffer ) - { - Init( psz, nCodePage ); - } - ~CW2AEX() throw() - { - if( m_psz != m_szBuffer ) - { - free( m_psz ); - } - } - - operator LPSTR() const throw() - { - return( m_psz ); - } - -private: - void Init( LPCWSTR psz, UINT nCodePage ) throw(...) - { - if (psz == NULL) - { - m_psz = NULL; - return; - } - int nLengthW = lstrlenW( psz )+1; - int nLengthA = nLengthW*2; - - if( nLengthA > t_nBufferLength ) - { - m_psz = static_cast< LPSTR >( malloc( nLengthA*sizeof( char ) ) ); - if (m_psz == NULL) - { - AtlThrow( E_OUTOFMEMORY ); - } - } - - if (::WideCharToMultiByte( nCodePage, 0, psz, nLengthW, m_psz, nLengthA, NULL, NULL ) == 0) - { - AtlThrowLastWin32(); - } - } - -public: - LPSTR m_psz; - char m_szBuffer[t_nBufferLength]; - -private: - CW2AEX( const CW2AEX& ) throw(); - CW2AEX& operator=( const CW2AEX& ) throw(); -}; -typedef CW2AEX<> CW2A; - -#ifdef _UNICODE - - #define CW2T CW2W - #define CW2TEX CW2WEX - #define CW2CT CW2CW - #define CW2CTEX CW2CWEX - #define CT2W CW2W - #define CT2WEX CW2WEX - #define CT2CW CW2CW - #define CT2CWEX CW2CWEX - - #define CA2T CA2W - #define CA2TEX CA2WEX - #define CA2CT CA2W - #define CA2CTEX CA2WEX - #define CT2A CW2A - #define CT2AEX CW2AEX - #define CT2CA CW2A - #define CT2CAEX CW2AEX - -#else // !_UNICODE - - #define CW2T CW2A - #define CW2TEX CW2AEX - #define CW2CT CW2A - #define CW2CTEX CW2AEX - #define CT2W CA2W - #define CT2WEX CA2WEX - #define CT2CW CA2W - #define CT2CWEX CA2WEX - - #define CA2T CA2A - #define CA2TEX CA2AEX - #define CA2CT CA2CA - #define CA2CTEX CA2CAEX - #define CT2A CA2A - #define CT2AEX CA2AEX - #define CT2CA CA2CA - #define CT2CAEX CA2CAEX - -#endif // !_UNICODE - -#define COLE2T CW2T -#define COLE2TEX CW2TEX -#define COLE2CT CW2CT -#define COLE2CTEX CW2CTEX -#define CT2OLE CT2W -#define CT2OLEEX CT2WEX -#define CT2COLE CT2CW -#define CT2COLEEX CT2CWEX - -}; // namespace ATL - -#pragma pack(push,8) - -#ifndef _ATL_EX_CONVERSION_MACROS_ONLY - -#ifndef _DEBUG - #define USES_CONVERSION int _convert; (_convert); UINT _acp = ATL::_AtlGetConversionACP() /*CP_THREAD_ACP*/; (_acp); LPCWSTR _lpw; (_lpw); LPCSTR _lpa; (_lpa) -#else - #define USES_CONVERSION int _convert = 0; (_convert); UINT _acp = ATL::_AtlGetConversionACP() /*CP_THREAD_ACP*/; (_acp); LPCWSTR _lpw = NULL; (_lpw); LPCSTR _lpa = NULL; (_lpa) -#endif - -#endif // _ATL_EX_CONVERSION_MACROS_ONLY - -#ifndef _DEBUG - #define USES_CONVERSION_EX int _convert_ex; (_convert_ex); UINT _acp_ex = ATL::_AtlGetConversionACP(); (_acp_ex); LPCWSTR _lpw_ex; (_lpw_ex); LPCSTR _lpa_ex; (_lpa_ex); USES_ATL_SAFE_ALLOCA -#else - #define USES_CONVERSION_EX int _convert_ex = 0; (_convert_ex); UINT _acp_ex = ATL::_AtlGetConversionACP(); (_acp_ex); LPCWSTR _lpw_ex = NULL; (_lpw_ex); LPCSTR _lpa_ex = NULL; (_lpa_ex); USES_ATL_SAFE_ALLOCA -#endif - -#ifdef _WINGDI_ - ATLAPI_(LPDEVMODEA) AtlDevModeW2A(LPDEVMODEA lpDevModeA, const DEVMODEW* lpDevModeW); -#endif - -///////////////////////////////////////////////////////////////////////////// -// Global UNICODE<>ANSI translation helpers -inline LPWSTR WINAPI AtlA2WHelper(LPWSTR lpw, LPCSTR lpa, int nChars, UINT acp) throw() -{ - ATLASSERT(lpa != NULL); - ATLASSERT(lpw != NULL); - if (lpw == NULL || lpa == NULL) - return NULL; - // verify that no illegal character present - // since lpw was allocated based on the size of lpa - // don't worry about the number of chars - lpw[0] = '\0'; - int ret = MultiByteToWideChar(acp, 0, lpa, -1, lpw, nChars); - if(ret == 0) - { - ATLASSERT(FALSE); - return NULL; - } - return lpw; -} - -inline LPSTR WINAPI AtlW2AHelper(LPSTR lpa, LPCWSTR lpw, int nChars, UINT acp) throw() -{ - ATLASSERT(lpw != NULL); - ATLASSERT(lpa != NULL); - if (lpa == NULL || lpw == NULL) - return NULL; - // verify that no illegal character present - // since lpa was allocated based on the size of lpw - // don't worry about the number of chars - lpa[0] = '\0'; - int ret = WideCharToMultiByte(acp, 0, lpw, -1, lpa, nChars, NULL, NULL); - if(ret == 0) - { - ATLASSERT(FALSE); - return NULL; - } - return lpa; -} -inline LPWSTR WINAPI AtlA2WHelper(LPWSTR lpw, LPCSTR lpa, int nChars) throw() -{ - return AtlA2WHelper(lpw, lpa, nChars, CP_ACP); -} - -inline LPSTR WINAPI AtlW2AHelper(LPSTR lpa, LPCWSTR lpw, int nChars) throw() -{ - return AtlW2AHelper(lpa, lpw, nChars, CP_ACP); -} - -#ifndef _CONVERSION_DONT_USE_THREAD_LOCALE - #ifdef ATLA2WHELPER - #undef ATLA2WHELPER - #undef ATLW2AHELPER - #endif - #define ATLA2WHELPER AtlA2WHelper - #define ATLW2AHELPER AtlW2AHelper -#else - #ifndef ATLA2WHELPER - #define ATLA2WHELPER AtlA2WHelper - #define ATLW2AHELPER AtlW2AHelper - #endif -#endif - -#ifndef _ATL_EX_CONVERSION_MACROS_ONLY - -#define A2W(lpa) (\ - ((_lpa = lpa) == NULL) ? NULL : (\ - _convert = (lstrlenA(_lpa)+1),\ - ATLA2WHELPER((LPWSTR) alloca(_convert*2), _lpa, _convert, _acp))) - -#define W2A(lpw) (\ - ((_lpw = lpw) == NULL) ? NULL : (\ - _convert = (lstrlenW(_lpw)+1)*2,\ - ATLW2AHELPER((LPSTR) alloca(_convert), _lpw, _convert, _acp))) - -#endif - -// The call to _alloca will not cause stack overflow if _AtlVerifyStackAvailable returns TRUE. -#define A2W_EX(lpa, nChars) (\ - ((_lpa_ex = lpa) == NULL) ? NULL : (\ - _convert_ex = (lstrlenA(_lpa_ex)+1),\ - ATLA2WHELPER( \ - (LPWSTR)_ATL_SAFE_ALLOCA(_convert_ex * sizeof(WCHAR), _ATL_SAFE_ALLOCA_DEF_THRESHOLD), \ - _lpa_ex, \ - _convert_ex, \ - _acp_ex))) - -#define W2A_EX(lpw, nChars) (\ - ((_lpw_ex = lpw) == NULL) ? NULL : (\ - _convert_ex = (lstrlenW(_lpw_ex)+1) * sizeof(WCHAR),\ - ATLW2AHELPER( \ - (LPSTR)_ATL_SAFE_ALLOCA(_convert_ex, _ATL_SAFE_ALLOCA_DEF_THRESHOLD), \ - _lpw_ex, \ - _convert_ex, \ - _acp_ex))) - -#ifndef _ATL_EX_CONVERSION_MACROS_ONLY - -#define A2CW(lpa) ((LPCWSTR)A2W(lpa)) -#define W2CA(lpw) ((LPCSTR)W2A(lpw)) - -#endif // _ATL_EX_CONVERSION_MACROS_ONLY - -#define A2CW_EX(lpa, nChar) ((LPCWSTR)A2W_EX(lpa, nChar)) -#define W2CA_EX(lpw, nChar) ((LPCSTR)W2A_EX(lpw, nChar)) - -#if defined(_UNICODE) -// in these cases the default (TCHAR) is the same as OLECHAR - inline int ocslen(LPCOLESTR x) throw() { return lstrlenW(x); } - inline OLECHAR* ocscpy(LPOLESTR dest, LPCOLESTR src) throw() { return lstrcpyW(dest, src); } - inline OLECHAR* ocscat(LPOLESTR dest, LPCOLESTR src) throw() { return lstrcatW(dest, src); } - - inline LPCOLESTR T2COLE_EX(LPCTSTR lp, UINT) { return lp; } - inline LPCTSTR OLE2CT_EX(LPCOLESTR lp, UINT) { return lp; } - inline LPOLESTR T2OLE_EX(LPTSTR lp, UINT) { return lp; } - inline LPTSTR OLE2T_EX(LPOLESTR lp, UINT) { return lp; } - -#ifndef _ATL_EX_CONVERSION_MACROS_ONLY - - inline LPCOLESTR T2COLE(LPCTSTR lp) { return lp; } - inline LPCTSTR OLE2CT(LPCOLESTR lp) { return lp; } - inline LPOLESTR T2OLE(LPTSTR lp) { return lp; } - inline LPTSTR OLE2T(LPOLESTR lp) { return lp; } - inline LPOLESTR CharNextO(LPCOLESTR lp) throw() {return CharNextW(lp);} - -#endif // _ATL_EX_CONVERSION_MACROS_ONLY - -#else - inline int ocslen(LPCOLESTR x) throw() { return lstrlenW(x); } - //lstrcpyW doesn't work on Win95, so we do this - inline OLECHAR* ocscpy(LPOLESTR dest, LPCOLESTR src) throw() - {return (LPOLESTR) memcpy(dest, src, (lstrlenW(src)+1)*sizeof(WCHAR));} - inline OLECHAR* ocscat(LPOLESTR dest, LPCOLESTR src) throw() { return ocscpy(dest+ocslen(dest), src); } - //CharNextW doesn't work on Win95 so we use this - - #define T2COLE_EX(lpa, nChar) A2CW_EX(lpa, nChar) - #define T2OLE_EX(lpa, nChar) A2W_EX(lpa, nChar) - #define OLE2CT_EX(lpo, nChar) W2CA_EX(lpo, nChar) - #define OLE2T_EX(lpo, nChar) W2A_EX(lpo, nChar) - -#ifndef _ATL_EX_CONVERSION_MACROS_ONLY - - #define T2COLE(lpa) A2CW(lpa) - #define T2OLE(lpa) A2W(lpa) - #define OLE2CT(lpo) W2CA(lpo) - #define OLE2T(lpo) W2A(lpo) - -#endif // _ATL_EX_CONVERSION_MACROS_ONLY - - inline LPOLESTR CharNextO(LPCOLESTR lp) throw() {return (LPOLESTR) ((*lp) ? (lp+1) : lp);} - -#endif - - inline LPOLESTR W2OLE_EX(LPWSTR lp, UINT) { return lp; } - inline LPWSTR OLE2W_EX(LPOLESTR lp, UINT) { return lp; } - #define A2OLE_EX A2W_EX - #define OLE2A_EX W2A_EX - inline LPCOLESTR W2COLE_EX(LPCWSTR lp, UINT) { return lp; } - inline LPCWSTR OLE2CW_EX(LPCOLESTR lp, UINT) { return lp; } - #define A2COLE_EX A2CW_EX - #define OLE2CA_EX W2CA_EX - -#ifndef _ATL_EX_CONVERSION_MACROS_ONLY - - inline LPOLESTR W2OLE(LPWSTR lp) { return lp; } - inline LPWSTR OLE2W(LPOLESTR lp) { return lp; } - #define A2OLE A2W - #define OLE2A W2A - inline LPCOLESTR W2COLE(LPCWSTR lp) { return lp; } - inline LPCWSTR OLE2CW(LPCOLESTR lp) { return lp; } - #define A2COLE A2CW - #define OLE2CA W2CA - -#endif // _ATL_EX_CONVERSION_MACROS_ONLY - -#ifdef _UNICODE - #define T2A_EX W2A_EX - #define A2T_EX A2W_EX - inline LPWSTR T2W_EX(LPTSTR lp, UINT) { return lp; } - inline LPTSTR W2T_EX(LPWSTR lp, UINT) { return lp; } - #define T2CA_EX W2CA_EX - #define A2CT_EX A2CW_EX - inline LPCWSTR T2CW_EX(LPCTSTR lp, UINT) { return lp; } - inline LPCTSTR W2CT_EX(LPCWSTR lp, UINT) { return lp; } - -#ifndef _ATL_EX_CONVERSION_MACROS_ONLY - - #define T2A W2A - #define A2T A2W - inline LPWSTR T2W(LPTSTR lp) { return lp; } - inline LPTSTR W2T(LPWSTR lp) { return lp; } - #define T2CA W2CA - #define A2CT A2CW - inline LPCWSTR T2CW(LPCTSTR lp) { return lp; } - inline LPCTSTR W2CT(LPCWSTR lp) { return lp; } - -#endif // _ATL_EX_CONVERSION_MACROS_ONLY - -#else - #define T2W_EX A2W_EX - #define W2T_EX W2A_EX - inline LPSTR T2A_EX(LPTSTR lp, UINT) { return lp; } - inline LPTSTR A2T_EX(LPSTR lp, UINT) { return lp; } - #define T2CW_EX A2CW_EX - #define W2CT_EX W2CA_EX - inline LPCSTR T2CA_EX(LPCTSTR lp, UINT) { return lp; } - inline LPCTSTR A2CT_EX(LPCSTR lp, UINT) { return lp; } - -#ifndef _ATL_EX_CONVERSION_MACROS_ONLY - - #define T2W A2W - #define W2T W2A - inline LPSTR T2A(LPTSTR lp) { return lp; } - inline LPTSTR A2T(LPSTR lp) { return lp; } - #define T2CW A2CW - #define W2CT W2CA - inline LPCSTR T2CA(LPCTSTR lp) { return lp; } - inline LPCTSTR A2CT(LPCSTR lp) { return lp; } - -#endif // _ATL_EX_CONVERSION_MACROS_ONLY - -#endif - -inline BSTR A2WBSTR(LPCSTR lp, int nLen = -1) -{ - if (lp == NULL || nLen == 0) - return NULL; - USES_CONVERSION_EX; - BSTR str = NULL; - int nConvertedLen = MultiByteToWideChar(_acp_ex, 0, lp, - nLen, NULL, NULL); - int nAllocLen = nConvertedLen; - if (nLen == -1) - nAllocLen -= 1; // Don't allocate terminating '\0' - str = ::SysAllocStringLen(NULL, nAllocLen); - - if (str != NULL) - { - int nResult; - nResult = MultiByteToWideChar(_acp_ex, 0, lp, nLen, str, nConvertedLen); - ATLASSERT(nResult == nConvertedLen); - if(nResult != nConvertedLen) - { - SysFreeString(str); - return NULL; - } - - } - return str; -} - -inline BSTR OLE2BSTR(LPCOLESTR lp) {return ::SysAllocString(lp);} -#if defined(_UNICODE) -// in these cases the default (TCHAR) is the same as OLECHAR - inline BSTR T2BSTR_EX(LPCTSTR lp) {return ::SysAllocString(lp);} - inline BSTR A2BSTR_EX(LPCSTR lp) {return A2WBSTR(lp);} - inline BSTR W2BSTR_EX(LPCWSTR lp) {return ::SysAllocString(lp);} - -#ifndef _ATL_EX_CONVERSION_MACROS_ONLY - - inline BSTR T2BSTR(LPCTSTR lp) {return ::SysAllocString(lp);} - inline BSTR A2BSTR(LPCSTR lp) {USES_CONVERSION; return A2WBSTR(lp);} - inline BSTR W2BSTR(LPCWSTR lp) {return ::SysAllocString(lp);} - -#endif // _ATL_EX_CONVERSION_MACROS_ONLY - -#else - inline BSTR T2BSTR_EX(LPCTSTR lp) {return A2WBSTR(lp);} - inline BSTR A2BSTR_EX(LPCSTR lp) {return A2WBSTR(lp);} - inline BSTR W2BSTR_EX(LPCWSTR lp) {return ::SysAllocString(lp);} - -#ifndef _ATL_EX_CONVERSION_MACROS_ONLY - - inline BSTR T2BSTR(LPCTSTR lp) {USES_CONVERSION; return A2WBSTR(lp);} - inline BSTR A2BSTR(LPCSTR lp) {USES_CONVERSION; return A2WBSTR(lp);} - inline BSTR W2BSTR(LPCWSTR lp) {return ::SysAllocString(lp);} - -#endif // _ATL_EX_CONVERSION_MACROS_ONLY - -#endif - -#ifdef _WINGDI_ -///////////////////////////////////////////////////////////////////////////// -// Global UNICODE<>ANSI translation helpers -inline LPDEVMODEW AtlDevModeA2W(LPDEVMODEW lpDevModeW, const DEVMODEA* lpDevModeA) -{ - USES_CONVERSION_EX; - ATLASSERT(lpDevModeW != NULL); - if (lpDevModeA == NULL || lpDevModeW == NULL) - return NULL; - AtlA2WHelper(lpDevModeW->dmDeviceName, (LPCSTR)lpDevModeA->dmDeviceName, 32, _acp_ex); - memcpy(&lpDevModeW->dmSpecVersion, &lpDevModeA->dmSpecVersion, - offsetof(DEVMODEW, dmFormName) - offsetof(DEVMODEW, dmSpecVersion)); - AtlA2WHelper(lpDevModeW->dmFormName, (LPCSTR)lpDevModeA->dmFormName, 32, _acp_ex); - memcpy(&lpDevModeW->dmLogPixels, &lpDevModeA->dmLogPixels, - sizeof(DEVMODEW) - offsetof(DEVMODEW, dmLogPixels)); - if (lpDevModeA->dmDriverExtra != 0) - memcpy(lpDevModeW+1, lpDevModeA+1, lpDevModeA->dmDriverExtra); - lpDevModeW->dmSize = sizeof(DEVMODEW); - return lpDevModeW; -} - -inline LPTEXTMETRICW AtlTextMetricA2W(LPTEXTMETRICW lptmW, LPTEXTMETRICA lptmA) -{ - USES_CONVERSION_EX; - ATLASSERT(lptmW != NULL); - if (lptmA == NULL || lptmW == NULL) - return NULL; - memcpy(lptmW, lptmA, sizeof(LONG) * 11); - memcpy(&lptmW->tmItalic, &lptmA->tmItalic, sizeof(BYTE) * 5); - - if(MultiByteToWideChar(_acp_ex, 0, (LPCSTR)&lptmA->tmFirstChar, 1, &lptmW->tmFirstChar, 1) == 0) - { - ATLASSERT(FALSE); - return NULL; - } - - if(MultiByteToWideChar(_acp_ex, 0, (LPCSTR)&lptmA->tmLastChar, 1, &lptmW->tmLastChar, 1) == 0) - { - ATLASSERT(FALSE); - return NULL; - } - - if(MultiByteToWideChar(_acp_ex, 0, (LPCSTR)&lptmA->tmDefaultChar, 1, &lptmW->tmDefaultChar, 1)== 0) - { - ATLASSERT(FALSE); - return NULL; - } - - if(MultiByteToWideChar(_acp_ex, 0, (LPCSTR)&lptmA->tmBreakChar, 1, &lptmW->tmBreakChar, 1) == 0) - { - ATLASSERT(FALSE); - return NULL; - } - - return lptmW; -} - -inline LPTEXTMETRICA AtlTextMetricW2A(LPTEXTMETRICA lptmA, LPTEXTMETRICW lptmW) -{ - USES_CONVERSION_EX; - ATLASSERT(lptmA != NULL); - if (lptmW == NULL || lptmA == NULL) - return NULL; - memcpy(lptmA, lptmW, sizeof(LONG) * 11); - memcpy(&lptmA->tmItalic, &lptmW->tmItalic, sizeof(BYTE) * 5); - - if(WideCharToMultiByte(_acp_ex, 0, &lptmW->tmFirstChar, 1, (LPSTR)&lptmA->tmFirstChar, 1, NULL, NULL) == 0) - { - ATLASSERT(FALSE); - return NULL; - } - - if(WideCharToMultiByte(_acp_ex, 0, &lptmW->tmLastChar, 1, (LPSTR)&lptmA->tmLastChar, 1, NULL, NULL) == 0) - { - ATLASSERT(FALSE); - return NULL; - } - - if(WideCharToMultiByte(_acp_ex, 0, &lptmW->tmDefaultChar, 1, (LPSTR)&lptmA->tmDefaultChar, 1, NULL, NULL) == 0) - { - ATLASSERT(FALSE); - return NULL; - } - - if(WideCharToMultiByte(_acp_ex, 0, &lptmW->tmBreakChar, 1, (LPSTR)&lptmA->tmBreakChar, 1, NULL, NULL) == 0) - { - ATLASSERT(FALSE); - return NULL; - } - - return lptmA; -} - -#ifndef ATLDEVMODEA2W -#define ATLDEVMODEA2W AtlDevModeA2W -#define ATLDEVMODEW2A AtlDevModeW2A -#define ATLTEXTMETRICA2W AtlTextMetricA2W -#define ATLTEXTMETRICW2A AtlTextMetricW2A -#endif - -// Requires USES_CONVERSION_EX or USES_ATL_SAFE_ALLOCA macro before using the _EX versions of the macros -#define DEVMODEW2A_EX(lpw)\ - (((lpw) == NULL) ? NULL : ATLDEVMODEW2A((LPDEVMODEA)_ATL_SAFE_ALLOCA(sizeof(DEVMODEA)+(lpw)->dmDriverExtra, _ATL_SAFE_ALLOCA_DEF_THRESHOLD), (lpw))) -#define DEVMODEA2W_EX(lpa)\ - (((lpa) == NULL) ? NULL : ATLDEVMODEA2W((LPDEVMODEW)_ATL_SAFE_ALLOCA(sizeof(DEVMODEW)+(lpa)->dmDriverExtra, _ATL_SAFE_ALLOCA_DEF_THRESHOLD), (lpa))) -#define TEXTMETRICW2A_EX(lptmw)\ - (((lptmw) == NULL) ? NULL : ATLTEXTMETRICW2A((LPTEXTMETRICA)_ATL_SAFE_ALLOCA(sizeof(TEXTMETRICA), _ATL_SAFE_ALLOCA_DEF_THRESHOLD), (lptmw))) -#define TEXTMETRICA2W_EX(lptma)\ - (((lptma) == NULL) ? NULL : ATLTEXTMETRICA2W((LPTEXTMETRICW)_ATL_SAFE_ALLOCA(sizeof(TEXTMETRICW), _ATL_SAFE_ALLOCA_DEF_THRESHOLD), (lptma))) - -#ifndef _ATL_EX_CONVERSION_MACROS_ONLY - -#define DEVMODEW2A(lpw)\ - ((lpw == NULL) ? NULL : ATLDEVMODEW2A((LPDEVMODEA)alloca(sizeof(DEVMODEA)+lpw->dmDriverExtra), lpw)) -#define DEVMODEA2W(lpa)\ - ((lpa == NULL) ? NULL : ATLDEVMODEA2W((LPDEVMODEW)alloca(sizeof(DEVMODEW)+lpa->dmDriverExtra), lpa)) -#define TEXTMETRICW2A(lptmw)\ - ((lptmw == NULL) ? NULL : ATLTEXTMETRICW2A((LPTEXTMETRICA)alloca(sizeof(TEXTMETRICA)), lptmw)) -#define TEXTMETRICA2W(lptma)\ - ((lptma == NULL) ? NULL : ATLTEXTMETRICA2W((LPTEXTMETRICW)alloca(sizeof(TEXTMETRICW)), lptma)) - -#endif // _ATL_EX_CONVERSION_MACROS_ONLY - -#define DEVMODEOLE DEVMODEW -#define LPDEVMODEOLE LPDEVMODEW -#define TEXTMETRICOLE TEXTMETRICW -#define LPTEXTMETRICOLE LPTEXTMETRICW - -#if defined(_UNICODE) -// in these cases the default (TCHAR) is the same as OLECHAR - inline LPDEVMODEW DEVMODEOLE2T_EX(LPDEVMODEOLE lp) { return lp; } - inline LPDEVMODEOLE DEVMODET2OLE_EX(LPDEVMODEW lp) { return lp; } - inline LPTEXTMETRICW TEXTMETRICOLE2T_EX(LPTEXTMETRICOLE lp) { return lp; } - inline LPTEXTMETRICOLE TEXTMETRICT2OLE_EX(LPTEXTMETRICW lp) { return lp; } -#ifndef _ATL_EX_CONVERSION_MACROS_ONLY - inline LPDEVMODEW DEVMODEOLE2T(LPDEVMODEOLE lp) { return lp; } - inline LPDEVMODEOLE DEVMODET2OLE(LPDEVMODEW lp) { return lp; } - inline LPTEXTMETRICW TEXTMETRICOLE2T(LPTEXTMETRICOLE lp) { return lp; } - inline LPTEXTMETRICOLE TEXTMETRICT2OLE(LPTEXTMETRICW lp) { return lp; } -#endif // _ATL_EX_CONVERSION_MACROS_ONLY - -#else - #define DEVMODEOLE2T_EX(lpo) DEVMODEW2A_EX(lpo) - #define DEVMODET2OLE_EX(lpa) DEVMODEA2W_EX(lpa) - #define TEXTMETRICOLE2T_EX(lptmw) TEXTMETRICW2A_EX(lptmw) - #define TEXTMETRICT2OLE_EX(lptma) TEXTMETRICA2W_EX(lptma) -#ifndef _ATL_EX_CONVERSION_MACROS_ONLY - #define DEVMODEOLE2T(lpo) DEVMODEW2A(lpo) - #define DEVMODET2OLE(lpa) DEVMODEA2W(lpa) - #define TEXTMETRICOLE2T(lptmw) TEXTMETRICW2A(lptmw) - #define TEXTMETRICT2OLE(lptma) TEXTMETRICA2W(lptma) -#endif // _ATL_EX_CONVERSION_MACROS_ONLY - -#endif - -#endif //_WINGDI_ - -#pragma pack(pop) - -#endif // __ATLCONV_H__ - -///////////////////////////////////////////////////////////////////////////// - -#ifndef _ATL_DLL - -#ifdef _WINGDI_ - -ATLINLINE ATLAPI_(LPDEVMODEA) AtlDevModeW2A(LPDEVMODEA lpDevModeA, const DEVMODEW* lpDevModeW) -{ - USES_CONVERSION_EX; - ATLASSERT(lpDevModeA != NULL); - if (lpDevModeW == NULL || lpDevModeA == NULL) - return NULL; - AtlW2AHelper((LPSTR)lpDevModeA->dmDeviceName, lpDevModeW->dmDeviceName, 32, _acp_ex); - memcpy(&lpDevModeA->dmSpecVersion, &lpDevModeW->dmSpecVersion, - offsetof(DEVMODEA, dmFormName) - offsetof(DEVMODEA, dmSpecVersion)); - AtlW2AHelper((LPSTR)lpDevModeA->dmFormName, lpDevModeW->dmFormName, 32, _acp_ex); - memcpy(&lpDevModeA->dmLogPixels, &lpDevModeW->dmLogPixels, - sizeof(DEVMODEA) - offsetof(DEVMODEA, dmLogPixels)); - if (lpDevModeW->dmDriverExtra != 0) - memcpy(lpDevModeA+1, lpDevModeW+1, lpDevModeW->dmDriverExtra); - lpDevModeA->dmSize = sizeof(DEVMODEA); - return lpDevModeA; -} - -#endif //_WINGDI - -#endif // !_ATL_DLL - -#ifndef _ATL_NO_PRAGMA_WARNINGS -#pragma warning (pop) -#endif //!_ATL_NO_PRAGMA_WARNINGS diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlcore.h b/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlcore.h deleted file mode 100644 index 8bbbed7e1..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlcore.h +++ /dev/null @@ -1,400 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLCORE_H__ -#define __ATLCORE_H__ - -#pragma once - -#ifdef _ATL_ALL_WARNINGS -#pragma warning( push ) -#endif - -#pragma warning(disable: 4786) // identifier was truncated in the debug information - -#include -#include - -#include -#include - -#include -#include - - -namespace ATL -{ -///////////////////////////////////////////////////////////////////////////// -// Verify that a null-terminated string points to valid memory -inline BOOL AtlIsValidString(LPCWSTR psz, size_t nMaxLength = INT_MAX) -{ -#if defined(_DEBUG) - // Implement ourselves because ::IsBadStringPtrW() isn't implemented on Win9x. - if ((psz == NULL) || (nMaxLength == 0)) - return FALSE; - - LPCWSTR pch; - LPCWSTR pchEnd; - __try - { - wchar_t ch; - - pch = psz; - pchEnd = psz+nMaxLength-1; - ch = *(volatile wchar_t*)pch; - while ((ch != L'\0') && (pch != pchEnd)) - { - pch++; - ch = *(volatile wchar_t*)pch; - } - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - return FALSE; - } - - return TRUE; -#else - (nMaxLength); - return (psz != NULL); -#endif -} - -// Verify that a null-terminated string points to valid memory -inline BOOL AtlIsValidString(LPCSTR psz, size_t nMaxLength = UINT_MAX) -{ -#if defined(_DEBUG) - if (psz == NULL) - return FALSE; - return ::IsBadStringPtrA(psz, nMaxLength) == 0; -#else - (nMaxLength); - return (psz != NULL); -#endif -} - -// Verify that a pointer points to valid memory -inline BOOL AtlIsValidAddress(const void* p, size_t nBytes, - BOOL bReadWrite = TRUE) -{ -#if defined(_DEBUG) - return ((p != NULL) && !IsBadReadPtr(p, nBytes) && - (!bReadWrite || !IsBadWritePtr(const_cast(p), nBytes))); -#else - nBytes,bReadWrite; - return (p != NULL); -#endif -} - -template -inline void AtlAssertValidObject(const T *pOb) -{ - ATLASSERT(pOb); - ATLASSERT(AtlIsValidAddress(pOb, sizeof(T))); - if(pOb) - pOb->AssertValid(); -} -#ifdef _DEBUG -#define ATLASSERT_VALID(x) ATL::AtlAssertValidObject(x) -#else -#define ATLASSERT_VALID(x) __noop; -#endif - -// COM Sync Classes -class CComCriticalSection -{ -public: - CComCriticalSection() throw() - { - memset(&m_sec, 0, sizeof(CRITICAL_SECTION)); - } - HRESULT Lock() throw() - { - EnterCriticalSection(&m_sec); - return S_OK; - } - HRESULT Unlock() throw() - { - LeaveCriticalSection(&m_sec); - return S_OK; - } - HRESULT Init() throw() - { - HRESULT hRes = S_OK; - __try - { - InitializeCriticalSection(&m_sec); - } - // structured exception may be raised in low memory situations - __except(EXCEPTION_EXECUTE_HANDLER) - { - if (STATUS_NO_MEMORY == GetExceptionCode()) - hRes = E_OUTOFMEMORY; - else - hRes = E_FAIL; - } - return hRes; - } - - HRESULT Term() throw() - { - DeleteCriticalSection(&m_sec); - return S_OK; - } - CRITICAL_SECTION m_sec; -}; - -class CComAutoCriticalSection : public CComCriticalSection -{ -public: - CComAutoCriticalSection() - { - HRESULT hr = CComCriticalSection::Init(); - if (FAILED(hr)) - AtlThrow(hr); - } - ~CComAutoCriticalSection() throw() - { - CComCriticalSection::Term(); - } -private : - HRESULT Init(); // Not implemented. CComAutoCriticalSection::Init should never be called - HRESULT Term(); // Not implemented. CComAutoCriticalSection::Term should never be called -}; - -class CComFakeCriticalSection -{ -public: - HRESULT Lock() throw() { return S_OK; } - HRESULT Unlock() throw() { return S_OK; } - HRESULT Init() throw() { return S_OK; } - HRESULT Term() throw() { return S_OK; } -}; - -///////////////////////////////////////////////////////////////////////////// -// Module - -// Used by any project that uses ATL -struct _ATL_BASE_MODULE70 -{ - UINT cbSize; - HINSTANCE m_hInst; - HINSTANCE m_hInstResource; - bool m_bNT5orWin98; - DWORD dwAtlBuildVer; - const GUID* pguidVer; - CComCriticalSection m_csResource; - CSimpleArray m_rgResourceInstance; -}; -typedef _ATL_BASE_MODULE70 _ATL_BASE_MODULE; - -class CAtlBaseModule : public _ATL_BASE_MODULE -{ -public : - static bool m_bInitFailed; - CAtlBaseModule() throw(); - ~CAtlBaseModule() throw (); - - HINSTANCE GetModuleInstance() throw() - { - return m_hInst; - } - HINSTANCE GetResourceInstance() throw() - { - return m_hInstResource; - } - HINSTANCE SetResourceInstance(HINSTANCE hInst) throw() - { - return static_cast< HINSTANCE >(InterlockedExchangePointer((void**)&m_hInstResource, hInst)); - } - - bool AddResourceInstance(HINSTANCE hInst) throw(); - bool RemoveResourceInstance(HINSTANCE hInst) throw(); - HINSTANCE GetHInstanceAt(int i) throw(); -}; - -__declspec(selectany) bool CAtlBaseModule::m_bInitFailed = false; -extern CAtlBaseModule _AtlBaseModule; - -///////////////////////////////////////////////////////////////////////////// -// String resource helpers - -#pragma warning(push) -#pragma warning(disable: 4200) - struct ATLSTRINGRESOURCEIMAGE - { - WORD nLength; - WCHAR achString[]; - }; -#pragma warning(pop) // C4200 - -inline const ATLSTRINGRESOURCEIMAGE* _AtlGetStringResourceImage( HINSTANCE hInstance, HRSRC hResource, UINT id ) throw() -{ - const ATLSTRINGRESOURCEIMAGE* pImage; - const ATLSTRINGRESOURCEIMAGE* pImageEnd; - ULONG nResourceSize; - HGLOBAL hGlobal; - UINT iIndex; - - hGlobal = ::LoadResource( hInstance, hResource ); - if( hGlobal == NULL ) - { - return( NULL ); - } - - pImage = (const ATLSTRINGRESOURCEIMAGE*)::LockResource( hGlobal ); - if( pImage == NULL ) - { - return( NULL ); - } - - nResourceSize = ::SizeofResource( hInstance, hResource ); - pImageEnd = (const ATLSTRINGRESOURCEIMAGE*)(LPBYTE( pImage )+nResourceSize); - iIndex = id&0x000f; - - while( (iIndex > 0) && (pImage < pImageEnd) ) - { - pImage = (const ATLSTRINGRESOURCEIMAGE*)(LPBYTE( pImage )+(sizeof( ATLSTRINGRESOURCEIMAGE )+(pImage->nLength*sizeof( WCHAR )))); - iIndex--; - } - if( pImage >= pImageEnd ) - { - return( NULL ); - } - if( pImage->nLength == 0 ) - { - return( NULL ); - } - - return( pImage ); -} - -inline const ATLSTRINGRESOURCEIMAGE* AtlGetStringResourceImage( HINSTANCE hInstance, UINT id ) throw() -{ - HRSRC hResource; - - hResource = ::FindResource( hInstance, MAKEINTRESOURCE( ((id>>4)+1) ), RT_STRING ); - if( hResource == NULL ) - { - return( NULL ); - } - - return _AtlGetStringResourceImage( hInstance, hResource, id ); -} - -inline const ATLSTRINGRESOURCEIMAGE* AtlGetStringResourceImage( HINSTANCE hInstance, UINT id, WORD wLanguage ) throw() -{ - HRSRC hResource; - - hResource = ::FindResourceEx( hInstance, RT_STRING, MAKEINTRESOURCE( ((id>>4)+1) ), wLanguage ); - if( hResource == NULL ) - { - return( NULL ); - } - - return _AtlGetStringResourceImage( hInstance, hResource, id ); -} - -inline const ATLSTRINGRESOURCEIMAGE* AtlGetStringResourceImage( UINT id ) throw() -{ - const ATLSTRINGRESOURCEIMAGE* p = NULL; - HINSTANCE hInst = _AtlBaseModule.GetHInstanceAt(0); - - for (int i = 1; hInst != NULL && p == NULL; hInst = _AtlBaseModule.GetHInstanceAt(i++)) - { - p = AtlGetStringResourceImage(hInst, id); - } - return p; -} - -inline const ATLSTRINGRESOURCEIMAGE* AtlGetStringResourceImage( UINT id, WORD wLanguage ) throw() -{ - const ATLSTRINGRESOURCEIMAGE* p = NULL; - HINSTANCE hInst = _AtlBaseModule.GetHInstanceAt(0); - - for (int i = 1; hInst != NULL && p == NULL; hInst = _AtlBaseModule.GetHInstanceAt(i++)) - { - p = AtlGetStringResourceImage(hInst, id, wLanguage); - } - return p; -} - -inline int AtlLoadString(UINT nID, LPTSTR lpBuffer, int nBufferMax) throw() -{ - HINSTANCE hInst = _AtlBaseModule.GetHInstanceAt(0); - int nRet = 0; - - for (int i = 1; hInst != NULL && nRet == 0; hInst = _AtlBaseModule.GetHInstanceAt(i++)) - { - nRet = LoadString(hInst, nID, lpBuffer, nBufferMax); - } - return nRet; -} - -inline HINSTANCE AtlFindResourceInstance(LPCTSTR lpName, LPCTSTR lpType, WORD wLanguage = 0) throw() -{ - ATLASSERT(lpType != RT_STRING); // Call AtlFindStringResourceInstance to find the string - if (lpType == RT_STRING) - return NULL; - - if (IS_INTRESOURCE(lpType)) - { - if (lpType == RT_ICON) - { - lpType = RT_GROUP_ICON; - } - else if (lpType == RT_CURSOR) - { - lpType = RT_GROUP_CURSOR; - } - } - - HINSTANCE hInst = _AtlBaseModule.GetHInstanceAt(0); - HRSRC hResource = NULL; - - for (int i = 1; hInst != NULL; hInst = _AtlBaseModule.GetHInstanceAt(i++)) - { - hResource = ::FindResourceEx(hInst, lpType, lpName, wLanguage); - if (hResource != NULL) - { - return hInst; - } - } - - return NULL; -} - -inline HINSTANCE AtlFindResourceInstance(UINT nID, LPCTSTR lpType, WORD wLanguage = 0) throw() -{ - return AtlFindResourceInstance(MAKEINTRESOURCE(nID), lpType, wLanguage); -} - -inline HINSTANCE AtlFindStringResourceInstance(UINT nID, WORD wLanguage = 0) throw() -{ - const ATLSTRINGRESOURCEIMAGE* p = NULL; - HINSTANCE hInst = _AtlBaseModule.GetHInstanceAt(0); - - for (int i = 1; hInst != NULL && p == NULL; hInst = _AtlBaseModule.GetHInstanceAt(i++)) - { - p = AtlGetStringResourceImage(hInst, nID, wLanguage); - if (p != NULL) - return hInst; - } - - return NULL; -} - -} // namespace ATL - -#ifdef _ATL_ALL_WARNINGS -#pragma warning( pop ) -#endif - -#endif // __ATLCORE_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atldef.h b/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atldef.h deleted file mode 100644 index ab02198e8..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atldef.h +++ /dev/null @@ -1,295 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLDEF_H__ -#define __ATLDEF_H__ - -#pragma once - -#pragma warning(disable : 4619) // there is no warning number - -#include - -#ifndef RC_INVOKED - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#ifdef UNDER_CE - #error ATL not currently supported for CE -#endif - -#ifdef _UNICODE -#ifndef UNICODE -#define UNICODE // UNICODE is used by Windows headers -#endif -#endif - -#ifdef UNICODE -#ifndef _UNICODE -#define _UNICODE // _UNICODE is used by C-runtime/MFC headers -#endif -#endif - -#ifdef _DEBUG -#ifndef DEBUG -#define DEBUG -#endif -#endif - -#ifdef _WIN64 -#define _ATL_SUPPORT_VT_I8 // Always support VT_I8 on Win64. -#endif - -#ifndef ATLASSERT -#define ATLASSERT(expr) _ASSERTE(expr) -#endif - -#ifndef ATLVERIFY -#ifdef _DEBUG -#define ATLVERIFY(expr) ATLASSERT(expr) -#else -#define ATLVERIFY(expr) (expr) -#endif // DEBUG -#endif // ATLVERIFY - -/////////////////////////////////////////////////////////////////////////////// -// __declspec(novtable) is used on a class declaration to prevent the vtable -// pointer from being initialized in the constructor and destructor for the -// class. This has many benefits because the linker can now eliminate the -// vtable and all the functions pointed to by the vtable. Also, the actual -// constructor and destructor code are now smaller. -/////////////////////////////////////////////////////////////////////////////// -// This should only be used on a class that is not directly createable but is -// rather only used as a base class. Additionally, the constructor and -// destructor (if provided by the user) should not call anything that may cause -// a virtual function call to occur back on the object. -/////////////////////////////////////////////////////////////////////////////// -// By default, the wizards will generate new ATL object classes with this -// attribute (through the ATL_NO_VTABLE macro). This is normally safe as long -// the restriction mentioned above is followed. It is always safe to remove -// this macro from your class, so if in doubt, remove it. -/////////////////////////////////////////////////////////////////////////////// - -#ifdef _ATL_DISABLE_NO_VTABLE -#define ATL_NO_VTABLE -#else -#define ATL_NO_VTABLE __declspec(novtable) -#endif - -#ifdef _ATL_DISABLE_NOTHROW -#define ATL_NOTHROW -#else -#define ATL_NOTHROW __declspec(nothrow) -#endif - -#ifdef _ATL_DISABLE_FORCEINLINE -#define ATL_FORCEINLINE -#else -#define ATL_FORCEINLINE __forceinline -#endif - -#ifdef _ATL_DISABLE_NOINLINE -#define ATL_NOINLINE -#else -#define ATL_NOINLINE __declspec( noinline ) -#endif - -#ifdef _ATL_DISABLE_DEPRECATED -#define ATL_DEPRECATED -#else -#define ATL_DEPRECATED __declspec( deprecated ) -#endif - -// If ATL71.DLL is being used then _ATL_STATIC_REGISTRY doesn't really make sense -#ifdef _ATL_DLL -#undef _ATL_STATIC_REGISTRY -#else -// If not linking to ATL71.DLL, use the static registrar and not building atl.dll -#ifndef _ATL_DLL_IMPL -#ifndef _ATL_STATIC_REGISTRY -#define _ATL_STATIC_REGISTRY -#endif -#endif -#endif - -#ifdef _ATL_DEBUG_REFCOUNT -#ifndef _ATL_DEBUG_INTERFACES -#define _ATL_DEBUG_INTERFACES -#endif -#endif - -#ifdef _DEBUG -#ifndef _ATL_DEBUG -#define _ATL_DEBUG -#endif // _ATL_DEBUG -#endif // _DEBUG - -#ifdef _ATL_DEBUG_INTERFACES -#ifndef _ATL_DEBUG -#define _ATL_DEBUG -#endif // _ATL_DEBUG -#endif // _ATL_DEBUG_INTERFACES - -#ifndef _ATL_HEAPFLAGS -#ifdef _MALLOC_ZEROINIT -#define _ATL_HEAPFLAGS HEAP_ZERO_MEMORY -#else -#define _ATL_HEAPFLAGS 0 -#endif -#endif - -#ifndef _ATL_PACKING -#define _ATL_PACKING 8 -#endif - -#if defined(_ATL_DLL) - #define ATLAPI extern "C" HRESULT __declspec(dllimport) __stdcall - #define ATLAPI_(x) extern "C" __declspec(dllimport) x __stdcall - #define ATLINLINE -#elif defined(_ATL_DLL_IMPL) - #define ATLAPI extern "C" inline HRESULT __stdcall - #define ATLAPI_(x) extern "C" inline x __stdcall - #define ATLINLINE -#else - #define ATLAPI __declspec(nothrow) HRESULT __stdcall - #define ATLAPI_(x) __declspec(nothrow) x __stdcall - #define ATLINLINE inline -#endif - -#ifdef _ATL_NO_EXCEPTIONS - #ifdef _AFX - #error MFC projects cannot define _ATL_NO_EXCEPTIONS - #endif -#else - #ifndef _CPPUNWIND - #define _ATL_NO_EXCEPTIONS - #endif -#endif - -#ifdef _CPPUNWIND - -#ifndef ATLTRYALLOC - -#ifdef _AFX -#define ATLTRYALLOC(x) try{x;} catch(CException* e){e->Delete();} -#else -#define ATLTRYALLOC(x) try{x;} catch(...){} -#endif //__AFX - -#endif //ATLTRYALLOC - -// If you define _ATLTRY before including this file, then -// you should define _ATLCATCH and _ATLRETHROW as well. -#ifndef _ATLTRY -#define _ATLTRY try -#ifdef _AFX -#define _ATLCATCH( e ) catch( CException* e ) -#else -#define _ATLCATCH( e ) catch( CAtlException e ) -#endif - -#define _ATLCATCHALL() catch( ... ) - -#ifdef _AFX -#define _ATLDELETEEXCEPTION(e) e->Delete(); -#else -#define _ATLDELETEEXCEPTION(e) e; -#endif - -#define _ATLRETHROW throw -#endif // _ATLTRY - -#else //_CPPUNWIND - -#ifndef ATLTRYALLOC -#define ATLTRYALLOC(x) x; -#endif //ATLTRYALLOC - -// if _ATLTRY is defined before including this file then -// _ATLCATCH and _ATLRETHROW should be defined as well. -#ifndef _ATLTRY -#define _ATLTRY -#define _ATLCATCH( e ) __pragma(warning(push)) __pragma(warning(disable: 4127)) if( false ) __pragma(warning(pop)) -#define _ATLCATCHALL() __pragma(warning(push)) __pragma(warning(disable: 4127)) if( false ) __pragma(warning(pop)) -#define _ATLDELETEEXCEPTION(e) -#define _ATLRETHROW -#endif // _ATLTRY - -#endif //_CPPUNWIND - -#ifndef ATLTRY -#define ATLTRY(x) ATLTRYALLOC(x) -#endif //ATLTRY - -#define offsetofclass(base, derived) ((DWORD_PTR)(static_cast((derived*)_ATL_PACKING))-_ATL_PACKING) - -///////////////////////////////////////////////////////////////////////////// -// Master version numbers - -#define _ATL 1 // Active Template Library -#define _ATL_VER 0x0710 // Active Template Library version 7.10 - -///////////////////////////////////////////////////////////////////////////// -// Threading - -#ifndef _ATL_SINGLE_THREADED -#ifndef _ATL_APARTMENT_THREADED -#ifndef _ATL_FREE_THREADED -#define _ATL_FREE_THREADED -#endif -#endif -#endif - -// UUIDOF -#ifndef _ATL_NO_UUIDOF -#define _ATL_IIDOF(x) __uuidof(x) -#else -#define _ATL_IIDOF(x) IID_##x -#endif - -// Lean and mean -#ifndef ATL_NO_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#define NOMCX -#endif // ATL_NO_LEAN_AND_MEAN - -#ifdef NOSERVICE -#ifndef _ATL_NO_SERVICE -#define _ATL_NO_SERVICE -#endif // _ATL_NO_SERVICE -#else -#ifdef _ATL_NO_SERVICE -#ifndef NOSERVICE -#define NOSERVICE -#endif // NOSERVICE -#endif // _ATL_NO_SERVICE -#endif // NOSERVICE - -#include -#ifdef _DEBUG -#include -#endif -#ifndef _ATL_NO_DEBUG_CRT -// Warning: if you define the above symbol, you will have -// to provide your own definition of the ATLASSERT(x) macro -// in order to compile ATL - #include -#endif - -#endif // RC_INVOKED - -#define ATLAXWIN_CLASS "AtlAxWin71" -#define ATLAXWINLIC_CLASS "AtlAxWinLic71" - -#endif // __ATLDEF_H__ - -///////////////////////////////////////////////////////////////////////////// diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlexcept.h b/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlexcept.h deleted file mode 100644 index 7f000aa71..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlexcept.h +++ /dev/null @@ -1,118 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLEXCEPT_H__ -#define __ATLEXCEPT_H__ - -#pragma once - -#include -#include - -namespace ATL -{ - -///////////////////////////////////////////////////////////////////////////// -// Exception raise (for functions that cannot return an error code) - -inline void __declspec(noreturn) _AtlRaiseException( DWORD dwExceptionCode, DWORD dwExceptionFlags = EXCEPTION_NONCONTINUABLE ) -{ - RaiseException( dwExceptionCode, dwExceptionFlags, 0, NULL ); -} - -class CAtlException -{ -public: - CAtlException() throw() : - m_hr( E_FAIL ) - { - } - - CAtlException( HRESULT hr ) throw() : - m_hr( hr ) - { - } - - operator HRESULT() const throw() - { - return( m_hr ); - } - -public: - HRESULT m_hr; -}; - -#ifndef _ATL_NO_EXCEPTIONS - -// Throw a CAtlException with the given HRESULT -#if defined( AtlThrow ) || defined( _ATL_CUSTOM_THROW ) // You can define your own AtlThrow to throw a custom exception. -#ifdef _AFX -#error MFC projects must use default implementation of AtlThrow() -#endif -#else -ATL_NOINLINE __declspec(noreturn) inline void WINAPI AtlThrow( HRESULT hr ) -{ - ATLTRACE(atlTraceException, 0, _T("AtlThrow: hr = 0x%x\n"), hr ); -#ifdef _AFX - if( hr == E_OUTOFMEMORY ) - { - AfxThrowMemoryException(); - } - else - { - AfxThrowOleException( hr ); - } -#else - throw CAtlException( hr ); -#endif -}; -#endif - -// Throw a CAtlException corresponding to the result of ::GetLastError -ATL_NOINLINE __declspec(noreturn) inline void WINAPI AtlThrowLastWin32() -{ - DWORD dwError = ::GetLastError(); - AtlThrow( HRESULT_FROM_WIN32( dwError ) ); -} - -#else // no exception handling - -// Throw a CAtlException with the given HRESULT -#if !defined( AtlThrow ) && !defined( _ATL_CUSTOM_THROW ) // You can define your own AtlThrow - -ATL_NOINLINE inline void WINAPI AtlThrow( HRESULT hr ) -{ - ATLTRACE(atlTraceException, 0, _T("AtlThrow: hr = 0x%x\n"), hr ); - ATLASSERT( false ); - DWORD dwExceptionCode; - switch(hr) - { - case E_OUTOFMEMORY: - dwExceptionCode = STATUS_NO_MEMORY; - break; - default: - dwExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; - } - _AtlRaiseException(dwExceptionCode); -} -#endif - -// Throw a CAtlException corresponding to the result of ::GetLastError -ATL_NOINLINE inline void WINAPI AtlThrowLastWin32() -{ - DWORD dwError = ::GetLastError(); - AtlThrow( HRESULT_FROM_WIN32( dwError ) ); -} - -#endif // no exception handling - -}; // namespace ATL - -#endif // __ATLEXCEPT_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlhost.h b/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlhost.h deleted file mode 100644 index 422618381..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlhost.h +++ /dev/null @@ -1,2628 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLHOST_H__ -#define __ATLHOST_H__ - -#pragma once - -#ifndef _ATL_NO_PRAGMA_WARNINGS -#pragma warning (push) -#pragma warning(disable: 4702) // unreachable code -#endif //!_ATL_NO_PRAGMA_WARNINGS - -#include -#include -#include -#include - -#ifndef _ATL_AXHOST -#define _ATL_AXHOST -#endif //_ATL_AXHOST - -#include -#include - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#ifdef _ATL_NO_HOSTING - #error atlhost.h requires Hosting support (_ATL_NO_HOSTING is defined) -#endif //_ATL_NO_HOSTING - -namespace ATL -{ -//AtlAxWinTerm is not exported -inline BOOL AtlAxWinTerm() -{ -#ifndef _ATL_DLL //don't unregister DLL's version - UnregisterClass(CAxWindow::GetWndClassName(), _AtlBaseModule.GetModuleInstance()); - UnregisterClass(CAxWindow2::GetWndClassName(), _AtlBaseModule.GetModuleInstance()); -#endif - return TRUE; -} - - -// Define this to host SHDOCVW rather than MSHTML -#define SHDOCVW - -UINT __declspec(selectany) WM_ATLGETHOST = 0; -UINT __declspec(selectany) WM_ATLGETCONTROL = 0; - -typedef HRESULT (__stdcall *typeMkParseDisplayName)(IBindCtx*, LPCWSTR , ULONG*, LPMONIKER*); - -static HRESULT CreateNormalizedObject(LPCOLESTR lpszTricsData, REFIID riid, void** ppvObj, bool& bWasHTML, BSTR bstrLicKey) -{ - ATLASSERT(ppvObj); - if (ppvObj == NULL) - return E_POINTER; - *ppvObj = NULL; - - CLSID clsid; - HRESULT hr = E_FAIL; - - bWasHTML = false; - - - if (lpszTricsData == NULL || lpszTricsData[0] == 0) - return S_OK; - - // Is it HTML ? - USES_CONVERSION; - if ((lpszTricsData[0] == OLECHAR('M') || lpszTricsData[0] == OLECHAR('m')) && - (lpszTricsData[1] == OLECHAR('S') || lpszTricsData[1] == OLECHAR('s')) && - (lpszTricsData[2] == OLECHAR('H') || lpszTricsData[2] == OLECHAR('h')) && - (lpszTricsData[3] == OLECHAR('T') || lpszTricsData[3] == OLECHAR('t')) && - (lpszTricsData[4] == OLECHAR('M') || lpszTricsData[4] == OLECHAR('m')) && - (lpszTricsData[5] == OLECHAR('L') || lpszTricsData[5] == OLECHAR('l')) && - (lpszTricsData[6] == OLECHAR(':'))) - { - // It's HTML, so let's create mshtml - hr = CoCreateInstance(__uuidof(HTMLDocument), NULL, CLSCTX_INPROC_SERVER, riid, ppvObj); - bWasHTML = true; - } - // Is it a URL? - else if (CAtlModule::FindOneOf(OLE2CT(lpszTricsData), _T(":"))) - { - // URL so let's create shdocvw - hr = CoCreateInstance(__uuidof(WebBrowser), NULL, CLSCTX_INPROC_SERVER, riid, ppvObj); - bWasHTML = true; - } - // assume ProgID or CLSID - else - { - // Can't be clsid, or progid if length is greater than 255 - if (ocslen(lpszTricsData) < 255) - { - if (lpszTricsData[0] == '{') // Is it a CLSID? - hr = CLSIDFromString((LPOLESTR)lpszTricsData, &clsid); - else - hr = CLSIDFromProgID((LPOLESTR)lpszTricsData, &clsid); // How about a ProgID? - } - if (SUCCEEDED(hr)) - { - // If the license key is present - // Create using IClassFactory2. - if (bstrLicKey != NULL) - { - CComPtr spClassFactory; - hr = CoGetClassObject(clsid, CLSCTX_INPROC_SERVER, NULL, __uuidof(IClassFactory2), (void**)&spClassFactory); - if (SUCCEEDED(hr)) - hr = spClassFactory->CreateInstanceLic(NULL, NULL, riid, bstrLicKey, ppvObj); - } - else - hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, riid, ppvObj); - } - } - return hr; -} - - -class ATL_NO_VTABLE CAxFrameWindow : - public CComObjectRootEx, - public CWindowImpl, - public IOleInPlaceFrame -{ -public: - CAxFrameWindow() - { - } - void FinalRelease() - { - m_spActiveObject.Release(); - if (m_hWnd) - DestroyWindow(); - } - - DECLARE_POLY_AGGREGATABLE(CAxFrameWindow) - - BEGIN_COM_MAP(CAxFrameWindow) - COM_INTERFACE_ENTRY(IOleInPlaceFrame) - COM_INTERFACE_ENTRY(IOleInPlaceUIWindow) - COM_INTERFACE_ENTRY(IOleWindow) - END_COM_MAP() - - DECLARE_EMPTY_MSG_MAP() - -// IOleWindow - STDMETHOD(GetWindow)(HWND* phwnd) - { - ATLASSERT(phwnd != NULL); - if (phwnd == NULL) - return E_POINTER; - - if (m_hWnd == NULL) - Create(NULL, NULL, _T("AXWIN Frame Window"), WS_OVERLAPPEDWINDOW, 0, (UINT)NULL); - *phwnd = m_hWnd; - return S_OK; - } - STDMETHOD(ContextSensitiveHelp)(BOOL /*fEnterMode*/) - { - return S_OK; - } - -// IOleInPlaceUIWindow - STDMETHOD(GetBorder)(LPRECT /*lprectBorder*/) - { - return S_OK; - } - - STDMETHOD(RequestBorderSpace)(LPCBORDERWIDTHS /*pborderwidths*/) - { - return INPLACE_E_NOTOOLSPACE; - } - - STDMETHOD(SetBorderSpace)(LPCBORDERWIDTHS /*pborderwidths*/) - { - return S_OK; - } - - STDMETHOD(SetActiveObject)(IOleInPlaceActiveObject* pActiveObject, LPCOLESTR /*pszObjName*/) - { - m_spActiveObject = pActiveObject; - return S_OK; - } - -// IOleInPlaceFrameWindow - STDMETHOD(InsertMenus)(HMENU /*hmenuShared*/, LPOLEMENUGROUPWIDTHS /*lpMenuWidths*/) - { - return S_OK; - } - - STDMETHOD(SetMenu)(HMENU /*hmenuShared*/, HOLEMENU /*holemenu*/, HWND /*hwndActiveObject*/) - { - return S_OK; - } - - STDMETHOD(RemoveMenus)(HMENU /*hmenuShared*/) - { - return S_OK; - } - - STDMETHOD(SetStatusText)(LPCOLESTR /*pszStatusText*/) - { - return S_OK; - } - - STDMETHOD(EnableModeless)(BOOL /*fEnable*/) - { - return S_OK; - } - - STDMETHOD(TranslateAccelerator)(LPMSG /*lpMsg*/, WORD /*wID*/) - { - return S_FALSE; - } - - CComPtr m_spActiveObject; -}; - - -class ATL_NO_VTABLE CAxUIWindow : - public CComObjectRootEx, - public CWindowImpl, - public IOleInPlaceUIWindow -{ -public: - CAxUIWindow() - { - } - - void FinalRelease() - { - m_spActiveObject.Release(); - if (m_hWnd) - DestroyWindow(); - } - - DECLARE_POLY_AGGREGATABLE(CAxUIWindow) - - BEGIN_COM_MAP(CAxUIWindow) - COM_INTERFACE_ENTRY(IOleInPlaceUIWindow) - COM_INTERFACE_ENTRY(IOleWindow) - END_COM_MAP() - - DECLARE_EMPTY_MSG_MAP() - -// IOleWindow - STDMETHOD(GetWindow)(HWND* phwnd) - { - if (m_hWnd == NULL) - Create(NULL, NULL, _T("AXWIN UI Window"), WS_OVERLAPPEDWINDOW, 0, (UINT)NULL); - *phwnd = m_hWnd; - return S_OK; - } - - STDMETHOD(ContextSensitiveHelp)(BOOL /*fEnterMode*/) - { - return S_OK; - } - -// IOleInPlaceUIWindow - STDMETHOD(GetBorder)(LPRECT /*lprectBorder*/) - { - return S_OK; - } - - STDMETHOD(RequestBorderSpace)(LPCBORDERWIDTHS /*pborderwidths*/) - { - return INPLACE_E_NOTOOLSPACE; - } - - STDMETHOD(SetBorderSpace)(LPCBORDERWIDTHS /*pborderwidths*/) - { - return S_OK; - } - - STDMETHOD(SetActiveObject)(IOleInPlaceActiveObject* pActiveObject, LPCOLESTR /*pszObjName*/) - { - m_spActiveObject = pActiveObject; - return S_OK; - } - - CComPtr m_spActiveObject; -}; - - -///////////////////////////////////////////////////////////////////////////// -// CAxHostWindow -// This class is not cocreateable - -class ATL_NO_VTABLE CAxHostWindow : - public CComCoClass, - public CComObjectRootEx, - public CWindowImpl, - public IAxWinHostWindowLic, - public IOleClientSite, - public IOleInPlaceSiteWindowless, - public IOleControlSite, - public IOleContainer, - public IObjectWithSiteImpl, - public IServiceProvider, - public IAdviseSink, -#ifndef _ATL_NO_DOCHOSTUIHANDLER - public IDocHostUIHandler, -#endif - public IDispatchImpl -{ -public: -// ctor/dtor - CAxHostWindow() - { - m_bInPlaceActive = FALSE; - m_bUIActive = FALSE; - m_bMDIApp = FALSE; - m_bWindowless = FALSE; - m_bCapture = FALSE; - m_bHaveFocus = FALSE; - - // Initialize ambient properties - m_bCanWindowlessActivate = TRUE; - m_bUserMode = TRUE; - m_bDisplayAsDefault = FALSE; - m_clrBackground = NULL; - m_clrForeground = GetSysColor(COLOR_WINDOWTEXT); - m_lcidLocaleID = LOCALE_USER_DEFAULT; - m_bMessageReflect = true; - - m_bReleaseAll = FALSE; - - m_bSubclassed = FALSE; - - m_dwAdviseSink = 0xCDCDCDCD; - m_dwDocHostFlags = DOCHOSTUIFLAG_NO3DBORDER; - m_dwDocHostDoubleClickFlags = DOCHOSTUIDBLCLK_DEFAULT; - m_bAllowContextMenu = true; - m_bAllowShowUI = false; - m_hDCScreen = NULL; - m_bDCReleased = true; - - m_hAccel = NULL; - } - - ~CAxHostWindow() - { - } - void FinalRelease() - { - ReleaseAll(); - } - - virtual void OnFinalMessage(HWND /*hWnd*/) - { - GetControllingUnknown()->Release(); - } - - DECLARE_NO_REGISTRY() - DECLARE_POLY_AGGREGATABLE(CAxHostWindow) - DECLARE_GET_CONTROLLING_UNKNOWN() - - BEGIN_COM_MAP(CAxHostWindow) - COM_INTERFACE_ENTRY2(IDispatch, IAxWinAmbientDispatchEx) - COM_INTERFACE_ENTRY(IAxWinHostWindow) - COM_INTERFACE_ENTRY(IAxWinHostWindowLic) - COM_INTERFACE_ENTRY(IOleClientSite) - COM_INTERFACE_ENTRY(IOleInPlaceSiteWindowless) - COM_INTERFACE_ENTRY(IOleInPlaceSiteEx) - COM_INTERFACE_ENTRY(IOleInPlaceSite) - COM_INTERFACE_ENTRY(IOleWindow) - COM_INTERFACE_ENTRY(IOleControlSite) - COM_INTERFACE_ENTRY(IOleContainer) - COM_INTERFACE_ENTRY(IObjectWithSite) - COM_INTERFACE_ENTRY(IServiceProvider) - COM_INTERFACE_ENTRY(IAxWinAmbientDispatchEx) - COM_INTERFACE_ENTRY(IAxWinAmbientDispatch) -#ifndef _ATL_NO_DOCHOSTUIHANDLER - COM_INTERFACE_ENTRY(IDocHostUIHandler) -#endif - COM_INTERFACE_ENTRY(IAdviseSink) - END_COM_MAP() - - static CWndClassInfo& GetWndClassInfo() - { - static CWndClassInfo wc = - { - { sizeof(WNDCLASSEX), 0, StartWindowProc, - 0, 0, 0, 0, 0, (HBRUSH)(COLOR_WINDOW + 1), 0, _T(ATLAXWIN_CLASS), 0 }, - NULL, NULL, IDC_ARROW, TRUE, 0, _T("") - }; - return wc; - } - - BEGIN_MSG_MAP(CAxHostWindow) - MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) - MESSAGE_HANDLER(WM_PAINT, OnPaint) - MESSAGE_HANDLER(WM_SIZE, OnSize) - MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActivate) - MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) - MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus) - if (m_bWindowless) - { - // Mouse messages handled when a windowless control has captured the cursor - // or if the cursor is over the control - DWORD dwHitResult = m_bCapture ? HITRESULT_HIT : HITRESULT_OUTSIDE; - if (dwHitResult == HITRESULT_OUTSIDE && m_spViewObject != NULL) - { - POINT ptMouse = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; - m_spViewObject->QueryHitPoint(DVASPECT_CONTENT, &m_rcPos, ptMouse, 0, &dwHitResult); - } - if (dwHitResult == HITRESULT_HIT) - { - MESSAGE_HANDLER(WM_MOUSEMOVE, OnWindowlessMouseMessage) - MESSAGE_HANDLER(WM_SETCURSOR, OnWindowlessMouseMessage) - MESSAGE_HANDLER(WM_LBUTTONUP, OnWindowlessMouseMessage) - MESSAGE_HANDLER(WM_RBUTTONUP, OnWindowlessMouseMessage) - MESSAGE_HANDLER(WM_MBUTTONUP, OnWindowlessMouseMessage) - MESSAGE_HANDLER(WM_LBUTTONDOWN, OnWindowlessMouseMessage) - MESSAGE_HANDLER(WM_RBUTTONDOWN, OnWindowlessMouseMessage) - MESSAGE_HANDLER(WM_MBUTTONDOWN, OnWindowlessMouseMessage) - MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnWindowlessMouseMessage) - MESSAGE_HANDLER(WM_RBUTTONDBLCLK, OnWindowlessMouseMessage) - MESSAGE_HANDLER(WM_MBUTTONDBLCLK, OnWindowlessMouseMessage) - } - } - if (m_bWindowless & m_bHaveFocus) - { - // Keyboard messages handled only when a windowless control has the focus - MESSAGE_HANDLER(WM_KEYDOWN, OnWindowMessage) - MESSAGE_HANDLER(WM_KEYUP, OnWindowMessage) - MESSAGE_HANDLER(WM_CHAR, OnWindowMessage) - MESSAGE_HANDLER(WM_DEADCHAR, OnWindowMessage) - MESSAGE_HANDLER(WM_SYSKEYDOWN, OnWindowMessage) - MESSAGE_HANDLER(WM_SYSKEYUP, OnWindowMessage) - MESSAGE_HANDLER(WM_SYSDEADCHAR, OnWindowMessage) - MESSAGE_HANDLER(WM_HELP, OnWindowMessage) - MESSAGE_HANDLER(WM_CANCELMODE, OnWindowMessage) - MESSAGE_HANDLER(WM_IME_CHAR, OnWindowMessage) - MESSAGE_HANDLER(WM_MBUTTONDBLCLK, OnWindowMessage) - MESSAGE_RANGE_HANDLER(WM_IME_SETCONTEXT, WM_IME_KEYUP, OnWindowMessage) - } - MESSAGE_HANDLER(WM_DESTROY, OnDestroy) - if (m_bMessageReflect) - { - bHandled = TRUE; - lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); - if(bHandled) - return TRUE; - } - MESSAGE_HANDLER(WM_ATLGETHOST, OnGetUnknown) - MESSAGE_HANDLER(WM_ATLGETCONTROL, OnGetControl) - MESSAGE_HANDLER(WM_FORWARDMSG, OnForwardMsg) - END_MSG_MAP() - - LRESULT OnForwardMsg(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) - { - ATLASSERT(lParam != 0); - LPMSG lpMsg = (LPMSG)lParam; - CComQIPtr spInPlaceActiveObject(m_spUnknown); - if(spInPlaceActiveObject) - { - if(spInPlaceActiveObject->TranslateAccelerator(lpMsg) == S_OK) - return 1; - } - return 0; - } - - LRESULT OnGetUnknown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - IUnknown* pUnk = GetControllingUnknown(); - pUnk->AddRef(); - return (LRESULT)pUnk; - } - LRESULT OnGetControl(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - IUnknown* pUnk = m_spUnknown; - if (pUnk) - pUnk->AddRef(); - return (LRESULT)pUnk; - } - - void ReleaseAll() - { - if (m_bReleaseAll) - return; - m_bReleaseAll = TRUE; - - if (m_spViewObject != NULL) - m_spViewObject->SetAdvise(DVASPECT_CONTENT, 0, NULL); - - if(m_dwAdviseSink != 0xCDCDCDCD) - { - AtlUnadvise(m_spUnknown, m_iidSink, m_dwAdviseSink); - m_dwAdviseSink = 0xCDCDCDCD; - } - - if (m_spOleObject) - { - m_spOleObject->Unadvise(m_dwOleObject); - m_spOleObject->Close(OLECLOSE_NOSAVE); - m_spOleObject->SetClientSite(NULL); - } - - if (m_spUnknown != NULL) - { - CComPtr spSite; - m_spUnknown->QueryInterface(__uuidof(IObjectWithSite), (void**)&spSite); - if (spSite != NULL) - spSite->SetSite(NULL); - } - - m_spViewObject.Release(); - m_dwViewObjectType = 0; - - m_spInPlaceObjectWindowless.Release(); - m_spOleObject.Release(); - m_spUnknown.Release(); - - m_spInPlaceUIWindow.Release(); - m_spInPlaceFrame.Release(); - - m_bInPlaceActive = FALSE; - m_bWindowless = FALSE; - m_bInPlaceActive = FALSE; - m_bUIActive = FALSE; - m_bCapture = FALSE; - m_bReleaseAll = FALSE; - - if (m_hAccel != NULL) - { - DestroyAcceleratorTable(m_hAccel); - m_hAccel = NULL; - } - } - - -// window message handlers - LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - if (m_spViewObject == NULL) - bHandled = false; - - return 1; - } - - LRESULT OnMouseActivate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - bHandled = FALSE; - if (m_dwMiscStatus & OLEMISC_NOUIACTIVATE) - { - if (m_spOleObject != NULL && !m_bInPlaceActive) - { - CComPtr spClientSite; - GetControllingUnknown()->QueryInterface(__uuidof(IOleClientSite), (void**)&spClientSite); - if (spClientSite != NULL) - m_spOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, spClientSite, 0, m_hWnd, &m_rcPos); - } - } - else - { - BOOL b; - OnSetFocus(0, 0, 0, b); - } - return 0; - } - LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - m_bHaveFocus = TRUE; - if (!m_bReleaseAll) - { - if (m_spOleObject != NULL && !m_bUIActive) - { - CComPtr spClientSite; - GetControllingUnknown()->QueryInterface(__uuidof(IOleClientSite), (void**)&spClientSite); - if (spClientSite != NULL) - m_spOleObject->DoVerb(OLEIVERB_UIACTIVATE, NULL, spClientSite, 0, m_hWnd, &m_rcPos); - } - if (m_bWindowless) - ::SetFocus(m_hWnd); - else if(!IsChild(::GetFocus())) - ::SetFocus(::GetWindow(m_hWnd, GW_CHILD)); - } - bHandled = FALSE; - return 0; - } - LRESULT OnKillFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - m_bHaveFocus = FALSE; - bHandled = FALSE; - return 0; - } - LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) - { - int nWidth = GET_X_LPARAM(lParam); // width of client area - int nHeight = GET_Y_LPARAM(lParam); // height of client area - - m_rcPos.right = m_rcPos.left + nWidth; - m_rcPos.bottom = m_rcPos.top + nHeight; - m_pxSize.cx = m_rcPos.right - m_rcPos.left; - m_pxSize.cy = m_rcPos.bottom - m_rcPos.top; - AtlPixelToHiMetric(&m_pxSize, &m_hmSize); - - if (m_spOleObject) - m_spOleObject->SetExtent(DVASPECT_CONTENT, &m_hmSize); - if (m_spInPlaceObjectWindowless) - m_spInPlaceObjectWindowless->SetObjectRects(&m_rcPos, &m_rcPos); - if (m_bWindowless) - InvalidateRect(NULL, TRUE); - bHandled = FALSE; - return 0; - } - LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - GetControllingUnknown()->AddRef(); - DefWindowProc(uMsg, wParam, lParam); - ReleaseAll(); - bHandled = FALSE; - return 0; - } - LRESULT OnWindowMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - LRESULT lRes = 0; - HRESULT hr = S_FALSE; - if (m_bInPlaceActive && m_bWindowless && m_spInPlaceObjectWindowless) - hr = m_spInPlaceObjectWindowless->OnWindowMessage(uMsg, wParam, lParam, &lRes); - if (hr == S_FALSE) - bHandled = FALSE; - return lRes; - } - LRESULT OnWindowlessMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - LRESULT lRes = 0; - if (m_bInPlaceActive && m_bWindowless && m_spInPlaceObjectWindowless) - m_spInPlaceObjectWindowless->OnWindowMessage(uMsg, wParam, lParam, &lRes); - bHandled = FALSE; - return lRes; - } - LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - if (m_spViewObject == NULL) - { - PAINTSTRUCT ps; - HDC hdc = ::BeginPaint(m_hWnd, &ps); - if (hdc == NULL) - return 0; - RECT rcClient; - GetClientRect(&rcClient); - HBRUSH hbrBack = CreateSolidBrush(m_clrBackground); - if (hbrBack != NULL) - { - FillRect(hdc, &rcClient, hbrBack); - DeleteObject(hbrBack); - } - ::EndPaint(m_hWnd, &ps); - return 1; - } - if (m_spViewObject && m_bWindowless) - { - PAINTSTRUCT ps; - HDC hdc = ::BeginPaint(m_hWnd, &ps); - - if (hdc == NULL) - return 0; - - RECT rcClient; - GetClientRect(&rcClient); - - HBITMAP hBitmap = CreateCompatibleBitmap(hdc, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top); - if (hBitmap != NULL) - { - HDC hdcCompatible = ::CreateCompatibleDC(hdc); - if (hdcCompatible != NULL) - { - HBITMAP hBitmapOld = (HBITMAP)SelectObject(hdcCompatible, hBitmap); - if (hBitmapOld != NULL) - { - HBRUSH hbrBack = CreateSolidBrush(m_clrBackground); - if (hbrBack != NULL) - { - FillRect(hdcCompatible, &rcClient, hbrBack); - DeleteObject(hbrBack); - - m_spViewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL, hdcCompatible, (RECTL*)&m_rcPos, (RECTL*)&m_rcPos, NULL, NULL); - - ::BitBlt(hdc, 0, 0, rcClient.right, rcClient.bottom, hdcCompatible, 0, 0, SRCCOPY); - } - ::SelectObject(hdcCompatible, hBitmapOld); - } - ::DeleteDC(hdcCompatible); - } - ::DeleteObject(hBitmap); - } - ::EndPaint(m_hWnd, &ps); - } - else - { - bHandled = FALSE; - return 0; - } - return 1; - } - -// IAxWinHostWindow - STDMETHOD(CreateControl)(LPCOLESTR lpTricsData, HWND hWnd, IStream* pStream) - { - CComPtr p; - return CreateControlLicEx(lpTricsData, hWnd, pStream, &p, IID_NULL, NULL, NULL); - } - STDMETHOD(CreateControlEx)(LPCOLESTR lpszTricsData, HWND hWnd, IStream* pStream, IUnknown** ppUnk, REFIID iidAdvise, IUnknown* punkSink) - { - return CreateControlLicEx(lpszTricsData, hWnd, pStream, ppUnk, iidAdvise, punkSink, NULL); - } - STDMETHOD(AttachControl)(IUnknown* pUnkControl, HWND hWnd) - { - HRESULT hr = S_FALSE; - - ReleaseAll(); - - bool bReleaseWindowOnFailure = false; // Used to keep track of whether we subclass the window - - if ((m_hWnd != NULL) && (m_hWnd != hWnd)) // Don't release the window if it's the same as the one we already subclass/own - { - RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_INTERNALPAINT | RDW_FRAME); - ReleaseWindow(); - } - - if (::IsWindow(hWnd)) - { - if (m_hWnd != hWnd) // Don't need to subclass the window if we already own it - { - SubclassWindow(hWnd); - bReleaseWindowOnFailure = true; - } - - hr = ActivateAx(pUnkControl, true, NULL); - - if (FAILED(hr)) - { - ReleaseAll(); - - if (m_hWnd != NULL) - { - RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_INTERNALPAINT | RDW_FRAME); - if (bReleaseWindowOnFailure) // We subclassed the window in an attempt to create this control, so we unsubclass on failure - ReleaseWindow(); - } - } - } - return hr; - } - STDMETHOD(QueryControl)(REFIID riid, void** ppvObject) - { - HRESULT hr = E_POINTER; - if (ppvObject) - { - if (m_spUnknown) - { - hr = m_spUnknown->QueryInterface(riid, ppvObject); - } - else - { - *ppvObject = NULL; - hr = OLE_E_NOCONNECTION; - } - } - return hr; - } - STDMETHOD(SetExternalDispatch)(IDispatch* pDisp) - { - m_spExternalDispatch = pDisp; - return S_OK; - } - STDMETHOD(SetExternalUIHandler)(IDocHostUIHandlerDispatch* pUIHandler) - { -#ifndef _ATL_NO_DOCHOSTUIHANDLER - m_spIDocHostUIHandlerDispatch = pUIHandler; -#endif - return S_OK; - } - - STDMETHOD(CreateControlLic)(LPCOLESTR lpTricsData, HWND hWnd, IStream* pStream, BSTR bstrLic) - { - CComPtr p; - return CreateControlLicEx(lpTricsData, hWnd, pStream, &p, IID_NULL, NULL, bstrLic); - } - STDMETHOD(CreateControlLicEx)(LPCOLESTR lpszTricsData, HWND hWnd, IStream* pStream, IUnknown** ppUnk, REFIID iidAdvise, IUnknown* punkSink, BSTR bstrLic) - { - ATLASSERT(ppUnk != NULL); - if (ppUnk == NULL) - return E_POINTER; - *ppUnk = NULL; - HRESULT hr = S_FALSE; - bool bReleaseWindowOnFailure = false; // Used to keep track of whether we subclass the window - - ReleaseAll(); - - if ((m_hWnd != NULL) && (m_hWnd != hWnd)) // Don't release the window if it's the same as the one we already subclass/own - { - RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_INTERNALPAINT | RDW_FRAME); - ReleaseWindow(); - } - - if (::IsWindow(hWnd)) - { - USES_CONVERSION; - if (m_hWnd != hWnd) // Don't need to subclass the window if we already own it - { - SubclassWindow(hWnd); - bReleaseWindowOnFailure = true; - } - if (m_clrBackground == NULL) - { - if (IsParentDialog()) - m_clrBackground = GetSysColor(COLOR_BTNFACE); - else - m_clrBackground = GetSysColor(COLOR_WINDOW); - } - - bool bWasHTML = false; - - hr = CreateNormalizedObject(lpszTricsData, __uuidof(IUnknown), (void**)ppUnk, bWasHTML, bstrLic); - - if (SUCCEEDED(hr)) - hr = ActivateAx(*ppUnk, false, pStream); - - // Try to hook up any sink the user might have given us. - m_iidSink = iidAdvise; - if(SUCCEEDED(hr) && *ppUnk && punkSink) - AtlAdvise(*ppUnk, punkSink, m_iidSink, &m_dwAdviseSink); - - if (SUCCEEDED(hr) && bWasHTML && *ppUnk != NULL) - { - if ((GetStyle() & (WS_VSCROLL | WS_HSCROLL)) == 0) - m_dwDocHostFlags |= DOCHOSTUIFLAG_SCROLL_NO; - else - { - DWORD dwStyle = GetStyle(); - SetWindowLong(GWL_STYLE, dwStyle & ~(WS_VSCROLL | WS_HSCROLL)); - SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOSIZE | SWP_FRAMECHANGED | SWP_DRAWFRAME); - } - - CComPtr spUnk(*ppUnk); - // Is it just plain HTML? - USES_CONVERSION; - if ((lpszTricsData[0] == OLECHAR('M') || lpszTricsData[0] == OLECHAR('m')) && - (lpszTricsData[1] == OLECHAR('S') || lpszTricsData[1] == OLECHAR('s')) && - (lpszTricsData[2] == OLECHAR('H') || lpszTricsData[2] == OLECHAR('h')) && - (lpszTricsData[3] == OLECHAR('T') || lpszTricsData[3] == OLECHAR('t')) && - (lpszTricsData[4] == OLECHAR('M') || lpszTricsData[4] == OLECHAR('m')) && - (lpszTricsData[5] == OLECHAR('L') || lpszTricsData[5] == OLECHAR('l')) && - (lpszTricsData[6] == OLECHAR(':'))) - { - // Just HTML: load the HTML data into the document - - UINT nCreateSize = (ocslen(lpszTricsData) - 7) * sizeof(OLECHAR); - HGLOBAL hGlobal = GlobalAlloc(GHND, nCreateSize); - if (hGlobal) - { - CComPtr spStream; - BYTE* pBytes = (BYTE*) GlobalLock(hGlobal); - memcpy(pBytes, lpszTricsData + 7, nCreateSize); - GlobalUnlock(hGlobal); - hr = CreateStreamOnHGlobal(hGlobal, TRUE, &spStream); - if (SUCCEEDED(hr)) - { - CComPtr spPSI; - hr = spUnk->QueryInterface(__uuidof(IPersistStreamInit), (void**)&spPSI); - if (SUCCEEDED(hr)) - hr = spPSI->Load(spStream); - } - } - else - hr = E_OUTOFMEMORY; - } - else - { - CComPtr spBrowser; - spUnk->QueryInterface(__uuidof(IWebBrowser2), (void**)&spBrowser); - if (spBrowser) - { - CComVariant ve; - CComVariant vurl(lpszTricsData); - spBrowser->put_Visible(ATL_VARIANT_TRUE); - spBrowser->Navigate2(&vurl, &ve, &ve, &ve, &ve); - } - } - - } - if (FAILED(hr) || m_spUnknown == NULL) - { - // We don't have a control or something failed so release - ReleaseAll(); - - if (m_hWnd != NULL) - { - RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_INTERNALPAINT | RDW_FRAME); - if (FAILED(hr) && bReleaseWindowOnFailure) // We subclassed the window in an attempt to create this control, so we unsubclass on failure - ReleaseWindow(); - } - } - } - return hr; - } - - - -#ifndef _ATL_NO_DOCHOSTUIHANDLER -// IDocHostUIHandler - // MSHTML requests to display its context menu - STDMETHOD(ShowContextMenu)(DWORD dwID, POINT* pptPosition, IUnknown* pCommandTarget, IDispatch* pDispatchObjectHit) - { - HRESULT hr = m_bAllowContextMenu ? S_FALSE : S_OK; - if (m_spIDocHostUIHandlerDispatch != NULL) - m_spIDocHostUIHandlerDispatch->ShowContextMenu( - dwID, - pptPosition->x, - pptPosition->y, - pCommandTarget, - pDispatchObjectHit, - &hr); - return hr; - } - // Called at initialisation to find UI styles from container - STDMETHOD(GetHostInfo)(DOCHOSTUIINFO* pInfo) - { - if (pInfo == NULL) - return E_POINTER; - - if (m_spIDocHostUIHandlerDispatch != NULL) - return m_spIDocHostUIHandlerDispatch->GetHostInfo(&pInfo->dwFlags, &pInfo->dwDoubleClick); - - pInfo->dwFlags = m_dwDocHostFlags; - pInfo->dwDoubleClick = m_dwDocHostDoubleClickFlags; - - return S_OK; - } - // Allows the host to replace the IE4/MSHTML menus and toolbars. - STDMETHOD(ShowUI)(DWORD dwID, IOleInPlaceActiveObject* pActiveObject, IOleCommandTarget* pCommandTarget, IOleInPlaceFrame* pFrame, IOleInPlaceUIWindow* pDoc) - { - HRESULT hr = m_bAllowShowUI ? S_FALSE : S_OK; - if (m_spIDocHostUIHandlerDispatch != NULL) - m_spIDocHostUIHandlerDispatch->ShowUI( - dwID, - pActiveObject, - pCommandTarget, - pFrame, - pDoc, - &hr); - return hr; - } - // Called when IE4/MSHTML removes its menus and toolbars. - STDMETHOD(HideUI)() - { - HRESULT hr = S_OK; - if (m_spIDocHostUIHandlerDispatch != NULL) - hr = m_spIDocHostUIHandlerDispatch->HideUI(); - return hr; - } - // Notifies the host that the command state has changed. - STDMETHOD(UpdateUI)() - { - HRESULT hr = S_OK; - if (m_spIDocHostUIHandlerDispatch != NULL) - hr = m_spIDocHostUIHandlerDispatch->UpdateUI(); - return hr; - } - // Called from the IE4/MSHTML implementation of IOleInPlaceActiveObject::EnableModeless - STDMETHOD(EnableModeless)(BOOL fEnable) - { - HRESULT hr = S_OK; - if (m_spIDocHostUIHandlerDispatch != NULL) - hr = m_spIDocHostUIHandlerDispatch->EnableModeless(fEnable ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE); - return hr; - } - // Called from the IE4/MSHTML implementation of IOleInPlaceActiveObject::OnDocWindowActivate - STDMETHOD(OnDocWindowActivate)(BOOL fActivate) - { - HRESULT hr = S_OK; - if (m_spIDocHostUIHandlerDispatch != NULL) - hr = m_spIDocHostUIHandlerDispatch->OnDocWindowActivate(fActivate ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE); - return hr; - } - // Called from the IE4/MSHTML implementation of IOleInPlaceActiveObject::OnFrameWindowActivate. - STDMETHOD(OnFrameWindowActivate)(BOOL fActivate) - { - HRESULT hr = S_OK; - if (m_spIDocHostUIHandlerDispatch != NULL) - hr = m_spIDocHostUIHandlerDispatch->OnFrameWindowActivate(fActivate ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE); - return hr; - } - // Called from the IE4/MSHTML implementation of IOleInPlaceActiveObject::ResizeBorder. - STDMETHOD(ResizeBorder)(LPCRECT prcBorder, IOleInPlaceUIWindow* pUIWindow, BOOL fFrameWindow) - { - HRESULT hr = S_OK; - if (m_spIDocHostUIHandlerDispatch != NULL) - hr = m_spIDocHostUIHandlerDispatch->ResizeBorder( - prcBorder->left, - prcBorder->top, - prcBorder->right, - prcBorder->bottom, - pUIWindow, - fFrameWindow ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE); - return hr; - } - // Called by IE4/MSHTML when IOleInPlaceActiveObject::TranslateAccelerator or IOleControlSite::TranslateAccelerator is called. - STDMETHOD(TranslateAccelerator)(LPMSG lpMsg, const GUID* pguidCmdGroup, DWORD nCmdID) - { - HRESULT hr = S_FALSE; - if (m_spIDocHostUIHandlerDispatch != NULL) - m_spIDocHostUIHandlerDispatch->TranslateAccelerator( - (DWORD_PTR) lpMsg->hwnd, - lpMsg->message, - lpMsg->wParam, - lpMsg->lParam, - CComBSTR(*pguidCmdGroup), - nCmdID, - &hr); - return hr; - } - // Returns the registry key under which IE4/MSHTML stores user preferences. - // Returns S_OK if successful, or S_FALSE otherwise. If S_FALSE, IE4/MSHTML will default to its own user options. - STDMETHOD(GetOptionKeyPath)(LPOLESTR* pchKey, DWORD dwReserved) - { - HRESULT hr = S_FALSE; - if (pchKey == NULL) - return E_POINTER; - *pchKey = NULL; - if (m_spIDocHostUIHandlerDispatch != NULL) - { - hr = m_spIDocHostUIHandlerDispatch->GetOptionKeyPath(pchKey, dwReserved); - if (FAILED(hr) || *pchKey == NULL) - hr = S_FALSE; - } - else - { - if (m_bstrOptionKeyPath.m_str != NULL) - { - UINT nByteLength = m_bstrOptionKeyPath.ByteLength(); - LPOLESTR pStr = (LPOLESTR)CoTaskMemAlloc(nByteLength + sizeof(OLECHAR)); - if (pStr == NULL) - return E_OUTOFMEMORY; - ocscpy(pStr, m_bstrOptionKeyPath.m_str); - *pchKey = pStr; - hr = S_OK; - } - } - return hr; - } - // Called by IE4/MSHTML when it is being used as a drop target to allow the host to supply an alternative IDropTarget - STDMETHOD(GetDropTarget)(IDropTarget* pDropTarget, IDropTarget** ppDropTarget) - { - ATLASSERT(ppDropTarget != NULL); - if (ppDropTarget == NULL) - return E_POINTER; - *ppDropTarget = NULL; - - HRESULT hr = E_NOTIMPL; - if (m_spIDocHostUIHandlerDispatch != NULL) - { - CComPtr spUnk; - hr = m_spIDocHostUIHandlerDispatch->GetDropTarget(pDropTarget, &spUnk); - if (spUnk) - hr = spUnk->QueryInterface(__uuidof(IDropTarget), (void**)ppDropTarget); - if (FAILED(hr) || *ppDropTarget == NULL) - hr = S_FALSE; - } - return hr; - } - // Called by IE4/MSHTML to obtain the host's IDispatch interface - STDMETHOD(GetExternal)(IDispatch** ppDispatch) - { - ATLASSERT(ppDispatch != NULL); - if (ppDispatch == NULL) - return E_POINTER; - *ppDispatch = NULL; - - HRESULT hr = E_NOINTERFACE; - if (m_spIDocHostUIHandlerDispatch != NULL) - { - hr = m_spIDocHostUIHandlerDispatch->GetExternal(ppDispatch); - if (FAILED(hr) || *ppDispatch == NULL) - hr = E_NOINTERFACE; - } - else - { - // return the IDispatch we have for extending the object Model - if (ppDispatch != NULL) - { - m_spExternalDispatch.CopyTo(ppDispatch); - hr = S_OK; - } - else - hr = E_POINTER; - } - return hr; - } - // Called by IE4/MSHTML to allow the host an opportunity to modify the URL to be loaded - STDMETHOD(TranslateUrl)(DWORD dwTranslate, OLECHAR* pchURLIn, OLECHAR** ppchURLOut) - { - ATLASSERT(ppchURLOut != NULL); - if (ppchURLOut == NULL) - return E_POINTER; - *ppchURLOut = NULL; - - HRESULT hr = S_FALSE; - if (m_spIDocHostUIHandlerDispatch != NULL) - { - CComBSTR bstrURLOut; - hr = m_spIDocHostUIHandlerDispatch->TranslateUrl(dwTranslate, CComBSTR(pchURLIn), &bstrURLOut); - if (SUCCEEDED(hr) && bstrURLOut.m_str != NULL) - { - UINT nLen = (bstrURLOut.Length() + 1) * 2; - *ppchURLOut = (OLECHAR*) CoTaskMemAlloc(nLen); - if (*ppchURLOut == NULL) - return E_OUTOFMEMORY; - memcpy(*ppchURLOut, bstrURLOut.m_str, nLen); - } - else - hr = S_FALSE; - } - return hr; - } - // Called on the host by IE4/MSHTML to allow the host to replace IE4/MSHTML's data object. - // This allows the host to block certain clipboard formats or support additional clipboard formats. - STDMETHOD(FilterDataObject)(IDataObject* pDO, IDataObject** ppDORet) - { - ATLASSERT(ppDORet != NULL); - if (ppDORet == NULL) - return E_POINTER; - *ppDORet = NULL; - - HRESULT hr = S_FALSE; - if (m_spIDocHostUIHandlerDispatch != NULL) - { - CComPtr spUnk; - hr = m_spIDocHostUIHandlerDispatch->FilterDataObject(pDO, &spUnk); - if (spUnk) - hr = QueryInterface(__uuidof(IDataObject), (void**)ppDORet); - if (FAILED(hr) || *ppDORet == NULL) - hr = S_FALSE; - } - return hr; - } -#endif - - HRESULT FireAmbientPropertyChange(DISPID dispChanged) - { - HRESULT hr = S_OK; - CComQIPtr spOleControl(m_spUnknown); - if (spOleControl != NULL) - hr = spOleControl->OnAmbientPropertyChange(dispChanged); - return hr; - } - -// IAxWinAmbientDispatch - - CComPtr m_spAmbientDispatch; - - STDMETHOD(Invoke)(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, - VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) - { - HRESULT hr = IDispatchImpl::Invoke - (dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); - if ((hr == DISP_E_MEMBERNOTFOUND || hr == TYPE_E_ELEMENTNOTFOUND) && m_spAmbientDispatch != NULL) - { - hr = m_spAmbientDispatch->Invoke(dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); - if (SUCCEEDED(hr) && (wFlags & DISPATCH_PROPERTYPUT) != 0) - { - hr = FireAmbientPropertyChange(dispIdMember); - } - } - return hr; - } - - STDMETHOD(put_AllowWindowlessActivation)(VARIANT_BOOL bAllowWindowless) - { - m_bCanWindowlessActivate = bAllowWindowless; - return S_OK; - } - STDMETHOD(get_AllowWindowlessActivation)(VARIANT_BOOL* pbAllowWindowless) - { - ATLASSERT(pbAllowWindowless != NULL); - if (pbAllowWindowless == NULL) - return E_POINTER; - - *pbAllowWindowless = m_bCanWindowlessActivate ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE; - return S_OK; - } - STDMETHOD(put_BackColor)(OLE_COLOR clrBackground) - { - m_clrBackground = clrBackground; - FireAmbientPropertyChange(DISPID_AMBIENT_BACKCOLOR); - InvalidateRect(0, FALSE); - return S_OK; - } - STDMETHOD(get_BackColor)(OLE_COLOR* pclrBackground) - { - ATLASSERT(pclrBackground != NULL); - if (pclrBackground == NULL) - return E_POINTER; - - *pclrBackground = m_clrBackground; - return S_OK; - } - STDMETHOD(put_ForeColor)(OLE_COLOR clrForeground) - { - m_clrForeground = clrForeground; - FireAmbientPropertyChange(DISPID_AMBIENT_FORECOLOR); - return S_OK; - } - STDMETHOD(get_ForeColor)(OLE_COLOR* pclrForeground) - { - ATLASSERT(pclrForeground != NULL); - if (pclrForeground == NULL) - return E_POINTER; - - *pclrForeground = m_clrForeground; - return S_OK; - } - STDMETHOD(put_LocaleID)(LCID lcidLocaleID) - { - m_lcidLocaleID = lcidLocaleID; - FireAmbientPropertyChange(DISPID_AMBIENT_LOCALEID); - return S_OK; - } - STDMETHOD(get_LocaleID)(LCID* plcidLocaleID) - { - ATLASSERT(plcidLocaleID != NULL); - if (plcidLocaleID == NULL) - return E_POINTER; - - *plcidLocaleID = m_lcidLocaleID; - return S_OK; - } - STDMETHOD(put_UserMode)(VARIANT_BOOL bUserMode) - { - m_bUserMode = bUserMode; - FireAmbientPropertyChange(DISPID_AMBIENT_USERMODE); - return S_OK; - } - STDMETHOD(get_UserMode)(VARIANT_BOOL* pbUserMode) - { - ATLASSERT(pbUserMode != NULL); - if (pbUserMode == NULL) - return E_POINTER; - - *pbUserMode = m_bUserMode ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE; - return S_OK; - } - STDMETHOD(put_DisplayAsDefault)(VARIANT_BOOL bDisplayAsDefault) - { - m_bDisplayAsDefault = bDisplayAsDefault; - FireAmbientPropertyChange(DISPID_AMBIENT_DISPLAYASDEFAULT); - return S_OK; - } - STDMETHOD(get_DisplayAsDefault)(VARIANT_BOOL* pbDisplayAsDefault) - { - ATLASSERT(pbDisplayAsDefault != NULL); - if (pbDisplayAsDefault == NULL) - return E_POINTER; - - *pbDisplayAsDefault = m_bDisplayAsDefault ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE; - return S_OK; - } - STDMETHOD(put_Font)(IFontDisp* pFont) - { - m_spFont = pFont; - FireAmbientPropertyChange(DISPID_AMBIENT_FONT); - return S_OK; - } - STDMETHOD(get_Font)(IFontDisp** pFont) - { - ATLASSERT(pFont != NULL); - if (pFont == NULL) - return E_POINTER; - *pFont = NULL; - - if (m_spFont == NULL) - { - USES_CONVERSION; - HFONT hSystemFont = (HFONT) GetStockObject(DEFAULT_GUI_FONT); - if (hSystemFont == NULL) - hSystemFont = (HFONT) GetStockObject(SYSTEM_FONT); - if (hSystemFont == NULL) - return AtlHresultFromLastError(); - LOGFONT logfont; - GetObject(hSystemFont, sizeof(logfont), &logfont); - FONTDESC fd; - fd.cbSizeofstruct = sizeof(FONTDESC); - fd.lpstrName = T2OLE(logfont.lfFaceName); - fd.sWeight = (short)logfont.lfWeight; - fd.sCharset = logfont.lfCharSet; - fd.fItalic = logfont.lfItalic; - fd.fUnderline = logfont.lfUnderline; - fd.fStrikethrough = logfont.lfStrikeOut; - - long lfHeight = logfont.lfHeight; - if (lfHeight < 0) - lfHeight = -lfHeight; - - int ppi; - HDC hdc; - if (m_hWnd) - { - hdc = ::GetDC(m_hWnd); - if (hdc == NULL) - return AtlHresultFromLastError(); - ppi = GetDeviceCaps(hdc, LOGPIXELSY); - ::ReleaseDC(m_hWnd, hdc); - } - else - { - hdc = ::GetDC(GetDesktopWindow()); - if (hdc == NULL) - return AtlHresultFromLastError(); - ppi = GetDeviceCaps(hdc, LOGPIXELSY); - ::ReleaseDC(GetDesktopWindow(), hdc); - } - fd.cySize.Lo = lfHeight * 720000 / ppi; - fd.cySize.Hi = 0; - - OleCreateFontIndirect(&fd, __uuidof(IFontDisp), (void**) &m_spFont); - } - - return m_spFont.CopyTo(pFont); - } - STDMETHOD(put_MessageReflect)(VARIANT_BOOL bMessageReflect) - { - m_bMessageReflect = bMessageReflect; - FireAmbientPropertyChange(DISPID_AMBIENT_MESSAGEREFLECT); - return S_OK; - } - STDMETHOD(get_MessageReflect)(VARIANT_BOOL* pbMessageReflect) - { - - ATLASSERT(pbMessageReflect != NULL); - if (pbMessageReflect == NULL) - return E_POINTER; - - *pbMessageReflect = m_bMessageReflect ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE; - return S_OK; - } - STDMETHOD(get_ShowGrabHandles)(VARIANT_BOOL* pbShowGrabHandles) - { - *pbShowGrabHandles = ATL_VARIANT_FALSE; - return S_OK; - } - STDMETHOD(get_ShowHatching)(VARIANT_BOOL* pbShowHatching) - { - ATLASSERT(pbShowHatching != NULL); - if (pbShowHatching == NULL) - return E_POINTER; - - *pbShowHatching = ATL_VARIANT_FALSE; - return S_OK; - } - STDMETHOD(put_DocHostFlags)(DWORD dwDocHostFlags) - { - m_dwDocHostFlags = dwDocHostFlags; - FireAmbientPropertyChange(DISPID_UNKNOWN); - return S_OK; - } - STDMETHOD(get_DocHostFlags)(DWORD* pdwDocHostFlags) - { - ATLASSERT(pdwDocHostFlags != NULL); - if (pdwDocHostFlags == NULL) - return E_POINTER; - - *pdwDocHostFlags = m_dwDocHostFlags; - return S_OK; - } - STDMETHOD(put_DocHostDoubleClickFlags)(DWORD dwDocHostDoubleClickFlags) - { - m_dwDocHostDoubleClickFlags = dwDocHostDoubleClickFlags; - return S_OK; - } - STDMETHOD(get_DocHostDoubleClickFlags)(DWORD* pdwDocHostDoubleClickFlags) - { - ATLASSERT(pdwDocHostDoubleClickFlags != NULL); - if (pdwDocHostDoubleClickFlags == NULL) - return E_POINTER; - - *pdwDocHostDoubleClickFlags = m_dwDocHostDoubleClickFlags; - return S_OK; - } - STDMETHOD(put_AllowContextMenu)(VARIANT_BOOL bAllowContextMenu) - { - m_bAllowContextMenu = bAllowContextMenu; - return S_OK; - } - STDMETHOD(get_AllowContextMenu)(VARIANT_BOOL* pbAllowContextMenu) - { - ATLASSERT(pbAllowContextMenu != NULL); - if (pbAllowContextMenu == NULL) - return E_POINTER; - - *pbAllowContextMenu = m_bAllowContextMenu ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE; - return S_OK; - } - STDMETHOD(put_AllowShowUI)(VARIANT_BOOL bAllowShowUI) - { - m_bAllowShowUI = bAllowShowUI; - return S_OK; - } - STDMETHOD(get_AllowShowUI)(VARIANT_BOOL* pbAllowShowUI) - { - ATLASSERT(pbAllowShowUI != NULL); - if (pbAllowShowUI == NULL) - return E_POINTER; - - *pbAllowShowUI = m_bAllowShowUI ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE; - return S_OK; - } - STDMETHOD(put_OptionKeyPath)(BSTR bstrOptionKeyPath) - { - m_bstrOptionKeyPath = bstrOptionKeyPath;; - return S_OK; - } - STDMETHOD(get_OptionKeyPath)(BSTR* pbstrOptionKeyPath) - { - ATLASSERT(pbstrOptionKeyPath != NULL); - if (pbstrOptionKeyPath == NULL) - return E_POINTER; - - *pbstrOptionKeyPath = m_bstrOptionKeyPath; - return S_OK; - } - - STDMETHOD(SetAmbientDispatch)(IDispatch* pDispatch) - { - m_spAmbientDispatch = pDispatch; - return S_OK; - } - -// IObjectWithSite - STDMETHOD(SetSite)(IUnknown* pUnkSite) - { - HRESULT hr = IObjectWithSiteImpl::SetSite(pUnkSite); - - if (SUCCEEDED(hr) && m_spUnkSite) - { - // Look for "outer" IServiceProvider - hr = m_spUnkSite->QueryInterface(__uuidof(IServiceProvider), (void**)&m_spServices); - ATLASSERT( !hr && "No ServiceProvider!" ); - } - - if (pUnkSite == NULL) - m_spServices.Release(); - - return hr; - } - -// IOleClientSite - STDMETHOD(SaveObject)() - { - ATLTRACENOTIMPL(_T("IOleClientSite::SaveObject")); - } - STDMETHOD(GetMoniker)(DWORD /*dwAssign*/, DWORD /*dwWhichMoniker*/, IMoniker** /*ppmk*/) - { - ATLTRACENOTIMPL(_T("IOleClientSite::GetMoniker")); - } - STDMETHOD(GetContainer)(IOleContainer** ppContainer) - { - ATLTRACE(atlTraceHosting, 2, _T("IOleClientSite::GetContainer\n")); - ATLASSERT(ppContainer != NULL); - - HRESULT hr = E_POINTER; - if (ppContainer) - { - hr = E_NOTIMPL; - (*ppContainer) = NULL; - if (m_spUnkSite) - hr = m_spUnkSite->QueryInterface(__uuidof(IOleContainer), (void**)ppContainer); - if (FAILED(hr)) - hr = QueryInterface(__uuidof(IOleContainer), (void**)ppContainer); - } - return hr; - } - STDMETHOD(ShowObject)() - { - ATLTRACE(atlTraceHosting, 2, _T("IOleClientSite::ShowObject\r\n")); - - HDC hdc = CWindowImpl::GetDC(); - if (hdc == NULL) - return E_FAIL; - if (m_spViewObject) - m_spViewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL, hdc, (RECTL*)&m_rcPos, (RECTL*)&m_rcPos, NULL, NULL); - CWindowImpl::ReleaseDC(hdc); - return S_OK; - } - STDMETHOD(OnShowWindow)(BOOL /*fShow*/) - { - ATLTRACENOTIMPL(_T("IOleClientSite::OnShowWindow")); - } - STDMETHOD(RequestNewObjectLayout)() - { - ATLTRACENOTIMPL(_T("IOleClientSite::RequestNewObjectLayout")); - } - -// IOleInPlaceSite - STDMETHOD(GetWindow)(HWND* phwnd) - { - *phwnd = m_hWnd; - return S_OK; - } - STDMETHOD(ContextSensitiveHelp)(BOOL /*fEnterMode*/) - { - ATLTRACENOTIMPL(_T("IOleInPlaceSite::ContextSensitiveHelp")); - } - STDMETHOD(CanInPlaceActivate)() - { - return S_OK; - } - STDMETHOD(OnInPlaceActivate)() - { - // should only be called once the first time control is inplace-activated - ATLASSERT(m_bInPlaceActive == FALSE); - ATLASSERT(m_spInPlaceObjectWindowless == NULL); - - m_bInPlaceActive = TRUE; - OleLockRunning(m_spOleObject, TRUE, FALSE); - m_bWindowless = FALSE; - m_spOleObject->QueryInterface(__uuidof(IOleInPlaceObject), (void**) &m_spInPlaceObjectWindowless); - return S_OK; - } - STDMETHOD(OnUIActivate)() - { - ATLTRACE(atlTraceHosting, 2, _T("IOleInPlaceSite::OnUIActivate\n")); - m_bUIActive = TRUE; - return S_OK; - } - STDMETHOD(GetWindowContext)(IOleInPlaceFrame** ppFrame, IOleInPlaceUIWindow** ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO pFrameInfo) - { - if (ppFrame != NULL) - *ppFrame = NULL; - if (ppDoc != NULL) - *ppDoc = NULL; - if (ppFrame == NULL || ppDoc == NULL || lprcPosRect == NULL || lprcClipRect == NULL) - { - ATLASSERT(false); - return E_POINTER; - } - - if (!m_spInPlaceFrame) - { - CComObject* pFrameWindow; - CComObject::CreateInstance(&pFrameWindow); - pFrameWindow->QueryInterface(__uuidof(IOleInPlaceFrame), (void**) &m_spInPlaceFrame); - ATLASSERT(m_spInPlaceFrame); - } - if (!m_spInPlaceUIWindow) - { - CComObject* pUIWindow; - CComObject::CreateInstance(&pUIWindow); - pUIWindow->QueryInterface(__uuidof(IOleInPlaceUIWindow), (void**) &m_spInPlaceUIWindow); - ATLASSERT(m_spInPlaceUIWindow); - } - m_spInPlaceFrame.CopyTo(ppFrame); - m_spInPlaceUIWindow.CopyTo(ppDoc); - GetClientRect(lprcPosRect); - GetClientRect(lprcClipRect); - - if (m_hAccel == NULL) - { - ACCEL ac = { 0,0,0 }; - m_hAccel = CreateAcceleratorTable(&ac, 1); - } - pFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO); - pFrameInfo->fMDIApp = m_bMDIApp; - pFrameInfo->hwndFrame = GetParent(); - pFrameInfo->haccel = m_hAccel; - pFrameInfo->cAccelEntries = (m_hAccel != NULL) ? 1 : 0; - - return S_OK; - } - STDMETHOD(Scroll)(SIZE /*scrollExtant*/) - { - ATLTRACENOTIMPL(_T("IOleInPlaceSite::Scroll")); - } - STDMETHOD(OnUIDeactivate)(BOOL /*fUndoable*/) - { - ATLTRACE(atlTraceHosting, 2, _T("IOleInPlaceSite::OnUIDeactivate\n")); - m_bUIActive = FALSE; - return S_OK; - } - STDMETHOD(OnInPlaceDeactivate)() - { - m_bInPlaceActive = FALSE; - m_spInPlaceObjectWindowless.Release(); - return S_OK; - } - STDMETHOD(DiscardUndoState)() - { - ATLTRACENOTIMPL(_T("IOleInPlaceSite::DiscardUndoState")); - } - STDMETHOD(DeactivateAndUndo)() - { - ATLTRACENOTIMPL(_T("IOleInPlaceSite::DeactivateAndUndo")); - } - STDMETHOD(OnPosRectChange)(LPCRECT /*lprcPosRect*/) - { - ATLTRACENOTIMPL(_T("IOleInPlaceSite::OnPosRectChange")); - } - -// IOleInPlaceSiteEx - STDMETHOD(OnInPlaceActivateEx)(BOOL* /*pfNoRedraw*/, DWORD dwFlags) - { - // should only be called once the first time control is inplace-activated - ATLASSERT(m_bInPlaceActive == FALSE); - ATLASSERT(m_spInPlaceObjectWindowless == NULL); - - m_bInPlaceActive = TRUE; - OleLockRunning(m_spOleObject, TRUE, FALSE); - HRESULT hr = E_FAIL; - if (dwFlags & ACTIVATE_WINDOWLESS) - { - m_bWindowless = TRUE; - hr = m_spOleObject->QueryInterface(__uuidof(IOleInPlaceObjectWindowless), (void**) &m_spInPlaceObjectWindowless); - } - if (FAILED(hr)) - { - m_bWindowless = FALSE; - hr = m_spOleObject->QueryInterface(__uuidof(IOleInPlaceObject), (void**) &m_spInPlaceObjectWindowless); - } - if (m_spInPlaceObjectWindowless) - m_spInPlaceObjectWindowless->SetObjectRects(&m_rcPos, &m_rcPos); - return S_OK; - } - STDMETHOD(OnInPlaceDeactivateEx)(BOOL /*fNoRedraw*/) - { - m_bInPlaceActive = FALSE; - m_spInPlaceObjectWindowless.Release(); - return S_OK; - } - STDMETHOD(RequestUIActivate)() - { - return S_OK; - } - -// IOleInPlaceSiteWindowless - HDC m_hDCScreen; - bool m_bDCReleased; - - STDMETHOD(CanWindowlessActivate)() - { - return m_bCanWindowlessActivate ? S_OK : S_FALSE; - } - STDMETHOD(GetCapture)() - { - return m_bCapture ? S_OK : S_FALSE; - } - STDMETHOD(SetCapture)(BOOL fCapture) - { - if (fCapture) - { - CWindow::SetCapture(); - m_bCapture = TRUE; - } - else - { - ReleaseCapture(); - m_bCapture = FALSE; - } - return S_OK; - } - STDMETHOD(GetFocus)() - { - return m_bHaveFocus ? S_OK : S_FALSE; - } - STDMETHOD(SetFocus)(BOOL fGotFocus) - { - m_bHaveFocus = fGotFocus; - return S_OK; - } - STDMETHOD(GetDC)(LPCRECT /*pRect*/, DWORD grfFlags, HDC* phDC) - { - if (phDC == NULL) - return E_POINTER; - if (!m_bDCReleased) - return E_FAIL; - - *phDC = CWindowImpl::GetDC(); - if (*phDC == NULL) - return E_FAIL; - - m_bDCReleased = false; - - if (grfFlags & OLEDC_NODRAW) - return S_OK; - - RECT rect; - GetClientRect(&rect); - if (grfFlags & OLEDC_OFFSCREEN) - { - HDC hDCOffscreen = CreateCompatibleDC(*phDC); - if (hDCOffscreen != NULL) - { - HBITMAP hBitmap = CreateCompatibleBitmap(*phDC, rect.right - rect.left, rect.bottom - rect.top); - if (hBitmap == NULL) - DeleteDC(hDCOffscreen); - else - { - HGDIOBJ hOldBitmap = SelectObject(hDCOffscreen, hBitmap); - if (hOldBitmap == NULL) - { - DeleteObject(hBitmap); - DeleteDC(hDCOffscreen); - } - else - { - DeleteObject(hOldBitmap); - m_hDCScreen = *phDC; - *phDC = hDCOffscreen; - } - } - } - } - - if (grfFlags & OLEDC_PAINTBKGND) - ::FillRect(*phDC, &rect, (HBRUSH) (COLOR_WINDOW+1)); - return S_OK; - } - STDMETHOD(ReleaseDC)(HDC hDC) - { - m_bDCReleased = true; - if (m_hDCScreen != NULL) - { - RECT rect; - GetClientRect(&rect); - // Offscreen DC has to be copied to screen DC before releasing the screen dc; - BitBlt(m_hDCScreen, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, hDC, 0, 0, SRCCOPY); - DeleteDC(hDC); - hDC = m_hDCScreen; - } - - CWindowImpl::ReleaseDC(hDC); - return S_OK; - } - STDMETHOD(InvalidateRect)(LPCRECT pRect, BOOL fErase) - { - CWindowImpl::InvalidateRect(pRect, fErase); - return S_OK; - } - STDMETHOD(InvalidateRgn)(HRGN hRGN, BOOL fErase) - { - CWindowImpl::InvalidateRgn(hRGN, fErase); - return S_OK; - } - STDMETHOD(ScrollRect)(INT /*dx*/, INT /*dy*/, LPCRECT /*pRectScroll*/, LPCRECT /*pRectClip*/) - { - return S_OK; - } - STDMETHOD(AdjustRect)(LPRECT /*prc*/) - { - return S_OK; - } - STDMETHOD(OnDefWindowMessage)(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT* plResult) - { - *plResult = DefWindowProc(msg, wParam, lParam); - return S_OK; - } - -// IOleControlSite - STDMETHOD(OnControlInfoChanged)() - { - return S_OK; - } - STDMETHOD(LockInPlaceActive)(BOOL /*fLock*/) - { - return S_OK; - } - STDMETHOD(GetExtendedControl)(IDispatch** ppDisp) - { - if (ppDisp == NULL) - return E_POINTER; - return m_spOleObject.QueryInterface(ppDisp); - } - STDMETHOD(TransformCoords)(POINTL* /*pPtlHimetric*/, POINTF* /*pPtfContainer*/, DWORD /*dwFlags*/) - { - ATLTRACENOTIMPL(_T("CAxHostWindow::TransformCoords")); - } - STDMETHOD(TranslateAccelerator)(LPMSG /*lpMsg*/, DWORD /*grfModifiers*/) - { - return S_FALSE; - } - STDMETHOD(OnFocus)(BOOL fGotFocus) - { - m_bHaveFocus = fGotFocus; - return S_OK; - } - STDMETHOD(ShowPropertyFrame)() - { - ATLTRACENOTIMPL(_T("CAxHostWindow::ShowPropertyFrame")); - } - -// IAdviseSink - STDMETHOD_(void, OnDataChange)(FORMATETC* /*pFormatetc*/, STGMEDIUM* /*pStgmed*/) - { - } - STDMETHOD_(void, OnViewChange)(DWORD /*dwAspect*/, LONG /*lindex*/) - { - } - STDMETHOD_(void, OnRename)(IMoniker* /*pmk*/) - { - } - STDMETHOD_(void, OnSave)() - { - } - STDMETHOD_(void, OnClose)() - { - } - -// IOleContainer - STDMETHOD(ParseDisplayName)(IBindCtx* /*pbc*/, LPOLESTR /*pszDisplayName*/, ULONG* /*pchEaten*/, IMoniker** /*ppmkOut*/) - { - ATLTRACENOTIMPL(_T("CAxHostWindow::ParseDisplayName")); - } - STDMETHOD(EnumObjects)(DWORD /*grfFlags*/, IEnumUnknown** ppenum) - { - if (ppenum == NULL) - return E_POINTER; - *ppenum = NULL; - typedef CComObject > > enumunk; - enumunk* p = NULL; - ATLTRY(p = new enumunk); - if(p == NULL) - return E_OUTOFMEMORY; - IUnknown* pTemp = m_spUnknown; - // There is always only one object. - HRESULT hRes = p->Init(reinterpret_cast(&pTemp), reinterpret_cast(&pTemp + 1), GetControllingUnknown(), AtlFlagCopy); - if (SUCCEEDED(hRes)) - hRes = p->QueryInterface(__uuidof(IEnumUnknown), (void**)ppenum); - if (FAILED(hRes)) - delete p; - return hRes; - } - STDMETHOD(LockContainer)(BOOL fLock) - { - m_bLocked = fLock; - return S_OK; - } - - HRESULT ActivateAx(IUnknown* pUnkControl, bool bInited, IStream* pStream) - { - if (pUnkControl == NULL) - return S_OK; - - m_spUnknown = pUnkControl; - - HRESULT hr = S_OK; - pUnkControl->QueryInterface(__uuidof(IOleObject), (void**)&m_spOleObject); - if (m_spOleObject) - { - m_spOleObject->GetMiscStatus(DVASPECT_CONTENT, &m_dwMiscStatus); - if (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST) - { - CComQIPtr spClientSite(GetControllingUnknown()); - m_spOleObject->SetClientSite(spClientSite); - } - - if (!bInited) // If user hasn't initialized the control, initialize/load using IPersistStreamInit or IPersistStream - { - CComQIPtr spPSI(m_spOleObject); - if (spPSI) - { - if (pStream) - hr = spPSI->Load(pStream); - else - hr = spPSI->InitNew(); - } - else if (pStream) - { - CComQIPtr spPS(m_spOleObject); - if (spPS) - hr = spPS->Load(pStream); - } - - if (FAILED(hr)) // If the initialization of the control failed... - { - // Clean up and return - if (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST) - m_spOleObject->SetClientSite(NULL); - - m_dwMiscStatus = 0; - m_spOleObject.Release(); - m_spUnknown.Release(); - - return hr; - } - } - - if (0 == (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)) - { - CComQIPtr spClientSite(GetControllingUnknown()); - m_spOleObject->SetClientSite(spClientSite); - } - - m_dwViewObjectType = 0; - hr = m_spOleObject->QueryInterface(__uuidof(IViewObjectEx), (void**) &m_spViewObject); - if (FAILED(hr)) - { - hr = m_spOleObject->QueryInterface(__uuidof(IViewObject2), (void**) &m_spViewObject); - if (SUCCEEDED(hr)) - m_dwViewObjectType = 3; - } else - m_dwViewObjectType = 7; - - if (FAILED(hr)) - { - hr = m_spOleObject->QueryInterface(__uuidof(IViewObject), (void**) &m_spViewObject); - if (SUCCEEDED(hr)) - m_dwViewObjectType = 1; - } - CComQIPtr spAdviseSink(GetControllingUnknown()); - m_spOleObject->Advise(spAdviseSink, &m_dwOleObject); - if (m_spViewObject) - m_spViewObject->SetAdvise(DVASPECT_CONTENT, 0, spAdviseSink); - m_spOleObject->SetHostNames(OLESTR("AXWIN"), NULL); - - if ((m_dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME) == 0) - { - GetClientRect(&m_rcPos); - m_pxSize.cx = m_rcPos.right - m_rcPos.left; - m_pxSize.cy = m_rcPos.bottom - m_rcPos.top; - AtlPixelToHiMetric(&m_pxSize, &m_hmSize); - m_spOleObject->SetExtent(DVASPECT_CONTENT, &m_hmSize); - m_spOleObject->GetExtent(DVASPECT_CONTENT, &m_hmSize); - AtlHiMetricToPixel(&m_hmSize, &m_pxSize); - m_rcPos.right = m_rcPos.left + m_pxSize.cx; - m_rcPos.bottom = m_rcPos.top + m_pxSize.cy; - - CComQIPtr spClientSite(GetControllingUnknown()); - hr = m_spOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, spClientSite, 0, m_hWnd, &m_rcPos); - RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_INTERNALPAINT | RDW_FRAME); - } - } - CComPtr spSite; - pUnkControl->QueryInterface(__uuidof(IObjectWithSite), (void**)&spSite); - if (spSite != NULL) - spSite->SetSite(GetControllingUnknown()); - - return hr; - } - - -// pointers - CComPtr m_spUnknown; - CComPtr m_spOleObject; - CComPtr m_spInPlaceFrame; - CComPtr m_spInPlaceUIWindow; - CComPtr m_spViewObject; - CComPtr m_spInPlaceObjectWindowless; - CComPtr m_spExternalDispatch; -#ifndef _ATL_NO_DOCHOSTUIHANDLER - CComPtr m_spIDocHostUIHandlerDispatch; -#endif - IID m_iidSink; - DWORD m_dwViewObjectType; - DWORD m_dwAdviseSink; - -// state - unsigned long m_bInPlaceActive:1; - unsigned long m_bUIActive:1; - unsigned long m_bMDIApp:1; - unsigned long m_bWindowless:1; - unsigned long m_bCapture:1; - unsigned long m_bHaveFocus:1; - unsigned long m_bReleaseAll:1; - unsigned long m_bLocked:1; - - DWORD m_dwOleObject; - DWORD m_dwMiscStatus; - SIZEL m_hmSize; - SIZEL m_pxSize; - RECT m_rcPos; - - // Accelerator table - HACCEL m_hAccel; - - // Ambient property storage - unsigned long m_bCanWindowlessActivate:1; - unsigned long m_bUserMode:1; - unsigned long m_bDisplayAsDefault:1; - unsigned long m_bMessageReflect:1; - unsigned long m_bSubclassed:1; - unsigned long m_bAllowContextMenu:1; - unsigned long m_bAllowShowUI:1; - OLE_COLOR m_clrBackground; - OLE_COLOR m_clrForeground; - LCID m_lcidLocaleID; - CComPtr m_spFont; - CComPtr m_spServices; - DWORD m_dwDocHostFlags; - DWORD m_dwDocHostDoubleClickFlags; - CComBSTR m_bstrOptionKeyPath; - - void SubclassWindow(HWND hWnd) - { - m_bSubclassed = CWindowImpl::SubclassWindow(hWnd); - } - - void ReleaseWindow() - { - if (m_bSubclassed) - { - if(UnsubclassWindow(TRUE) != NULL) - m_bSubclassed = FALSE; - } - else - DestroyWindow(); - } - - // Reflection - LRESULT ReflectNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - HWND hWndChild = NULL; - - switch(uMsg) - { - case WM_COMMAND: - if(lParam != NULL) // not from a menu - hWndChild = (HWND)lParam; - break; - case WM_NOTIFY: - hWndChild = ((LPNMHDR)lParam)->hwndFrom; - break; - case WM_PARENTNOTIFY: - DefWindowProc(); - switch(LOWORD(wParam)) - { - case WM_CREATE: - case WM_DESTROY: - hWndChild = (HWND)lParam; - break; - default: - hWndChild = GetDlgItem(HIWORD(wParam)); - break; - } - break; - case WM_DRAWITEM: - { - DRAWITEMSTRUCT* pdis = ((LPDRAWITEMSTRUCT)lParam); - if (pdis->CtlType != ODT_MENU) // not from a menu - hWndChild = pdis->hwndItem; - else // Status bar control sends this message with type set to ODT_MENU - if (::IsWindow(pdis->hwndItem)) - hWndChild = pdis->hwndItem; - } - break; - case WM_MEASUREITEM: - { - MEASUREITEMSTRUCT* pmis = ((LPMEASUREITEMSTRUCT)lParam); - if(pmis->CtlType != ODT_MENU) // not from a menu - hWndChild = GetDlgItem(pmis->CtlID); - } - break; - case WM_COMPAREITEM: - // Sent only by combo or list box - hWndChild = GetDlgItem(((LPCOMPAREITEMSTRUCT)lParam)->CtlID); - break; - case WM_DELETEITEM: - // Sent only by combo or list box - hWndChild = GetDlgItem(((LPDELETEITEMSTRUCT)lParam)->CtlID); - break; - case WM_VKEYTOITEM: - case WM_CHARTOITEM: - case WM_HSCROLL: - case WM_VSCROLL: - hWndChild = (HWND)lParam; - break; - case WM_CTLCOLORBTN: - case WM_CTLCOLORDLG: - case WM_CTLCOLOREDIT: - case WM_CTLCOLORLISTBOX: - case WM_CTLCOLORMSGBOX: - case WM_CTLCOLORSCROLLBAR: - case WM_CTLCOLORSTATIC: - hWndChild = (HWND)lParam; - break; - default: - break; - } - - if(hWndChild == NULL) - { - bHandled = FALSE; - return 1; - } - - if (m_bWindowless) - { - LRESULT lRes = 0; - if (m_bInPlaceActive && m_spInPlaceObjectWindowless) - m_spInPlaceObjectWindowless->OnWindowMessage(OCM__BASE + uMsg, wParam, lParam, &lRes); - return lRes; - } - - ATLASSERT(::IsWindow(hWndChild)); - return ::SendMessage(hWndChild, OCM__BASE + uMsg, wParam, lParam); - } - - STDMETHOD(QueryService)( REFGUID rsid, REFIID riid, void** ppvObj) - { - ATLASSERT(ppvObj != NULL); - if (ppvObj == NULL) - return E_POINTER; - *ppvObj = NULL; - - HRESULT hr = E_NOINTERFACE; - // Try for service on this object - - // No services currently - - // If that failed try to find the service on the outer object - if (FAILED(hr) && m_spServices) - hr = m_spServices->QueryService(rsid, riid, ppvObj); - - return hr; - } -}; - -static LRESULT CALLBACK AtlAxWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch(uMsg) - { - case WM_CREATE: - { - // create control from a PROGID in the title - // This is to make sure drag drop works - ::OleInitialize(NULL); - - CREATESTRUCT* lpCreate = (CREATESTRUCT*)lParam; - int nLen = ::GetWindowTextLength(hWnd); - LPTSTR lpstrName = (LPTSTR)_alloca((nLen + 1) * sizeof(TCHAR)); - ::GetWindowText(hWnd, lpstrName, nLen + 1); - ::SetWindowText(hWnd, _T("")); - IAxWinHostWindow* pAxWindow = NULL; - int nCreateSize = 0; - if (lpCreate && lpCreate->lpCreateParams) - nCreateSize = *((WORD*)lpCreate->lpCreateParams); - - HGLOBAL h = GlobalAlloc(GHND, nCreateSize); - CComPtr spStream; - if (h && nCreateSize) - { - BYTE* pBytes = (BYTE*) GlobalLock(h); - BYTE* pSource = ((BYTE*)(lpCreate->lpCreateParams)) + sizeof(WORD); - //Align to DWORD - //pSource += (((~((DWORD)pSource)) + 1) & 3); - memcpy(pBytes, pSource, nCreateSize); - GlobalUnlock(h); - CreateStreamOnHGlobal(h, TRUE, &spStream); - } - - USES_CONVERSION; - CComPtr spUnk; - HRESULT hRet = AtlAxCreateControlLic(T2COLE(lpstrName), hWnd, spStream, &spUnk, NULL); - if(FAILED(hRet)) - { -#ifdef _DEBUG - LPTSTR pszMsg = NULL; - ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL, hRet, 0, (LPTSTR)&pszMsg, 0, NULL); - ATLTRACE(atlTraceControls, 0, _T("Control creation failed for '%s'\n"), lpstrName); - ATLTRACE(atlTraceControls, 0, _T("Error code: 0x%x - %s"), hRet, pszMsg); - ::LocalFree(pszMsg); -#endif - return -1; // abort window creation - } - hRet = spUnk->QueryInterface(__uuidof(IAxWinHostWindow), (void**)&pAxWindow); - if(FAILED(hRet)) - return -1; // abort window creation - - ::SetWindowLongPtr(hWnd, GWLP_USERDATA, (DWORD_PTR)pAxWindow); - // continue with DefWindowProc - } - break; - case WM_NCDESTROY: - { - IAxWinHostWindow* pAxWindow = (IAxWinHostWindow*)::GetWindowLongPtr(hWnd, GWLP_USERDATA); - if(pAxWindow != NULL) - pAxWindow->Release(); - OleUninitialize(); - } - break; - - case WM_PARENTNOTIFY: - { - if((UINT)wParam == WM_CREATE) - { - ATLASSERT(lParam); - // Set the control parent style for the AxWindow - DWORD dwExStyle = ::GetWindowLong((HWND)lParam, GWL_EXSTYLE); - if(dwExStyle & WS_EX_CONTROLPARENT) - { - dwExStyle = ::GetWindowLong(hWnd, GWL_EXSTYLE); - dwExStyle |= WS_EX_CONTROLPARENT; - ::SetWindowLong(hWnd, GWL_EXSTYLE, dwExStyle); - } - } - } - break; - - default: - break; - } - - return ::DefWindowProc(hWnd, uMsg, wParam, lParam); -} - -static LRESULT CALLBACK AtlAxWindowProc2(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch(uMsg) - { - case WM_CREATE: - { - // create control from a PROGID in the title - // This is to make sure drag drop works - ::OleInitialize(NULL); - - CREATESTRUCT* lpCreate = (CREATESTRUCT*)lParam; - int nLen = ::GetWindowTextLength(hWnd); - LPTSTR lpstrName = (LPTSTR)_alloca((nLen + 1) * sizeof(TCHAR)); - ::GetWindowText(hWnd, lpstrName, nLen + 1); - ::SetWindowText(hWnd, _T("")); - IAxWinHostWindowLic* pAxWindow = NULL; - int nCreateSize = 0; - if (lpCreate && lpCreate->lpCreateParams) - nCreateSize = *((WORD*)lpCreate->lpCreateParams); - - // Format of data in lpCreateParams - // int nCreateSize; // size of Create data in bytes - // WORD nMsg; //constant used to indicate type of DLGINIT data. See _DialogSplitHelper for values. - // DWORD dwLen; // Length of data strored for control in DLGINIT format in bytes. - // DWORD cchLicKey; // Length of licence key in OLECHAR's - // OLECHAR *szLicKey; // This will be present only if cchLicKey is greater than 0. This is of variable length and will contain cchLicKey OLECHAR's that represent the licence key. - // The following two fields will be present only if nMsg is WM_OCC_LOADFROMSTREAM_EX or WM_OCC_LOADFROMSTORAGE_EX. If present this information will be ignored since databinding is not supported. - // ULONG cbDataBinding; // Lenght of databinding information in bytes. - // BYTE *pbDataBindingInfo // cbDataBinding bytes that contain databinding information - // BYTE *pbControlData; // Actual control data persisted by the control. - - - HGLOBAL h = GlobalAlloc(GHND, nCreateSize); - CComPtr spStream; - if (h && nCreateSize) - { - BYTE* pBytes = (BYTE*) GlobalLock(h); - BYTE* pSource = ((BYTE*)(lpCreate->lpCreateParams)) + sizeof(WORD); - //Align to DWORD - //pSource += (((~((DWORD)pSource)) + 1) & 3); - memcpy(pBytes, pSource, nCreateSize); - GlobalUnlock(h); - CreateStreamOnHGlobal(h, TRUE, &spStream); - } - - CComBSTR bstrLicKey; - HRESULT hRet = _DialogSplitHelper::ParseInitData(spStream, &bstrLicKey.m_str); - if (FAILED(hRet)) - return -1; - - USES_CONVERSION; - CComPtr spUnk; - hRet = AtlAxCreateControlLic(T2COLE(lpstrName), hWnd, spStream, &spUnk, bstrLicKey); - if(FAILED(hRet)) - { -#ifdef _DEBUG - LPTSTR pszMsg = NULL; - ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL, hRet, 0, (LPTSTR)&pszMsg, 0, NULL); - ATLTRACE(atlTraceControls, 0, _T("Control creation failed for '%s'\n"), lpstrName); - ATLTRACE(atlTraceControls, 0, _T("Error code: 0x%x - %s"), hRet, pszMsg); - ::LocalFree(pszMsg); -#endif - return -1; // abort window creation - } - hRet = spUnk->QueryInterface(__uuidof(IAxWinHostWindowLic), (void**)&pAxWindow); - if(FAILED(hRet)) - return -1; // abort window creation - ::SetWindowLongPtr(hWnd, GWLP_USERDATA, (DWORD_PTR)pAxWindow); - // continue with DefWindowProc - } - break; - case WM_NCDESTROY: - { - IAxWinHostWindowLic* pAxWindow = (IAxWinHostWindowLic*)::GetWindowLongPtr(hWnd, GWLP_USERDATA); - if(pAxWindow != NULL) - pAxWindow->Release(); - OleUninitialize(); - } - break; - - case WM_PARENTNOTIFY: - { - if((UINT)wParam == WM_CREATE) - { - ATLASSERT(lParam); - // Set the control parent style for the AxWindow - DWORD dwExStyle = ::GetWindowLong((HWND)lParam, GWL_EXSTYLE); - if(dwExStyle & WS_EX_CONTROLPARENT) - { - dwExStyle = ::GetWindowLong(hWnd, GWL_EXSTYLE); - dwExStyle |= WS_EX_CONTROLPARENT; - ::SetWindowLong(hWnd, GWL_EXSTYLE, dwExStyle); - } - } - } - break; - - default: - break; - } - - return ::DefWindowProc(hWnd, uMsg, wParam, lParam); -} - -//All exports go here -#ifndef _ATL_DLL - -inline HRSRC AtlFindResource(HMODULE hModule, LPCSTR lpName, LPCSTR lpType) -{ - return ::FindResourceA(hModule, lpName, lpType); -} - -inline HRSRC AtlFindResource(HMODULE hModule, LPCWSTR lpName, LPCWSTR lpType) -{ - return ::FindResourceW(hModule, lpName, lpType); -} - -class _AtlDialogBoxIndirectParamHelper -{ -public : - typedef INT_PTR ReturnType; - static ReturnType GetInvalidValue() - { - return -1; - } - static bool IsValidReturnVal(ReturnType nRet) - { - return (nRet != 0 && nRet != -1); - } -}; - -class _AtlCreateDialogIndirectParamHelper -{ -public : - typedef HWND ReturnType; - static ReturnType GetInvalidValue() - { - return NULL; - } - static bool IsValidReturnVal(ReturnType nRet) - { - return (nRet != 0); - } -}; - -template -typename Helper::ReturnType AtlAxDialogCreateT(HINSTANCE hInstance, StringType lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam) -{ - AtlAxWinInit(); - Helper::ReturnType nRet = Helper::GetInvalidValue(); - - HRSRC hDlg = AtlFindResource(hInstance, lpTemplateName, (StringType)RT_DIALOG); - if (hDlg != NULL) - { - HRSRC hDlgInit = AtlFindResource(hInstance, lpTemplateName, (StringType)_ATL_RT_DLGINIT); - HGLOBAL hData = NULL; - BYTE* pInitData = NULL; - - if (hDlgInit) - { - hData = ::LoadResource(hInstance, hDlgInit); - pInitData = (BYTE*) ::LockResource(hData); - } - - DWORD dwLastError = 0; - HGLOBAL hResource = LoadResource(hInstance, hDlg); - if (hResource != NULL) - { - DLGTEMPLATE* pDlg = (DLGTEMPLATE*) LockResource(hResource); - if (pDlg != NULL) - { - LPCDLGTEMPLATE lpDialogTemplate; - - lpDialogTemplate = _DialogSplitHelper::SplitDialogTemplate(pDlg, pInitData); - - nRet = (*pFunc)(hInstance, lpDialogTemplate, hWndParent, lpDialogProc, dwInitParam); - if (!Helper::IsValidReturnVal(nRet)) - { - dwLastError = ::GetLastError(); - } - if (lpDialogTemplate != pDlg) - GlobalFree(GlobalHandle(lpDialogTemplate)); - } - else - dwLastError = ::GetLastError(); - } - else - dwLastError = ::GetLastError(); - - if (dwLastError != 0) - SetLastError(dwLastError); - } - return nRet; -} - -// fix this once compiler is fixed -//ATLINLINE ATLAPI_(INT_PTR) AtlAxDialogBoxW(HINSTANCE hInstance, LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam) -ATLINLINE INT_PTR __stdcall AtlAxDialogBoxW(HINSTANCE hInstance, LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam) -{ - return AtlAxDialogCreateT( - hInstance, lpTemplateName, hWndParent, lpDialogProc, dwInitParam); -} - -// fix this once compiler is fixed -//ATLINLINE ATLAPI_(INT_PTR) AtlAxDialogBoxA(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam) -ATLINLINE INT_PTR __stdcall AtlAxDialogBoxA(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam) -{ - return AtlAxDialogCreateT( - hInstance, lpTemplateName, hWndParent, lpDialogProc, dwInitParam); -} - -// fix this once compiler is fixed -//ATLINLINE ATLAPI_(HWND) AtlAxCreateDialogW(HINSTANCE hInstance, LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam) -ATLINLINE HWND __stdcall AtlAxCreateDialogW(HINSTANCE hInstance, LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam) -{ - return AtlAxDialogCreateT( - hInstance, lpTemplateName, hWndParent, lpDialogProc, dwInitParam); -} - -// fix this once compiler is fixed -//ATLINLINE ATLAPI_(HWND) AtlAxCreateDialogA(HINSTANCE hInstance, LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam) -ATLINLINE HWND __stdcall AtlAxCreateDialogA(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam) -{ - return AtlAxDialogCreateT( - hInstance, lpTemplateName, hWndParent, lpDialogProc, dwInitParam); -} - -ATLINLINE ATLAPI AtlAxCreateControl(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, IUnknown** ppUnkContainer) -{ - return AtlAxCreateControlEx(lpszName, hWnd, pStream, ppUnkContainer, NULL, IID_NULL, NULL); -} - -ATLINLINE ATLAPI AtlAxCreateControlEx(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, - IUnknown** ppUnkContainer, IUnknown** ppUnkControl, REFIID iidSink, IUnknown* punkSink) -{ - return AtlAxCreateControlLicEx(lpszName, hWnd, pStream, ppUnkContainer, ppUnkControl, iidSink, punkSink, NULL); -} - -ATLINLINE ATLAPI AtlAxCreateControlLic(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, IUnknown** ppUnkContainer, BSTR bstrLic) -{ - return AtlAxCreateControlLicEx(lpszName, hWnd, pStream, ppUnkContainer, NULL, IID_NULL, NULL, bstrLic); -} - -ATLINLINE ATLAPI AtlAxCreateControlLicEx(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, - IUnknown** ppUnkContainer, IUnknown** ppUnkControl, REFIID iidSink, IUnknown* punkSink, BSTR bstrLic) -{ - AtlAxWinInit(); - HRESULT hr; - CComPtr spUnkContainer; - CComPtr spUnkControl; - - hr = CAxHostWindow::_CreatorClass::CreateInstance(NULL, __uuidof(IUnknown), (void**)&spUnkContainer); - if (SUCCEEDED(hr)) - { - CComPtr pAxWindow; - spUnkContainer->QueryInterface(__uuidof(IAxWinHostWindow), (void**)&pAxWindow); - CComBSTR bstrName(lpszName); - hr = pAxWindow->CreateControlLicEx(bstrName, hWnd, pStream, &spUnkControl, iidSink, punkSink, bstrLic); - } - if (ppUnkContainer != NULL) - { - if (SUCCEEDED(hr)) - { - *ppUnkContainer = spUnkContainer.p; - spUnkContainer.p = NULL; - } - else - *ppUnkContainer = NULL; - } - if (ppUnkControl != NULL) - { - if (SUCCEEDED(hr)) - { - *ppUnkControl = SUCCEEDED(hr) ? spUnkControl.p : NULL; - spUnkControl.p = NULL; - } - else - *ppUnkControl = NULL; - } - return hr; -} - -ATLINLINE ATLAPI AtlAxAttachControl(IUnknown* pControl, HWND hWnd, IUnknown** ppUnkContainer) -{ - AtlAxWinInit(); - if (pControl == NULL) - return E_INVALIDARG; - CComPtr spUnkContainer; - - HRESULT hr = CAxHostWindow::_CreatorClass::CreateInstance(NULL, __uuidof(IUnknown), (void**)&spUnkContainer); - if (SUCCEEDED(hr)) - { - CComPtr spAxWindow; - hr = spUnkContainer->QueryInterface(&spAxWindow); - if (SUCCEEDED(hr)) - hr = spAxWindow->AttachControl(pControl, hWnd); - } - if (ppUnkContainer != NULL) - { - *ppUnkContainer = SUCCEEDED(hr) ? spUnkContainer.Detach() : NULL; - } - return hr; -} - -#ifdef _ATL_DLL_IMPL -// global variable in ATL.DLL to keep track if AtlAxWin window class has been registered in ATL.DLL -bool __declspec(selectany) bAtlAxWinInitialized; -#endif - -//This either registers a global class (if AtlAxWinInit is in ATL.DLL) -// or it registers a local class -ATLINLINE ATLAPI_(BOOL) AtlAxWinInit() -{ - CComCritSecLock lock(_AtlWinModule.m_csWindowCreate, false); - if (FAILED(lock.Lock())) - { - ATLTRACE(atlTraceHosting, 0, _T("ERROR : Unable to lock critical section in AtlAxWinInit\n")); - ATLASSERT(0); - return FALSE; - } - WM_ATLGETHOST = RegisterWindowMessage(_T("WM_ATLGETHOST")); - WM_ATLGETCONTROL = RegisterWindowMessage(_T("WM_ATLGETCONTROL")); - WNDCLASSEX wc; -// first check if the class is already registered - wc.cbSize = sizeof(WNDCLASSEX); - BOOL bRet = ::GetClassInfoEx(_AtlBaseModule.GetModuleInstance(), CAxWindow::GetWndClassName(), &wc); - -// register class if not - - if(!bRet) - { - wc.cbSize = sizeof(WNDCLASSEX); -#ifdef _ATL_DLL_IMPL - wc.style = CS_GLOBALCLASS | CS_DBLCLKS; - bAtlAxWinInitialized = true; -#else - wc.style = CS_DBLCLKS; -#endif - wc.lpfnWndProc = AtlAxWindowProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = _AtlBaseModule.GetModuleInstance(); - wc.hIcon = NULL; - wc.hCursor = ::LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); - wc.lpszMenuName = NULL; - wc.lpszClassName = CAxWindow::GetWndClassName(); - wc.hIconSm = NULL; - - bRet = (BOOL)::RegisterClassEx(&wc); - } - - if (bRet) - { - // first check if the class is already registered - memset(&wc, 0, sizeof(WNDCLASSEX)); - wc.cbSize = sizeof(WNDCLASSEX); - bRet = ::GetClassInfoEx(_AtlBaseModule.GetModuleInstance(), CAxWindow2::GetWndClassName(), &wc); - - // register class if not - - if(!bRet) - { - wc.cbSize = sizeof(WNDCLASSEX); - #ifdef _ATL_DLL_IMPL - wc.style = CS_GLOBALCLASS | CS_DBLCLKS; - #else - wc.style = CS_DBLCLKS; - #endif - wc.lpfnWndProc = AtlAxWindowProc2; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = _AtlBaseModule.GetModuleInstance(); - wc.hIcon = NULL; - wc.hCursor = ::LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); - wc.lpszMenuName = NULL; - wc.lpszClassName = CAxWindow2::GetWndClassName(); - wc.hIconSm = NULL; - - bRet = (BOOL)::RegisterClassEx(&wc); - } - } - return bRet; -} - -ATLINLINE ATLAPI AtlAxGetControl(HWND h, IUnknown** pp) -{ - ATLASSERT(WM_ATLGETCONTROL != 0); - if (pp == NULL) - return E_POINTER; - *pp = (IUnknown*)SendMessage(h, WM_ATLGETCONTROL, 0, 0); - return (*pp) ? S_OK : E_FAIL; -} - -ATLINLINE ATLAPI AtlAxGetHost(HWND h, IUnknown** pp) -{ - ATLASSERT(WM_ATLGETHOST != 0); - if (pp == NULL) - return E_POINTER; - *pp = (IUnknown*)SendMessage(h, WM_ATLGETHOST, 0, 0); - return (*pp) ? S_OK : E_FAIL; -} - -#endif // _ATL_DLL - -}; //namespace ATL - -#ifndef _ATL_NO_PRAGMA_WARNINGS -#pragma warning (pop) -#endif //!_ATL_NO_PRAGMA_WARNINGS - -#endif // __ATLHOST_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atliface.h b/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atliface.h deleted file mode 100644 index 0480966b6..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atliface.h +++ /dev/null @@ -1,2954 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#pragma warning( disable: 4049 ) /* more than 64k source lines */ - -/* this ALWAYS GENERATED file contains the definitions for the interfaces */ - - - /* File created by MIDL compiler version 6.00.0342 */ -/* at Mon Feb 12 21:31:09 2001 - */ -/* Compiler settings for atliface.idl: - Oicf, W1, Zp8, env=Win32 (32b run) - protocol : dce , ms_ext, c_ext - error checks: allocation ref bounds_check enum stub_data - VC __declspec() decoration level: - __declspec(uuid()), __declspec(selectany), __declspec(novtable) - DECLSPEC_UUID(), MIDL_INTERFACE() -*/ -//@@MIDL_FILE_HEADING( ) - - -/* verify that the version is high enough to compile this file*/ -#ifndef __REQUIRED_RPCNDR_H_VERSION__ -#define __REQUIRED_RPCNDR_H_VERSION__ 440 -#endif - -#include "rpc.h" -#include "rpcndr.h" - -#ifndef __RPCNDR_H_VERSION__ -#error this stub requires an updated version of -#endif // __RPCNDR_H_VERSION__ - -#ifndef COM_NO_WINDOWS_H -#include "windows.h" -#include "ole2.h" -#endif /*COM_NO_WINDOWS_H*/ - -#ifndef __atliface_h__ -#define __atliface_h__ - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -#pragma once -#endif - -/* Forward Declarations */ - -#ifndef __IRegistrarBase_FWD_DEFINED__ -#define __IRegistrarBase_FWD_DEFINED__ -typedef interface IRegistrarBase IRegistrarBase; -#endif /* __IRegistrarBase_FWD_DEFINED__ */ - - -#ifndef __IRegistrar_FWD_DEFINED__ -#define __IRegistrar_FWD_DEFINED__ -typedef interface IRegistrar IRegistrar; -#endif /* __IRegistrar_FWD_DEFINED__ */ - - -#ifndef __IDocHostUIHandlerDispatch_FWD_DEFINED__ -#define __IDocHostUIHandlerDispatch_FWD_DEFINED__ -typedef interface IDocHostUIHandlerDispatch IDocHostUIHandlerDispatch; -#endif /* __IDocHostUIHandlerDispatch_FWD_DEFINED__ */ - - -#ifndef __IAxWinHostWindow_FWD_DEFINED__ -#define __IAxWinHostWindow_FWD_DEFINED__ -typedef interface IAxWinHostWindow IAxWinHostWindow; -#endif /* __IAxWinHostWindow_FWD_DEFINED__ */ - - -#ifndef __IAxWinHostWindowLic_FWD_DEFINED__ -#define __IAxWinHostWindowLic_FWD_DEFINED__ -typedef interface IAxWinHostWindowLic IAxWinHostWindowLic; -#endif /* __IAxWinHostWindowLic_FWD_DEFINED__ */ - - -#ifndef __IAxWinAmbientDispatch_FWD_DEFINED__ -#define __IAxWinAmbientDispatch_FWD_DEFINED__ -typedef interface IAxWinAmbientDispatch IAxWinAmbientDispatch; -#endif /* __IAxWinAmbientDispatch_FWD_DEFINED__ */ - - -#ifndef __IAxWinAmbientDispatchEx_FWD_DEFINED__ -#define __IAxWinAmbientDispatchEx_FWD_DEFINED__ -typedef interface IAxWinAmbientDispatchEx IAxWinAmbientDispatchEx; -#endif /* __IAxWinAmbientDispatchEx_FWD_DEFINED__ */ - - -#ifndef __IInternalConnection_FWD_DEFINED__ -#define __IInternalConnection_FWD_DEFINED__ -typedef interface IInternalConnection IInternalConnection; -#endif /* __IInternalConnection_FWD_DEFINED__ */ - - -#ifndef __IAccessibleProxy_FWD_DEFINED__ -#define __IAccessibleProxy_FWD_DEFINED__ -typedef interface IAccessibleProxy IAccessibleProxy; -#endif /* __IAccessibleProxy_FWD_DEFINED__ */ - - -#ifndef __IAccessibleServer_FWD_DEFINED__ -#define __IAccessibleServer_FWD_DEFINED__ -typedef interface IAccessibleServer IAccessibleServer; -#endif /* __IAccessibleServer_FWD_DEFINED__ */ - - -/* header files for imported files */ -#include "oaidl.h" -#include "ocidl.h" -#include "oleacc.h" - -#ifdef __cplusplus -extern "C"{ -#endif - -void * __RPC_USER MIDL_user_allocate(size_t); -void __RPC_USER MIDL_user_free( void * ); - -/* interface __MIDL_itf_atliface_0000 */ -/* [local] */ - -EXTERN_C const CLSID CLSID_Registrar; - - -extern RPC_IF_HANDLE __MIDL_itf_atliface_0000_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_atliface_0000_v0_0_s_ifspec; - -#ifndef __IRegistrarBase_INTERFACE_DEFINED__ -#define __IRegistrarBase_INTERFACE_DEFINED__ - -/* interface IRegistrarBase */ -/* [unique][helpstring][uuid][object] */ - - -EXTERN_C const IID IID_IRegistrarBase; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("e21f8a85-b05d-4243-8183-c7cb405588f7") - IRegistrarBase : public IUnknown - { - public: - virtual HRESULT STDMETHODCALLTYPE AddReplacement( - /* [in] */ LPCOLESTR key, - /* [in] */ LPCOLESTR item) = 0; - - virtual HRESULT STDMETHODCALLTYPE ClearReplacements( void) = 0; - - }; - -#else /* C style interface */ - - typedef struct IRegistrarBaseVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IRegistrarBase * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IRegistrarBase * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IRegistrarBase * This); - - HRESULT ( STDMETHODCALLTYPE *AddReplacement )( - IRegistrarBase * This, - /* [in] */ LPCOLESTR key, - /* [in] */ LPCOLESTR item); - - HRESULT ( STDMETHODCALLTYPE *ClearReplacements )( - IRegistrarBase * This); - - END_INTERFACE - } IRegistrarBaseVtbl; - - interface IRegistrarBase - { - CONST_VTBL struct IRegistrarBaseVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IRegistrarBase_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IRegistrarBase_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IRegistrarBase_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IRegistrarBase_AddReplacement(This,key,item) \ - (This)->lpVtbl -> AddReplacement(This,key,item) - -#define IRegistrarBase_ClearReplacements(This) \ - (This)->lpVtbl -> ClearReplacements(This) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -HRESULT STDMETHODCALLTYPE IRegistrarBase_AddReplacement_Proxy( - IRegistrarBase * This, - /* [in] */ LPCOLESTR key, - /* [in] */ LPCOLESTR item); - - -void __RPC_STUB IRegistrarBase_AddReplacement_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IRegistrarBase_ClearReplacements_Proxy( - IRegistrarBase * This); - - -void __RPC_STUB IRegistrarBase_ClearReplacements_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IRegistrarBase_INTERFACE_DEFINED__ */ - - -#ifndef __IRegistrar_INTERFACE_DEFINED__ -#define __IRegistrar_INTERFACE_DEFINED__ - -/* interface IRegistrar */ -/* [unique][helpstring][uuid][object] */ - - -EXTERN_C const IID IID_IRegistrar; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("44EC053B-400F-11D0-9DCD-00A0C90391D3") - IRegistrar : public IRegistrarBase - { - public: - virtual HRESULT STDMETHODCALLTYPE ResourceRegisterSz( - /* [in] */ LPCOLESTR resFileName, - /* [in] */ LPCOLESTR szID, - /* [in] */ LPCOLESTR szType) = 0; - - virtual HRESULT STDMETHODCALLTYPE ResourceUnregisterSz( - /* [in] */ LPCOLESTR resFileName, - /* [in] */ LPCOLESTR szID, - /* [in] */ LPCOLESTR szType) = 0; - - virtual HRESULT STDMETHODCALLTYPE FileRegister( - /* [in] */ LPCOLESTR fileName) = 0; - - virtual HRESULT STDMETHODCALLTYPE FileUnregister( - /* [in] */ LPCOLESTR fileName) = 0; - - virtual HRESULT STDMETHODCALLTYPE StringRegister( - /* [in] */ LPCOLESTR data) = 0; - - virtual HRESULT STDMETHODCALLTYPE StringUnregister( - /* [in] */ LPCOLESTR data) = 0; - - virtual HRESULT STDMETHODCALLTYPE ResourceRegister( - /* [in] */ LPCOLESTR resFileName, - /* [in] */ UINT nID, - /* [in] */ LPCOLESTR szType) = 0; - - virtual HRESULT STDMETHODCALLTYPE ResourceUnregister( - /* [in] */ LPCOLESTR resFileName, - /* [in] */ UINT nID, - /* [in] */ LPCOLESTR szType) = 0; - - }; - -#else /* C style interface */ - - typedef struct IRegistrarVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IRegistrar * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IRegistrar * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IRegistrar * This); - - HRESULT ( STDMETHODCALLTYPE *AddReplacement )( - IRegistrar * This, - /* [in] */ LPCOLESTR key, - /* [in] */ LPCOLESTR item); - - HRESULT ( STDMETHODCALLTYPE *ClearReplacements )( - IRegistrar * This); - - HRESULT ( STDMETHODCALLTYPE *ResourceRegisterSz )( - IRegistrar * This, - /* [in] */ LPCOLESTR resFileName, - /* [in] */ LPCOLESTR szID, - /* [in] */ LPCOLESTR szType); - - HRESULT ( STDMETHODCALLTYPE *ResourceUnregisterSz )( - IRegistrar * This, - /* [in] */ LPCOLESTR resFileName, - /* [in] */ LPCOLESTR szID, - /* [in] */ LPCOLESTR szType); - - HRESULT ( STDMETHODCALLTYPE *FileRegister )( - IRegistrar * This, - /* [in] */ LPCOLESTR fileName); - - HRESULT ( STDMETHODCALLTYPE *FileUnregister )( - IRegistrar * This, - /* [in] */ LPCOLESTR fileName); - - HRESULT ( STDMETHODCALLTYPE *StringRegister )( - IRegistrar * This, - /* [in] */ LPCOLESTR data); - - HRESULT ( STDMETHODCALLTYPE *StringUnregister )( - IRegistrar * This, - /* [in] */ LPCOLESTR data); - - HRESULT ( STDMETHODCALLTYPE *ResourceRegister )( - IRegistrar * This, - /* [in] */ LPCOLESTR resFileName, - /* [in] */ UINT nID, - /* [in] */ LPCOLESTR szType); - - HRESULT ( STDMETHODCALLTYPE *ResourceUnregister )( - IRegistrar * This, - /* [in] */ LPCOLESTR resFileName, - /* [in] */ UINT nID, - /* [in] */ LPCOLESTR szType); - - END_INTERFACE - } IRegistrarVtbl; - - interface IRegistrar - { - CONST_VTBL struct IRegistrarVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IRegistrar_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IRegistrar_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IRegistrar_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IRegistrar_AddReplacement(This,key,item) \ - (This)->lpVtbl -> AddReplacement(This,key,item) - -#define IRegistrar_ClearReplacements(This) \ - (This)->lpVtbl -> ClearReplacements(This) - - -#define IRegistrar_ResourceRegisterSz(This,resFileName,szID,szType) \ - (This)->lpVtbl -> ResourceRegisterSz(This,resFileName,szID,szType) - -#define IRegistrar_ResourceUnregisterSz(This,resFileName,szID,szType) \ - (This)->lpVtbl -> ResourceUnregisterSz(This,resFileName,szID,szType) - -#define IRegistrar_FileRegister(This,fileName) \ - (This)->lpVtbl -> FileRegister(This,fileName) - -#define IRegistrar_FileUnregister(This,fileName) \ - (This)->lpVtbl -> FileUnregister(This,fileName) - -#define IRegistrar_StringRegister(This,data) \ - (This)->lpVtbl -> StringRegister(This,data) - -#define IRegistrar_StringUnregister(This,data) \ - (This)->lpVtbl -> StringUnregister(This,data) - -#define IRegistrar_ResourceRegister(This,resFileName,nID,szType) \ - (This)->lpVtbl -> ResourceRegister(This,resFileName,nID,szType) - -#define IRegistrar_ResourceUnregister(This,resFileName,nID,szType) \ - (This)->lpVtbl -> ResourceUnregister(This,resFileName,nID,szType) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -HRESULT STDMETHODCALLTYPE IRegistrar_ResourceRegisterSz_Proxy( - IRegistrar * This, - /* [in] */ LPCOLESTR resFileName, - /* [in] */ LPCOLESTR szID, - /* [in] */ LPCOLESTR szType); - - -void __RPC_STUB IRegistrar_ResourceRegisterSz_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IRegistrar_ResourceUnregisterSz_Proxy( - IRegistrar * This, - /* [in] */ LPCOLESTR resFileName, - /* [in] */ LPCOLESTR szID, - /* [in] */ LPCOLESTR szType); - - -void __RPC_STUB IRegistrar_ResourceUnregisterSz_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IRegistrar_FileRegister_Proxy( - IRegistrar * This, - /* [in] */ LPCOLESTR fileName); - - -void __RPC_STUB IRegistrar_FileRegister_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IRegistrar_FileUnregister_Proxy( - IRegistrar * This, - /* [in] */ LPCOLESTR fileName); - - -void __RPC_STUB IRegistrar_FileUnregister_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IRegistrar_StringRegister_Proxy( - IRegistrar * This, - /* [in] */ LPCOLESTR data); - - -void __RPC_STUB IRegistrar_StringRegister_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IRegistrar_StringUnregister_Proxy( - IRegistrar * This, - /* [in] */ LPCOLESTR data); - - -void __RPC_STUB IRegistrar_StringUnregister_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IRegistrar_ResourceRegister_Proxy( - IRegistrar * This, - /* [in] */ LPCOLESTR resFileName, - /* [in] */ UINT nID, - /* [in] */ LPCOLESTR szType); - - -void __RPC_STUB IRegistrar_ResourceRegister_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IRegistrar_ResourceUnregister_Proxy( - IRegistrar * This, - /* [in] */ LPCOLESTR resFileName, - /* [in] */ UINT nID, - /* [in] */ LPCOLESTR szType); - - -void __RPC_STUB IRegistrar_ResourceUnregister_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IRegistrar_INTERFACE_DEFINED__ */ - - -#ifndef __IDocHostUIHandlerDispatch_INTERFACE_DEFINED__ -#define __IDocHostUIHandlerDispatch_INTERFACE_DEFINED__ - -/* interface IDocHostUIHandlerDispatch */ -/* [object][unique][helpstring][uuid][local] */ - -typedef -enum tagDOCHOSTUIDBLCLKDispatch - { docHostUIDblClkDEFAULT = 0, - docHostUIDblClkSHOWPROPERTIES = 1, - docHostUIDblClkSHOWCODE = 2 - } DOCHOSTUIDBLCLKDispatch; - -typedef -enum tagDocHostUIFlagDispatch - { docHostUIFlagDIALOG = 1, - docHostUIFlagDISABLE_HELP_MENU = 2, - docHostUIFlagNO3DBORDER = 4, - docHostUIFlagSCROLL_NO = 8, - docHostUIFlagDISABLE_SCRIPT_INACTIVE = 16, - docHostUIFlagOPENNEWWIN = 32, - docHostUIFlagDISABLE_OFFSCREEN = 64, - docHostUIFlagFLAT_SCROLLBAR = 128, - docHostUIFlagDIV_BLOCKDEFAULT = 256, - docHostUIFlagACTIVATE_CLIENTHIT_ONLY = 512 - } DocHostUIFlagDispatch; - - -EXTERN_C const IID IID_IDocHostUIHandlerDispatch; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("425B5AF0-65F1-11d1-9611-0000F81E0D0D") - IDocHostUIHandlerDispatch : public IDispatch - { - public: - virtual HRESULT STDMETHODCALLTYPE ShowContextMenu( - /* [in] */ DWORD dwID, - /* [in] */ DWORD x, - /* [in] */ DWORD y, - /* [in] */ IUnknown *pcmdtReserved, - /* [in] */ IDispatch *pdispReserved, - /* [retval][out] */ HRESULT *dwRetVal) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetHostInfo( - /* [out][in] */ DWORD *pdwFlags, - /* [out][in] */ DWORD *pdwDoubleClick) = 0; - - virtual HRESULT STDMETHODCALLTYPE ShowUI( - /* [in] */ DWORD dwID, - /* [in] */ IUnknown *pActiveObject, - /* [in] */ IUnknown *pCommandTarget, - /* [in] */ IUnknown *pFrame, - /* [in] */ IUnknown *pDoc, - /* [retval][out] */ HRESULT *dwRetVal) = 0; - - virtual HRESULT STDMETHODCALLTYPE HideUI( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE UpdateUI( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnableModeless( - /* [in] */ VARIANT_BOOL fEnable) = 0; - - virtual HRESULT STDMETHODCALLTYPE OnDocWindowActivate( - /* [in] */ VARIANT_BOOL fActivate) = 0; - - virtual HRESULT STDMETHODCALLTYPE OnFrameWindowActivate( - /* [in] */ VARIANT_BOOL fActivate) = 0; - - virtual HRESULT STDMETHODCALLTYPE ResizeBorder( - /* [in] */ long left, - /* [in] */ long top, - /* [in] */ long right, - /* [in] */ long bottom, - /* [in] */ IUnknown *pUIWindow, - /* [in] */ VARIANT_BOOL fFrameWindow) = 0; - - virtual HRESULT STDMETHODCALLTYPE TranslateAccelerator( - /* [in] */ DWORD_PTR hWnd, - /* [in] */ DWORD nMessage, - /* [in] */ DWORD_PTR wParam, - /* [in] */ DWORD_PTR lParam, - /* [in] */ BSTR bstrGuidCmdGroup, - /* [in] */ DWORD nCmdID, - /* [retval][out] */ HRESULT *dwRetVal) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetOptionKeyPath( - /* [out] */ BSTR *pbstrKey, - /* [in] */ DWORD dw) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetDropTarget( - /* [in] */ IUnknown *pDropTarget, - /* [out] */ IUnknown **ppDropTarget) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetExternal( - /* [out] */ IDispatch **ppDispatch) = 0; - - virtual HRESULT STDMETHODCALLTYPE TranslateUrl( - /* [in] */ DWORD dwTranslate, - /* [in] */ BSTR bstrURLIn, - /* [out] */ BSTR *pbstrURLOut) = 0; - - virtual HRESULT STDMETHODCALLTYPE FilterDataObject( - /* [in] */ IUnknown *pDO, - /* [out] */ IUnknown **ppDORet) = 0; - - }; - -#else /* C style interface */ - - typedef struct IDocHostUIHandlerDispatchVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IDocHostUIHandlerDispatch * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IDocHostUIHandlerDispatch * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IDocHostUIHandlerDispatch * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IDocHostUIHandlerDispatch * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IDocHostUIHandlerDispatch * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IDocHostUIHandlerDispatch * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IDocHostUIHandlerDispatch * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - HRESULT ( STDMETHODCALLTYPE *ShowContextMenu )( - IDocHostUIHandlerDispatch * This, - /* [in] */ DWORD dwID, - /* [in] */ DWORD x, - /* [in] */ DWORD y, - /* [in] */ IUnknown *pcmdtReserved, - /* [in] */ IDispatch *pdispReserved, - /* [retval][out] */ HRESULT *dwRetVal); - - HRESULT ( STDMETHODCALLTYPE *GetHostInfo )( - IDocHostUIHandlerDispatch * This, - /* [out][in] */ DWORD *pdwFlags, - /* [out][in] */ DWORD *pdwDoubleClick); - - HRESULT ( STDMETHODCALLTYPE *ShowUI )( - IDocHostUIHandlerDispatch * This, - /* [in] */ DWORD dwID, - /* [in] */ IUnknown *pActiveObject, - /* [in] */ IUnknown *pCommandTarget, - /* [in] */ IUnknown *pFrame, - /* [in] */ IUnknown *pDoc, - /* [retval][out] */ HRESULT *dwRetVal); - - HRESULT ( STDMETHODCALLTYPE *HideUI )( - IDocHostUIHandlerDispatch * This); - - HRESULT ( STDMETHODCALLTYPE *UpdateUI )( - IDocHostUIHandlerDispatch * This); - - HRESULT ( STDMETHODCALLTYPE *EnableModeless )( - IDocHostUIHandlerDispatch * This, - /* [in] */ VARIANT_BOOL fEnable); - - HRESULT ( STDMETHODCALLTYPE *OnDocWindowActivate )( - IDocHostUIHandlerDispatch * This, - /* [in] */ VARIANT_BOOL fActivate); - - HRESULT ( STDMETHODCALLTYPE *OnFrameWindowActivate )( - IDocHostUIHandlerDispatch * This, - /* [in] */ VARIANT_BOOL fActivate); - - HRESULT ( STDMETHODCALLTYPE *ResizeBorder )( - IDocHostUIHandlerDispatch * This, - /* [in] */ long left, - /* [in] */ long top, - /* [in] */ long right, - /* [in] */ long bottom, - /* [in] */ IUnknown *pUIWindow, - /* [in] */ VARIANT_BOOL fFrameWindow); - - HRESULT ( STDMETHODCALLTYPE *TranslateAccelerator )( - IDocHostUIHandlerDispatch * This, - /* [in] */ DWORD_PTR hWnd, - /* [in] */ DWORD nMessage, - /* [in] */ DWORD_PTR wParam, - /* [in] */ DWORD_PTR lParam, - /* [in] */ BSTR bstrGuidCmdGroup, - /* [in] */ DWORD nCmdID, - /* [retval][out] */ HRESULT *dwRetVal); - - HRESULT ( STDMETHODCALLTYPE *GetOptionKeyPath )( - IDocHostUIHandlerDispatch * This, - /* [out] */ BSTR *pbstrKey, - /* [in] */ DWORD dw); - - HRESULT ( STDMETHODCALLTYPE *GetDropTarget )( - IDocHostUIHandlerDispatch * This, - /* [in] */ IUnknown *pDropTarget, - /* [out] */ IUnknown **ppDropTarget); - - HRESULT ( STDMETHODCALLTYPE *GetExternal )( - IDocHostUIHandlerDispatch * This, - /* [out] */ IDispatch **ppDispatch); - - HRESULT ( STDMETHODCALLTYPE *TranslateUrl )( - IDocHostUIHandlerDispatch * This, - /* [in] */ DWORD dwTranslate, - /* [in] */ BSTR bstrURLIn, - /* [out] */ BSTR *pbstrURLOut); - - HRESULT ( STDMETHODCALLTYPE *FilterDataObject )( - IDocHostUIHandlerDispatch * This, - /* [in] */ IUnknown *pDO, - /* [out] */ IUnknown **ppDORet); - - END_INTERFACE - } IDocHostUIHandlerDispatchVtbl; - - interface IDocHostUIHandlerDispatch - { - CONST_VTBL struct IDocHostUIHandlerDispatchVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IDocHostUIHandlerDispatch_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IDocHostUIHandlerDispatch_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IDocHostUIHandlerDispatch_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IDocHostUIHandlerDispatch_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IDocHostUIHandlerDispatch_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IDocHostUIHandlerDispatch_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IDocHostUIHandlerDispatch_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IDocHostUIHandlerDispatch_ShowContextMenu(This,dwID,x,y,pcmdtReserved,pdispReserved,dwRetVal) \ - (This)->lpVtbl -> ShowContextMenu(This,dwID,x,y,pcmdtReserved,pdispReserved,dwRetVal) - -#define IDocHostUIHandlerDispatch_GetHostInfo(This,pdwFlags,pdwDoubleClick) \ - (This)->lpVtbl -> GetHostInfo(This,pdwFlags,pdwDoubleClick) - -#define IDocHostUIHandlerDispatch_ShowUI(This,dwID,pActiveObject,pCommandTarget,pFrame,pDoc,dwRetVal) \ - (This)->lpVtbl -> ShowUI(This,dwID,pActiveObject,pCommandTarget,pFrame,pDoc,dwRetVal) - -#define IDocHostUIHandlerDispatch_HideUI(This) \ - (This)->lpVtbl -> HideUI(This) - -#define IDocHostUIHandlerDispatch_UpdateUI(This) \ - (This)->lpVtbl -> UpdateUI(This) - -#define IDocHostUIHandlerDispatch_EnableModeless(This,fEnable) \ - (This)->lpVtbl -> EnableModeless(This,fEnable) - -#define IDocHostUIHandlerDispatch_OnDocWindowActivate(This,fActivate) \ - (This)->lpVtbl -> OnDocWindowActivate(This,fActivate) - -#define IDocHostUIHandlerDispatch_OnFrameWindowActivate(This,fActivate) \ - (This)->lpVtbl -> OnFrameWindowActivate(This,fActivate) - -#define IDocHostUIHandlerDispatch_ResizeBorder(This,left,top,right,bottom,pUIWindow,fFrameWindow) \ - (This)->lpVtbl -> ResizeBorder(This,left,top,right,bottom,pUIWindow,fFrameWindow) - -#define IDocHostUIHandlerDispatch_TranslateAccelerator(This,hWnd,nMessage,wParam,lParam,bstrGuidCmdGroup,nCmdID,dwRetVal) \ - (This)->lpVtbl -> TranslateAccelerator(This,hWnd,nMessage,wParam,lParam,bstrGuidCmdGroup,nCmdID,dwRetVal) - -#define IDocHostUIHandlerDispatch_GetOptionKeyPath(This,pbstrKey,dw) \ - (This)->lpVtbl -> GetOptionKeyPath(This,pbstrKey,dw) - -#define IDocHostUIHandlerDispatch_GetDropTarget(This,pDropTarget,ppDropTarget) \ - (This)->lpVtbl -> GetDropTarget(This,pDropTarget,ppDropTarget) - -#define IDocHostUIHandlerDispatch_GetExternal(This,ppDispatch) \ - (This)->lpVtbl -> GetExternal(This,ppDispatch) - -#define IDocHostUIHandlerDispatch_TranslateUrl(This,dwTranslate,bstrURLIn,pbstrURLOut) \ - (This)->lpVtbl -> TranslateUrl(This,dwTranslate,bstrURLIn,pbstrURLOut) - -#define IDocHostUIHandlerDispatch_FilterDataObject(This,pDO,ppDORet) \ - (This)->lpVtbl -> FilterDataObject(This,pDO,ppDORet) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_ShowContextMenu_Proxy( - IDocHostUIHandlerDispatch * This, - /* [in] */ DWORD dwID, - /* [in] */ DWORD x, - /* [in] */ DWORD y, - /* [in] */ IUnknown *pcmdtReserved, - /* [in] */ IDispatch *pdispReserved, - /* [retval][out] */ HRESULT *dwRetVal); - - -void __RPC_STUB IDocHostUIHandlerDispatch_ShowContextMenu_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_GetHostInfo_Proxy( - IDocHostUIHandlerDispatch * This, - /* [out][in] */ DWORD *pdwFlags, - /* [out][in] */ DWORD *pdwDoubleClick); - - -void __RPC_STUB IDocHostUIHandlerDispatch_GetHostInfo_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_ShowUI_Proxy( - IDocHostUIHandlerDispatch * This, - /* [in] */ DWORD dwID, - /* [in] */ IUnknown *pActiveObject, - /* [in] */ IUnknown *pCommandTarget, - /* [in] */ IUnknown *pFrame, - /* [in] */ IUnknown *pDoc, - /* [retval][out] */ HRESULT *dwRetVal); - - -void __RPC_STUB IDocHostUIHandlerDispatch_ShowUI_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_HideUI_Proxy( - IDocHostUIHandlerDispatch * This); - - -void __RPC_STUB IDocHostUIHandlerDispatch_HideUI_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_UpdateUI_Proxy( - IDocHostUIHandlerDispatch * This); - - -void __RPC_STUB IDocHostUIHandlerDispatch_UpdateUI_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_EnableModeless_Proxy( - IDocHostUIHandlerDispatch * This, - /* [in] */ VARIANT_BOOL fEnable); - - -void __RPC_STUB IDocHostUIHandlerDispatch_EnableModeless_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_OnDocWindowActivate_Proxy( - IDocHostUIHandlerDispatch * This, - /* [in] */ VARIANT_BOOL fActivate); - - -void __RPC_STUB IDocHostUIHandlerDispatch_OnDocWindowActivate_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_OnFrameWindowActivate_Proxy( - IDocHostUIHandlerDispatch * This, - /* [in] */ VARIANT_BOOL fActivate); - - -void __RPC_STUB IDocHostUIHandlerDispatch_OnFrameWindowActivate_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_ResizeBorder_Proxy( - IDocHostUIHandlerDispatch * This, - /* [in] */ long left, - /* [in] */ long top, - /* [in] */ long right, - /* [in] */ long bottom, - /* [in] */ IUnknown *pUIWindow, - /* [in] */ VARIANT_BOOL fFrameWindow); - - -void __RPC_STUB IDocHostUIHandlerDispatch_ResizeBorder_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_TranslateAccelerator_Proxy( - IDocHostUIHandlerDispatch * This, - /* [in] */ DWORD_PTR hWnd, - /* [in] */ DWORD nMessage, - /* [in] */ DWORD_PTR wParam, - /* [in] */ DWORD_PTR lParam, - /* [in] */ BSTR bstrGuidCmdGroup, - /* [in] */ DWORD nCmdID, - /* [retval][out] */ HRESULT *dwRetVal); - - -void __RPC_STUB IDocHostUIHandlerDispatch_TranslateAccelerator_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_GetOptionKeyPath_Proxy( - IDocHostUIHandlerDispatch * This, - /* [out] */ BSTR *pbstrKey, - /* [in] */ DWORD dw); - - -void __RPC_STUB IDocHostUIHandlerDispatch_GetOptionKeyPath_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_GetDropTarget_Proxy( - IDocHostUIHandlerDispatch * This, - /* [in] */ IUnknown *pDropTarget, - /* [out] */ IUnknown **ppDropTarget); - - -void __RPC_STUB IDocHostUIHandlerDispatch_GetDropTarget_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_GetExternal_Proxy( - IDocHostUIHandlerDispatch * This, - /* [out] */ IDispatch **ppDispatch); - - -void __RPC_STUB IDocHostUIHandlerDispatch_GetExternal_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_TranslateUrl_Proxy( - IDocHostUIHandlerDispatch * This, - /* [in] */ DWORD dwTranslate, - /* [in] */ BSTR bstrURLIn, - /* [out] */ BSTR *pbstrURLOut); - - -void __RPC_STUB IDocHostUIHandlerDispatch_TranslateUrl_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_FilterDataObject_Proxy( - IDocHostUIHandlerDispatch * This, - /* [in] */ IUnknown *pDO, - /* [out] */ IUnknown **ppDORet); - - -void __RPC_STUB IDocHostUIHandlerDispatch_FilterDataObject_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IDocHostUIHandlerDispatch_INTERFACE_DEFINED__ */ - - -#ifndef __IAxWinHostWindow_INTERFACE_DEFINED__ -#define __IAxWinHostWindow_INTERFACE_DEFINED__ - -/* interface IAxWinHostWindow */ -/* [object][unique][helpstring][uuid] */ - - -EXTERN_C const IID IID_IAxWinHostWindow; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("B6EA2050-048A-11d1-82B9-00C04FB9942E") - IAxWinHostWindow : public IUnknown - { - public: - virtual HRESULT STDMETHODCALLTYPE CreateControl( - /* [in] */ LPCOLESTR lpTricsData, - /* [in] */ HWND hWnd, - /* [in] */ IStream *pStream) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateControlEx( - /* [in] */ LPCOLESTR lpTricsData, - /* [in] */ HWND hWnd, - /* [in] */ IStream *pStream, - /* [out] */ IUnknown **ppUnk, - /* [in] */ REFIID riidAdvise, - /* [in] */ IUnknown *punkAdvise) = 0; - - virtual HRESULT STDMETHODCALLTYPE AttachControl( - /* [in] */ IUnknown *pUnkControl, - /* [in] */ HWND hWnd) = 0; - - virtual HRESULT STDMETHODCALLTYPE QueryControl( - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetExternalDispatch( - /* [in] */ IDispatch *pDisp) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetExternalUIHandler( - /* [in] */ IDocHostUIHandlerDispatch *pDisp) = 0; - - }; - -#else /* C style interface */ - - typedef struct IAxWinHostWindowVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IAxWinHostWindow * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IAxWinHostWindow * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IAxWinHostWindow * This); - - HRESULT ( STDMETHODCALLTYPE *CreateControl )( - IAxWinHostWindow * This, - /* [in] */ LPCOLESTR lpTricsData, - /* [in] */ HWND hWnd, - /* [in] */ IStream *pStream); - - HRESULT ( STDMETHODCALLTYPE *CreateControlEx )( - IAxWinHostWindow * This, - /* [in] */ LPCOLESTR lpTricsData, - /* [in] */ HWND hWnd, - /* [in] */ IStream *pStream, - /* [out] */ IUnknown **ppUnk, - /* [in] */ REFIID riidAdvise, - /* [in] */ IUnknown *punkAdvise); - - HRESULT ( STDMETHODCALLTYPE *AttachControl )( - IAxWinHostWindow * This, - /* [in] */ IUnknown *pUnkControl, - /* [in] */ HWND hWnd); - - HRESULT ( STDMETHODCALLTYPE *QueryControl )( - IAxWinHostWindow * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - HRESULT ( STDMETHODCALLTYPE *SetExternalDispatch )( - IAxWinHostWindow * This, - /* [in] */ IDispatch *pDisp); - - HRESULT ( STDMETHODCALLTYPE *SetExternalUIHandler )( - IAxWinHostWindow * This, - /* [in] */ IDocHostUIHandlerDispatch *pDisp); - - END_INTERFACE - } IAxWinHostWindowVtbl; - - interface IAxWinHostWindow - { - CONST_VTBL struct IAxWinHostWindowVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IAxWinHostWindow_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IAxWinHostWindow_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IAxWinHostWindow_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IAxWinHostWindow_CreateControl(This,lpTricsData,hWnd,pStream) \ - (This)->lpVtbl -> CreateControl(This,lpTricsData,hWnd,pStream) - -#define IAxWinHostWindow_CreateControlEx(This,lpTricsData,hWnd,pStream,ppUnk,riidAdvise,punkAdvise) \ - (This)->lpVtbl -> CreateControlEx(This,lpTricsData,hWnd,pStream,ppUnk,riidAdvise,punkAdvise) - -#define IAxWinHostWindow_AttachControl(This,pUnkControl,hWnd) \ - (This)->lpVtbl -> AttachControl(This,pUnkControl,hWnd) - -#define IAxWinHostWindow_QueryControl(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryControl(This,riid,ppvObject) - -#define IAxWinHostWindow_SetExternalDispatch(This,pDisp) \ - (This)->lpVtbl -> SetExternalDispatch(This,pDisp) - -#define IAxWinHostWindow_SetExternalUIHandler(This,pDisp) \ - (This)->lpVtbl -> SetExternalUIHandler(This,pDisp) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -HRESULT STDMETHODCALLTYPE IAxWinHostWindow_CreateControl_Proxy( - IAxWinHostWindow * This, - /* [in] */ LPCOLESTR lpTricsData, - /* [in] */ HWND hWnd, - /* [in] */ IStream *pStream); - - -void __RPC_STUB IAxWinHostWindow_CreateControl_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IAxWinHostWindow_CreateControlEx_Proxy( - IAxWinHostWindow * This, - /* [in] */ LPCOLESTR lpTricsData, - /* [in] */ HWND hWnd, - /* [in] */ IStream *pStream, - /* [out] */ IUnknown **ppUnk, - /* [in] */ REFIID riidAdvise, - /* [in] */ IUnknown *punkAdvise); - - -void __RPC_STUB IAxWinHostWindow_CreateControlEx_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IAxWinHostWindow_AttachControl_Proxy( - IAxWinHostWindow * This, - /* [in] */ IUnknown *pUnkControl, - /* [in] */ HWND hWnd); - - -void __RPC_STUB IAxWinHostWindow_AttachControl_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IAxWinHostWindow_QueryControl_Proxy( - IAxWinHostWindow * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - -void __RPC_STUB IAxWinHostWindow_QueryControl_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IAxWinHostWindow_SetExternalDispatch_Proxy( - IAxWinHostWindow * This, - /* [in] */ IDispatch *pDisp); - - -void __RPC_STUB IAxWinHostWindow_SetExternalDispatch_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IAxWinHostWindow_SetExternalUIHandler_Proxy( - IAxWinHostWindow * This, - /* [in] */ IDocHostUIHandlerDispatch *pDisp); - - -void __RPC_STUB IAxWinHostWindow_SetExternalUIHandler_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IAxWinHostWindow_INTERFACE_DEFINED__ */ - - -#ifndef __IAxWinHostWindowLic_INTERFACE_DEFINED__ -#define __IAxWinHostWindowLic_INTERFACE_DEFINED__ - -/* interface IAxWinHostWindowLic */ -/* [object][unique][helpstring][uuid] */ - - -EXTERN_C const IID IID_IAxWinHostWindowLic; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("3935BDA8-4ED9-495c-8650-E01FC1E38A4B") - IAxWinHostWindowLic : public IAxWinHostWindow - { - public: - virtual HRESULT STDMETHODCALLTYPE CreateControlLic( - /* [in] */ LPCOLESTR lpTricsData, - /* [in] */ HWND hWnd, - /* [in] */ IStream *pStream, - /* [in] */ BSTR bstrLic) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateControlLicEx( - /* [in] */ LPCOLESTR lpTricsData, - /* [in] */ HWND hWnd, - /* [in] */ IStream *pStream, - /* [out] */ IUnknown **ppUnk, - /* [in] */ REFIID riidAdvise, - /* [in] */ IUnknown *punkAdvise, - /* [in] */ BSTR bstrLic) = 0; - - }; - -#else /* C style interface */ - - typedef struct IAxWinHostWindowLicVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IAxWinHostWindowLic * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IAxWinHostWindowLic * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IAxWinHostWindowLic * This); - - HRESULT ( STDMETHODCALLTYPE *CreateControl )( - IAxWinHostWindowLic * This, - /* [in] */ LPCOLESTR lpTricsData, - /* [in] */ HWND hWnd, - /* [in] */ IStream *pStream); - - HRESULT ( STDMETHODCALLTYPE *CreateControlEx )( - IAxWinHostWindowLic * This, - /* [in] */ LPCOLESTR lpTricsData, - /* [in] */ HWND hWnd, - /* [in] */ IStream *pStream, - /* [out] */ IUnknown **ppUnk, - /* [in] */ REFIID riidAdvise, - /* [in] */ IUnknown *punkAdvise); - - HRESULT ( STDMETHODCALLTYPE *AttachControl )( - IAxWinHostWindowLic * This, - /* [in] */ IUnknown *pUnkControl, - /* [in] */ HWND hWnd); - - HRESULT ( STDMETHODCALLTYPE *QueryControl )( - IAxWinHostWindowLic * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - HRESULT ( STDMETHODCALLTYPE *SetExternalDispatch )( - IAxWinHostWindowLic * This, - /* [in] */ IDispatch *pDisp); - - HRESULT ( STDMETHODCALLTYPE *SetExternalUIHandler )( - IAxWinHostWindowLic * This, - /* [in] */ IDocHostUIHandlerDispatch *pDisp); - - HRESULT ( STDMETHODCALLTYPE *CreateControlLic )( - IAxWinHostWindowLic * This, - /* [in] */ LPCOLESTR lpTricsData, - /* [in] */ HWND hWnd, - /* [in] */ IStream *pStream, - /* [in] */ BSTR bstrLic); - - HRESULT ( STDMETHODCALLTYPE *CreateControlLicEx )( - IAxWinHostWindowLic * This, - /* [in] */ LPCOLESTR lpTricsData, - /* [in] */ HWND hWnd, - /* [in] */ IStream *pStream, - /* [out] */ IUnknown **ppUnk, - /* [in] */ REFIID riidAdvise, - /* [in] */ IUnknown *punkAdvise, - /* [in] */ BSTR bstrLic); - - END_INTERFACE - } IAxWinHostWindowLicVtbl; - - interface IAxWinHostWindowLic - { - CONST_VTBL struct IAxWinHostWindowLicVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IAxWinHostWindowLic_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IAxWinHostWindowLic_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IAxWinHostWindowLic_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IAxWinHostWindowLic_CreateControl(This,lpTricsData,hWnd,pStream) \ - (This)->lpVtbl -> CreateControl(This,lpTricsData,hWnd,pStream) - -#define IAxWinHostWindowLic_CreateControlEx(This,lpTricsData,hWnd,pStream,ppUnk,riidAdvise,punkAdvise) \ - (This)->lpVtbl -> CreateControlEx(This,lpTricsData,hWnd,pStream,ppUnk,riidAdvise,punkAdvise) - -#define IAxWinHostWindowLic_AttachControl(This,pUnkControl,hWnd) \ - (This)->lpVtbl -> AttachControl(This,pUnkControl,hWnd) - -#define IAxWinHostWindowLic_QueryControl(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryControl(This,riid,ppvObject) - -#define IAxWinHostWindowLic_SetExternalDispatch(This,pDisp) \ - (This)->lpVtbl -> SetExternalDispatch(This,pDisp) - -#define IAxWinHostWindowLic_SetExternalUIHandler(This,pDisp) \ - (This)->lpVtbl -> SetExternalUIHandler(This,pDisp) - - -#define IAxWinHostWindowLic_CreateControlLic(This,lpTricsData,hWnd,pStream,bstrLic) \ - (This)->lpVtbl -> CreateControlLic(This,lpTricsData,hWnd,pStream,bstrLic) - -#define IAxWinHostWindowLic_CreateControlLicEx(This,lpTricsData,hWnd,pStream,ppUnk,riidAdvise,punkAdvise,bstrLic) \ - (This)->lpVtbl -> CreateControlLicEx(This,lpTricsData,hWnd,pStream,ppUnk,riidAdvise,punkAdvise,bstrLic) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -HRESULT STDMETHODCALLTYPE IAxWinHostWindowLic_CreateControlLic_Proxy( - IAxWinHostWindowLic * This, - /* [in] */ LPCOLESTR lpTricsData, - /* [in] */ HWND hWnd, - /* [in] */ IStream *pStream, - /* [in] */ BSTR bstrLic); - - -void __RPC_STUB IAxWinHostWindowLic_CreateControlLic_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IAxWinHostWindowLic_CreateControlLicEx_Proxy( - IAxWinHostWindowLic * This, - /* [in] */ LPCOLESTR lpTricsData, - /* [in] */ HWND hWnd, - /* [in] */ IStream *pStream, - /* [out] */ IUnknown **ppUnk, - /* [in] */ REFIID riidAdvise, - /* [in] */ IUnknown *punkAdvise, - /* [in] */ BSTR bstrLic); - - -void __RPC_STUB IAxWinHostWindowLic_CreateControlLicEx_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IAxWinHostWindowLic_INTERFACE_DEFINED__ */ - - -#ifndef __IAxWinAmbientDispatch_INTERFACE_DEFINED__ -#define __IAxWinAmbientDispatch_INTERFACE_DEFINED__ - -/* interface IAxWinAmbientDispatch */ -/* [unique][helpstring][uuid][dual][object] */ - - -EXTERN_C const IID IID_IAxWinAmbientDispatch; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("B6EA2051-048A-11d1-82B9-00C04FB9942E") - IAxWinAmbientDispatch : public IDispatch - { - public: - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AllowWindowlessActivation( - /* [in] */ VARIANT_BOOL bCanWindowlessActivate) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AllowWindowlessActivation( - /* [retval][out] */ VARIANT_BOOL *pbCanWindowlessActivate) = 0; - - virtual /* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_BackColor( - /* [in] */ OLE_COLOR clrBackground) = 0; - - virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_BackColor( - /* [retval][out] */ OLE_COLOR *pclrBackground) = 0; - - virtual /* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_ForeColor( - /* [in] */ OLE_COLOR clrForeground) = 0; - - virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ForeColor( - /* [retval][out] */ OLE_COLOR *pclrForeground) = 0; - - virtual /* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_LocaleID( - /* [in] */ LCID lcidLocaleID) = 0; - - virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LocaleID( - /* [retval][out] */ LCID *plcidLocaleID) = 0; - - virtual /* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_UserMode( - /* [in] */ VARIANT_BOOL bUserMode) = 0; - - virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_UserMode( - /* [retval][out] */ VARIANT_BOOL *pbUserMode) = 0; - - virtual /* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_DisplayAsDefault( - /* [in] */ VARIANT_BOOL bDisplayAsDefault) = 0; - - virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DisplayAsDefault( - /* [retval][out] */ VARIANT_BOOL *pbDisplayAsDefault) = 0; - - virtual /* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Font( - /* [in] */ IFontDisp *pFont) = 0; - - virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Font( - /* [retval][out] */ IFontDisp **pFont) = 0; - - virtual /* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_MessageReflect( - /* [in] */ VARIANT_BOOL bMsgReflect) = 0; - - virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_MessageReflect( - /* [retval][out] */ VARIANT_BOOL *pbMsgReflect) = 0; - - virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ShowGrabHandles( - /* [retval][out] */ VARIANT_BOOL *pbShowGrabHandles) = 0; - - virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ShowHatching( - /* [retval][out] */ VARIANT_BOOL *pbShowHatching) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_DocHostFlags( - /* [in] */ DWORD dwDocHostFlags) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DocHostFlags( - /* [retval][out] */ DWORD *pdwDocHostFlags) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_DocHostDoubleClickFlags( - /* [in] */ DWORD dwDocHostDoubleClickFlags) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DocHostDoubleClickFlags( - /* [retval][out] */ DWORD *pdwDocHostDoubleClickFlags) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AllowContextMenu( - /* [in] */ VARIANT_BOOL bAllowContextMenu) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AllowContextMenu( - /* [retval][out] */ VARIANT_BOOL *pbAllowContextMenu) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AllowShowUI( - /* [in] */ VARIANT_BOOL bAllowShowUI) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AllowShowUI( - /* [retval][out] */ VARIANT_BOOL *pbAllowShowUI) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_OptionKeyPath( - /* [in] */ BSTR bstrOptionKeyPath) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_OptionKeyPath( - /* [retval][out] */ BSTR *pbstrOptionKeyPath) = 0; - - }; - -#else /* C style interface */ - - typedef struct IAxWinAmbientDispatchVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IAxWinAmbientDispatch * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IAxWinAmbientDispatch * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IAxWinAmbientDispatch * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IAxWinAmbientDispatch * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IAxWinAmbientDispatch * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IAxWinAmbientDispatch * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IAxWinAmbientDispatch * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AllowWindowlessActivation )( - IAxWinAmbientDispatch * This, - /* [in] */ VARIANT_BOOL bCanWindowlessActivate); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AllowWindowlessActivation )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbCanWindowlessActivate); - - /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_BackColor )( - IAxWinAmbientDispatch * This, - /* [in] */ OLE_COLOR clrBackground); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BackColor )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ OLE_COLOR *pclrBackground); - - /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_ForeColor )( - IAxWinAmbientDispatch * This, - /* [in] */ OLE_COLOR clrForeground); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ForeColor )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ OLE_COLOR *pclrForeground); - - /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_LocaleID )( - IAxWinAmbientDispatch * This, - /* [in] */ LCID lcidLocaleID); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LocaleID )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ LCID *plcidLocaleID); - - /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_UserMode )( - IAxWinAmbientDispatch * This, - /* [in] */ VARIANT_BOOL bUserMode); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_UserMode )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbUserMode); - - /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DisplayAsDefault )( - IAxWinAmbientDispatch * This, - /* [in] */ VARIANT_BOOL bDisplayAsDefault); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DisplayAsDefault )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbDisplayAsDefault); - - /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Font )( - IAxWinAmbientDispatch * This, - /* [in] */ IFontDisp *pFont); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Font )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ IFontDisp **pFont); - - /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_MessageReflect )( - IAxWinAmbientDispatch * This, - /* [in] */ VARIANT_BOOL bMsgReflect); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_MessageReflect )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbMsgReflect); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ShowGrabHandles )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbShowGrabHandles); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ShowHatching )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbShowHatching); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DocHostFlags )( - IAxWinAmbientDispatch * This, - /* [in] */ DWORD dwDocHostFlags); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DocHostFlags )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ DWORD *pdwDocHostFlags); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DocHostDoubleClickFlags )( - IAxWinAmbientDispatch * This, - /* [in] */ DWORD dwDocHostDoubleClickFlags); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DocHostDoubleClickFlags )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ DWORD *pdwDocHostDoubleClickFlags); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AllowContextMenu )( - IAxWinAmbientDispatch * This, - /* [in] */ VARIANT_BOOL bAllowContextMenu); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AllowContextMenu )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbAllowContextMenu); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AllowShowUI )( - IAxWinAmbientDispatch * This, - /* [in] */ VARIANT_BOOL bAllowShowUI); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AllowShowUI )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbAllowShowUI); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_OptionKeyPath )( - IAxWinAmbientDispatch * This, - /* [in] */ BSTR bstrOptionKeyPath); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_OptionKeyPath )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ BSTR *pbstrOptionKeyPath); - - END_INTERFACE - } IAxWinAmbientDispatchVtbl; - - interface IAxWinAmbientDispatch - { - CONST_VTBL struct IAxWinAmbientDispatchVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IAxWinAmbientDispatch_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IAxWinAmbientDispatch_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IAxWinAmbientDispatch_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IAxWinAmbientDispatch_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IAxWinAmbientDispatch_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IAxWinAmbientDispatch_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IAxWinAmbientDispatch_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IAxWinAmbientDispatch_put_AllowWindowlessActivation(This,bCanWindowlessActivate) \ - (This)->lpVtbl -> put_AllowWindowlessActivation(This,bCanWindowlessActivate) - -#define IAxWinAmbientDispatch_get_AllowWindowlessActivation(This,pbCanWindowlessActivate) \ - (This)->lpVtbl -> get_AllowWindowlessActivation(This,pbCanWindowlessActivate) - -#define IAxWinAmbientDispatch_put_BackColor(This,clrBackground) \ - (This)->lpVtbl -> put_BackColor(This,clrBackground) - -#define IAxWinAmbientDispatch_get_BackColor(This,pclrBackground) \ - (This)->lpVtbl -> get_BackColor(This,pclrBackground) - -#define IAxWinAmbientDispatch_put_ForeColor(This,clrForeground) \ - (This)->lpVtbl -> put_ForeColor(This,clrForeground) - -#define IAxWinAmbientDispatch_get_ForeColor(This,pclrForeground) \ - (This)->lpVtbl -> get_ForeColor(This,pclrForeground) - -#define IAxWinAmbientDispatch_put_LocaleID(This,lcidLocaleID) \ - (This)->lpVtbl -> put_LocaleID(This,lcidLocaleID) - -#define IAxWinAmbientDispatch_get_LocaleID(This,plcidLocaleID) \ - (This)->lpVtbl -> get_LocaleID(This,plcidLocaleID) - -#define IAxWinAmbientDispatch_put_UserMode(This,bUserMode) \ - (This)->lpVtbl -> put_UserMode(This,bUserMode) - -#define IAxWinAmbientDispatch_get_UserMode(This,pbUserMode) \ - (This)->lpVtbl -> get_UserMode(This,pbUserMode) - -#define IAxWinAmbientDispatch_put_DisplayAsDefault(This,bDisplayAsDefault) \ - (This)->lpVtbl -> put_DisplayAsDefault(This,bDisplayAsDefault) - -#define IAxWinAmbientDispatch_get_DisplayAsDefault(This,pbDisplayAsDefault) \ - (This)->lpVtbl -> get_DisplayAsDefault(This,pbDisplayAsDefault) - -#define IAxWinAmbientDispatch_put_Font(This,pFont) \ - (This)->lpVtbl -> put_Font(This,pFont) - -#define IAxWinAmbientDispatch_get_Font(This,pFont) \ - (This)->lpVtbl -> get_Font(This,pFont) - -#define IAxWinAmbientDispatch_put_MessageReflect(This,bMsgReflect) \ - (This)->lpVtbl -> put_MessageReflect(This,bMsgReflect) - -#define IAxWinAmbientDispatch_get_MessageReflect(This,pbMsgReflect) \ - (This)->lpVtbl -> get_MessageReflect(This,pbMsgReflect) - -#define IAxWinAmbientDispatch_get_ShowGrabHandles(This,pbShowGrabHandles) \ - (This)->lpVtbl -> get_ShowGrabHandles(This,pbShowGrabHandles) - -#define IAxWinAmbientDispatch_get_ShowHatching(This,pbShowHatching) \ - (This)->lpVtbl -> get_ShowHatching(This,pbShowHatching) - -#define IAxWinAmbientDispatch_put_DocHostFlags(This,dwDocHostFlags) \ - (This)->lpVtbl -> put_DocHostFlags(This,dwDocHostFlags) - -#define IAxWinAmbientDispatch_get_DocHostFlags(This,pdwDocHostFlags) \ - (This)->lpVtbl -> get_DocHostFlags(This,pdwDocHostFlags) - -#define IAxWinAmbientDispatch_put_DocHostDoubleClickFlags(This,dwDocHostDoubleClickFlags) \ - (This)->lpVtbl -> put_DocHostDoubleClickFlags(This,dwDocHostDoubleClickFlags) - -#define IAxWinAmbientDispatch_get_DocHostDoubleClickFlags(This,pdwDocHostDoubleClickFlags) \ - (This)->lpVtbl -> get_DocHostDoubleClickFlags(This,pdwDocHostDoubleClickFlags) - -#define IAxWinAmbientDispatch_put_AllowContextMenu(This,bAllowContextMenu) \ - (This)->lpVtbl -> put_AllowContextMenu(This,bAllowContextMenu) - -#define IAxWinAmbientDispatch_get_AllowContextMenu(This,pbAllowContextMenu) \ - (This)->lpVtbl -> get_AllowContextMenu(This,pbAllowContextMenu) - -#define IAxWinAmbientDispatch_put_AllowShowUI(This,bAllowShowUI) \ - (This)->lpVtbl -> put_AllowShowUI(This,bAllowShowUI) - -#define IAxWinAmbientDispatch_get_AllowShowUI(This,pbAllowShowUI) \ - (This)->lpVtbl -> get_AllowShowUI(This,pbAllowShowUI) - -#define IAxWinAmbientDispatch_put_OptionKeyPath(This,bstrOptionKeyPath) \ - (This)->lpVtbl -> put_OptionKeyPath(This,bstrOptionKeyPath) - -#define IAxWinAmbientDispatch_get_OptionKeyPath(This,pbstrOptionKeyPath) \ - (This)->lpVtbl -> get_OptionKeyPath(This,pbstrOptionKeyPath) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_AllowWindowlessActivation_Proxy( - IAxWinAmbientDispatch * This, - /* [in] */ VARIANT_BOOL bCanWindowlessActivate); - - -void __RPC_STUB IAxWinAmbientDispatch_put_AllowWindowlessActivation_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_AllowWindowlessActivation_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbCanWindowlessActivate); - - -void __RPC_STUB IAxWinAmbientDispatch_get_AllowWindowlessActivation_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_BackColor_Proxy( - IAxWinAmbientDispatch * This, - /* [in] */ OLE_COLOR clrBackground); - - -void __RPC_STUB IAxWinAmbientDispatch_put_BackColor_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_BackColor_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ OLE_COLOR *pclrBackground); - - -void __RPC_STUB IAxWinAmbientDispatch_get_BackColor_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_ForeColor_Proxy( - IAxWinAmbientDispatch * This, - /* [in] */ OLE_COLOR clrForeground); - - -void __RPC_STUB IAxWinAmbientDispatch_put_ForeColor_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_ForeColor_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ OLE_COLOR *pclrForeground); - - -void __RPC_STUB IAxWinAmbientDispatch_get_ForeColor_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_LocaleID_Proxy( - IAxWinAmbientDispatch * This, - /* [in] */ LCID lcidLocaleID); - - -void __RPC_STUB IAxWinAmbientDispatch_put_LocaleID_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_LocaleID_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ LCID *plcidLocaleID); - - -void __RPC_STUB IAxWinAmbientDispatch_get_LocaleID_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_UserMode_Proxy( - IAxWinAmbientDispatch * This, - /* [in] */ VARIANT_BOOL bUserMode); - - -void __RPC_STUB IAxWinAmbientDispatch_put_UserMode_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_UserMode_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbUserMode); - - -void __RPC_STUB IAxWinAmbientDispatch_get_UserMode_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_DisplayAsDefault_Proxy( - IAxWinAmbientDispatch * This, - /* [in] */ VARIANT_BOOL bDisplayAsDefault); - - -void __RPC_STUB IAxWinAmbientDispatch_put_DisplayAsDefault_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_DisplayAsDefault_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbDisplayAsDefault); - - -void __RPC_STUB IAxWinAmbientDispatch_get_DisplayAsDefault_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_Font_Proxy( - IAxWinAmbientDispatch * This, - /* [in] */ IFontDisp *pFont); - - -void __RPC_STUB IAxWinAmbientDispatch_put_Font_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_Font_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ IFontDisp **pFont); - - -void __RPC_STUB IAxWinAmbientDispatch_get_Font_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_MessageReflect_Proxy( - IAxWinAmbientDispatch * This, - /* [in] */ VARIANT_BOOL bMsgReflect); - - -void __RPC_STUB IAxWinAmbientDispatch_put_MessageReflect_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_MessageReflect_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbMsgReflect); - - -void __RPC_STUB IAxWinAmbientDispatch_get_MessageReflect_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_ShowGrabHandles_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbShowGrabHandles); - - -void __RPC_STUB IAxWinAmbientDispatch_get_ShowGrabHandles_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_ShowHatching_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbShowHatching); - - -void __RPC_STUB IAxWinAmbientDispatch_get_ShowHatching_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_DocHostFlags_Proxy( - IAxWinAmbientDispatch * This, - /* [in] */ DWORD dwDocHostFlags); - - -void __RPC_STUB IAxWinAmbientDispatch_put_DocHostFlags_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_DocHostFlags_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ DWORD *pdwDocHostFlags); - - -void __RPC_STUB IAxWinAmbientDispatch_get_DocHostFlags_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_DocHostDoubleClickFlags_Proxy( - IAxWinAmbientDispatch * This, - /* [in] */ DWORD dwDocHostDoubleClickFlags); - - -void __RPC_STUB IAxWinAmbientDispatch_put_DocHostDoubleClickFlags_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_DocHostDoubleClickFlags_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ DWORD *pdwDocHostDoubleClickFlags); - - -void __RPC_STUB IAxWinAmbientDispatch_get_DocHostDoubleClickFlags_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_AllowContextMenu_Proxy( - IAxWinAmbientDispatch * This, - /* [in] */ VARIANT_BOOL bAllowContextMenu); - - -void __RPC_STUB IAxWinAmbientDispatch_put_AllowContextMenu_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_AllowContextMenu_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbAllowContextMenu); - - -void __RPC_STUB IAxWinAmbientDispatch_get_AllowContextMenu_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_AllowShowUI_Proxy( - IAxWinAmbientDispatch * This, - /* [in] */ VARIANT_BOOL bAllowShowUI); - - -void __RPC_STUB IAxWinAmbientDispatch_put_AllowShowUI_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_AllowShowUI_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbAllowShowUI); - - -void __RPC_STUB IAxWinAmbientDispatch_get_AllowShowUI_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_OptionKeyPath_Proxy( - IAxWinAmbientDispatch * This, - /* [in] */ BSTR bstrOptionKeyPath); - - -void __RPC_STUB IAxWinAmbientDispatch_put_OptionKeyPath_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_OptionKeyPath_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ BSTR *pbstrOptionKeyPath); - - -void __RPC_STUB IAxWinAmbientDispatch_get_OptionKeyPath_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IAxWinAmbientDispatch_INTERFACE_DEFINED__ */ - - -#ifndef __IAxWinAmbientDispatchEx_INTERFACE_DEFINED__ -#define __IAxWinAmbientDispatchEx_INTERFACE_DEFINED__ - -/* interface IAxWinAmbientDispatchEx */ -/* [unique][helpstring][uuid][dual][object] */ - - -EXTERN_C const IID IID_IAxWinAmbientDispatchEx; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("B2D0778B-AC99-4c58-A5C8-E7724E5316B5") - IAxWinAmbientDispatchEx : public IAxWinAmbientDispatch - { - public: - virtual /* [id] */ HRESULT STDMETHODCALLTYPE SetAmbientDispatch( - /* [in] */ IDispatch *pDispatch) = 0; - - }; - -#else /* C style interface */ - - typedef struct IAxWinAmbientDispatchExVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IAxWinAmbientDispatchEx * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IAxWinAmbientDispatchEx * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IAxWinAmbientDispatchEx * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IAxWinAmbientDispatchEx * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IAxWinAmbientDispatchEx * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IAxWinAmbientDispatchEx * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IAxWinAmbientDispatchEx * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AllowWindowlessActivation )( - IAxWinAmbientDispatchEx * This, - /* [in] */ VARIANT_BOOL bCanWindowlessActivate); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AllowWindowlessActivation )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ VARIANT_BOOL *pbCanWindowlessActivate); - - /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_BackColor )( - IAxWinAmbientDispatchEx * This, - /* [in] */ OLE_COLOR clrBackground); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BackColor )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ OLE_COLOR *pclrBackground); - - /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_ForeColor )( - IAxWinAmbientDispatchEx * This, - /* [in] */ OLE_COLOR clrForeground); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ForeColor )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ OLE_COLOR *pclrForeground); - - /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_LocaleID )( - IAxWinAmbientDispatchEx * This, - /* [in] */ LCID lcidLocaleID); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LocaleID )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ LCID *plcidLocaleID); - - /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_UserMode )( - IAxWinAmbientDispatchEx * This, - /* [in] */ VARIANT_BOOL bUserMode); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_UserMode )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ VARIANT_BOOL *pbUserMode); - - /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DisplayAsDefault )( - IAxWinAmbientDispatchEx * This, - /* [in] */ VARIANT_BOOL bDisplayAsDefault); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DisplayAsDefault )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ VARIANT_BOOL *pbDisplayAsDefault); - - /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Font )( - IAxWinAmbientDispatchEx * This, - /* [in] */ IFontDisp *pFont); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Font )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ IFontDisp **pFont); - - /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_MessageReflect )( - IAxWinAmbientDispatchEx * This, - /* [in] */ VARIANT_BOOL bMsgReflect); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_MessageReflect )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ VARIANT_BOOL *pbMsgReflect); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ShowGrabHandles )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ VARIANT_BOOL *pbShowGrabHandles); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ShowHatching )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ VARIANT_BOOL *pbShowHatching); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DocHostFlags )( - IAxWinAmbientDispatchEx * This, - /* [in] */ DWORD dwDocHostFlags); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DocHostFlags )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ DWORD *pdwDocHostFlags); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DocHostDoubleClickFlags )( - IAxWinAmbientDispatchEx * This, - /* [in] */ DWORD dwDocHostDoubleClickFlags); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DocHostDoubleClickFlags )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ DWORD *pdwDocHostDoubleClickFlags); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AllowContextMenu )( - IAxWinAmbientDispatchEx * This, - /* [in] */ VARIANT_BOOL bAllowContextMenu); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AllowContextMenu )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ VARIANT_BOOL *pbAllowContextMenu); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AllowShowUI )( - IAxWinAmbientDispatchEx * This, - /* [in] */ VARIANT_BOOL bAllowShowUI); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AllowShowUI )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ VARIANT_BOOL *pbAllowShowUI); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_OptionKeyPath )( - IAxWinAmbientDispatchEx * This, - /* [in] */ BSTR bstrOptionKeyPath); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_OptionKeyPath )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ BSTR *pbstrOptionKeyPath); - - /* [id] */ HRESULT ( STDMETHODCALLTYPE *SetAmbientDispatch )( - IAxWinAmbientDispatchEx * This, - /* [in] */ IDispatch *pDispatch); - - END_INTERFACE - } IAxWinAmbientDispatchExVtbl; - - interface IAxWinAmbientDispatchEx - { - CONST_VTBL struct IAxWinAmbientDispatchExVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IAxWinAmbientDispatchEx_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IAxWinAmbientDispatchEx_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IAxWinAmbientDispatchEx_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IAxWinAmbientDispatchEx_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IAxWinAmbientDispatchEx_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IAxWinAmbientDispatchEx_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IAxWinAmbientDispatchEx_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IAxWinAmbientDispatchEx_put_AllowWindowlessActivation(This,bCanWindowlessActivate) \ - (This)->lpVtbl -> put_AllowWindowlessActivation(This,bCanWindowlessActivate) - -#define IAxWinAmbientDispatchEx_get_AllowWindowlessActivation(This,pbCanWindowlessActivate) \ - (This)->lpVtbl -> get_AllowWindowlessActivation(This,pbCanWindowlessActivate) - -#define IAxWinAmbientDispatchEx_put_BackColor(This,clrBackground) \ - (This)->lpVtbl -> put_BackColor(This,clrBackground) - -#define IAxWinAmbientDispatchEx_get_BackColor(This,pclrBackground) \ - (This)->lpVtbl -> get_BackColor(This,pclrBackground) - -#define IAxWinAmbientDispatchEx_put_ForeColor(This,clrForeground) \ - (This)->lpVtbl -> put_ForeColor(This,clrForeground) - -#define IAxWinAmbientDispatchEx_get_ForeColor(This,pclrForeground) \ - (This)->lpVtbl -> get_ForeColor(This,pclrForeground) - -#define IAxWinAmbientDispatchEx_put_LocaleID(This,lcidLocaleID) \ - (This)->lpVtbl -> put_LocaleID(This,lcidLocaleID) - -#define IAxWinAmbientDispatchEx_get_LocaleID(This,plcidLocaleID) \ - (This)->lpVtbl -> get_LocaleID(This,plcidLocaleID) - -#define IAxWinAmbientDispatchEx_put_UserMode(This,bUserMode) \ - (This)->lpVtbl -> put_UserMode(This,bUserMode) - -#define IAxWinAmbientDispatchEx_get_UserMode(This,pbUserMode) \ - (This)->lpVtbl -> get_UserMode(This,pbUserMode) - -#define IAxWinAmbientDispatchEx_put_DisplayAsDefault(This,bDisplayAsDefault) \ - (This)->lpVtbl -> put_DisplayAsDefault(This,bDisplayAsDefault) - -#define IAxWinAmbientDispatchEx_get_DisplayAsDefault(This,pbDisplayAsDefault) \ - (This)->lpVtbl -> get_DisplayAsDefault(This,pbDisplayAsDefault) - -#define IAxWinAmbientDispatchEx_put_Font(This,pFont) \ - (This)->lpVtbl -> put_Font(This,pFont) - -#define IAxWinAmbientDispatchEx_get_Font(This,pFont) \ - (This)->lpVtbl -> get_Font(This,pFont) - -#define IAxWinAmbientDispatchEx_put_MessageReflect(This,bMsgReflect) \ - (This)->lpVtbl -> put_MessageReflect(This,bMsgReflect) - -#define IAxWinAmbientDispatchEx_get_MessageReflect(This,pbMsgReflect) \ - (This)->lpVtbl -> get_MessageReflect(This,pbMsgReflect) - -#define IAxWinAmbientDispatchEx_get_ShowGrabHandles(This,pbShowGrabHandles) \ - (This)->lpVtbl -> get_ShowGrabHandles(This,pbShowGrabHandles) - -#define IAxWinAmbientDispatchEx_get_ShowHatching(This,pbShowHatching) \ - (This)->lpVtbl -> get_ShowHatching(This,pbShowHatching) - -#define IAxWinAmbientDispatchEx_put_DocHostFlags(This,dwDocHostFlags) \ - (This)->lpVtbl -> put_DocHostFlags(This,dwDocHostFlags) - -#define IAxWinAmbientDispatchEx_get_DocHostFlags(This,pdwDocHostFlags) \ - (This)->lpVtbl -> get_DocHostFlags(This,pdwDocHostFlags) - -#define IAxWinAmbientDispatchEx_put_DocHostDoubleClickFlags(This,dwDocHostDoubleClickFlags) \ - (This)->lpVtbl -> put_DocHostDoubleClickFlags(This,dwDocHostDoubleClickFlags) - -#define IAxWinAmbientDispatchEx_get_DocHostDoubleClickFlags(This,pdwDocHostDoubleClickFlags) \ - (This)->lpVtbl -> get_DocHostDoubleClickFlags(This,pdwDocHostDoubleClickFlags) - -#define IAxWinAmbientDispatchEx_put_AllowContextMenu(This,bAllowContextMenu) \ - (This)->lpVtbl -> put_AllowContextMenu(This,bAllowContextMenu) - -#define IAxWinAmbientDispatchEx_get_AllowContextMenu(This,pbAllowContextMenu) \ - (This)->lpVtbl -> get_AllowContextMenu(This,pbAllowContextMenu) - -#define IAxWinAmbientDispatchEx_put_AllowShowUI(This,bAllowShowUI) \ - (This)->lpVtbl -> put_AllowShowUI(This,bAllowShowUI) - -#define IAxWinAmbientDispatchEx_get_AllowShowUI(This,pbAllowShowUI) \ - (This)->lpVtbl -> get_AllowShowUI(This,pbAllowShowUI) - -#define IAxWinAmbientDispatchEx_put_OptionKeyPath(This,bstrOptionKeyPath) \ - (This)->lpVtbl -> put_OptionKeyPath(This,bstrOptionKeyPath) - -#define IAxWinAmbientDispatchEx_get_OptionKeyPath(This,pbstrOptionKeyPath) \ - (This)->lpVtbl -> get_OptionKeyPath(This,pbstrOptionKeyPath) - - -#define IAxWinAmbientDispatchEx_SetAmbientDispatch(This,pDispatch) \ - (This)->lpVtbl -> SetAmbientDispatch(This,pDispatch) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [id] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatchEx_SetAmbientDispatch_Proxy( - IAxWinAmbientDispatchEx * This, - /* [in] */ IDispatch *pDispatch); - - -void __RPC_STUB IAxWinAmbientDispatchEx_SetAmbientDispatch_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IAxWinAmbientDispatchEx_INTERFACE_DEFINED__ */ - - -#ifndef __IInternalConnection_INTERFACE_DEFINED__ -#define __IInternalConnection_INTERFACE_DEFINED__ - -/* interface IInternalConnection */ -/* [object][unique][helpstring][uuid] */ - - -EXTERN_C const IID IID_IInternalConnection; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("72AD0770-6A9F-11d1-BCEC-0060088F444E") - IInternalConnection : public IUnknown - { - public: - virtual HRESULT STDMETHODCALLTYPE AddConnection( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE ReleaseConnection( void) = 0; - - }; - -#else /* C style interface */ - - typedef struct IInternalConnectionVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IInternalConnection * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IInternalConnection * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IInternalConnection * This); - - HRESULT ( STDMETHODCALLTYPE *AddConnection )( - IInternalConnection * This); - - HRESULT ( STDMETHODCALLTYPE *ReleaseConnection )( - IInternalConnection * This); - - END_INTERFACE - } IInternalConnectionVtbl; - - interface IInternalConnection - { - CONST_VTBL struct IInternalConnectionVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IInternalConnection_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IInternalConnection_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IInternalConnection_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IInternalConnection_AddConnection(This) \ - (This)->lpVtbl -> AddConnection(This) - -#define IInternalConnection_ReleaseConnection(This) \ - (This)->lpVtbl -> ReleaseConnection(This) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -HRESULT STDMETHODCALLTYPE IInternalConnection_AddConnection_Proxy( - IInternalConnection * This); - - -void __RPC_STUB IInternalConnection_AddConnection_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IInternalConnection_ReleaseConnection_Proxy( - IInternalConnection * This); - - -void __RPC_STUB IInternalConnection_ReleaseConnection_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IInternalConnection_INTERFACE_DEFINED__ */ - - -/* interface __MIDL_itf_atliface_0257 */ -/* [local] */ - -namespace ATL -{ -#ifdef __cplusplus -#include -#else -#define ATLAPI EXTERN_C HRESULT __declspec(dllimport) __stdcall -#define ATLAPI_(x) EXTERN_C __declspec(dllimport) x __stdcall -#define ATLINLINE -#endif // __cplusplus - -ATLAPI_(INT_PTR) AtlAxDialogBoxW(HINSTANCE hInstance, LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam); -ATLAPI_(INT_PTR) AtlAxDialogBoxA(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam); -#ifdef UNICODE -#define AtlAxDialogBox AtlAxDialogBoxW -#else -#define AtlAxDialogBox AtlAxDialogBoxA -#endif - -ATLAPI_(HWND) AtlAxCreateDialogW(HINSTANCE hInstance, LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam); -ATLAPI_(HWND) AtlAxCreateDialogA(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam); -#ifdef UNICODE -#define AtlAxCreateDialog AtlAxCreateDialogW -#else -#define AtlAxCreateDialog AtlAxCreateDialogA -#endif - -ATLAPI AtlAxCreateControl(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, IUnknown** ppUnkContainer); -#ifdef __cplusplus -ATLAPI AtlAxCreateControlEx(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, - IUnknown** ppUnkContainer, IUnknown** ppUnkControl, - REFIID iidSink=IID_NULL, IUnknown* punkSink=NULL); -ATLAPI AtlAxCreateControlLic(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, IUnknown** ppUnkContainer, BSTR bstrLic = NULL); -ATLAPI AtlAxCreateControlLicEx(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, - IUnknown** ppUnkContainer, IUnknown** ppUnkControl, - REFIID iidSink=IID_NULL, IUnknown* punkSink=NULL, BSTR bstrLic = NULL); -#else -ATLAPI AtlAxCreateControlEx(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, - IUnknown** ppUnkContainer, IUnknown** ppUnkControl, - REFIID iidSink, IUnknown* punkSink); -ATLAPI AtlAxCreateControlLic(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, IUnknown** ppUnkContainer, BSTR bstrLic); -ATLAPI AtlAxCreateControlLicEx(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, - IUnknown** ppUnkContainer, IUnknown** ppUnkControl, - REFIID iidSink, IUnknown* punkSink, BSTR bstrLic); -#endif // __cplusplus -ATLAPI AtlAxAttachControl(IUnknown* pControl, HWND hWnd, IUnknown** ppUnkContainer); -ATLAPI_(BOOL) AtlAxWinInit(); - -ATLAPI AtlAxGetHost(HWND h, IUnknown** pp); -ATLAPI AtlAxGetControl(HWND h, IUnknown** pp); - -}; //namespace ATL - - - -extern RPC_IF_HANDLE __MIDL_itf_atliface_0257_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_atliface_0257_v0_0_s_ifspec; - -#ifndef __IAccessibleProxy_INTERFACE_DEFINED__ -#define __IAccessibleProxy_INTERFACE_DEFINED__ - -/* interface IAccessibleProxy */ -/* [unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IAccessibleProxy; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("7A7D9DCF-B7A1-4019-9031-258268846980") - IAccessibleProxy : public IUnknown - { - public: - virtual HRESULT STDMETHODCALLTYPE SetServer( - /* [in] */ IAccessible *pAccessible, - /* [in] */ IAccessibleServer *pServer) = 0; - - }; - -#else /* C style interface */ - - typedef struct IAccessibleProxyVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IAccessibleProxy * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IAccessibleProxy * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IAccessibleProxy * This); - - HRESULT ( STDMETHODCALLTYPE *SetServer )( - IAccessibleProxy * This, - /* [in] */ IAccessible *pAccessible, - /* [in] */ IAccessibleServer *pServer); - - END_INTERFACE - } IAccessibleProxyVtbl; - - interface IAccessibleProxy - { - CONST_VTBL struct IAccessibleProxyVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IAccessibleProxy_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IAccessibleProxy_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IAccessibleProxy_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IAccessibleProxy_SetServer(This,pAccessible,pServer) \ - (This)->lpVtbl -> SetServer(This,pAccessible,pServer) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -HRESULT STDMETHODCALLTYPE IAccessibleProxy_SetServer_Proxy( - IAccessibleProxy * This, - /* [in] */ IAccessible *pAccessible, - /* [in] */ IAccessibleServer *pServer); - - -void __RPC_STUB IAccessibleProxy_SetServer_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IAccessibleProxy_INTERFACE_DEFINED__ */ - - -#ifndef __IAccessibleServer_INTERFACE_DEFINED__ -#define __IAccessibleServer_INTERFACE_DEFINED__ - -/* interface IAccessibleServer */ -/* [unique][helpstring][uuid][object] */ - - -EXTERN_C const IID IID_IAccessibleServer; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("52C8FB5E-D779-4e77-AE9F-F611FA7E9D7A") - IAccessibleServer : public IUnknown - { - public: - virtual HRESULT STDMETHODCALLTYPE SetProxy( - /* [in] */ IAccessibleProxy *pUnknown) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetHWND( - /* [out] */ HWND *phWnd) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetEnumVariant( - /* [out] */ IEnumVARIANT **ppEnumVariant) = 0; - - }; - -#else /* C style interface */ - - typedef struct IAccessibleServerVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IAccessibleServer * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IAccessibleServer * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IAccessibleServer * This); - - HRESULT ( STDMETHODCALLTYPE *SetProxy )( - IAccessibleServer * This, - /* [in] */ IAccessibleProxy *pUnknown); - - HRESULT ( STDMETHODCALLTYPE *GetHWND )( - IAccessibleServer * This, - /* [out] */ HWND *phWnd); - - HRESULT ( STDMETHODCALLTYPE *GetEnumVariant )( - IAccessibleServer * This, - /* [out] */ IEnumVARIANT **ppEnumVariant); - - END_INTERFACE - } IAccessibleServerVtbl; - - interface IAccessibleServer - { - CONST_VTBL struct IAccessibleServerVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IAccessibleServer_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IAccessibleServer_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IAccessibleServer_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IAccessibleServer_SetProxy(This,pUnknown) \ - (This)->lpVtbl -> SetProxy(This,pUnknown) - -#define IAccessibleServer_GetHWND(This,phWnd) \ - (This)->lpVtbl -> GetHWND(This,phWnd) - -#define IAccessibleServer_GetEnumVariant(This,ppEnumVariant) \ - (This)->lpVtbl -> GetEnumVariant(This,ppEnumVariant) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -HRESULT STDMETHODCALLTYPE IAccessibleServer_SetProxy_Proxy( - IAccessibleServer * This, - /* [in] */ IAccessibleProxy *pUnknown); - - -void __RPC_STUB IAccessibleServer_SetProxy_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IAccessibleServer_GetHWND_Proxy( - IAccessibleServer * This, - /* [out] */ HWND *phWnd); - - -void __RPC_STUB IAccessibleServer_GetHWND_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IAccessibleServer_GetEnumVariant_Proxy( - IAccessibleServer * This, - /* [out] */ IEnumVARIANT **ppEnumVariant); - - -void __RPC_STUB IAccessibleServer_GetEnumVariant_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IAccessibleServer_INTERFACE_DEFINED__ */ - - -/* Additional Prototypes for ALL interfaces */ - -unsigned long __RPC_USER BSTR_UserSize( unsigned long *, unsigned long , BSTR * ); -unsigned char * __RPC_USER BSTR_UserMarshal( unsigned long *, unsigned char *, BSTR * ); -unsigned char * __RPC_USER BSTR_UserUnmarshal(unsigned long *, unsigned char *, BSTR * ); -void __RPC_USER BSTR_UserFree( unsigned long *, BSTR * ); - -unsigned long __RPC_USER HWND_UserSize( unsigned long *, unsigned long , HWND * ); -unsigned char * __RPC_USER HWND_UserMarshal( unsigned long *, unsigned char *, HWND * ); -unsigned char * __RPC_USER HWND_UserUnmarshal(unsigned long *, unsigned char *, HWND * ); -void __RPC_USER HWND_UserFree( unsigned long *, HWND * ); - -/* end of Additional Prototypes */ - -#ifdef __cplusplus -} -#endif - -#endif - - diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlmem.h b/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlmem.h deleted file mode 100644 index ec82fa686..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlmem.h +++ /dev/null @@ -1,216 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLMEM_H__ -#define __ATLMEM_H__ - -#pragma once - -#include -#include - -namespace ATL -{ - -template< typename N > -inline N WINAPI AtlAlignUp( N n, ULONG nAlign ) throw() -{ - return( N( (n+(nAlign-1))&~(N( nAlign )-1) ) ); -} - -template< typename N > -inline N WINAPI AtlAlignDown( N n, ULONG nAlign ) throw() -{ - return( N( n&~(N( nAlign )-1) ) ); -} - -__interface __declspec(uuid("654F7EF5-CFDF-4df9-A450-6C6A13C622C0")) IAtlMemMgr -{ -public: - void* Allocate( size_t nBytes ) throw(); - void Free( void* p ) throw(); - void* Reallocate( void* p, size_t nBytes ) throw(); - size_t GetSize( void* p ) throw(); -}; - -#ifndef _ATL_MIN_CRT -class CCRTHeap : - public IAtlMemMgr -{ -public: - virtual void* Allocate( size_t nBytes ) throw() - { - return( malloc( nBytes ) ); - } - virtual void Free( void* p ) throw() - { - free( p ); - } - virtual void* Reallocate( void* p, size_t nBytes ) throw() - { - return( realloc( p, nBytes ) ); - } - virtual size_t GetSize( void* p ) throw() - { - return( _msize( p ) ); - } - -public: -}; - -#endif //!_ATL_MIN_CRT - -class CWin32Heap : - public IAtlMemMgr -{ -public: - CWin32Heap() throw() : - m_hHeap( NULL ), - m_bOwnHeap( false ) - { - } - CWin32Heap( HANDLE hHeap ) throw() : - m_hHeap( hHeap ), - m_bOwnHeap( false ) - { - ATLASSERT( hHeap != NULL ); - } - CWin32Heap( DWORD dwFlags, size_t nInitialSize, size_t nMaxSize = 0 ) : - m_hHeap( NULL ), - m_bOwnHeap( true ) - { - ATLASSERT( !(dwFlags&HEAP_GENERATE_EXCEPTIONS) ); - m_hHeap = ::HeapCreate( dwFlags, nInitialSize, nMaxSize ); - if( m_hHeap == NULL ) - { - AtlThrowLastWin32(); - } - } - virtual ~CWin32Heap() throw() - { - if( m_bOwnHeap && (m_hHeap != NULL) ) - { - BOOL bSuccess; - - bSuccess = ::HeapDestroy( m_hHeap ); - ATLASSERT( bSuccess ); - } - } - - void Attach( HANDLE hHeap, bool bTakeOwnership ) throw() - { - ATLASSERT( hHeap != NULL ); - ATLASSERT( m_hHeap == NULL ); - - m_hHeap = hHeap; - m_bOwnHeap = bTakeOwnership; - } - HANDLE Detach() throw() - { - HANDLE hHeap; - - hHeap = m_hHeap; - m_hHeap = NULL; - m_bOwnHeap = false; - - return( hHeap ); - } - -// IAtlMemMgr - virtual void* Allocate( size_t nBytes ) throw() - { - return( ::HeapAlloc( m_hHeap, 0, nBytes ) ); - } - virtual void Free( void* p ) throw() - { - if( p != NULL ) - { - BOOL bSuccess; - - bSuccess = ::HeapFree( m_hHeap, 0, p ); - ATLASSERT( bSuccess ); - } - } - virtual void* Reallocate( void* p, size_t nBytes ) throw() - { - if( p == NULL ) - { - return( Allocate( nBytes ) ); - } - else - { - return( ::HeapReAlloc( m_hHeap, 0, p, nBytes ) ); - } - } - virtual size_t GetSize( void* p ) throw() - { - return( ::HeapSize( m_hHeap, 0, p ) ); - } - -public: - HANDLE m_hHeap; - bool m_bOwnHeap; -}; - -class CLocalHeap : - public IAtlMemMgr -{ -// IAtlMemMgr -public: - virtual void* Allocate( size_t nBytes ) throw() - { - return( ::LocalAlloc( LMEM_FIXED, nBytes ) ); - } - virtual void Free( void* p ) throw() - { - ::LocalFree( p ); - } - virtual void* Reallocate( void* p, size_t nBytes ) throw() - { - return( ::LocalReAlloc( p, nBytes, 0 ) ); - } - virtual size_t GetSize( void* p ) throw() - { - return( ::LocalSize( p ) ); - } -}; - -class CGlobalHeap : - public IAtlMemMgr -{ -// IAtlMemMgr -public: - virtual void* Allocate( size_t nBytes ) throw() - { - return( ::GlobalAlloc( LMEM_FIXED, nBytes ) ); - } - virtual void Free( void* p ) throw() - { - ::GlobalFree( p ); - } - virtual void* Reallocate( void* p, size_t nBytes ) throw() - { - return( ::GlobalReAlloc( p, nBytes, 0 ) ); - } - virtual size_t GetSize( void* p ) throw() - { - return( ::GlobalSize( p ) ); - } -}; - -}; // namespace ATL - -#ifdef _OBJBASE_H_ -#include -#endif // _OBJBASE_H_ - -#endif //__ATLMEM_H__ - - diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlrc.h b/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlrc.h deleted file mode 100644 index ab52f9f3b..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlrc.h +++ /dev/null @@ -1,27 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#pragma once - -#ifndef __ATLRC_H__ - -#define ATL_RESID_BASE 0xD800 -#define ATL_STRING_BASE ATL_RESID_BASE - -#define ATL_IDS_DATETIME_INVALID (ATL_STRING_BASE + 0) -#define ATL_IDS_DATETIMESPAN_INVALID (ATL_STRING_BASE + 1) - -#define ATL_SERVICE_MANAGER_OPEN_ERROR (ATL_STRING_BASE + 10) -#define ATL_SERVICE_START_ERROR (ATL_STRING_BASE + 11) -#define ATL_SERVICE_OPEN_ERROR (ATL_STRING_BASE + 12) -#define ATL_SERVICE_DELETE_ERROR (ATL_STRING_BASE + 13) -#define ATL_SERVICE_STOP_ERROR (ATL_STRING_BASE + 14) - -#endif // __ATLRC_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlsimpcoll.h b/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlsimpcoll.h deleted file mode 100644 index 8a434c67e..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlsimpcoll.h +++ /dev/null @@ -1,459 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLSIMPCOLL_H__ -#define __ATLSIMPCOLL_H__ - -#pragma once - -#include - -#pragma push_macro("malloc") -#undef malloc -#pragma push_macro("realloc") -#undef realloc -#pragma push_macro("free") -#undef free - -#pragma warning(push) -#pragma warning(disable: 4800) // forcing 'int' value to bool - -namespace ATL -{ - -#pragma push_macro("new") -#undef new - -///////////////////////////////////////////////////////////////////////////// -// Collection helpers - CSimpleArray & CSimpleMap - -// template class helpers with functions for comparing elements -// override if using complex types without operator== -template -class CSimpleArrayEqualHelper -{ -public: - static bool IsEqual(const T& t1, const T& t2) - { - return (t1 == t2); - } -}; - -template -class CSimpleArrayEqualHelperFalse -{ -public: - static bool IsEqual(const T&, const T&) - { - ATLASSERT(false); - return false; - } -}; - -template -class CSimpleMapEqualHelper -{ -public: - static bool IsEqualKey(const TKey& k1, const TKey& k2) - { - return CSimpleArrayEqualHelper::IsEqual(k1, k2); - } - - static bool IsEqualValue(const TVal& v1, const TVal& v2) - { - return CSimpleArrayEqualHelper::IsEqual(v1, v2); - } -}; - -template -class CSimpleMapEqualHelperFalse -{ -public: - static bool IsEqualKey(const TKey& k1, const TKey& k2) - { - return CSimpleArrayEqualHelper::IsEqual(k1, k2); - } - - static bool IsEqualValue(const TVal&, const TVal&) - { - ATLASSERT(FALSE); - return false; - } -}; - -template > -class CSimpleArray -{ -public: -// Construction/destruction - CSimpleArray() : m_aT(NULL), m_nSize(0), m_nAllocSize(0) - { } - - ~CSimpleArray() - { - RemoveAll(); - } - - CSimpleArray(const CSimpleArray< T, TEqual >& src) : m_aT(NULL), m_nSize(0), m_nAllocSize(0) - { - m_aT = (T*)malloc(src.GetSize() * sizeof(T)); - if (m_aT != NULL) - { - m_nAllocSize = src.GetSize(); - for (int i=0; i& operator=(const CSimpleArray< T, TEqual >& src) - { - if (GetSize() != src.GetSize()) - { - RemoveAll(); - m_aT = (T*)malloc(src.GetSize() * sizeof(T)); - if (m_aT != NULL) - m_nAllocSize = src.GetSize(); - } - else - { - for (int i = GetSize(); i > 0; i--) - RemoveAt(i - 1); - } - for (int i=0; i= 0 && nIndex < m_nSize); - if (nIndex < 0 || nIndex >= m_nSize) - return FALSE; - m_aT[nIndex].~T(); - if(nIndex != (m_nSize - 1)) - memmove((void*)(m_aT + nIndex), (void*)(m_aT + nIndex + 1), (m_nSize - (nIndex + 1)) * sizeof(T)); - m_nSize--; - return TRUE; - } - void RemoveAll() - { - if(m_aT != NULL) - { - for(int i = 0; i < m_nSize; i++) - m_aT[i].~T(); - free(m_aT); - m_aT = NULL; - } - m_nSize = 0; - m_nAllocSize = 0; - } - const T& operator[] (int nIndex) const - { - ATLASSERT(nIndex >= 0 && nIndex < m_nSize); - if(nIndex < 0 || nIndex >= m_nSize) - { - _AtlRaiseException(EXCEPTION_ARRAY_BOUNDS_EXCEEDED); - } - return m_aT[nIndex]; - } - T& operator[] (int nIndex) - { - ATLASSERT(nIndex >= 0 && nIndex < m_nSize); - if(nIndex < 0 || nIndex >= m_nSize) - { - _AtlRaiseException(EXCEPTION_ARRAY_BOUNDS_EXCEEDED); - } - return m_aT[nIndex]; - } - T* GetData() const - { - return m_aT; - } - - int Find(const T& t) const - { - for(int i = 0; i < m_nSize; i++) - { - if(TEqual::IsEqual(m_aT[i], t)) - return i; - } - return -1; // not found - } - - BOOL SetAtIndex(int nIndex, const T& t) - { - if (nIndex < 0 || nIndex >= m_nSize) - return FALSE; - InternalSetAtIndex(nIndex, t); - return TRUE; - } - -// Implementation - class Wrapper - { - public: - Wrapper(const T& _t) : t(_t) - { - } - template - void * __cdecl operator new(size_t, _Ty* p) - { - return p; - } - template - void __cdecl operator delete(void* /* pv */, _Ty* /* p */) - { - } - T t; - }; - -// Implementation - void InternalSetAtIndex(int nIndex, const T& t) - { - new(m_aT + nIndex) Wrapper(t); - } - - typedef T _ArrayElementType; - T* m_aT; - int m_nSize; - int m_nAllocSize; - -}; - -#define CSimpleValArray CSimpleArray - -// intended for small number of simple types or pointers -template > -class CSimpleMap -{ -public: - TKey* m_aKey; - TVal* m_aVal; - int m_nSize; - - typedef TKey _ArrayKeyType; - typedef TVal _ArrayElementType; - -// Construction/destruction - CSimpleMap() : m_aKey(NULL), m_aVal(NULL), m_nSize(0) - { } - - ~CSimpleMap() - { - RemoveAll(); - } - -// Operations - int GetSize() const - { - return m_nSize; - } - BOOL Add(const TKey& key, const TVal& val) - { - TKey* pKey; - pKey = (TKey*)realloc(m_aKey, (m_nSize + 1) * sizeof(TKey)); - if(pKey == NULL) - return FALSE; - m_aKey = pKey; - TVal* pVal; - pVal = (TVal*)realloc(m_aVal, (m_nSize + 1) * sizeof(TVal)); - if(pVal == NULL) - return FALSE; - m_aVal = pVal; - InternalSetAtIndex(m_nSize, key, val); - m_nSize++; - return TRUE; - } - BOOL Remove(const TKey& key) - { - int nIndex = FindKey(key); - if(nIndex == -1) - return FALSE; - return RemoveAt(nIndex); - } - BOOL RemoveAt(int nIndex) - { - ATLASSERT(nIndex >= 0 && nIndex < m_nSize); - if (nIndex < 0 || nIndex >= m_nSize) - return FALSE; - m_aKey[nIndex].~TKey(); - m_aVal[nIndex].~TVal(); - if(nIndex != (m_nSize - 1)) - { - memmove((void*)(m_aKey + nIndex), (void*)(m_aKey + nIndex + 1), (m_nSize - (nIndex + 1)) * sizeof(TKey)); - memmove((void*)(m_aVal + nIndex), (void*)(m_aVal + nIndex + 1), (m_nSize - (nIndex + 1)) * sizeof(TVal)); - } - TKey* pKey; - pKey = (TKey*)realloc(m_aKey, (m_nSize - 1) * sizeof(TKey)); - if(pKey != NULL || m_nSize == 1) - m_aKey = pKey; - TVal* pVal; - pVal = (TVal*)realloc(m_aVal, (m_nSize - 1) * sizeof(TVal)); - if(pVal != NULL || m_nSize == 1) - m_aVal = pVal; - m_nSize--; - return TRUE; - } - void RemoveAll() - { - if(m_aKey != NULL) - { - for(int i = 0; i < m_nSize; i++) - { - m_aKey[i].~TKey(); - m_aVal[i].~TVal(); - } - free(m_aKey); - m_aKey = NULL; - } - if(m_aVal != NULL) - { - free(m_aVal); - m_aVal = NULL; - } - - m_nSize = 0; - } - BOOL SetAt(const TKey& key, const TVal& val) - { - int nIndex = FindKey(key); - if(nIndex == -1) - return FALSE; - ATLASSERT(nIndex >= 0 && nIndex < m_nSize); - m_aKey[nIndex].~TKey(); - m_aVal[nIndex].~TVal(); - InternalSetAtIndex(nIndex, key, val); - return TRUE; - } - TVal Lookup(const TKey& key) const - { - int nIndex = FindKey(key); - if(nIndex == -1) - return NULL; // must be able to convert - return GetValueAt(nIndex); - } - TKey ReverseLookup(const TVal& val) const - { - int nIndex = FindVal(val); - if(nIndex == -1) - return NULL; // must be able to convert - return GetKeyAt(nIndex); - } - TKey& GetKeyAt(int nIndex) const - { - ATLASSERT(nIndex >= 0 && nIndex < m_nSize); - if(nIndex < 0 || nIndex >= m_nSize) - _AtlRaiseException(EXCEPTION_ARRAY_BOUNDS_EXCEEDED); - - return m_aKey[nIndex]; - } - TVal& GetValueAt(int nIndex) const - { - ATLASSERT(nIndex >= 0 && nIndex < m_nSize); - if(nIndex < 0 || nIndex >= m_nSize) - _AtlRaiseException(EXCEPTION_ARRAY_BOUNDS_EXCEEDED); - - return m_aVal[nIndex]; - } - - int FindKey(const TKey& key) const - { - for(int i = 0; i < m_nSize; i++) - { - if(TEqual::IsEqualKey(m_aKey[i], key)) - return i; - } - return -1; // not found - } - int FindVal(const TVal& val) const - { - for(int i = 0; i < m_nSize; i++) - { - if(TEqual::IsEqualValue(m_aVal[i], val)) - return i; - } - return -1; // not found - } - - BOOL SetAtIndex(int nIndex, const TKey& key, const TVal& val) - { - if (nIndex < 0 || nIndex >= m_nSize) - return FALSE; - InternalSetAtIndex(nIndex, key, val); - return TRUE; - } - - -// Implementation - - template - class Wrapper - { - public: - Wrapper(const T& _t) : t(_t) - { - } - template - void *operator new(size_t, _Ty* p) - { - return p; - } - template - void operator delete(void* /* pv */, _Ty* /* p */) - { - } - T t; - }; - void InternalSetAtIndex(int nIndex, const TKey& key, const TVal& val) - { - new(m_aKey + nIndex) Wrapper(key); - new(m_aVal + nIndex) Wrapper(val); - } -}; - -#pragma pop_macro("new") - -}; // namespace ATL - -#pragma warning(pop) - -#pragma pop_macro("free") -#pragma pop_macro("realloc") -#pragma pop_macro("malloc") - - -#endif // __ATLSIMPCOLL_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlsimpstr.h b/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlsimpstr.h deleted file mode 100644 index b46e7463a..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlsimpstr.h +++ /dev/null @@ -1,923 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLSIMPSTR_H__ -#define __ATLSIMPSTR_H__ - -#pragma once - -#include -#include -#include -#include - -namespace ATL -{ - -struct CStringData; - -__interface IAtlStringMgr -{ -public: - // Allocate a new CStringData - CStringData* Allocate( int nAllocLength, int nCharSize ) throw(); - // Free an existing CStringData - void Free( CStringData* pData ) throw(); - // Change the size of an existing CStringData - CStringData* Reallocate( CStringData* pData, int nAllocLength, int nCharSize ) throw(); - // Get the CStringData for a Nil string - CStringData* GetNilString() throw(); - IAtlStringMgr* Clone() throw(); -}; - -#ifdef _M_IX86 -#ifndef _M_CEE -extern "C" -{ - LONG _InterlockedIncrement( LONG* pn ); - LONG _InterlockedDecrement( LONG* pn ); -}; - -#pragma intrinsic( _InterlockedIncrement ) -#pragma intrinsic( _InterlockedDecrement ) -#else -#define _InterlockedIncrement InterlockedIncrement -#define _InterlockedDecrement InterlockedDecrement -#endif // !_M_CEE -#endif // _M_IX86_ - -struct CStringData -{ - IAtlStringMgr* pStringMgr; // String manager for this CStringData - int nDataLength; // Length of currently used data in XCHARs (not including terminating null) - int nAllocLength; // Length of allocated data in XCHARs (not including terminating null) - long nRefs; // Reference count: negative == locked - // XCHAR data[nAllocLength+1] // A CStringData is always followed in memory by the actual array of character data - - void* data() throw() - { - return (this+1); - } - - void AddRef() throw() - { - ATLASSERT(nRefs > 0); - _InterlockedIncrement(&nRefs); - } - bool IsLocked() const throw() - { - return nRefs < 0; - } - bool IsShared() const throw() - { - return( nRefs > 1 ); - } - void Lock() throw() - { - ATLASSERT( nRefs <= 1 ); - nRefs--; // Locked buffers can't be shared, so no interlocked operation necessary - if( nRefs == 0 ) - { - nRefs = -1; - } - } - void Release() throw() - { - ATLASSERT( nRefs != 0 ); - - if( _InterlockedDecrement( &nRefs ) <= 0 ) - { - pStringMgr->Free( this ); - } - } - void Unlock() throw() - { - ATLASSERT( IsLocked() ); - - if(IsLocked()) - { - nRefs++; // Locked buffers can't be shared, so no interlocked operation necessary - if( nRefs == 0 ) - { - nRefs = 1; - } - } - } -}; - -class CNilStringData : - public CStringData -{ -public: - CNilStringData() throw() - { - pStringMgr = NULL; - nRefs = 2; // Never gets freed by IAtlStringMgr - nDataLength = 0; - nAllocLength = 0; - achNil[0] = 0; - achNil[1] = 0; - } - - void SetManager( IAtlStringMgr* pMgr ) throw() - { - ATLASSERT( pStringMgr == NULL ); - pStringMgr = pMgr; - } - -public: - wchar_t achNil[2]; -}; - -template< typename BaseType, const int t_nSize > -class CStaticString -{ -public: - CStaticString( const BaseType* psz ) : - m_psz( psz ) - { - } - - operator const BaseType*() const - { - return m_psz; - } - - static int __cdecl GetLength() - { - return (t_nSize/sizeof( BaseType ))-1; - } - -private: - const BaseType* m_psz; - -private: - CStaticString( const CStaticString& str ) throw(); - CStaticString& operator=( const CStaticString& str ) throw(); -}; - -#define _ST( psz ) ATL::CStaticString< TCHAR, sizeof( _T( psz ) ) >( _T( psz ) ) -#define _SA( psz ) ATL::CStaticString< char, sizeof( psz ) >( psz ) -#define _SW( psz ) ATL::CStaticString< wchar_t, sizeof( L##psz ) >( L##psz ) -#define _SO( psz ) _SW( psz ) - -template< typename BaseType = char > -class ChTraitsBase -{ -public: - typedef char XCHAR; - typedef LPSTR PXSTR; - typedef LPCSTR PCXSTR; - typedef wchar_t YCHAR; - typedef LPWSTR PYSTR; - typedef LPCWSTR PCYSTR; -}; - -template<> -class ChTraitsBase< wchar_t > -{ -public: - typedef wchar_t XCHAR; - typedef LPWSTR PXSTR; - typedef LPCWSTR PCXSTR; - typedef char YCHAR; - typedef LPSTR PYSTR; - typedef LPCSTR PCYSTR; -}; - -template< typename TCharType, bool t_bMFCDLL = false > -class CStrBufT; - -template< typename BaseType , bool t_bMFCDLL = false> -class CSimpleStringT -{ -public: - typedef typename ChTraitsBase< BaseType >::XCHAR XCHAR; - typedef typename ChTraitsBase< BaseType >::PXSTR PXSTR; - typedef typename ChTraitsBase< BaseType >::PCXSTR PCXSTR; - typedef typename ChTraitsBase< BaseType >::YCHAR YCHAR; - typedef typename ChTraitsBase< BaseType >::PYSTR PYSTR; - typedef typename ChTraitsBase< BaseType >::PCYSTR PCYSTR; - -public: - explicit CSimpleStringT( IAtlStringMgr* pStringMgr ) throw() - { - ATLASSERT( pStringMgr != NULL ); - CStringData* pData = pStringMgr->GetNilString(); - Attach( pData ); - } - - CSimpleStringT( const CSimpleStringT& strSrc ) - { - CStringData* pSrcData = strSrc.GetData(); - CStringData* pNewData = CloneData( pSrcData ); - Attach( pNewData ); - } - - CSimpleStringT( const CSimpleStringT& strSrc ) - { - CStringData* pSrcData = strSrc.GetData(); - CStringData* pNewData = CloneData( pSrcData ); - Attach( pNewData ); - } - - CSimpleStringT( PCXSTR pszSrc, IAtlStringMgr* pStringMgr ) - { - ATLASSERT( pStringMgr != NULL ); - - int nLength = StringLength( pszSrc ); - CStringData* pData = pStringMgr->Allocate( nLength, sizeof( XCHAR ) ); - if( pData == NULL ) - { - ThrowMemoryException(); - } - Attach( pData ); - SetLength( nLength ); - CopyChars( m_pszData, pszSrc, nLength ); - } - CSimpleStringT( const XCHAR* pchSrc, int nLength, IAtlStringMgr* pStringMgr ) - { - ATLASSERT( pStringMgr != NULL ); - - if(pchSrc == NULL && nLength != 0) - AtlThrow(E_INVALIDARG); - - CStringData* pData = pStringMgr->Allocate( nLength, sizeof( XCHAR ) ); - if( pData == NULL ) - { - ThrowMemoryException(); - } - Attach( pData ); - SetLength( nLength ); - CopyChars( m_pszData, pchSrc, nLength ); - } - ~CSimpleStringT() throw() - { - CStringData* pData = GetData(); - pData->Release(); - } - - operator CSimpleStringT&() - { - return *(CSimpleStringT*)this; - } - - CSimpleStringT& operator=( const CSimpleStringT& strSrc ) - { - CStringData* pSrcData = strSrc.GetData(); - CStringData* pOldData = GetData(); - if( pSrcData != pOldData) - { - if( pOldData->IsLocked() || pSrcData->pStringMgr != pOldData->pStringMgr ) - { - SetString( strSrc.GetString(), strSrc.GetLength() ); - } - else - { - CStringData* pNewData = CloneData( pSrcData ); - pOldData->Release(); - Attach( pNewData ); - } - } - - return( *this ); - } - - CSimpleStringT& operator=( const CSimpleStringT& strSrc ) - { - CStringData* pSrcData = strSrc.GetData(); - CStringData* pOldData = GetData(); - if( pSrcData != pOldData) - { - if( pOldData->IsLocked() || pSrcData->pStringMgr != pOldData->pStringMgr ) - { - SetString( strSrc.GetString(), strSrc.GetLength() ); - } - else - { - CStringData* pNewData = CloneData( pSrcData ); - pOldData->Release(); - Attach( pNewData ); - } - } - - return( *this ); - } - - CSimpleStringT& operator=( PCXSTR pszSrc ) - { - SetString( pszSrc ); - - return( *this ); - } - - CSimpleStringT& operator+=( const CSimpleStringT& strSrc ) - { - Append( strSrc ); - - return( *this ); - } - template - CSimpleStringT& operator+=( const CSimpleStringT& strSrc ) - { - Append( strSrc ); - - return( *this ); - } - - CSimpleStringT& operator+=( PCXSTR pszSrc ) - { - Append( pszSrc ); - - return( *this ); - } - template< int t_nSize > - CSimpleStringT& operator+=( const CStaticString< XCHAR, t_nSize >& strSrc ) - { - Append( strSrc.m_psz, strSrc.GetLength() ); - - return( *this ); - } - CSimpleStringT& operator+=( char ch ) - { - AppendChar( XCHAR( ch ) ); - - return( *this ); - } - CSimpleStringT& operator+=( unsigned char ch ) - { - AppendChar( XCHAR( ch ) ); - - return( *this ); - } - CSimpleStringT& operator+=( wchar_t ch ) - { - AppendChar( XCHAR( ch ) ); - - return( *this ); - } - - XCHAR operator[]( int iChar ) const - { - ATLASSERT( (iChar >= 0) && (iChar <= GetLength()) ); // Indexing the '\0' is OK - - if( (iChar < 0) || (iChar > GetLength()) ) - AtlThrow(E_INVALIDARG); - - return( m_pszData[iChar] ); - } - - operator PCXSTR() const throw() - { - return( m_pszData ); - } - - void Append( PCXSTR pszSrc ) - { - Append( pszSrc, StringLength( pszSrc ) ); - } - void Append( PCXSTR pszSrc, int nLength ) - { - // See comment in SetString() about why we do this - UINT_PTR nOffset = pszSrc-GetString(); - - UINT nOldLength = GetLength(); - int nNewLength = nOldLength+nLength; - PXSTR pszBuffer = GetBuffer( nNewLength ); - if( nOffset <= nOldLength ) - { - pszSrc = pszBuffer+nOffset; - // No need to call CopyCharsOverlapped, since the destination is - // beyond the end of the original buffer - } - CopyChars( pszBuffer+nOldLength, pszSrc, nLength ); - ReleaseBufferSetLength( nNewLength ); - } - void AppendChar( XCHAR ch ) - { - UINT nOldLength = GetLength(); - int nNewLength = nOldLength+1; - PXSTR pszBuffer = GetBuffer( nNewLength ); - pszBuffer[nOldLength] = ch; - ReleaseBufferSetLength( nNewLength ); - } - void Append( const CSimpleStringT& strSrc ) - { - Append( strSrc.GetString(), strSrc.GetLength() ); - } - template - void Append( const CSimpleStringT& strSrc ) - { - Append( strSrc.GetString(), strSrc.GetLength() ); - } - void Empty() throw() - { - CStringData* pOldData = GetData(); - IAtlStringMgr* pStringMgr = pOldData->pStringMgr; - if( pOldData->nDataLength == 0 ) - { - return; - } - - if( pOldData->IsLocked() ) - { - // Don't reallocate a locked buffer that's shrinking - SetLength( 0 ); - } - else - { - pOldData->Release(); - CStringData* pNewData = pStringMgr->GetNilString(); - Attach( pNewData ); - } - } - void FreeExtra() - { - CStringData* pOldData = GetData(); - int nLength = pOldData->nDataLength; - IAtlStringMgr* pStringMgr = pOldData->pStringMgr; - if( pOldData->nAllocLength == nLength ) - { - return; - } - - if( !pOldData->IsLocked() ) // Don't reallocate a locked buffer that's shrinking - { - CStringData* pNewData = pStringMgr->Allocate( nLength, sizeof( XCHAR ) ); - if( pNewData == NULL ) - { - SetLength( nLength ); - return; - } - CopyChars( PXSTR( pNewData->data() ), PCXSTR( pOldData->data() ), nLength ); - pOldData->Release(); - Attach( pNewData ); - SetLength( nLength ); - } - } - - int GetAllocLength() const throw() - { - return( GetData()->nAllocLength ); - } - XCHAR GetAt( int iChar ) const - { - ATLASSERT( (iChar >= 0) && (iChar <= GetLength()) ); // Indexing the '\0' is OK - if( (iChar < 0) || (iChar > GetLength()) ) - AtlThrow(E_INVALIDARG); - - return( m_pszData[iChar] ); - } - PXSTR GetBuffer() - { - CStringData* pData = GetData(); - if( pData->IsShared() ) - { - Fork( pData->nDataLength ); - } - - return( m_pszData ); - } - PXSTR GetBuffer( int nMinBufferLength ) - { - return( PrepareWrite( nMinBufferLength ) ); - } - PXSTR GetBufferSetLength( int nLength ) - { - PXSTR pszBuffer = GetBuffer( nLength ); - SetLength( nLength ); - - return( pszBuffer ); - } - int GetLength() const throw() - { - return( GetData()->nDataLength ); - } - IAtlStringMgr* GetManager() const throw() - { - return( GetData()->pStringMgr->Clone() ); - } - - PCXSTR GetString() const throw() - { - return( m_pszData ); - } - bool IsEmpty() const throw() - { - return( GetLength() == 0 ); - } - PXSTR LockBuffer() - { - CStringData* pData = GetData(); - if( pData->IsShared() ) - { - Fork( pData->nDataLength ); - pData = GetData(); // Do it again, because the fork might have changed it - } - pData->Lock(); - - return( m_pszData ); - } - void UnlockBuffer() throw() - { - CStringData* pData = GetData(); - pData->Unlock(); - } - void Preallocate( int nLength ) - { - PrepareWrite( nLength ); - } - void ReleaseBuffer( int nNewLength = -1 ) - { - if( nNewLength == -1 ) - { - nNewLength = StringLength( m_pszData ); - } - SetLength( nNewLength ); - } - void ReleaseBufferSetLength( int nNewLength ) - { - ATLASSERT( nNewLength >= 0 ); - SetLength( nNewLength ); - } - void Truncate( int nNewLength ) - { - ATLASSERT( nNewLength <= GetLength() ); - GetBuffer( nNewLength ); - ReleaseBufferSetLength( nNewLength ); - } - void SetAt( int iChar, XCHAR ch ) - { - ATLASSERT( (iChar >= 0) && (iChar < GetLength()) ); - - if( (iChar < 0) || (iChar >= GetLength()) ) - AtlThrow(E_INVALIDARG); - - int nLength = GetLength(); - PXSTR pszBuffer = GetBuffer(); - pszBuffer[iChar] = ch; - ReleaseBufferSetLength( nLength ); - - } - void SetManager( IAtlStringMgr* pStringMgr ) - { - ATLASSERT( IsEmpty() ); - - CStringData* pData = GetData(); - pData->Release(); - pData = pStringMgr->GetNilString(); - Attach( pData ); - } - void SetString( PCXSTR pszSrc ) - { - SetString( pszSrc, StringLength( pszSrc ) ); - } - void SetString( PCXSTR pszSrc, int nLength ) - { - if( nLength == 0 ) - { - Empty(); - } - else - { - // It is possible that pszSrc points to a location inside of our - // buffer. GetBuffer() might change m_pszData if (1) the buffer - // is shared or (2) the buffer is too small to hold the new - // string. We detect this aliasing, and modify pszSrc to point - // into the newly allocated buffer instead. - - if(pszSrc == NULL) - AtlThrow(E_INVALIDARG); - - UINT nOldLength = GetLength(); - UINT_PTR nOffset = pszSrc-GetString(); - // If 0 <= nOffset <= nOldLength, then pszSrc points into our - // buffer - - PXSTR pszBuffer = GetBuffer( nLength ); - if( nOffset <= nOldLength ) - { - CopyCharsOverlapped( pszBuffer, pszBuffer+nOffset, nLength ); - } - else - { - CopyChars( pszBuffer, pszSrc, nLength ); - } - ReleaseBufferSetLength( nLength ); - } - } - -public: - friend CSimpleStringT operator+( - const CSimpleStringT& str1, - const CSimpleStringT& str2 ) - { - CSimpleStringT s( str1.GetManager() ); - - Concatenate( s, str1, str1.GetLength(), str2, str2.GetLength() ); - - return( s ); - } - - friend CSimpleStringT operator+( - const CSimpleStringT& str1, - PCXSTR psz2 ) - { - CSimpleStringT s( str1.GetManager() ); - - Concatenate( s, str1, str1.GetLength(), psz2, StringLength( psz2 ) ); - - return( s ); - } - - friend CSimpleStringT operator+( - PCXSTR psz1, - const CSimpleStringT& str2 ) - { - CSimpleStringT s( str2.GetManager() ); - - Concatenate( s, psz1, StringLength( psz1 ), str2, str2.GetLength() ); - - return( s ); - } - - static void __cdecl CopyChars( XCHAR* pchDest, const XCHAR* pchSrc, int nChars ) throw() - { - memcpy( pchDest, pchSrc, nChars*sizeof( XCHAR ) ); - } - static void __cdecl CopyCharsOverlapped( XCHAR* pchDest, const XCHAR* pchSrc, int nChars ) throw() - { - memmove( pchDest, pchSrc, nChars*sizeof( XCHAR ) ); - } -#ifdef _ATL_MIN_CRT - ATL_NOINLINE static int __cdecl StringLength( PCXSTR psz ) throw() - { - int nLength = 0; - if( psz != NULL ) - { - const XCHAR* pch = psz; - while( *pch != 0 ) - { - nLength++; - pch++; - } - } - - return( nLength ); - } -#else - static int __cdecl StringLength( const char* psz ) throw() - { - if( psz == NULL ) - { - return( 0 ); - } - return( int( strlen( psz ) ) ); - } - static int __cdecl StringLength( const wchar_t* psz ) throw() - { - if( psz == NULL ) - { - return( 0 ); - } - return( int( wcslen( psz ) ) ); - } -#endif - -protected: - static void __cdecl Concatenate( CSimpleStringT& strResult, PCXSTR psz1, int nLength1, PCXSTR psz2, int nLength2 ) - { - int nNewLength = nLength1+nLength2; - PXSTR pszBuffer = strResult.GetBuffer( nNewLength ); - CopyChars( pszBuffer, psz1, nLength1 ); - CopyChars( pszBuffer+nLength1, psz2, nLength2 ); - strResult.ReleaseBufferSetLength( nNewLength ); - } - ATL_NOINLINE __declspec( noreturn ) static void __cdecl ThrowMemoryException() - { - AtlThrow( E_OUTOFMEMORY ); - } - -// Implementation -private: - void Attach( CStringData* pData ) throw() - { - m_pszData = static_cast< PXSTR >( pData->data() ); - } - ATL_NOINLINE void Fork( int nLength ) - { - CStringData* pOldData = GetData(); - int nOldLength = pOldData->nDataLength; - CStringData* pNewData = pOldData->pStringMgr->Clone()->Allocate( nLength, sizeof( XCHAR ) ); - if( pNewData == NULL ) - { - ThrowMemoryException(); - } - int nCharsToCopy = ((nOldLength < nLength) ? nOldLength : nLength)+1; // Copy '\0' - CopyChars( PXSTR( pNewData->data() ), PCXSTR( pOldData->data() ), nCharsToCopy ); - pNewData->nDataLength = nOldLength; - pOldData->Release(); - Attach( pNewData ); - } - CStringData* GetData() const throw() - { - return( reinterpret_cast< CStringData* >( m_pszData )-1 ); - } - PXSTR PrepareWrite( int nLength ) - { - CStringData* pOldData = GetData(); - int nShared = 1-pOldData->nRefs; // nShared < 0 means true, >= 0 means false - int nTooShort = pOldData->nAllocLength-nLength; // nTooShort < 0 means true, >= 0 means false - if( (nShared|nTooShort) < 0 ) // If either sign bit is set (i.e. either is less than zero), we need to copy data - { - PrepareWrite2( nLength ); - } - - return( m_pszData ); - } - ATL_NOINLINE void PrepareWrite2( int nLength ) - { - CStringData* pOldData = GetData(); - if( pOldData->nDataLength > nLength ) - { - nLength = pOldData->nDataLength; - } - if( pOldData->IsShared() ) - { - Fork( nLength ); - } - else if( pOldData->nAllocLength < nLength ) - { - // Grow exponentially, until we hit 1K. - int nNewLength = pOldData->nAllocLength; - if( nNewLength > 1024 ) - { - nNewLength += 1024; - } - else - { - nNewLength *= 2; - } - if( nNewLength < nLength ) - { - nNewLength = nLength; - } - Reallocate( nNewLength ); - } - } - ATL_NOINLINE void Reallocate( int nLength ) - { - CStringData* pOldData = GetData(); - ATLASSERT( pOldData->nAllocLength < nLength ); - IAtlStringMgr* pStringMgr = pOldData->pStringMgr; - CStringData* pNewData = pStringMgr->Reallocate( pOldData, nLength, sizeof( XCHAR ) ); - if( pNewData == NULL ) - { - ThrowMemoryException(); - } - Attach( pNewData ); - } - - void SetLength( int nLength ) - { - ATLASSERT( nLength >= 0 ); - ATLASSERT( nLength <= GetData()->nAllocLength ); - - if( nLength < 0 || nLength > GetData()->nAllocLength) - AtlThrow(E_INVALIDARG); - - GetData()->nDataLength = nLength; - m_pszData[nLength] = 0; - } - - static CStringData* __cdecl CloneData( CStringData* pData ) - { - CStringData* pNewData = NULL; - - IAtlStringMgr* pNewStringMgr = pData->pStringMgr->Clone(); - if( !pData->IsLocked() && (pNewStringMgr == pData->pStringMgr) ) - { - pNewData = pData; - pNewData->AddRef(); - } - else - { - pNewData = pNewStringMgr->Allocate( pData->nDataLength, sizeof( XCHAR ) ); - if( pNewData == NULL ) - { - ThrowMemoryException(); - } - pNewData->nDataLength = pData->nDataLength; - CopyChars( PXSTR( pNewData->data() ), PCXSTR( pData->data() ), pData->nDataLength+1 ); // Copy '\0' - } - - return( pNewData ); - } - -public : - typedef CStrBufT CStrBuf; -private: - PXSTR m_pszData; - - friend class CSimpleStringT; -}; - -template< typename TCharType, bool t_bMFCDLL > -class CStrBufT -{ -public: - typedef CSimpleStringT< TCharType, t_bMFCDLL> StringType; - typedef typename StringType::XCHAR XCHAR; - typedef typename StringType::PXSTR PXSTR; - typedef typename StringType::PCXSTR PCXSTR; - - static const DWORD AUTO_LENGTH = 0x01; // Automatically determine the new length of the string at release. The string must be null-terminated. - static const DWORD SET_LENGTH = 0x02; // Set the length of the string object at GetBuffer time - -public: - explicit CStrBufT( StringType& str ) throw( ... ) : - m_str( str ), - m_pszBuffer( NULL ), -#ifdef _DEBUG - m_nBufferLength( str.GetLength() ), -#endif - m_nLength( str.GetLength() ) - { - m_pszBuffer = m_str.GetBuffer(); - } - - CStrBufT( StringType& str, int nMinLength, DWORD dwFlags = AUTO_LENGTH ) throw( ... ) : - m_str( str ), - m_pszBuffer( NULL ), -#ifdef _DEBUG - m_nBufferLength( nMinLength ), -#endif - m_nLength( (dwFlags&AUTO_LENGTH) ? -1 : nMinLength ) - { - if( dwFlags&SET_LENGTH ) - { - m_pszBuffer = m_str.GetBufferSetLength( nMinLength ); - } - else - { - m_pszBuffer = m_str.GetBuffer( nMinLength ); - } - } - - ~CStrBufT() - { - m_str.ReleaseBuffer( m_nLength ); - } - - operator PXSTR() throw() - { - return( m_pszBuffer ); - } - operator PCXSTR() const throw() - { - return( m_pszBuffer ); - } - - void SetLength( int nLength ) - { - ATLASSERT( nLength >= 0 ); - ATLASSERT( nLength <= m_nBufferLength ); - - if( nLength < 0 ) - AtlThrow(E_INVALIDARG); - - m_nLength = nLength; - } - -// Implementation -private: - StringType& m_str; - PXSTR m_pszBuffer; - int m_nLength; -#ifdef _DEBUG - int m_nBufferLength; -#endif - -// Private copy constructor and copy assignment operator to prevent accidental use -private: - CStrBufT( const CStrBufT& ) throw(); - CStrBufT& operator=( const CStrBufT& ) throw(); -}; - -typedef CSimpleStringT< TCHAR > CSimpleString; -typedef CSimpleStringT< char > CSimpleStringA; -typedef CSimpleStringT< wchar_t > CSimpleStringW; -typedef CStrBufT< TCHAR > CStrBuf; -typedef CStrBufT< char > CStrBufA; -typedef CStrBufT< wchar_t > CStrBufW; - -}; // namespace ATL - -#endif // __ATLSIMPSTR_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atltrace.h b/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atltrace.h deleted file mode 100644 index a9502e6b4..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atltrace.h +++ /dev/null @@ -1,404 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLTRACE_H__ -#define __ATLTRACE_H__ - -#pragma once - -#include -#include - -#ifdef _DEBUG -#include -#include -#endif - -#ifdef _DEBUG -#include - -extern "C" IMAGE_DOS_HEADER __ImageBase; -#endif // _DEBUG - -namespace ATL -{ - -// Declare a global instance of this class to automatically register a custom trace category at startup -class CTraceCategory -{ -public: - explicit CTraceCategory( LPCTSTR pszCategoryName, UINT nStartingLevel = 0 ) throw(); - -#ifdef _DEBUG - UINT GetLevel() const throw(); - void SetLevel( UINT nLevel ) throw(); - ATLTRACESTATUS GetStatus() const throw(); - void SetStatus( ATLTRACESTATUS eStatus) throw(); -#endif - - operator DWORD_PTR() const throw(); - -public: -#ifdef _DEBUG - DWORD_PTR m_dwCategory; -#endif -}; - -#ifdef _DEBUG - -class CTrace -{ -public: - typedef int (__cdecl *fnCrtDbgReport_t)(int,const char *,int,const char *,const char *,...); - -private: - CTrace( -#ifdef _ATL_NO_DEBUG_CRT - fnCrtDbgReport_t pfnCrtDbgReport = NULL) -#else - fnCrtDbgReport_t pfnCrtDbgReport = _CrtDbgReport) -#endif - : m_hInst(reinterpret_cast(&__ImageBase)), - m_dwModule( 0 ) - { - m_dwModule = AtlTraceRegister(m_hInst, pfnCrtDbgReport); -// LoadSettings(); - } - - ~CTrace() - { - AtlTraceUnregister(m_dwModule); - } - -public: - bool ChangeCategory(DWORD_PTR dwCategory, UINT nLevel, ATLTRACESTATUS eStatus) - { - return 0 != - AtlTraceModifyCategory(0, dwCategory, nLevel, eStatus); - } - - bool GetCategory(DWORD_PTR dwCategory, UINT *pnLevel, ATLTRACESTATUS *peStatus) - { - ATLASSERT(pnLevel && peStatus); - return 0 != AtlTraceGetCategory(0, dwCategory, pnLevel, peStatus); - } - UINT GetLevel() - { - ATLTRACESTATUS eStatus; - UINT nLevel; - AtlTraceGetModule(0, m_dwModule, &nLevel, &eStatus); - - return nLevel; - } - void SetLevel(UINT nLevel) - { - AtlTraceModifyModule(0, m_dwModule, nLevel, ATLTRACESTATUS_ENABLED); - } - ATLTRACESTATUS GetStatus() - { - ATLTRACESTATUS eStatus; - UINT nLevel; - AtlTraceGetModule(0, m_dwModule, &nLevel, &eStatus); - - return eStatus; - } - void SetStatus(ATLTRACESTATUS eStatus) - { - ATLTRACESTATUS eOldStatus; - UINT nLevel; - AtlTraceGetModule(0, m_dwModule, &nLevel, &eOldStatus); - AtlTraceModifyModule(0, m_dwModule, nLevel, eStatus); - } - void __cdecl TraceV(const char *pszFileName, int nLine, - DWORD_PTR dwCategory, UINT nLevel, LPCSTR pszFmt, va_list args) const - { - AtlTraceVA(m_dwModule, pszFileName, nLine, dwCategory, nLevel, pszFmt, args); - } - void __cdecl TraceV(const char *pszFileName, int nLine, - DWORD_PTR dwCategory, UINT nLevel, LPCWSTR pszFmt, va_list args) const - { - AtlTraceVU(m_dwModule, pszFileName, nLine, dwCategory, nLevel, pszFmt, args); - } - - DWORD_PTR RegisterCategory(LPCSTR pszCategory) - {return(AtlTraceRegisterCategoryA(m_dwModule, pszCategory));} -#ifdef _UNICODE - DWORD_PTR RegisterCategory(LPCWSTR pszCategory) - {return(AtlTraceRegisterCategoryU(m_dwModule, pszCategory));} -#endif - - bool LoadSettings(LPCTSTR pszFileName = NULL) const - {return 0 != AtlTraceLoadSettings(pszFileName);} - void SaveSettings(LPCTSTR pszFileName = NULL) const - {AtlTraceSaveSettings(pszFileName);} - -public: - static CTrace s_trace; - -protected: - HINSTANCE m_hInst; - DWORD_PTR m_dwModule; -}; - - -extern CTraceCategory atlTraceGeneral; - -class CTraceFileAndLineInfo -{ -public: - CTraceFileAndLineInfo(const char *pszFileName, int nLineNo) - : m_pszFileName(pszFileName), m_nLineNo(nLineNo) - {} - - void __cdecl operator()(DWORD_PTR dwCategory, UINT nLevel, const char *pszFmt, ...) const - { - va_list ptr; va_start(ptr, pszFmt); - ATL::CTrace::s_trace.TraceV(m_pszFileName, m_nLineNo, dwCategory, nLevel, pszFmt, ptr); - va_end(ptr); - } - void __cdecl operator()(DWORD_PTR dwCategory, UINT nLevel, const wchar_t *pszFmt, ...) const - { - va_list ptr; va_start(ptr, pszFmt); - ATL::CTrace::s_trace.TraceV(m_pszFileName, m_nLineNo, dwCategory, nLevel, pszFmt, ptr); - va_end(ptr); - } - void __cdecl operator()(const char *pszFmt, ...) const - { - va_list ptr; va_start(ptr, pszFmt); - ATL::CTrace::s_trace.TraceV(m_pszFileName, m_nLineNo, atlTraceGeneral, 0, pszFmt, ptr); - va_end(ptr); - } - void __cdecl operator()(const wchar_t *pszFmt, ...) const - { - va_list ptr; va_start(ptr, pszFmt); - ATL::CTrace::s_trace.TraceV(m_pszFileName, m_nLineNo, atlTraceGeneral, 0, pszFmt, ptr); - va_end(ptr); - } - -private: - const char *const m_pszFileName; - const int m_nLineNo; -}; - -#endif // _DEBUG - -#ifdef _DEBUG - -inline CTraceCategory::CTraceCategory( LPCTSTR pszCategoryName, UINT nStartingLevel ) throw() : - m_dwCategory( 0 ) -{ - m_dwCategory = ATL::CTrace::s_trace.RegisterCategory( pszCategoryName ); - ATL::CTrace::s_trace.ChangeCategory( m_dwCategory, nStartingLevel, ATLTRACESTATUS_INHERIT); -} - -inline CTraceCategory::operator DWORD_PTR() const throw() -{ - return( m_dwCategory ); -} - -inline UINT CTraceCategory::GetLevel() const throw() -{ - UINT nLevel; - ATLTRACESTATUS eStatus; - ATL::CTrace::s_trace.GetCategory( m_dwCategory, &nLevel, &eStatus ); - - return( nLevel ); -} - -inline void CTraceCategory::SetLevel( UINT nLevel ) throw() -{ - ATL::CTrace::s_trace.ChangeCategory( m_dwCategory, nLevel, ATLTRACESTATUS_ENABLED ); -} - -inline ATLTRACESTATUS CTraceCategory::GetStatus() const throw() -{ - UINT nLevel; - ATLTRACESTATUS eStatus; - ATL::CTrace::s_trace.GetCategory( m_dwCategory, &nLevel, &eStatus ); - - return( eStatus ); -} - -inline void CTraceCategory::SetStatus( ATLTRACESTATUS eStatus ) throw() -{ - UINT nLevel; - ATLTRACESTATUS eOldStatus; - ATL::CTrace::s_trace.GetCategory( m_dwCategory, &nLevel, &eOldStatus ); - ATL::CTrace::s_trace.ChangeCategory( m_dwCategory, nLevel, eStatus ); -} - -#else // !_DEBUG - -inline CTraceCategory::CTraceCategory( LPCTSTR pszCategoryName, UINT nStartingLevel ) throw() -{ - (void)pszCategoryName; - (void)nStartingLevel; -} - -inline CTraceCategory::operator DWORD_PTR() const throw() -{ - return( 0 ); -} - -#endif // _DEBUG - -} // namespace ATL - -namespace ATL -{ - -#ifdef _DEBUG -#define DECLARE_TRACE_CATEGORY( name ) extern ATL::CTraceCategory name; -#else -#define DECLARE_TRACE_CATEGORY( name ) const DWORD_PTR name = 0; -#endif - -DECLARE_TRACE_CATEGORY( atlTraceGeneral ) -DECLARE_TRACE_CATEGORY( atlTraceCOM ) -DECLARE_TRACE_CATEGORY( atlTraceQI ) -DECLARE_TRACE_CATEGORY( atlTraceRegistrar ) -DECLARE_TRACE_CATEGORY( atlTraceRefcount ) -DECLARE_TRACE_CATEGORY( atlTraceWindowing ) -DECLARE_TRACE_CATEGORY( atlTraceControls ) -DECLARE_TRACE_CATEGORY( atlTraceHosting ) -DECLARE_TRACE_CATEGORY( atlTraceDBClient ) -DECLARE_TRACE_CATEGORY( atlTraceDBProvider ) -DECLARE_TRACE_CATEGORY( atlTraceSnapin ) -DECLARE_TRACE_CATEGORY( atlTraceNotImpl ) -DECLARE_TRACE_CATEGORY( atlTraceAllocation ) -DECLARE_TRACE_CATEGORY( atlTraceException ) -DECLARE_TRACE_CATEGORY( atlTraceTime ) -DECLARE_TRACE_CATEGORY( atlTraceCache ) -DECLARE_TRACE_CATEGORY( atlTraceStencil ) -DECLARE_TRACE_CATEGORY( atlTraceString ) -DECLARE_TRACE_CATEGORY( atlTraceMap ) -DECLARE_TRACE_CATEGORY( atlTraceUtil ) -DECLARE_TRACE_CATEGORY( atlTraceSecurity ) -DECLARE_TRACE_CATEGORY( atlTraceSync ) -DECLARE_TRACE_CATEGORY( atlTraceISAPI ) - -// atlTraceUser categories are no longer needed. Just declare your own trace category using CTraceCategory. -DECLARE_TRACE_CATEGORY( atlTraceUser ) -DECLARE_TRACE_CATEGORY( atlTraceUser2 ) -DECLARE_TRACE_CATEGORY( atlTraceUser3 ) -DECLARE_TRACE_CATEGORY( atlTraceUser4 ) - -#pragma deprecated( atlTraceUser ) -#pragma deprecated( atlTraceUser2 ) -#pragma deprecated( atlTraceUser3 ) -#pragma deprecated( atlTraceUser4 ) - -#ifdef _DEBUG - -#ifndef _ATL_NO_DEBUG_CRT -class CNoUIAssertHook -{ -public: - CNoUIAssertHook() - { - ATLASSERT( s_pfnPrevHook == NULL ); - s_pfnPrevHook = _CrtSetReportHook(CrtHookProc); - } - ~CNoUIAssertHook() - { - _CrtSetReportHook(s_pfnPrevHook); - s_pfnPrevHook = NULL; - } - -private: - static int __cdecl CrtHookProc(int eReportType, char* pszMessage, int* pnRetVal) - { - if (eReportType == _CRT_ASSERT) - { - ::OutputDebugStringA( "ASSERTION FAILED\n" ); - ::OutputDebugStringA( pszMessage ); - *pnRetVal = 1; - return TRUE; - } - - if (s_pfnPrevHook != NULL) - { - return s_pfnPrevHook(eReportType, pszMessage, pnRetVal); - } - else - { - return FALSE; - } - } - -private: - static _CRT_REPORT_HOOK s_pfnPrevHook; -}; - -__declspec( selectany ) _CRT_REPORT_HOOK CNoUIAssertHook::s_pfnPrevHook = NULL; - -#define DECLARE_NOUIASSERT() ATL::CNoUIAssertHook _g_NoUIAssertHook; - -#endif // _ATL_NO_DEBUG_CRT - -#ifndef ATLTRACE -#define ATLTRACE ATL::CTraceFileAndLineInfo(__FILE__, __LINE__) -#define ATLTRACE2 ATLTRACE -#endif - -inline void _cdecl AtlTrace(LPCSTR pszFormat, ...) -{ - va_list ptr; - va_start(ptr, pszFormat); - ATL::CTrace::s_trace.TraceV(NULL, -1, atlTraceGeneral, 0, pszFormat, ptr); - va_end(ptr); -} - -inline void _cdecl AtlTrace(LPCWSTR pszFormat, ...) -{ - va_list ptr; - va_start(ptr, pszFormat); - ATL::CTrace::s_trace.TraceV(NULL, -1, atlTraceGeneral, 0, pszFormat, ptr); - va_end(ptr); -} - -inline void _cdecl AtlTrace2(DWORD_PTR dwCategory, UINT nLevel, LPCSTR pszFormat, ...) -{ - va_list ptr; - va_start(ptr, pszFormat); - ATL::CTrace::s_trace.TraceV(NULL, -1, dwCategory, nLevel, pszFormat, ptr); - va_end(ptr); -} - -inline void _cdecl AtlTrace2(DWORD_PTR dwCategory, UINT nLevel, LPCWSTR pszFormat, ...) -{ - va_list ptr; - va_start(ptr, pszFormat); - ATL::CTrace::s_trace.TraceV(NULL, -1, dwCategory, nLevel, pszFormat, ptr); - va_end(ptr); -} - -#define ATLTRACENOTIMPL(funcname) ATLTRACE(ATL::atlTraceNotImpl, 0, _T("ATL: %s not implemented.\n"), funcname); return E_NOTIMPL - -#else // !DEBUG - -inline void _cdecl AtlTraceNull(...){} -inline void _cdecl AtlTrace(LPCSTR , ...){} -inline void _cdecl AtlTrace2(DWORD_PTR, UINT, LPCSTR , ...){} -inline void _cdecl AtlTrace(LPCWSTR , ...){} -inline void _cdecl AtlTrace2(DWORD_PTR, UINT, LPCWSTR , ...){} -#ifndef ATLTRACE - -#define ATLTRACE __noop -#define ATLTRACE2 __noop -#endif //ATLTRACE -#define ATLTRACENOTIMPL(funcname) return E_NOTIMPL -#define DECLARE_NOUIASSERT() - -#endif //!_DEBUG - -}; // namespace ATL - -#endif // __ATLTRACE_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlwin.h b/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlwin.h deleted file mode 100644 index 485468d44..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/atlwin.h +++ /dev/null @@ -1,4525 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef _ATL_NO_PRAGMA_WARNINGS -#pragma warning (push) -#pragma warning(disable : 4668) // is not defined as a preprocessor macro, replacing with '0' for '#if/#elif -#pragma warning(disable : 4820) // padding added after member -#endif //!_ATL_NO_PRAGMA_WARNINGS - -#ifndef __ATLWIN_H__ -#define __ATLWIN_H__ - -#pragma once - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#ifndef __ATLBASE_H__ - #error atlwin.h requires atlbase.h to be included first -#endif - -#include -#include - -// protect template members from windowsx.h macros -#ifdef _INC_WINDOWSX -#undef SubclassWindow -#endif //_INC_WINDOWSX - -#ifdef SetWindowLongPtrA -#undef SetWindowLongPtrA -inline LONG_PTR SetWindowLongPtrA( HWND hWnd, int nIndex, LONG_PTR dwNewLong ) -{ - return( ::SetWindowLongA( hWnd, nIndex, LONG( dwNewLong ) ) ); -} -#endif - -#ifdef SetWindowLongPtrW -#undef SetWindowLongPtrW -inline LONG_PTR SetWindowLongPtrW( HWND hWnd, int nIndex, LONG_PTR dwNewLong ) -{ - return( ::SetWindowLongW( hWnd, nIndex, LONG( dwNewLong ) ) ); -} -#endif - -#ifdef GetWindowLongPtrA -#undef GetWindowLongPtrA -inline LONG_PTR GetWindowLongPtrA( HWND hWnd, int nIndex ) -{ - return( ::GetWindowLongA( hWnd, nIndex ) ); -} -#endif - -#ifdef GetWindowLongPtrW -#undef GetWindowLongPtrW -inline LONG_PTR GetWindowLongPtrW( HWND hWnd, int nIndex ) -{ - return( ::GetWindowLongW( hWnd, nIndex ) ); -} -#endif - -//#ifndef _ATL_DLL_IMPL -namespace ATL -{ -//#endif - -///////////////////////////////////////////////////////////////////////////// -// Dual argument helper classes - -class _U_RECT -{ -public: - _U_RECT(LPRECT lpRect) : m_lpRect(lpRect) - { } - _U_RECT(RECT& rc) : m_lpRect(&rc) - { } - LPRECT m_lpRect; -}; - -class _U_MENUorID -{ -public: - _U_MENUorID(HMENU hMenu) : m_hMenu(hMenu) - { } - _U_MENUorID(UINT nID) : m_hMenu((HMENU)(UINT_PTR)nID) - { } - HMENU m_hMenu; -}; - -class _U_STRINGorID -{ -public: - _U_STRINGorID(LPCTSTR lpString) : m_lpstr(lpString) - { } - _U_STRINGorID(UINT nID) : m_lpstr(MAKEINTRESOURCE(nID)) - { } - LPCTSTR m_lpstr; -}; - -struct _ATL_WNDCLASSINFOA; -struct _ATL_WNDCLASSINFOW; - -ATLAPI_(ATOM) AtlWinModuleRegisterWndClassInfoA(_ATL_WIN_MODULE* pWinModule, _ATL_BASE_MODULE* pBaseModule, _ATL_WNDCLASSINFOA* p, WNDPROC* pProc); -inline ATOM AtlModuleRegisterWndClassInfoA(_ATL_MODULE* /*pM*/, _ATL_WNDCLASSINFOA* p, WNDPROC* pProc) -{ - return AtlWinModuleRegisterWndClassInfoA(&_AtlWinModule, &_AtlBaseModule, p, pProc); -} - -ATLAPI_(ATOM) AtlWinModuleRegisterWndClassInfoW(_ATL_WIN_MODULE* pWinModule, _ATL_BASE_MODULE* pBaseModule, _ATL_WNDCLASSINFOW* p, WNDPROC* pProc); -inline ATOM AtlModuleRegisterWndClassInfoW(_ATL_MODULE* /*pM*/, _ATL_WNDCLASSINFOW* p, WNDPROC* pProc) -{ - return AtlWinModuleRegisterWndClassInfoW(&_AtlWinModule, &_AtlBaseModule, p, pProc); -} - -ATLAPI_(ATOM) AtlWinModuleRegisterClassExA(_ATL_WIN_MODULE* pWinModule, const WNDCLASSEXA *lpwc); -inline ATOM AtlModuleRegisterClassExA(_ATL_MODULE* /*pM*/, const WNDCLASSEXA *lpwc) -{ - return AtlWinModuleRegisterClassExA(&_AtlWinModule, lpwc); -} - -ATLAPI_(ATOM) AtlWinModuleRegisterClassExW(_ATL_WIN_MODULE* pWinModule, const WNDCLASSEXW *lpwc); -inline ATOM AtlModuleRegisterClassExW(_ATL_MODULE* /*pM*/, const WNDCLASSEXW *lpwc) -{ - return AtlWinModuleRegisterClassExW(&_AtlWinModule, lpwc); -} - - -#ifdef UNICODE -#define AtlWinModuleRegisterWndClassInfo AtlWinModuleRegisterWndClassInfoW -#define AtlWinModuleRegisterClassEx AtlWinModuleRegisterClassExW -#define AtlModuleRegisterWndClassInfo AtlModuleRegisterWndClassInfoW -#define AtlModuleRegisterClassEx AtlModuleRegisterClassExW -#else -#define AtlWinModuleRegisterWndClassInfo AtlWinModuleRegisterWndClassInfoA -#define AtlWinModuleRegisterClassEx AtlWinModuleRegisterClassExA -#define AtlModuleRegisterWndClassInfo AtlModuleRegisterWndClassInfoA -#define AtlModuleRegisterClassEx AtlModuleRegisterClassExA -#endif - - -#define HIMETRIC_PER_INCH 2540 -#define MAP_PIX_TO_LOGHIM(x,ppli) MulDiv(HIMETRIC_PER_INCH, (x), (ppli)) -#define MAP_LOGHIM_TO_PIX(x,ppli) MulDiv((ppli), (x), HIMETRIC_PER_INCH) - -ATLAPI_(HDC) AtlCreateTargetDC(HDC hdc, DVTARGETDEVICE* ptd); -ATLAPI_(void) AtlHiMetricToPixel(const SIZEL * lpSizeInHiMetric, LPSIZEL lpSizeInPix); -ATLAPI_(void) AtlPixelToHiMetric(const SIZEL * lpSizeInPix, LPSIZEL lpSizeInHiMetric); - -#ifndef GET_X_LPARAM -#define GET_X_LPARAM(lParam) ((int)(short)LOWORD(lParam)) -#endif -#ifndef GET_Y_LPARAM -#define GET_Y_LPARAM(lParam) ((int)(short)HIWORD(lParam)) -#endif - - -//#ifndef _ATL_DLL_IMPL -}; //namespace ATL -//#endif - -namespace ATL -{ - -///////////////////////////////////////////////////////////////////////////// -// _ATL_MSG - extended MSG structure - -struct _ATL_MSG : public MSG -{ -public: -// Additional data members - int cbSize; - BOOL bHandled; - -// Constructors - _ATL_MSG() : cbSize(sizeof(_ATL_MSG)), bHandled(TRUE) - { - hwnd = NULL; - message = 0; - wParam = 0; - lParam = 0; - time = 0; - pt.x = pt.y = 0; - } - _ATL_MSG(HWND hWnd, UINT uMsg, WPARAM wParamIn, LPARAM lParamIn, DWORD dwTime, POINT ptIn, BOOL bHandledIn) : cbSize(sizeof(_ATL_MSG)), bHandled(bHandledIn) - { - hwnd = hWnd; - message = uMsg; - wParam = wParamIn; - lParam = lParamIn; - time = dwTime; - pt = ptIn; - } - _ATL_MSG(HWND hWnd, UINT uMsg, WPARAM wParamIn, LPARAM lParamIn, BOOL bHandledIn = TRUE) : cbSize(sizeof(_ATL_MSG)), bHandled(bHandledIn) - { - hwnd = hWnd; - message = uMsg; - wParam = wParamIn; - lParam = lParamIn; - time = 0; - pt.x = pt.y = 0; - } - _ATL_MSG(MSG& msg, BOOL bHandledIn = TRUE) : cbSize(sizeof(_ATL_MSG)), bHandled(bHandledIn) - { - hwnd = msg.hwnd; - message = msg.message; - wParam = msg.wParam; - lParam = msg.lParam; - time = msg.time; - pt = msg.pt; - } -}; - -struct _ATL_WNDCLASSINFOA -{ - WNDCLASSEXA m_wc; - LPCSTR m_lpszOrigName; - WNDPROC pWndProc; - LPCSTR m_lpszCursorID; - BOOL m_bSystemCursor; - ATOM m_atom; - CHAR m_szAutoName[5+sizeof(void*)*CHAR_BIT]; - ATOM Register(WNDPROC* p) - { - return AtlWinModuleRegisterWndClassInfoA(&_AtlWinModule, &_AtlBaseModule, this, p); - } -}; - -struct _ATL_WNDCLASSINFOW -{ - WNDCLASSEXW m_wc; - LPCWSTR m_lpszOrigName; - WNDPROC pWndProc; - LPCWSTR m_lpszCursorID; - BOOL m_bSystemCursor; - ATOM m_atom; - WCHAR m_szAutoName[5+sizeof(void*)*CHAR_BIT]; - ATOM Register(WNDPROC* p) - { - return AtlWinModuleRegisterWndClassInfoW(&_AtlWinModule, &_AtlBaseModule, this, p); - } -}; - -}; // namespace ATL - -namespace ATL -{ - -///////////////////////////////////////////////////////////////////////////// -// Forward declarations - -class CWindow; -#ifndef _ATL_NO_HOSTING -template class CAxWindowT; -template class CAxWindow2T; -#endif //!_ATL_NO_HOSTING -class CMessageMap; -class CDynamicChain; -typedef _ATL_WNDCLASSINFOA CWndClassInfoA; -typedef _ATL_WNDCLASSINFOW CWndClassInfoW; -#ifdef UNICODE -#define CWndClassInfo CWndClassInfoW -#else -#define CWndClassInfo CWndClassInfoA -#endif -template class CWindowImpl; -template class CWindowWithReflectorImpl; -template class CDialogImpl; -#ifndef _ATL_NO_HOSTING -template class CAxDialogImpl; -#endif //!_ATL_NO_HOSTING -template class CSimpleDialog; -template class CContainedWindowT; - -///////////////////////////////////////////////////////////////////////////// -// Helper functions for cracking dialog templates - -class _DialogSplitHelper -{ -public: - // Constants used in DLGINIT resources for OLE control containers - // NOTE: These are NOT real Windows messages they are simply tags - // used in the control resource and are never used as 'messages' - enum - { - ATL_WM_OCC_LOADFROMSTREAM = 0x0376, - ATL_WM_OCC_LOADFROMSTORAGE = 0x0377, - ATL_WM_OCC_INITNEW = 0x0378, - ATL_WM_OCC_LOADFROMSTREAM_EX = 0x037A, - ATL_WM_OCC_LOADFROMSTORAGE_EX = 0x037B, - ATL_DISPID_DATASOURCE = 0x80010001, - ATL_DISPID_DATAFIELD = 0x80010002, - }; - -//local struct used for implementation -#pragma pack(push, 1) - struct DLGINITSTRUCT - { - WORD nIDC; - WORD message; - DWORD dwSize; - }; - struct DLGTEMPLATEEX - { - WORD dlgVer; - WORD signature; - DWORD helpID; - DWORD exStyle; - DWORD style; - WORD cDlgItems; - short x; - short y; - short cx; - short cy; - - // Everything else in this structure is variable length, - // and therefore must be determined dynamically - - // sz_Or_Ord menu; // name or ordinal of a menu resource - // sz_Or_Ord windowClass; // name or ordinal of a window class - // WCHAR title[titleLen]; // title string of the dialog box - // short pointsize; // only if DS_SETFONT is set - // short weight; // only if DS_SETFONT is set - // short bItalic; // only if DS_SETFONT is set - // WCHAR font[fontLen]; // typeface name, if DS_SETFONT is set - }; - struct DLGITEMTEMPLATEEX - { - DWORD helpID; - DWORD exStyle; - DWORD style; - short x; - short y; - short cx; - short cy; - DWORD id; - - // Everything else in this structure is variable length, - // and therefore must be determined dynamically - - // sz_Or_Ord windowClass; // name or ordinal of a window class - // sz_Or_Ord title; // title string or ordinal of a resource - // WORD extraCount; // bytes following creation data - }; -#pragma pack(pop) - - static BOOL IsDialogEx(const DLGTEMPLATE* pTemplate) - { - return ((DLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF; - } - - inline static WORD& DlgTemplateItemCount(DLGTEMPLATE* pTemplate) - { - if (IsDialogEx(pTemplate)) - return reinterpret_cast(pTemplate)->cDlgItems; - else - return pTemplate->cdit; - } - - inline static const WORD& DlgTemplateItemCount(const DLGTEMPLATE* pTemplate) - { - if (IsDialogEx(pTemplate)) - return reinterpret_cast(pTemplate)->cDlgItems; - else - return pTemplate->cdit; - } - - static DLGITEMTEMPLATE* FindFirstDlgItem(const DLGTEMPLATE* pTemplate) - { - BOOL bDialogEx = IsDialogEx(pTemplate); - - WORD* pw; - DWORD dwStyle; - if (bDialogEx) - { - pw = (WORD*)((DLGTEMPLATEEX*)pTemplate + 1); - dwStyle = ((DLGTEMPLATEEX*)pTemplate)->style; - } - else - { - pw = (WORD*)(pTemplate + 1); - dwStyle = pTemplate->style; - } - - // Check for presence of menu and skip it if there is one - // 0x0000 means there is no menu - // 0xFFFF means there is a menu ID following - // Everything else means that this is a NULL terminated Unicode string - // which identifies the menu resource - if (*pw == 0xFFFF) - pw += 2; // Has menu ID, so skip 2 words - else - while (*pw++); // Either No menu, or string, skip past terminating NULL - - // Check for presence of class name string - // 0x0000 means "Use system dialog class name" - // 0xFFFF means there is a window class (atom) specified - // Everything else means that this is a NULL terminated Unicode string - // which identifies the menu resource - if (*pw == 0xFFFF) - pw += 2; // Has class atom, so skip 2 words - else - while (*pw++); // Either No class, or string, skip past terminating NULL - - // Skip caption string - while (*pw++); - - // If we have DS_SETFONT, there is extra font information which we must now skip - if (dwStyle & DS_SETFONT) - { - // If it is a regular DLGTEMPLATE there is only a short for the point size - // and a string specifying the font (typefacename). If this is a DLGTEMPLATEEX - // then there is also the font weight, and bItalic which must be skipped - if (bDialogEx) - pw += 3; // Skip font size, weight, (italic, charset) - else - pw += 1; // Skip font size - while (*pw++); // Skip typeface name - } - - // Dword-align and return - return (DLGITEMTEMPLATE*)(((DWORD_PTR)pw + 3) & ~3); - } - - // Given the current dialog item and whether this is an extended dialog - // return a pointer to the next DLGITEMTEMPLATE* - static DLGITEMTEMPLATE* FindNextDlgItem(DLGITEMTEMPLATE* pItem, BOOL bDialogEx) - { - WORD* pw; - - // First skip fixed size header information, size of which depends - // if this is a DLGITEMTEMPLATE or DLGITEMTEMPLATEEX - if (bDialogEx) - pw = (WORD*)((DLGITEMTEMPLATEEX*)pItem + 1); - else - pw = (WORD*)(pItem + 1); - - if (*pw == 0xFFFF) // Skip class name ordinal or string - pw += 2; // (WORDs) - else - while (*pw++); - - if (*pw == 0xFFFF) // Skip title ordinal or string - pw += 2; // (WORDs) - else - while (*pw++); - - WORD cbExtra = *pw++; // Skip extra data - - // cbExtra includes the size WORD in DIALOG resource. - if (cbExtra != 0 && !bDialogEx) - cbExtra -= 2; - - // Dword-align and return - return (DLGITEMTEMPLATE*)(((DWORD_PTR)pw + cbExtra + 3) & ~3); - } - - // Find the initialization data (Stream) for the control specified by the ID - // If found, return the pointer into the data and the length of the data - static DWORD FindCreateData(DWORD dwID, BYTE* pInitData, BYTE** pData) - { - while (pInitData) - { - // Read the DLGINIT header - WORD nIDC = *((UNALIGNED WORD*)pInitData); - pInitData += sizeof(WORD); - BYTE* pTemp = pInitData; - WORD nMsg = *((UNALIGNED WORD*)pInitData); - pInitData += sizeof(WORD); - DWORD dwLen = *((UNALIGNED DWORD*)pInitData); - pInitData += sizeof(DWORD); - - // If the header is for the control specified get the other info - if (nIDC == dwID) - { - if (nMsg == (WORD)ATL_WM_OCC_INITNEW) - { - ATLASSERT(dwLen == 0); - return 0; - } - *pData = pTemp; - return dwLen + sizeof(WORD) + sizeof(DWORD); - } - - // It's not the right control, skip past data - pInitData += dwLen; - } - return 0; - } - - static bool IsActiveXControl(DLGITEMTEMPLATE* pItem, BOOL bDialogEx) - { - LPWSTR pszClassName; - pszClassName = bDialogEx ? - (LPWSTR)(((DLGITEMTEMPLATEEX*)pItem) + 1) : - (LPWSTR)(pItem + 1); - if (pszClassName[0] == L'{') - return true; - return false; - } - - // Convert MSDEV (MFC) style DLGTEMPLATE with controls to regular DLGTEMPLATE - static DLGTEMPLATE* SplitDialogTemplate(DLGTEMPLATE* pTemplate, BYTE* /*pInitData*/) - { - // Calculate the size of the DLGTEMPLATE for allocating the new one - DLGITEMTEMPLATE* pFirstItem = FindFirstDlgItem(pTemplate); - ULONG_PTR cbHeader = (BYTE*)pFirstItem - (BYTE*)pTemplate; - ULONG_PTR cbNewTemplate = cbHeader; - - BOOL bDialogEx = IsDialogEx(pTemplate); - - int iItem; - int nItems = (int)DlgTemplateItemCount(pTemplate); - LPWSTR pszClassName; - BOOL bHasOleControls = FALSE; - - // Make first pass through the dialog template. On this pass, we're - // interested in determining: - // 1. Does this template contain any ActiveX Controls? - // 2. If so, how large a buffer is needed for a template containing - // only the non-OLE controls? - - DLGITEMTEMPLATE* pItem = pFirstItem; - DLGITEMTEMPLATE* pNextItem = pItem; - for (iItem = 0; iItem < nItems; iItem++) - { - pNextItem = FindNextDlgItem(pItem, bDialogEx); - - pszClassName = bDialogEx ? - (LPWSTR)(((DLGITEMTEMPLATEEX*)pItem) + 1) : - (LPWSTR)(pItem + 1); - - // Check if the class name begins with a '{' - // If it does, that means it is an ActiveX Control in MSDEV (MFC) format - if (pszClassName[0] == L'{') - { - // Item is an ActiveX control. - bHasOleControls = TRUE; - } - else - { - // Item is not an ActiveX Control: make room for it in new template. - cbNewTemplate += (BYTE*)pNextItem - (BYTE*)pItem; - } - - pItem = pNextItem; - } - - // No OLE controls were found, so there's no reason to go any further. - if (!bHasOleControls) - return pTemplate; - - // Copy entire header into new template. - BYTE* pNew = (BYTE*)GlobalAlloc(GMEM_FIXED, cbNewTemplate); - DLGTEMPLATE* pNewTemplate = (DLGTEMPLATE*)pNew; - memcpy(pNew, pTemplate, cbHeader); - pNew += cbHeader; - - // Initialize item count in new header to zero. - DlgTemplateItemCount(pNewTemplate) = 0; - - pItem = pFirstItem; - pNextItem = pItem; - - // Second pass through the dialog template. On this pass, we want to: - // 1. Copy all the non-OLE controls into the new template. - for (iItem = 0; iItem < nItems; iItem++) - { - pNextItem = FindNextDlgItem(pItem, bDialogEx); - - pszClassName = bDialogEx ? - (LPWSTR)(((DLGITEMTEMPLATEEX*)pItem) + 1) : - (LPWSTR)(pItem + 1); - - if (pszClassName[0] != L'{') - { - // Item is not an OLE control: copy it to the new template. - ULONG_PTR cbItem = (BYTE*)pNextItem - (BYTE*)pItem; - ATLASSERT(cbItem >= (bDialogEx ? - sizeof(DLGITEMTEMPLATEEX) : - sizeof(DLGITEMTEMPLATE))); - memcpy(pNew, pItem, cbItem); - pNew += cbItem; - - // Incrememt item count in new header. - ++DlgTemplateItemCount(pNewTemplate); - } - - pItem = pNextItem; - } - return pNewTemplate; - } - - static HRESULT ParseInitData(IStream* pStream, BSTR* pLicKey) - { - *pLicKey = NULL; - if(pStream == NULL) - return S_OK; // nothing to do - - ULONG uRead; - HRESULT hr; - - WORD nMsg; - hr = pStream->Read(&nMsg, sizeof(WORD), &uRead); - if (FAILED(hr)) - return hr; - - DWORD dwLen; - hr = pStream->Read(&dwLen, sizeof(DWORD), &uRead); - if (FAILED(hr)) - return hr; - - DWORD cchLicKey; - hr = pStream->Read(&cchLicKey, sizeof(DWORD), &uRead); - if (FAILED(hr)) - return hr; - - if (cchLicKey > 0) - { - CComBSTR bstr(cchLicKey); - if (bstr.Length() == 0) - return E_OUTOFMEMORY; - memset(bstr.m_str, 0, (cchLicKey + 1) * sizeof(OLECHAR)); - hr = pStream->Read(bstr.m_str, cchLicKey * sizeof(OLECHAR), &uRead); - if (FAILED(hr)) - return hr; - *pLicKey = bstr.Detach(); - } - - // Extended (DATABINDING) stream format is not supported, - // we reject databinding info but preserve other information - if (nMsg == (WORD)ATL_WM_OCC_LOADFROMSTREAM_EX || - nMsg == (WORD)ATL_WM_OCC_LOADFROMSTORAGE_EX) - { - // Read the size of the section - ULONG cbOffset; - hr = pStream->Read(&cbOffset, sizeof(ULONG), &uRead); - if (FAILED(hr)) - return hr; - BYTE pTemp[1000]; - cbOffset -= sizeof(ULONG); - - while (cbOffset > 0) - { - pStream->Read(pTemp, (cbOffset < 1000 ? cbOffset : 1000), &uRead); - cbOffset -= uRead; - } - return S_OK; - } - if (nMsg == (WORD)ATL_WM_OCC_LOADFROMSTREAM) - { - return S_OK; - } - return E_FAIL; - } -}; - -///////////////////////////////////////////////////////////////////////////// -// CWindow - client side for a Windows window - -class CWindow -{ -public: - static RECT rcDefault; - HWND m_hWnd; - - CWindow(HWND hWnd = NULL) throw() : - m_hWnd(hWnd) - { - } - - CWindow& operator=(HWND hWnd) throw() - { - m_hWnd = hWnd; - return *this; - } - - static LPCTSTR GetWndClassName() throw() - { - return NULL; - } - - void Attach(HWND hWndNew) throw() - { - ATLASSERT(m_hWnd == NULL); - ATLASSERT((hWndNew == NULL) || ::IsWindow(hWndNew)); - m_hWnd = hWndNew; - } - - HWND Detach() throw() - { - HWND hWnd = m_hWnd; - m_hWnd = NULL; - return hWnd; - } - - HWND Create(LPCTSTR lpstrWndClass, HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) throw() - { - ATLASSERT(m_hWnd == NULL); - if(rect.m_lpRect == NULL) - rect.m_lpRect = &rcDefault; - m_hWnd = ::CreateWindowEx(dwExStyle, lpstrWndClass, szWindowName, - dwStyle, rect.m_lpRect->left, rect.m_lpRect->top, rect.m_lpRect->right - rect.m_lpRect->left, - rect.m_lpRect->bottom - rect.m_lpRect->top, hWndParent, MenuOrID.m_hMenu, - _AtlBaseModule.GetModuleInstance(), lpCreateParam); - return m_hWnd; - } - - BOOL DestroyWindow() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - - if(!::DestroyWindow(m_hWnd)) - return FALSE; - - m_hWnd = NULL; - return TRUE; - } - -// Attributes - - operator HWND() const throw() - { - return m_hWnd; - } - - DWORD GetStyle() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::GetWindowLong(m_hWnd, GWL_STYLE); - } - - DWORD GetExStyle() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::GetWindowLong(m_hWnd, GWL_EXSTYLE); - } - - LONG GetWindowLong(int nIndex) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetWindowLong(m_hWnd, nIndex); - } - - LONG_PTR GetWindowLongPtr(int nIndex) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetWindowLongPtr(m_hWnd, nIndex); - } - - LONG SetWindowLong(int nIndex, LONG dwNewLong) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetWindowLong(m_hWnd, nIndex, dwNewLong); - } - - LONG_PTR SetWindowLongPtr(int nIndex, LONG_PTR dwNewLong) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetWindowLongPtr(m_hWnd, nIndex, dwNewLong); - } - - WORD GetWindowWord(int nIndex) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetWindowWord(m_hWnd, nIndex); - } - - WORD SetWindowWord(int nIndex, WORD wNewWord) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetWindowWord(m_hWnd, nIndex, wNewWord); - } - -// Message Functions - - LRESULT SendMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SendMessage(m_hWnd,message,wParam,lParam); - } - - BOOL PostMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::PostMessage(m_hWnd,message,wParam,lParam); - } - - BOOL SendNotifyMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SendNotifyMessage(m_hWnd, message, wParam, lParam); - } - - // support for C style macros - static LRESULT SendMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) throw() - { - ATLASSERT(::IsWindow(hWnd)); - return ::SendMessage(hWnd, message, wParam, lParam); - } - -// Window Text Functions - - BOOL SetWindowText(LPCTSTR lpszString) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetWindowText(m_hWnd, lpszString); - } - - int GetWindowText(LPTSTR lpszStringBuf, int nMaxCount) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetWindowText(m_hWnd, lpszStringBuf, nMaxCount); - } - int GetWindowText(CSimpleString& strText) const - { - int nLength; - LPTSTR pszText; - - nLength = GetWindowTextLength(); - pszText = strText.GetBuffer(nLength+1); - nLength = GetWindowText(pszText, nLength+1); - strText.ReleaseBuffer(nLength); - - return nLength; - } - int GetWindowTextLength() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetWindowTextLength(m_hWnd); - } - -// Font Functions - - void SetFont(HFONT hFont, BOOL bRedraw = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(bRedraw, 0)); - } - - HFONT GetFont() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HFONT)::SendMessage(m_hWnd, WM_GETFONT, 0, 0); - } - -// Menu Functions (non-child windows only) - - HMENU GetMenu() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HMENU)::GetMenu(m_hWnd); - } - - BOOL SetMenu(HMENU hMenu) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetMenu(m_hWnd, hMenu); - } - - BOOL DrawMenuBar() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::DrawMenuBar(m_hWnd); - } - - HMENU GetSystemMenu(BOOL bRevert) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HMENU)::GetSystemMenu(m_hWnd, bRevert); - } - - BOOL HiliteMenuItem(HMENU hMenu, UINT uItemHilite, UINT uHilite) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::HiliteMenuItem(m_hWnd, hMenu, uItemHilite, uHilite); - } - -// Window Size and Position Functions - - BOOL IsIconic() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::IsIconic(m_hWnd); - } - - BOOL IsZoomed() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::IsZoomed(m_hWnd); - } - - BOOL MoveWindow(int x, int y, int nWidth, int nHeight, BOOL bRepaint = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::MoveWindow(m_hWnd, x, y, nWidth, nHeight, bRepaint); - } - - BOOL MoveWindow(LPCRECT lpRect, BOOL bRepaint = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::MoveWindow(m_hWnd, lpRect->left, lpRect->top, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top, bRepaint); - } - - BOOL SetWindowPos(HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetWindowPos(m_hWnd, hWndInsertAfter, x, y, cx, cy, nFlags); - } - - BOOL SetWindowPos(HWND hWndInsertAfter, LPCRECT lpRect, UINT nFlags) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetWindowPos(m_hWnd, hWndInsertAfter, lpRect->left, lpRect->top, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top, nFlags); - } - - UINT ArrangeIconicWindows() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ArrangeIconicWindows(m_hWnd); - } - - BOOL BringWindowToTop() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::BringWindowToTop(m_hWnd); - } - - BOOL GetWindowRect(LPRECT lpRect) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetWindowRect(m_hWnd, lpRect); - } - - BOOL GetClientRect(LPRECT lpRect) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetClientRect(m_hWnd, lpRect); - } - - BOOL GetWindowPlacement(WINDOWPLACEMENT FAR* lpwndpl) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetWindowPlacement(m_hWnd, lpwndpl); - } - - BOOL SetWindowPlacement(const WINDOWPLACEMENT FAR* lpwndpl) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetWindowPlacement(m_hWnd, lpwndpl); - } - -// Coordinate Mapping Functions - - BOOL ClientToScreen(LPPOINT lpPoint) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ClientToScreen(m_hWnd, lpPoint); - } - - BOOL ClientToScreen(LPRECT lpRect) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - if(!::ClientToScreen(m_hWnd, (LPPOINT)lpRect)) - return FALSE; - return ::ClientToScreen(m_hWnd, ((LPPOINT)lpRect)+1); - } - - BOOL ScreenToClient(LPPOINT lpPoint) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ScreenToClient(m_hWnd, lpPoint); - } - - BOOL ScreenToClient(LPRECT lpRect) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - if(!::ScreenToClient(m_hWnd, (LPPOINT)lpRect)) - return FALSE; - return ::ScreenToClient(m_hWnd, ((LPPOINT)lpRect)+1); - } - - int MapWindowPoints(HWND hWndTo, LPPOINT lpPoint, UINT nCount) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::MapWindowPoints(m_hWnd, hWndTo, lpPoint, nCount); - } - - int MapWindowPoints(HWND hWndTo, LPRECT lpRect) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::MapWindowPoints(m_hWnd, hWndTo, (LPPOINT)lpRect, 2); - } - -// Update and Painting Functions - - HDC BeginPaint(LPPAINTSTRUCT lpPaint) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::BeginPaint(m_hWnd, lpPaint); - } - - void EndPaint(LPPAINTSTRUCT lpPaint) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::EndPaint(m_hWnd, lpPaint); - } - - HDC GetDC() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetDC(m_hWnd); - } - - HDC GetWindowDC() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetWindowDC(m_hWnd); - } - - int ReleaseDC(HDC hDC) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ReleaseDC(m_hWnd, hDC); - } - - void Print(HDC hDC, DWORD dwFlags) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_PRINT, (WPARAM)hDC, dwFlags); - } - - void PrintClient(HDC hDC, DWORD dwFlags) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_PRINTCLIENT, (WPARAM)hDC, dwFlags); - } - - BOOL UpdateWindow() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::UpdateWindow(m_hWnd); - } - - void SetRedraw(BOOL bRedraw = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_SETREDRAW, (WPARAM)bRedraw, 0); - } - - BOOL GetUpdateRect(LPRECT lpRect, BOOL bErase = FALSE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetUpdateRect(m_hWnd, lpRect, bErase); - } - - int GetUpdateRgn(HRGN hRgn, BOOL bErase = FALSE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetUpdateRgn(m_hWnd, hRgn, bErase); - } - - BOOL Invalidate(BOOL bErase = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::InvalidateRect(m_hWnd, NULL, bErase); - } - - BOOL InvalidateRect(LPCRECT lpRect, BOOL bErase = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::InvalidateRect(m_hWnd, lpRect, bErase); - } - - BOOL ValidateRect(LPCRECT lpRect) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ValidateRect(m_hWnd, lpRect); - } - - void InvalidateRgn(HRGN hRgn, BOOL bErase = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::InvalidateRgn(m_hWnd, hRgn, bErase); - } - - BOOL ValidateRgn(HRGN hRgn) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ValidateRgn(m_hWnd, hRgn); - } - - BOOL ShowWindow(int nCmdShow) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ShowWindow(m_hWnd, nCmdShow); - } - - BOOL IsWindowVisible() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::IsWindowVisible(m_hWnd); - } - - BOOL ShowOwnedPopups(BOOL bShow = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ShowOwnedPopups(m_hWnd, bShow); - } - - HDC GetDCEx(HRGN hRgnClip, DWORD flags) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetDCEx(m_hWnd, hRgnClip, flags); - } - - BOOL LockWindowUpdate(BOOL bLock = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::LockWindowUpdate(bLock ? m_hWnd : NULL); - } - - BOOL RedrawWindow(LPCRECT lpRectUpdate = NULL, HRGN hRgnUpdate = NULL, UINT flags = RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::RedrawWindow(m_hWnd, lpRectUpdate, hRgnUpdate, flags); - } - -// Timer Functions - - UINT_PTR SetTimer(UINT_PTR nIDEvent, UINT nElapse, void (CALLBACK* lpfnTimer)(HWND, UINT, UINT_PTR, DWORD) = NULL) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetTimer(m_hWnd, nIDEvent, nElapse, (TIMERPROC)lpfnTimer); - } - - BOOL KillTimer(UINT_PTR nIDEvent) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::KillTimer(m_hWnd, nIDEvent); - } - -// Window State Functions - - BOOL IsWindowEnabled() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::IsWindowEnabled(m_hWnd); - } - - BOOL EnableWindow(BOOL bEnable = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::EnableWindow(m_hWnd, bEnable); - } - - HWND SetActiveWindow() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetActiveWindow(m_hWnd); - } - - HWND SetCapture() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetCapture(m_hWnd); - } - - HWND SetFocus() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetFocus(m_hWnd); - } - -// Dialog-Box Item Functions - - BOOL CheckDlgButton(int nIDButton, UINT nCheck) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::CheckDlgButton(m_hWnd, nIDButton, nCheck); - } - - BOOL CheckRadioButton(int nIDFirstButton, int nIDLastButton, int nIDCheckButton) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::CheckRadioButton(m_hWnd, nIDFirstButton, nIDLastButton, nIDCheckButton); - } - - int DlgDirList(LPTSTR lpPathSpec, int nIDListBox, int nIDStaticPath, UINT nFileType) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::DlgDirList(m_hWnd, lpPathSpec, nIDListBox, nIDStaticPath, nFileType); - } - - int DlgDirListComboBox(LPTSTR lpPathSpec, int nIDComboBox, int nIDStaticPath, UINT nFileType) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::DlgDirListComboBox(m_hWnd, lpPathSpec, nIDComboBox, nIDStaticPath, nFileType); - } - - BOOL DlgDirSelect(LPTSTR lpString, int nCount, int nIDListBox) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::DlgDirSelectEx(m_hWnd, lpString, nCount, nIDListBox); - } - - BOOL DlgDirSelectComboBox(LPTSTR lpString, int nCount, int nIDComboBox) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::DlgDirSelectComboBoxEx(m_hWnd, lpString, nCount, nIDComboBox); - } - - UINT GetDlgItemInt(int nID, BOOL* lpTrans = NULL, BOOL bSigned = TRUE) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetDlgItemInt(m_hWnd, nID, lpTrans, bSigned); - } - - UINT GetDlgItemText(int nID, LPTSTR lpStr, int nMaxCount) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetDlgItemText(m_hWnd, nID, lpStr, nMaxCount); - } - - UINT GetDlgItemText(int nID, CSimpleString& strText) const - { - HWND hItem; - - ATLASSERT(::IsWindow(m_hWnd)); - hItem = GetDlgItem(nID); - if (hItem != NULL) - { - int nLength; - LPTSTR pszText; - - nLength = ::GetWindowTextLength(hItem); - pszText = strText.GetBuffer(nLength+1); - nLength = ::GetWindowText(hItem, pszText, nLength+1); - strText.ReleaseBuffer(nLength); - - return nLength; - } - else - { - strText.Empty(); - - return 0; - } - } -#ifdef _OLEAUTO_H_ - BOOL GetDlgItemText(int nID, BSTR& bstrText) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - - HWND hWndCtl = GetDlgItem(nID); - if(hWndCtl == NULL) - return FALSE; - - return CWindow(hWndCtl).GetWindowText(bstrText); - } -#endif // _OLEAUTO_H_ - CWindow GetNextDlgGroupItem(HWND hWndCtl, BOOL bPrevious = FALSE) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return CWindow(::GetNextDlgGroupItem(m_hWnd, hWndCtl, bPrevious)); - } - - CWindow GetNextDlgTabItem(HWND hWndCtl, BOOL bPrevious = FALSE) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return CWindow(::GetNextDlgTabItem(m_hWnd, hWndCtl, bPrevious)); - } - - UINT IsDlgButtonChecked(int nIDButton) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::IsDlgButtonChecked(m_hWnd, nIDButton); - } - - LRESULT SendDlgItemMessage(int nID, UINT message, WPARAM wParam = 0, LPARAM lParam = 0) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SendDlgItemMessage(m_hWnd, nID, message, wParam, lParam); - } - - BOOL SetDlgItemInt(int nID, UINT nValue, BOOL bSigned = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetDlgItemInt(m_hWnd, nID, nValue, bSigned); - } - - BOOL SetDlgItemText(int nID, LPCTSTR lpszString) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetDlgItemText(m_hWnd, nID, lpszString); - } - -#ifndef _ATL_NO_HOSTING - HRESULT GetDlgControl(int nID, REFIID iid, void** ppCtrl) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(ppCtrl != NULL); - if (ppCtrl == NULL) - return E_POINTER; - *ppCtrl = NULL; - HRESULT hr = HRESULT_FROM_WIN32(ERROR_CONTROL_ID_NOT_FOUND); - HWND hWndCtrl = GetDlgItem(nID); - if (hWndCtrl != NULL) - { - *ppCtrl = NULL; - CComPtr spUnk; - hr = AtlAxGetControl(hWndCtrl, &spUnk); - if (SUCCEEDED(hr)) - hr = spUnk->QueryInterface(iid, ppCtrl); - } - return hr; - } - HRESULT GetDlgHost(int nID, REFIID iid, void** ppHost) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(ppHost != NULL); - if (ppHost == NULL) - return E_POINTER; - *ppHost = NULL; - HRESULT hr = HRESULT_FROM_WIN32(ERROR_CONTROL_ID_NOT_FOUND); - HWND hWndCtrl = GetDlgItem(nID); - if (hWndCtrl != NULL) - { - CComPtr spUnk; - hr = AtlAxGetHost(hWndCtrl, &spUnk); - if (SUCCEEDED(hr)) - hr = spUnk->QueryInterface(iid, ppHost); - } - return hr; - } -#endif //!_ATL_NO_HOSTING - -// Scrolling Functions - - int GetScrollPos(int nBar) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetScrollPos(m_hWnd, nBar); - } - - BOOL GetScrollRange(int nBar, LPINT lpMinPos, LPINT lpMaxPos) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetScrollRange(m_hWnd, nBar, lpMinPos, lpMaxPos); - } - - BOOL ScrollWindow(int xAmount, int yAmount, LPCRECT lpRect = NULL, LPCRECT lpClipRect = NULL) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ScrollWindow(m_hWnd, xAmount, yAmount, lpRect, lpClipRect); - } - - int ScrollWindowEx(int dx, int dy, LPCRECT lpRectScroll, LPCRECT lpRectClip, HRGN hRgnUpdate, LPRECT lpRectUpdate, UINT uFlags) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ScrollWindowEx(m_hWnd, dx, dy, lpRectScroll, lpRectClip, hRgnUpdate, lpRectUpdate, uFlags); - } - - int ScrollWindowEx(int dx, int dy, UINT uFlags, LPCRECT lpRectScroll = NULL, LPCRECT lpRectClip = NULL, HRGN hRgnUpdate = NULL, LPRECT lpRectUpdate = NULL) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ScrollWindowEx(m_hWnd, dx, dy, lpRectScroll, lpRectClip, hRgnUpdate, lpRectUpdate, uFlags); - } - - int SetScrollPos(int nBar, int nPos, BOOL bRedraw = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetScrollPos(m_hWnd, nBar, nPos, bRedraw); - } - - BOOL SetScrollRange(int nBar, int nMinPos, int nMaxPos, BOOL bRedraw = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetScrollRange(m_hWnd, nBar, nMinPos, nMaxPos, bRedraw); - } - - BOOL ShowScrollBar(UINT nBar, BOOL bShow = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ShowScrollBar(m_hWnd, nBar, bShow); - } - - BOOL EnableScrollBar(UINT uSBFlags, UINT uArrowFlags = ESB_ENABLE_BOTH) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::EnableScrollBar(m_hWnd, uSBFlags, uArrowFlags); - } - -// Window Access Functions - - CWindow ChildWindowFromPoint(POINT point) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return CWindow(::ChildWindowFromPoint(m_hWnd, point)); - } - - CWindow ChildWindowFromPointEx(POINT point, UINT uFlags) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return CWindow(::ChildWindowFromPointEx(m_hWnd, point, uFlags)); - } - - CWindow GetTopWindow() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return CWindow(::GetTopWindow(m_hWnd)); - } - - CWindow GetWindow(UINT nCmd) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return CWindow(::GetWindow(m_hWnd, nCmd)); - } - - CWindow GetLastActivePopup() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return CWindow(::GetLastActivePopup(m_hWnd)); - } - - BOOL IsChild(HWND hWnd) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::IsChild(m_hWnd, hWnd); - } - - CWindow GetParent() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return CWindow(::GetParent(m_hWnd)); - } - - CWindow SetParent(HWND hWndNewParent) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return CWindow(::SetParent(m_hWnd, hWndNewParent)); - } - -// Window Tree Access - - int GetDlgCtrlID() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetDlgCtrlID(m_hWnd); - } - - int SetDlgCtrlID(int nID) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SetWindowLong(m_hWnd, GWL_ID, nID); - } - - CWindow GetDlgItem(int nID) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return CWindow(::GetDlgItem(m_hWnd, nID)); - } - -// Alert Functions - - BOOL FlashWindow(BOOL bInvert) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::FlashWindow(m_hWnd, bInvert); - } - - int MessageBox(LPCTSTR lpszText, LPCTSTR lpszCaption = _T(""), UINT nType = MB_OK) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::MessageBox(m_hWnd, lpszText, lpszCaption, nType); - } - -// Clipboard Functions - - BOOL ChangeClipboardChain(HWND hWndNewNext) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ChangeClipboardChain(m_hWnd, hWndNewNext); - } - - HWND SetClipboardViewer() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetClipboardViewer(m_hWnd); - } - - BOOL OpenClipboard() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::OpenClipboard(m_hWnd); - } - -// Caret Functions - - BOOL CreateCaret(HBITMAP hBitmap) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::CreateCaret(m_hWnd, hBitmap, 0, 0); - } - - BOOL CreateSolidCaret(int nWidth, int nHeight) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::CreateCaret(m_hWnd, (HBITMAP)0, nWidth, nHeight); - } - - BOOL CreateGrayCaret(int nWidth, int nHeight) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::CreateCaret(m_hWnd, (HBITMAP)1, nWidth, nHeight); - } - - BOOL HideCaret() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::HideCaret(m_hWnd); - } - - BOOL ShowCaret() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ShowCaret(m_hWnd); - } - -#ifdef _INC_SHELLAPI -// Drag-Drop Functions - void DragAcceptFiles(BOOL bAccept = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); ::DragAcceptFiles(m_hWnd, bAccept); - } -#endif - -// Icon Functions - - HICON SetIcon(HICON hIcon, BOOL bBigIcon = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HICON)::SendMessage(m_hWnd, WM_SETICON, bBigIcon, (LPARAM)hIcon); - } - - HICON GetIcon(BOOL bBigIcon = TRUE) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HICON)::SendMessage(m_hWnd, WM_GETICON, bBigIcon, 0); - } - -// Help Functions - - BOOL WinHelp(LPCTSTR lpszHelp, UINT nCmd = HELP_CONTEXT, DWORD dwData = 0) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::WinHelp(m_hWnd, lpszHelp, nCmd, dwData); - } - - BOOL SetWindowContextHelpId(DWORD dwContextHelpId) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetWindowContextHelpId(m_hWnd, dwContextHelpId); - } - - DWORD GetWindowContextHelpId() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetWindowContextHelpId(m_hWnd); - } - -// Hot Key Functions - - int SetHotKey(WORD wVirtualKeyCode, WORD wModifiers) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, WM_SETHOTKEY, MAKEWORD(wVirtualKeyCode, wModifiers), 0); - } - - DWORD GetHotKey() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, WM_GETHOTKEY, 0, 0); - } - -// Misc. Operations - -//N new - BOOL GetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetScrollInfo(m_hWnd, nBar, lpScrollInfo); - } - int SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetScrollInfo(m_hWnd, nBar, lpScrollInfo, bRedraw); - } - BOOL IsDialogMessage(LPMSG lpMsg) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::IsDialogMessage(m_hWnd, lpMsg); - } - - void NextDlgCtrl() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_NEXTDLGCTL, 0, 0L); - } - void PrevDlgCtrl() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_NEXTDLGCTL, 1, 0L); - } - void GotoDlgCtrl(HWND hWndCtrl) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_NEXTDLGCTL, (WPARAM)hWndCtrl, 1L); - } - - BOOL ResizeClient(int nWidth, int nHeight, BOOL bRedraw = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - - RECT rcWnd; - if(!GetClientRect(&rcWnd)) - return FALSE; - - if(nWidth != -1) - rcWnd.right = nWidth; - if(nHeight != -1) - rcWnd.bottom = nHeight; - - if(!::AdjustWindowRectEx(&rcWnd, GetStyle(), (!(GetStyle() & WS_CHILD) && (GetMenu() != NULL)), GetExStyle())) - return FALSE; - - UINT uFlags = SWP_NOZORDER | SWP_NOMOVE; - if(!bRedraw) - uFlags |= SWP_NOREDRAW; - - return SetWindowPos(NULL, 0, 0, rcWnd.right - rcWnd.left, rcWnd.bottom - rcWnd.top, uFlags); - } - - int GetWindowRgn(HRGN hRgn) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetWindowRgn(m_hWnd, hRgn); - } - int SetWindowRgn(HRGN hRgn, BOOL bRedraw = FALSE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetWindowRgn(m_hWnd, hRgn, bRedraw); - } - HDWP DeferWindowPos(HDWP hWinPosInfo, HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT uFlags) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::DeferWindowPos(hWinPosInfo, m_hWnd, hWndInsertAfter, x, y, cx, cy, uFlags); - } - DWORD GetWindowThreadID() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetWindowThreadProcessId(m_hWnd, NULL); - } - DWORD GetWindowProcessID() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - DWORD dwProcessID; - ::GetWindowThreadProcessId(m_hWnd, &dwProcessID); - return dwProcessID; - } - BOOL IsWindow() const throw() - { - return ::IsWindow(m_hWnd); - } - BOOL IsWindowUnicode() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::IsWindowUnicode(m_hWnd); - } - BOOL IsParentDialog() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - TCHAR szBuf[8]; // "#32770" + NUL character - if (GetClassName(GetParent(), szBuf, sizeof(szBuf)/sizeof(TCHAR)) == 0) - return FALSE; - return lstrcmp(szBuf, _T("#32770")) == 0; - } - BOOL ShowWindowAsync(int nCmdShow) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ShowWindowAsync(m_hWnd, nCmdShow); - } - - CWindow GetDescendantWindow(int nID) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - - // GetDlgItem recursive (return first found) - // breadth-first for 1 level, then depth-first for next level - - // use GetDlgItem since it is a fast USER function - HWND hWndChild, hWndTmp; - if((hWndChild = ::GetDlgItem(m_hWnd, nID)) != NULL) - { - if(::GetTopWindow(hWndChild) != NULL) - { - // children with the same ID as their parent have priority - CWindow wnd(hWndChild); - hWndTmp = wnd.GetDescendantWindow(nID); - if(hWndTmp != NULL) - return CWindow(hWndTmp); - } - return CWindow(hWndChild); - } - - // walk each child - for(hWndChild = ::GetTopWindow(m_hWnd); hWndChild != NULL; - hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT)) - { - CWindow wnd(hWndChild); - hWndTmp = wnd.GetDescendantWindow(nID); - if(hWndTmp != NULL) - return CWindow(hWndTmp); - } - - return CWindow(NULL); // not found - } - - void SendMessageToDescendants(UINT message, WPARAM wParam = 0, LPARAM lParam = 0, BOOL bDeep = TRUE) throw() - { - for(HWND hWndChild = ::GetTopWindow(m_hWnd); hWndChild != NULL; - hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT)) - { - ::SendMessage(hWndChild, message, wParam, lParam); - - if(bDeep && ::GetTopWindow(hWndChild) != NULL) - { - // send to child windows after parent - CWindow wnd(hWndChild); - wnd.SendMessageToDescendants(message, wParam, lParam, bDeep); - } - } - } - - BOOL CenterWindow(HWND hWndCenter = NULL) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - - // determine owner window to center against - DWORD dwStyle = GetStyle(); - if(hWndCenter == NULL) - { - if(dwStyle & WS_CHILD) - hWndCenter = ::GetParent(m_hWnd); - else - hWndCenter = ::GetWindow(m_hWnd, GW_OWNER); - } - - // get coordinates of the window relative to its parent - RECT rcDlg; - ::GetWindowRect(m_hWnd, &rcDlg); - RECT rcArea; - RECT rcCenter; - HWND hWndParent; - if(!(dwStyle & WS_CHILD)) - { - // don't center against invisible or minimized windows - if(hWndCenter != NULL) - { - DWORD dwStyleCenter = ::GetWindowLong(hWndCenter, GWL_STYLE); - if(!(dwStyleCenter & WS_VISIBLE) || (dwStyleCenter & WS_MINIMIZE)) - hWndCenter = NULL; - } - - // center within screen coordinates - ::SystemParametersInfo(SPI_GETWORKAREA, NULL, &rcArea, NULL); - if(hWndCenter == NULL) - rcCenter = rcArea; - else - ::GetWindowRect(hWndCenter, &rcCenter); - } - else - { - // center within parent client coordinates - hWndParent = ::GetParent(m_hWnd); - ATLASSERT(::IsWindow(hWndParent)); - - ::GetClientRect(hWndParent, &rcArea); - ATLASSERT(::IsWindow(hWndCenter)); - ::GetClientRect(hWndCenter, &rcCenter); - ::MapWindowPoints(hWndCenter, hWndParent, (POINT*)&rcCenter, 2); - } - - int DlgWidth = rcDlg.right - rcDlg.left; - int DlgHeight = rcDlg.bottom - rcDlg.top; - - // find dialog's upper left based on rcCenter - int xLeft = (rcCenter.left + rcCenter.right) / 2 - DlgWidth / 2; - int yTop = (rcCenter.top + rcCenter.bottom) / 2 - DlgHeight / 2; - - // if the dialog is outside the screen, move it inside - if(xLeft < rcArea.left) - xLeft = rcArea.left; - else if(xLeft + DlgWidth > rcArea.right) - xLeft = rcArea.right - DlgWidth; - - if(yTop < rcArea.top) - yTop = rcArea.top; - else if(yTop + DlgHeight > rcArea.bottom) - yTop = rcArea.bottom - DlgHeight; - - // map screen coordinates to child coordinates - return ::SetWindowPos(m_hWnd, NULL, xLeft, yTop, -1, -1, - SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); - } - - BOOL ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - - DWORD dwStyle = ::GetWindowLong(m_hWnd, GWL_STYLE); - DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd; - if(dwStyle == dwNewStyle) - return FALSE; - - ::SetWindowLong(m_hWnd, GWL_STYLE, dwNewStyle); - if(nFlags != 0) - { - ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, - SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags); - } - - return TRUE; - } - - BOOL ModifyStyleEx(DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - - DWORD dwStyle = ::GetWindowLong(m_hWnd, GWL_EXSTYLE); - DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd; - if(dwStyle == dwNewStyle) - return FALSE; - - ::SetWindowLong(m_hWnd, GWL_EXSTYLE, dwNewStyle); - if(nFlags != 0) - { - ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, - SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags); - } - - return TRUE; - } - -#ifdef _OLEAUTO_H_ - BOOL GetWindowText(BSTR* pbstrText) throw() - { - return GetWindowText(*pbstrText); - } - BOOL GetWindowText(BSTR& bstrText) throw() - { - USES_CONVERSION; - ATLASSERT(::IsWindow(m_hWnd)); - if (bstrText != NULL) - { - SysFreeString(bstrText); - bstrText = NULL; - } - - int nLen = ::GetWindowTextLength(m_hWnd); - if(nLen == 0) - { - bstrText = ::SysAllocString(OLESTR("")); - return (bstrText != NULL) ? TRUE : FALSE; - } - - CTempBuffer lpszText; - ATLTRY(lpszText.Allocate(nLen+1)); - if (lpszText == NULL) - return FALSE; - - if(!::GetWindowText(m_hWnd, lpszText, nLen+1)) - return FALSE; - - bstrText = ::SysAllocString(T2OLE(lpszText)); - return (bstrText != NULL) ? TRUE : FALSE; - } -#endif // _OLEAUTO_H_ - CWindow GetTopLevelParent() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - - HWND hWndParent = m_hWnd; - HWND hWndTmp; - while((hWndTmp = ::GetParent(hWndParent)) != NULL) - hWndParent = hWndTmp; - - return CWindow(hWndParent); - } - - CWindow GetTopLevelWindow() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - - HWND hWndParent; - HWND hWndTmp = m_hWnd; - - do - { - hWndParent = hWndTmp; - hWndTmp = (::GetWindowLong(hWndParent, GWL_STYLE) & WS_CHILD) ? ::GetParent(hWndParent) : ::GetWindow(hWndParent, GW_OWNER); - } - while(hWndTmp != NULL); - - return CWindow(hWndParent); - } -}; - -_declspec(selectany) RECT CWindow::rcDefault = { CW_USEDEFAULT, CW_USEDEFAULT, 0, 0 }; - -///////////////////////////////////////////////////////////////////////////// -// CAxWindow - client side for an ActiveX host window - -#ifndef _ATL_NO_HOSTING - -template -class CAxWindowT : public TBase -{ -public: -// Constructors - CAxWindowT(HWND hWnd = NULL) : TBase(hWnd) - { - AtlAxWinInit(); - } - - CAxWindowT< TBase >& operator=(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return _T(ATLAXWIN_CLASS); - } - -// Operations - HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return CWindow::Create(GetWndClassName(), hWndParent, rect, szWindowName, dwStyle, dwExStyle, MenuOrID, lpCreateParam); - } - - HRESULT CreateControl(LPCOLESTR lpszName, IStream* pStream = NULL, IUnknown** ppUnkContainer = NULL) - { - return CreateControlEx(lpszName, pStream, ppUnkContainer); - } - - HRESULT CreateControl(DWORD dwResID, IStream* pStream = NULL, IUnknown** ppUnkContainer = NULL) - { - return CreateControlEx(dwResID, pStream, ppUnkContainer); - } - - HRESULT CreateControlEx(LPCOLESTR lpszName, IStream* pStream = NULL, - IUnknown** ppUnkContainer = NULL, IUnknown** ppUnkControl = NULL, - REFIID iidSink = IID_NULL, IUnknown* punkSink = NULL) - { - ATLASSERT(::IsWindow(m_hWnd)); - // We must have a valid window! - - // Get a pointer to the container object connected to this window - CComPtr spWinHost; - HRESULT hr = QueryHost(&spWinHost); - - // If QueryHost failed, there is no host attached to this window - // We assume that the user wants to create a new host and subclass the current window - if (FAILED(hr)) - return AtlAxCreateControlEx(lpszName, m_hWnd, pStream, ppUnkContainer, ppUnkControl, iidSink, punkSink); - - // Create the control requested by the caller - CComPtr pControl; - if (SUCCEEDED(hr)) - hr = spWinHost->CreateControlEx(lpszName, m_hWnd, pStream, &pControl, iidSink, punkSink); - - // Send back the necessary interface pointers - if (SUCCEEDED(hr)) - { - if (ppUnkControl) - *ppUnkControl = pControl.Detach(); - - if (ppUnkContainer) - { - hr = spWinHost.QueryInterface(ppUnkContainer); - ATLASSERT(SUCCEEDED(hr)); // This should not fail! - } - } - - return hr; - } - - HRESULT CreateControlEx(DWORD dwResID, IStream* pStream = NULL, - IUnknown** ppUnkContainer = NULL, IUnknown** ppUnkControl = NULL, - REFIID iidSink = IID_NULL, IUnknown* punkSink = NULL) - { - TCHAR szModule[MAX_PATH]; - DWORD dwFLen = GetModuleFileName(_AtlBaseModule.GetModuleInstance(), szModule, MAX_PATH); - if( dwFLen == 0 ) - return AtlHresultFromLastError(); - else if( dwFLen == MAX_PATH ) - return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - - CComBSTR bstrURL(OLESTR("res://")); - bstrURL.Append(szModule); - bstrURL.Append(OLESTR("/")); - TCHAR szResID[11]; - wsprintf(szResID, _T("%0d"), dwResID); - bstrURL.Append(szResID); - - ATLASSERT(::IsWindow(m_hWnd)); - return CreateControlEx(bstrURL, pStream, ppUnkContainer, ppUnkControl, iidSink, punkSink); - } - - HRESULT AttachControl(IUnknown* pControl, IUnknown** ppUnkContainer) - { - ATLASSERT(::IsWindow(m_hWnd)); - // We must have a valid window! - - // Get a pointer to the container object connected to this window - CComPtr spWinHost; - HRESULT hr = QueryHost(&spWinHost); - - // If QueryHost failed, there is no host attached to this window - // We assume that the user wants to create a new host and subclass the current window - if (FAILED(hr)) - return AtlAxAttachControl(pControl, m_hWnd, ppUnkContainer); - - // Attach the control specified by the caller - if (SUCCEEDED(hr)) - hr = spWinHost->AttachControl(pControl, m_hWnd); - - // Get the IUnknown interface of the container - if (SUCCEEDED(hr) && ppUnkContainer) - { - hr = spWinHost.QueryInterface(ppUnkContainer); - ATLASSERT(SUCCEEDED(hr)); // This should not fail! - } - - return hr; - } - - HRESULT QueryHost(REFIID iid, void** ppUnk) - { - ATLASSERT(ppUnk != NULL); - if (ppUnk == NULL) - return E_POINTER; - HRESULT hr; - *ppUnk = NULL; - CComPtr spUnk; - hr = AtlAxGetHost(m_hWnd, &spUnk); - if (SUCCEEDED(hr)) - hr = spUnk->QueryInterface(iid, ppUnk); - return hr; - } - template - HRESULT QueryHost(Q** ppUnk) - { - return QueryHost(__uuidof(Q), (void**)ppUnk); - } - HRESULT QueryControl(REFIID iid, void** ppUnk) - { - ATLASSERT(ppUnk != NULL); - if (ppUnk == NULL) - return E_POINTER; - HRESULT hr; - *ppUnk = NULL; - CComPtr spUnk; - hr = AtlAxGetControl(m_hWnd, &spUnk); - if (SUCCEEDED(hr)) - hr = spUnk->QueryInterface(iid, ppUnk); - return hr; - } - template - HRESULT QueryControl(Q** ppUnk) - { - return QueryControl(__uuidof(Q), (void**)ppUnk); - } - HRESULT SetExternalDispatch(IDispatch* pDisp) - { - HRESULT hr; - CComPtr spHost; - hr = QueryHost(__uuidof(IAxWinHostWindow), (void**)&spHost); - if (SUCCEEDED(hr)) - hr = spHost->SetExternalDispatch(pDisp); - return hr; - } - HRESULT SetExternalUIHandler(IDocHostUIHandlerDispatch* pUIHandler) - { - HRESULT hr; - CComPtr spHost; - hr = QueryHost(__uuidof(IAxWinHostWindow), (void**)&spHost); - if (SUCCEEDED(hr)) - hr = spHost->SetExternalUIHandler(pUIHandler); - return hr; - } -}; - -typedef CAxWindowT CAxWindow; - -template -class CAxWindow2T : public CAxWindowT -{ -public: -// Constructors - CAxWindow2T(HWND hWnd = NULL) : CAxWindowT(hWnd) - { - } - - CAxWindow2T< TBase >& operator=(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return _T(ATLAXWINLIC_CLASS); - } - -// Operations - HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return CWindow::Create(GetWndClassName(), hWndParent, rect, szWindowName, dwStyle, dwExStyle, MenuOrID, lpCreateParam); - } - - HRESULT CreateControlLic(LPCOLESTR lpszName, IStream* pStream = NULL, IUnknown** ppUnkContainer = NULL, BSTR bstrLicKey = NULL) - { - return CreateControlLicEx(lpszName, pStream, ppUnkContainer, NULL, IID_NULL, NULL, bstrLicKey); - } - - HRESULT CreateControlLic(DWORD dwResID, IStream* pStream = NULL, IUnknown** ppUnkContainer = NULL, BSTR bstrLicKey = NULL) - { - return CreateControlLicEx(dwResID, pStream, ppUnkContainer, NULL, IID_NULL, NULL, bstrLicKey); - } - - HRESULT CreateControlLicEx(LPCOLESTR lpszName, IStream* pStream = NULL, - IUnknown** ppUnkContainer = NULL, IUnknown** ppUnkControl = NULL, - REFIID iidSink = IID_NULL, IUnknown* punkSink = NULL, BSTR bstrLicKey = NULL) - { - ATLASSERT(::IsWindow(m_hWnd)); - // We must have a valid window! - - // Get a pointer to the container object connected to this window - CComPtr spWinHost; - HRESULT hr = QueryHost(&spWinHost); - - // If QueryHost failed, there is no host attached to this window - // We assume that the user wants to create a new host and subclass the current window - if (FAILED(hr)) - return AtlAxCreateControlLicEx(lpszName, m_hWnd, pStream, ppUnkContainer, ppUnkControl, iidSink, punkSink, bstrLicKey); - - // Create the control requested by the caller - CComPtr pControl; - if (SUCCEEDED(hr)) - hr = spWinHost->CreateControlLicEx(lpszName, m_hWnd, pStream, &pControl, iidSink, punkSink, bstrLicKey); - - // Send back the necessary interface pointers - if (SUCCEEDED(hr)) - { - if (ppUnkControl) - *ppUnkControl = pControl.Detach(); - - if (ppUnkContainer) - { - hr = spWinHost.QueryInterface(ppUnkContainer); - ATLASSERT(SUCCEEDED(hr)); // This should not fail! - } - } - - return hr; - } - - HRESULT CreateControlLicEx(DWORD dwResID, IStream* pStream = NULL, - IUnknown** ppUnkContainer = NULL, IUnknown** ppUnkControl = NULL, - REFIID iidSink = IID_NULL, IUnknown* punkSink = NULL, BSTR bstrLickey = NULL) - { - TCHAR szModule[MAX_PATH]; - DWORD dwFLen = GetModuleFileName(_AtlBaseModule.GetModuleInstance(), szModule, MAX_PATH); - if( dwFLen == 0 ) - return AtlHresultFromLastError(); - else if( dwFLen == MAX_PATH ) - return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - - CComBSTR bstrURL(OLESTR("res://")); - bstrURL.Append(szModule); - bstrURL.Append(OLESTR("/")); - TCHAR szResID[11]; - wsprintf(szResID, _T("%0d"), dwResID); - bstrURL.Append(szResID); - - ATLASSERT(::IsWindow(m_hWnd)); - return CreateControlLicEx(bstrURL, pStream, ppUnkContainer, ppUnkControl, iidSink, punkSink, bstrLickey); - } -}; - -typedef CAxWindow2T CAxWindow2; - - -#endif //_ATL_NO_HOSTING - -///////////////////////////////////////////////////////////////////////////// -// WindowProc thunks - -class CWndProcThunk -{ -public: - _AtlCreateWndData cd; - CStdCallThunk thunk; - - void Init(WNDPROC proc, void* pThis) - { - thunk.Init((DWORD_PTR)proc, pThis); - } - WNDPROC GetWNDPROC() - { - return (WNDPROC)thunk.GetCodeAddress(); - } -}; - -///////////////////////////////////////////////////////////////////////////// -// CMessageMap - abstract class that provides an interface for message maps - -class ATL_NO_VTABLE CMessageMap -{ -public: - virtual BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, - LRESULT& lResult, DWORD dwMsgMapID) = 0; -}; - -///////////////////////////////////////////////////////////////////////////// -// Message map - -#define BEGIN_MSG_MAP(theClass) \ -public: \ - BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) \ - { \ - BOOL bHandled = TRUE; \ - (hWnd); \ - (uMsg); \ - (wParam); \ - (lParam); \ - (lResult); \ - (bHandled); \ - switch(dwMsgMapID) \ - { \ - case 0: - -#define ALT_MSG_MAP(msgMapID) \ - break; \ - case msgMapID: - -#define MESSAGE_HANDLER(msg, func) \ - if(uMsg == msg) \ - { \ - bHandled = TRUE; \ - lResult = func(uMsg, wParam, lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define MESSAGE_RANGE_HANDLER(msgFirst, msgLast, func) \ - if(uMsg >= msgFirst && uMsg <= msgLast) \ - { \ - bHandled = TRUE; \ - lResult = func(uMsg, wParam, lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define COMMAND_HANDLER(id, code, func) \ - if(uMsg == WM_COMMAND && id == LOWORD(wParam) && code == HIWORD(wParam)) \ - { \ - bHandled = TRUE; \ - lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define COMMAND_ID_HANDLER(id, func) \ - if(uMsg == WM_COMMAND && id == LOWORD(wParam)) \ - { \ - bHandled = TRUE; \ - lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define COMMAND_CODE_HANDLER(code, func) \ - if(uMsg == WM_COMMAND && code == HIWORD(wParam)) \ - { \ - bHandled = TRUE; \ - lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define COMMAND_RANGE_HANDLER(idFirst, idLast, func) \ - if(uMsg == WM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \ - { \ - bHandled = TRUE; \ - lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define COMMAND_RANGE_CODE_HANDLER(idFirst, idLast, code, func) \ - if(uMsg == WM_COMMAND && code == HIWORD(wParam) && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \ - { \ - bHandled = TRUE; \ - lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define NOTIFY_HANDLER(id, cd, func) \ - if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code) \ - { \ - bHandled = TRUE; \ - lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define NOTIFY_ID_HANDLER(id, func) \ - if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) \ - { \ - bHandled = TRUE; \ - lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define NOTIFY_CODE_HANDLER(cd, func) \ - if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \ - { \ - bHandled = TRUE; \ - lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define NOTIFY_RANGE_HANDLER(idFirst, idLast, func) \ - if(uMsg == WM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \ - { \ - bHandled = TRUE; \ - lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define NOTIFY_RANGE_CODE_HANDLER(idFirst, idLast, cd, func) \ - if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \ - { \ - bHandled = TRUE; \ - lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define CHAIN_MSG_MAP(theChainClass) \ - { \ - if(theChainClass::ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult)) \ - return TRUE; \ - } - -#define CHAIN_MSG_MAP_MEMBER(theChainMember) \ - { \ - if(theChainMember.ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult)) \ - return TRUE; \ - } - -#define CHAIN_MSG_MAP_ALT(theChainClass, msgMapID) \ - { \ - if(theChainClass::ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, msgMapID)) \ - return TRUE; \ - } - -#define CHAIN_MSG_MAP_ALT_MEMBER(theChainMember, msgMapID) \ - { \ - if(theChainMember.ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, msgMapID)) \ - return TRUE; \ - } - -#define CHAIN_MSG_MAP_DYNAMIC(dynaChainID) \ - { \ - if(CDynamicChain::CallChain(dynaChainID, hWnd, uMsg, wParam, lParam, lResult)) \ - return TRUE; \ - } - -#define END_MSG_MAP() \ - break; \ - default: \ - ATLTRACE(ATL::atlTraceWindowing, 0, _T("Invalid message map ID (%i)\n"), dwMsgMapID); \ - ATLASSERT(FALSE); \ - break; \ - } \ - return FALSE; \ - } - - -// Handler prototypes: -// LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); -// LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); -// LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled); - - -// Empty message map macro - -#define DECLARE_EMPTY_MSG_MAP() \ -public: \ - BOOL ProcessWindowMessage(HWND, UINT, WPARAM, LPARAM, LRESULT&, DWORD = 0) \ - { \ - return FALSE; \ - } - -// Message forwarding and reflection macros - -#define FORWARD_NOTIFICATIONS() \ - { \ - bHandled = TRUE; \ - lResult = ForwardNotifications(uMsg, wParam, lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECT_NOTIFICATIONS() \ - { \ - bHandled = TRUE; \ - lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define DEFAULT_REFLECTION_HANDLER() \ - if(DefaultReflectionHandler(hWnd, uMsg, wParam, lParam, lResult)) \ - return TRUE; - -#define REFLECTED_COMMAND_HANDLER(id, code, func) \ - if(uMsg == OCM_COMMAND && id == LOWORD(wParam) && code == HIWORD(wParam)) \ - { \ - bHandled = TRUE; \ - lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECTED_COMMAND_ID_HANDLER(id, func) \ - if(uMsg == OCM_COMMAND && id == LOWORD(wParam)) \ - { \ - bHandled = TRUE; \ - lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECTED_COMMAND_CODE_HANDLER(code, func) \ - if(uMsg == OCM_COMMAND && code == HIWORD(wParam)) \ - { \ - bHandled = TRUE; \ - lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECTED_COMMAND_RANGE_HANDLER(idFirst, idLast, func) \ - if(uMsg == OCM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \ - { \ - bHandled = TRUE; \ - lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECTED_COMMAND_RANGE_CODE_HANDLER(idFirst, idLast, code, func) \ - if(uMsg == OCM_COMMAND && code == HIWORD(wParam) && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \ - { \ - bHandled = TRUE; \ - lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECTED_NOTIFY_HANDLER(id, cd, func) \ - if(uMsg == OCM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code) \ - { \ - bHandled = TRUE; \ - lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECTED_NOTIFY_ID_HANDLER(id, func) \ - if(uMsg == OCM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) \ - { \ - bHandled = TRUE; \ - lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECTED_NOTIFY_CODE_HANDLER(cd, func) \ - if(uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \ - { \ - bHandled = TRUE; \ - lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECTED_NOTIFY_RANGE_HANDLER(idFirst, idLast, func) \ - if(uMsg == OCM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \ - { \ - bHandled = TRUE; \ - lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECTED_NOTIFY_RANGE_CODE_HANDLER(idFirst, idLast, cd, func) \ - if(uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \ - { \ - bHandled = TRUE; \ - lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -///////////////////////////////////////////////////////////////////////////// -// CDynamicChain - provides support for dynamic chaining - -class CDynamicChain -{ -public: - struct ATL_CHAIN_ENTRY - { - DWORD m_dwChainID; - CMessageMap* m_pObject; - DWORD m_dwMsgMapID; - }; - - CSimpleArray m_aChainEntry; - - CDynamicChain() - { } - - ~CDynamicChain() - { - for(int i = 0; i < m_aChainEntry.GetSize(); i++) - { - if(m_aChainEntry[i] != NULL) - delete m_aChainEntry[i]; - } - } - - BOOL SetChainEntry(DWORD dwChainID, CMessageMap* pObject, DWORD dwMsgMapID = 0) - { - // first search for an existing entry - - int i; - for(i = 0; i < m_aChainEntry.GetSize(); i++) - { - if(m_aChainEntry[i] != NULL && m_aChainEntry[i]->m_dwChainID == dwChainID) - { - m_aChainEntry[i]->m_pObject = pObject; - m_aChainEntry[i]->m_dwMsgMapID = dwMsgMapID; - return TRUE; - } - } - - // create a new one - - ATL_CHAIN_ENTRY* pEntry = NULL; - ATLTRY(pEntry = new ATL_CHAIN_ENTRY); - - if(pEntry == NULL) - return FALSE; - - pEntry->m_dwChainID = dwChainID; - pEntry->m_pObject = pObject; - pEntry->m_dwMsgMapID = dwMsgMapID; - - // search for an empty one - - for(i = 0; i < m_aChainEntry.GetSize(); i++) - { - if(m_aChainEntry[i] == NULL) - { - m_aChainEntry[i] = pEntry; - return TRUE; - } - } - - // add a new one - - BOOL bRet = m_aChainEntry.Add(pEntry); - - if(!bRet) - { - delete pEntry; - return FALSE; - } - - return TRUE; - } - - BOOL RemoveChainEntry(DWORD dwChainID) - { - for(int i = 0; i < m_aChainEntry.GetSize(); i++) - { - if(m_aChainEntry[i] != NULL && m_aChainEntry[i]->m_dwChainID == dwChainID) - { - delete m_aChainEntry[i]; - m_aChainEntry[i] = NULL; - return TRUE; - } - } - - return FALSE; - } - - BOOL CallChain(DWORD dwChainID, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult) - { - for(int i = 0; i < m_aChainEntry.GetSize(); i++) - { - if(m_aChainEntry[i] != NULL && m_aChainEntry[i]->m_dwChainID == dwChainID) - return (m_aChainEntry[i]->m_pObject)->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, m_aChainEntry[i]->m_dwMsgMapID); - } - - return FALSE; - } -}; - -///////////////////////////////////////////////////////////////////////////// -// CWndClassInfo - Manages Windows class information - -#define DECLARE_WND_CLASS(WndClassName) \ -static ATL::CWndClassInfo& GetWndClassInfo() \ -{ \ - static ATL::CWndClassInfo wc = \ - { \ - { sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS, StartWindowProc, \ - 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName, NULL }, \ - NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \ - }; \ - return wc; \ -} - -#define DECLARE_WND_CLASS_EX(WndClassName, style, bkgnd) \ -static ATL::CWndClassInfo& GetWndClassInfo() \ -{ \ - static ATL::CWndClassInfo wc = \ - { \ - { sizeof(WNDCLASSEX), style, StartWindowProc, \ - 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName, NULL }, \ - NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \ - }; \ - return wc; \ -} - -#define DECLARE_WND_SUPERCLASS(WndClassName, OrigWndClassName) \ -static ATL::CWndClassInfo& GetWndClassInfo() \ -{ \ - static ATL::CWndClassInfo wc = \ - { \ - { sizeof(WNDCLASSEX), 0, StartWindowProc, \ - 0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName, NULL }, \ - OrigWndClassName, NULL, NULL, TRUE, 0, _T("") \ - }; \ - return wc; \ -} - -///////////////////////////////////////////////////////////////////////////// -// CWinTraits - Defines various default values for a window - -template -class CWinTraits -{ -public: - static DWORD GetWndStyle(DWORD dwStyle) - { - return dwStyle == 0 ? t_dwStyle : dwStyle; - } - static DWORD GetWndExStyle(DWORD dwExStyle) - { - return dwExStyle == 0 ? t_dwExStyle : dwExStyle; - } -}; - -typedef CWinTraits CControlWinTraits; -typedef CWinTraits CFrameWinTraits; -typedef CWinTraits CMDIChildWinTraits; - -typedef CWinTraits<0, 0> CNullTraits; - -template -class CWinTraitsOR -{ -public: - static DWORD GetWndStyle(DWORD dwStyle) - { - return dwStyle | t_dwStyle | TWinTraits::GetWndStyle(dwStyle); - } - static DWORD GetWndExStyle(DWORD dwExStyle) - { - return dwExStyle | t_dwExStyle | TWinTraits::GetWndExStyle(dwExStyle); - } -}; - -///////////////////////////////////////////////////////////////////////////// -// CWindowImpl - Implements a window - -template -class ATL_NO_VTABLE CWindowImplRoot : public TBase, public CMessageMap -{ -public: - CWndProcThunk m_thunk; - const _ATL_MSG* m_pCurrentMsg; - DWORD m_dwState; - - enum { WINSTATE_DESTROYED = 0x00000001 }; - -// Constructor/destructor - CWindowImplRoot() : m_pCurrentMsg(NULL), m_dwState(0) - { } - - virtual ~CWindowImplRoot() - { -#ifdef _DEBUG - if(m_hWnd != NULL) // should be cleared in WindowProc - { - ATLTRACE(atlTraceWindowing, 0, _T("ERROR - Object deleted before window was destroyed\n")); - ATLASSERT(FALSE); - } -#endif //_DEBUG - } - -// Current message - const _ATL_MSG* GetCurrentMessage() const - { - return m_pCurrentMsg; - } - - // "handled" management for cracked handlers - BOOL IsMsgHandled() const - { - const _ATL_MSG* pMsg = GetCurrentMessage(); - ATLASSERT(pMsg != NULL); - ATLASSERT(pMsg->cbSize >= sizeof(_ATL_MSG)); - return pMsg->bHandled; - } - void SetMsgHandled(BOOL bHandled) - { - _ATL_MSG* pMsg = (_ATL_MSG*)GetCurrentMessage(); // override const - ATLASSERT(pMsg != NULL); - ATLASSERT(pMsg->cbSize >= sizeof(_ATL_MSG)); - pMsg->bHandled = bHandled; - } - -// Message forwarding and reflection support - LRESULT ForwardNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); - LRESULT ReflectNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); - static BOOL DefaultReflectionHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult); -}; - -template -LRESULT CWindowImplRoot< TBase >::ForwardNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) -{ - LRESULT lResult = 0; - switch(uMsg) - { - case WM_COMMAND: - case WM_NOTIFY: - case WM_PARENTNOTIFY: - case WM_DRAWITEM: - case WM_MEASUREITEM: - case WM_COMPAREITEM: - case WM_DELETEITEM: - case WM_VKEYTOITEM: - case WM_CHARTOITEM: - case WM_HSCROLL: - case WM_VSCROLL: - case WM_CTLCOLORBTN: - case WM_CTLCOLORDLG: - case WM_CTLCOLOREDIT: - case WM_CTLCOLORLISTBOX: - case WM_CTLCOLORMSGBOX: - case WM_CTLCOLORSCROLLBAR: - case WM_CTLCOLORSTATIC: - lResult = GetParent().SendMessage(uMsg, wParam, lParam); - break; - default: - bHandled = FALSE; - break; - } - return lResult; -} - -template -LRESULT CWindowImplRoot< TBase >::ReflectNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) -{ - HWND hWndChild = NULL; - - switch(uMsg) - { - case WM_COMMAND: - if(lParam != NULL) // not from a menu - hWndChild = (HWND)lParam; - break; - case WM_NOTIFY: - hWndChild = ((LPNMHDR)lParam)->hwndFrom; - break; - case WM_PARENTNOTIFY: - switch(LOWORD(wParam)) - { - case WM_CREATE: - case WM_DESTROY: - hWndChild = (HWND)lParam; - break; - default: - hWndChild = GetDlgItem(HIWORD(wParam)); - break; - } - break; - case WM_DRAWITEM: - if(wParam) // not from a menu - hWndChild = ((LPDRAWITEMSTRUCT)lParam)->hwndItem; - break; - case WM_MEASUREITEM: - if(wParam) // not from a menu - hWndChild = GetDlgItem(((LPMEASUREITEMSTRUCT)lParam)->CtlID); - break; - case WM_COMPAREITEM: - if(wParam) // not from a menu - hWndChild = GetDlgItem(((LPCOMPAREITEMSTRUCT)lParam)->CtlID); - break; - case WM_DELETEITEM: - if(wParam) // not from a menu - hWndChild = GetDlgItem(((LPDELETEITEMSTRUCT)lParam)->CtlID); - break; - case WM_VKEYTOITEM: - case WM_CHARTOITEM: - case WM_HSCROLL: - case WM_VSCROLL: - hWndChild = (HWND)lParam; - break; - case WM_CTLCOLORBTN: - case WM_CTLCOLORDLG: - case WM_CTLCOLOREDIT: - case WM_CTLCOLORLISTBOX: - case WM_CTLCOLORMSGBOX: - case WM_CTLCOLORSCROLLBAR: - case WM_CTLCOLORSTATIC: - hWndChild = (HWND)lParam; - break; - default: - break; - } - - if(hWndChild == NULL) - { - bHandled = FALSE; - return 1; - } - - ATLASSERT(::IsWindow(hWndChild)); - return ::SendMessage(hWndChild, OCM__BASE + uMsg, wParam, lParam); -} - -template -BOOL CWindowImplRoot< TBase >::DefaultReflectionHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult) -{ - switch(uMsg) - { - case OCM_COMMAND: - case OCM_NOTIFY: - case OCM_PARENTNOTIFY: - case OCM_DRAWITEM: - case OCM_MEASUREITEM: - case OCM_COMPAREITEM: - case OCM_DELETEITEM: - case OCM_VKEYTOITEM: - case OCM_CHARTOITEM: - case OCM_HSCROLL: - case OCM_VSCROLL: - case OCM_CTLCOLORBTN: - case OCM_CTLCOLORDLG: - case OCM_CTLCOLOREDIT: - case OCM_CTLCOLORLISTBOX: - case OCM_CTLCOLORMSGBOX: - case OCM_CTLCOLORSCROLLBAR: - case OCM_CTLCOLORSTATIC: - lResult = ::DefWindowProc(hWnd, uMsg - OCM__BASE, wParam, lParam); - return TRUE; - default: - break; - } - return FALSE; -} - -template -class ATL_NO_VTABLE CWindowImplBaseT : public CWindowImplRoot< TBase > -{ -public: - WNDPROC m_pfnSuperWindowProc; - - CWindowImplBaseT() : m_pfnSuperWindowProc(::DefWindowProc) - {} - - static DWORD GetWndStyle(DWORD dwStyle) - { - return TWinTraits::GetWndStyle(dwStyle); - } - static DWORD GetWndExStyle(DWORD dwExStyle) - { - return TWinTraits::GetWndExStyle(dwExStyle); - } - - virtual WNDPROC GetWindowProc() - { - return WindowProc; - } - static LRESULT CALLBACK StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - HWND Create(HWND hWndParent, _U_RECT rect, LPCTSTR szWindowName, - DWORD dwStyle, DWORD dwExStyle, _U_MENUorID MenuOrID, ATOM atom, LPVOID lpCreateParam = NULL); - BOOL DestroyWindow() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::DestroyWindow(m_hWnd); - } - BOOL SubclassWindow(HWND hWnd); - HWND UnsubclassWindow(BOOL bForce = FALSE); - - LRESULT DefWindowProc() - { - const _ATL_MSG* pMsg = m_pCurrentMsg; - LRESULT lRes = 0; - if (pMsg != NULL) - lRes = DefWindowProc(pMsg->message, pMsg->wParam, pMsg->lParam); - return lRes; - } - - LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) - { -#ifdef STRICT - return ::CallWindowProc(m_pfnSuperWindowProc, m_hWnd, uMsg, wParam, lParam); -#else - return ::CallWindowProc((FARPROC)m_pfnSuperWindowProc, m_hWnd, uMsg, wParam, lParam); -#endif - } - - virtual void OnFinalMessage(HWND /*hWnd*/) - { - // override to do something, if needed - } -}; - -typedef CWindowImplBaseT CWindowImplBase; - -template -LRESULT CALLBACK CWindowImplBaseT< TBase, TWinTraits >::StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - CWindowImplBaseT< TBase, TWinTraits >* pThis = (CWindowImplBaseT< TBase, TWinTraits >*)_AtlWinModule.ExtractCreateWndData(); - ATLASSERT(pThis != NULL); - pThis->m_hWnd = hWnd; - pThis->m_thunk.Init(pThis->GetWindowProc(), pThis); - WNDPROC pProc = pThis->m_thunk.GetWNDPROC(); - WNDPROC pOldProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc); -#ifdef _DEBUG - // check if somebody has subclassed us already since we discard it - if(pOldProc != StartWindowProc) - ATLTRACE(atlTraceWindowing, 0, _T("Subclassing through a hook discarded.\n")); -#else - (pOldProc); // avoid unused warning -#endif - return pProc(hWnd, uMsg, wParam, lParam); -} - -template -LRESULT CALLBACK CWindowImplBaseT< TBase, TWinTraits >::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - CWindowImplBaseT< TBase, TWinTraits >* pThis = (CWindowImplBaseT< TBase, TWinTraits >*)hWnd; - // set a ptr to this message and save the old value - _ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam); - const _ATL_MSG* pOldMsg = pThis->m_pCurrentMsg; - pThis->m_pCurrentMsg = &msg; - // pass to the message map to process - LRESULT lRes; - BOOL bRet = pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0); - // restore saved value for the current message - ATLASSERT(pThis->m_pCurrentMsg == &msg); - pThis->m_pCurrentMsg = pOldMsg; - // do the default processing if message was not handled - if(!bRet) - { - if(uMsg != WM_NCDESTROY) - lRes = pThis->DefWindowProc(uMsg, wParam, lParam); - else - { - // unsubclass, if needed - LONG_PTR pfnWndProc = ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC); - lRes = pThis->DefWindowProc(uMsg, wParam, lParam); - if(pThis->m_pfnSuperWindowProc != ::DefWindowProc && ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC) == pfnWndProc) - ::SetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC, (LONG_PTR)pThis->m_pfnSuperWindowProc); - // mark window as destryed - pThis->m_dwState |= WINSTATE_DESTROYED; - } - } - if((pThis->m_dwState & WINSTATE_DESTROYED) && pThis->m_pCurrentMsg == NULL) - { - // clear out window handle - HWND hWnd = pThis->m_hWnd; - pThis->m_hWnd = NULL; - pThis->m_dwState &= ~WINSTATE_DESTROYED; - // clean up after window is destroyed - pThis->OnFinalMessage(hWnd); - } - return lRes; -} - -template -HWND CWindowImplBaseT< TBase, TWinTraits >::Create(HWND hWndParent, _U_RECT rect, LPCTSTR szWindowName, - DWORD dwStyle, DWORD dwExStyle, _U_MENUorID MenuOrID, ATOM atom, LPVOID lpCreateParam) -{ - ATLASSERT(m_hWnd == NULL); - - if(atom == 0) - return NULL; - - _AtlWinModule.AddCreateWndData(&m_thunk.cd, this); - - if(MenuOrID.m_hMenu == NULL && (dwStyle & WS_CHILD)) - MenuOrID.m_hMenu = (HMENU)(UINT_PTR)this; - if(rect.m_lpRect == NULL) - rect.m_lpRect = &TBase::rcDefault; - - HWND hWnd = ::CreateWindowEx(dwExStyle, MAKEINTATOM(atom), szWindowName, - dwStyle, rect.m_lpRect->left, rect.m_lpRect->top, rect.m_lpRect->right - rect.m_lpRect->left, - rect.m_lpRect->bottom - rect.m_lpRect->top, hWndParent, MenuOrID.m_hMenu, - _AtlBaseModule.GetModuleInstance(), lpCreateParam); - - ATLASSERT(m_hWnd == hWnd); - - return hWnd; -} - -template -BOOL CWindowImplBaseT< TBase, TWinTraits >::SubclassWindow(HWND hWnd) -{ - ATLASSERT(m_hWnd == NULL); - ATLASSERT(::IsWindow(hWnd)); - m_thunk.Init(GetWindowProc(), this); - WNDPROC pProc = m_thunk.GetWNDPROC(); - WNDPROC pfnWndProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc); - if(pfnWndProc == NULL) - return FALSE; - m_pfnSuperWindowProc = pfnWndProc; - m_hWnd = hWnd; - return TRUE; -} - -// Use only if you want to subclass before window is destroyed, -// WindowProc will automatically subclass when window goes away -template -HWND CWindowImplBaseT< TBase, TWinTraits >::UnsubclassWindow(BOOL bForce /*= FALSE*/) -{ - ATLASSERT(m_hWnd != NULL); - - WNDPROC pOurProc = m_thunk.GetWNDPROC(); - WNDPROC pActiveProc = (WNDPROC)::GetWindowLongPtr(m_hWnd, GWLP_WNDPROC); - - HWND hWnd = NULL; - if (bForce || pOurProc == pActiveProc) - { - if(!::SetWindowLongPtr(m_hWnd, GWLP_WNDPROC, (LONG_PTR)m_pfnSuperWindowProc)) - return NULL; - - m_pfnSuperWindowProc = ::DefWindowProc; - hWnd = m_hWnd; - m_hWnd = NULL; - } - return hWnd; -} - -template -class ATL_NO_VTABLE CWindowImpl : public CWindowImplBaseT< TBase, TWinTraits > -{ -public: - DECLARE_WND_CLASS(NULL) - - static LPCTSTR GetWndCaption() - { - return NULL; - } - - HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - if (T::GetWndClassInfo().m_lpszOrigName == NULL) - T::GetWndClassInfo().m_lpszOrigName = GetWndClassName(); - ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc); - - dwStyle = T::GetWndStyle(dwStyle); - dwExStyle = T::GetWndExStyle(dwExStyle); - - // set caption - if (szWindowName == NULL) - szWindowName = T::GetWndCaption(); - - return CWindowImplBaseT< TBase, TWinTraits >::Create(hWndParent, rect, szWindowName, - dwStyle, dwExStyle, MenuOrID, atom, lpCreateParam); - } -}; - -template -class ATL_NO_VTABLE CWindowWithReflectorImpl : public CWindowImpl< T, TBase, TWinTraits > -{ -public: - HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - m_wndReflector.Create(hWndParent, rect, NULL, WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, Reflector::REFLECTOR_MAP_ID); - RECT rcPos = { 0, 0, rect.m_lpRect->right, rect.m_lpRect->bottom }; - return CWindowImpl< T, TBase, TWinTraits >::Create(m_wndReflector, rcPos, szWindowName, dwStyle, dwExStyle, MenuOrID, lpCreateParam); - } - -// message map and handlers - typedef CWindowWithReflectorImpl< T, TBase, TWinTraits > thisClass; - BEGIN_MSG_MAP(thisClass) - MESSAGE_HANDLER(WM_NCDESTROY, OnNcDestroy) - MESSAGE_HANDLER(WM_WINDOWPOSCHANGING, OnWindowPosChanging) - END_MSG_MAP() - - LRESULT OnNcDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - m_wndReflector.DestroyWindow(); - bHandled = FALSE; - return 1; - } - LRESULT OnWindowPosChanging(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) - { - WINDOWPOS* pWP = (WINDOWPOS*)lParam; - m_wndReflector.SetWindowPos(m_wndReflector.GetParent(), pWP->x, pWP->y, pWP->cx, pWP->cy, pWP->flags); - pWP->flags |= SWP_NOMOVE; - pWP->x = 0; - pWP->y = 0; - return DefWindowProc(uMsg, wParam, lParam); - } - - // reflector window stuff - class Reflector : public CWindowImpl - { - public: - enum { REFLECTOR_MAP_ID = 69 }; - DECLARE_WND_CLASS_EX(_T("ATLReflectorWindow"), 0, -1) - BEGIN_MSG_MAP(Reflector) - REFLECT_NOTIFICATIONS() - END_MSG_MAP() - } m_wndReflector; -}; - -///////////////////////////////////////////////////////////////////////////// -// CDialogImpl - Implements a dialog box - -#define _ATL_RT_DLGINIT MAKEINTRESOURCE(240) - -template -class ATL_NO_VTABLE CDialogImplBaseT : public CWindowImplRoot< TBase > -{ -public: - virtual ~CDialogImplBaseT() - { - } - virtual DLGPROC GetDialogProc() - { - return DialogProc; - } - static INT_PTR CALLBACK StartDialogProc(HWND hWnd, UINT uMsg, - WPARAM wParam, LPARAM lParam); - static INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - BOOL MapDialogRect(LPRECT lpRect) - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::MapDialogRect(m_hWnd, lpRect); - } - virtual void OnFinalMessage(HWND /*hWnd*/) - { - // override to do something, if needed - } - // has no meaning for a dialog, but needed for handlers that use it - LRESULT DefWindowProc() - { - return 0; - } - // initialize combobox and comboboxex from RT_DLGINIT resource if any - BOOL ExecuteDlgInit(int iDlgID) - { - BOOL bSuccess = TRUE; - HINSTANCE hInst = _AtlBaseModule.GetResourceInstance(); - HRSRC hrsrc = ::FindResource(hInst, MAKEINTRESOURCE(iDlgID), _ATL_RT_DLGINIT); - if (hrsrc) - { - HGLOBAL hResData = ::LoadResource(hInst, hrsrc); - if (hResData) - { - UNALIGNED WORD* pDlgInit = (UNALIGNED WORD*)::LockResource(hResData); - if (pDlgInit) - { - USES_CONVERSION; - while (bSuccess && NULL != *pDlgInit) - { - WORD wID = *pDlgInit++; - WORD wMsg = *pDlgInit++; - DWORD dwSize = *((UNALIGNED DWORD*&)pDlgInit)++; - - // CB_ADDSTRING is stored as 0x403 - if (0x403 == wMsg) - { - if (-1 == SendDlgItemMessage(wID, CB_ADDSTRING, 0, (LPARAM)(A2T((LPSTR)pDlgInit)))) - bSuccess = FALSE; - } - // CBEM_INSERTITEM is stored as 0x1234 - else if (0x1234 == wMsg) - { - COMBOBOXEXITEM item; - item.mask = CBEIF_TEXT; - item.iItem = -1; - item.pszText = A2T(LPSTR(pDlgInit)); - if (-1 == SendDlgItemMessage(wID, CBEM_INSERTITEM, 0, (LPARAM)&item)) - bSuccess = FALSE; - } - pDlgInit = (LPWORD)((LPBYTE)pDlgInit + dwSize); - } - } - } - } - return bSuccess; - } -}; - -template -INT_PTR CALLBACK CDialogImplBaseT< TBase >::StartDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - CDialogImplBaseT< TBase >* pThis = (CDialogImplBaseT< TBase >*)_AtlWinModule.ExtractCreateWndData(); - ATLASSERT(pThis != NULL); - pThis->m_hWnd = hWnd; - pThis->m_thunk.Init((WNDPROC)pThis->GetDialogProc(), pThis); - DLGPROC pProc = (DLGPROC)pThis->m_thunk.GetWNDPROC(); - DLGPROC pOldProc = (DLGPROC)::SetWindowLongPtr(hWnd, DWLP_DLGPROC, (LONG_PTR)pProc); -#ifdef _DEBUG - // check if somebody has subclassed us already since we discard it - if(pOldProc != StartDialogProc) - ATLTRACE(atlTraceWindowing, 0, _T("Subclassing through a hook discarded.\n")); -#else - pOldProc; // avoid unused warning -#endif - return pProc(hWnd, uMsg, wParam, lParam); -} - -template -INT_PTR CALLBACK CDialogImplBaseT< TBase >::DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - CDialogImplBaseT< TBase >* pThis = (CDialogImplBaseT< TBase >*)hWnd; - // set a ptr to this message and save the old value - _ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam); - const _ATL_MSG* pOldMsg = pThis->m_pCurrentMsg; - pThis->m_pCurrentMsg = &msg; - // pass to the message map to process - LRESULT lRes; - BOOL bRet = pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0); - // restore saved value for the current message - ATLASSERT(pThis->m_pCurrentMsg == &msg); - pThis->m_pCurrentMsg = pOldMsg; - // set result if message was handled - if(bRet) - { - switch (uMsg) - { - case WM_COMPAREITEM: - case WM_VKEYTOITEM: - case WM_CHARTOITEM: - case WM_INITDIALOG: - case WM_QUERYDRAGICON: - case WM_CTLCOLORMSGBOX: - case WM_CTLCOLOREDIT: - case WM_CTLCOLORLISTBOX: - case WM_CTLCOLORBTN: - case WM_CTLCOLORDLG: - case WM_CTLCOLORSCROLLBAR: - case WM_CTLCOLORSTATIC: - // return directly - bRet = (BOOL)lRes; - break; - default: - // return in DWL_MSGRESULT - ::SetWindowLongPtr(pThis->m_hWnd, DWLP_MSGRESULT, lRes); - break; - } - } - else if(uMsg == WM_NCDESTROY) - { - // mark dialog as destryed - pThis->m_dwState |= WINSTATE_DESTROYED; - } - - if((pThis->m_dwState & WINSTATE_DESTROYED) && pThis->m_pCurrentMsg == NULL) - { - // clear out window handle - HWND hWnd = pThis->m_hWnd; - pThis->m_hWnd = NULL; - pThis->m_dwState &= ~WINSTATE_DESTROYED; - // clean up after dialog is destroyed - pThis->OnFinalMessage(hWnd); - } - return bRet; -} - -typedef CDialogImplBaseT CDialogImplBase; - -template -class ATL_NO_VTABLE CDialogImpl : public CDialogImplBaseT< TBase > -{ -public: -#ifdef _DEBUG - bool m_bModal; - CDialogImpl() : m_bModal(false) { } -#endif //_DEBUG - // modal dialogs - INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow(), LPARAM dwInitParam = NULL) - { - ATLASSERT(m_hWnd == NULL); - _AtlWinModule.AddCreateWndData(&m_thunk.cd, (CDialogImplBaseT< TBase >*)this); -#ifdef _DEBUG - m_bModal = true; -#endif //_DEBUG - return ::DialogBoxParam(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(static_cast(this)->IDD), - hWndParent, T::StartDialogProc, dwInitParam); - } - BOOL EndDialog(int nRetCode) - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(m_bModal); // must be a modal dialog - return ::EndDialog(m_hWnd, nRetCode); - } - // modeless dialogs - HWND Create(HWND hWndParent, LPARAM dwInitParam = NULL) - { - ATLASSERT(m_hWnd == NULL); - _AtlWinModule.AddCreateWndData(&m_thunk.cd, (CDialogImplBaseT< TBase >*)this); -#ifdef _DEBUG - m_bModal = false; -#endif //_DEBUG - HWND hWnd = ::CreateDialogParam(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(static_cast(this)->IDD), - hWndParent, T::StartDialogProc, dwInitParam); - ATLASSERT(m_hWnd == hWnd); - return hWnd; - } - // for CComControl - HWND Create(HWND hWndParent, RECT&, LPARAM dwInitParam = NULL) - { - return Create(hWndParent, dwInitParam); - } - BOOL DestroyWindow() - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(!m_bModal); // must not be a modal dialog - return ::DestroyWindow(m_hWnd); - } -}; - -///////////////////////////////////////////////////////////////////////////// -// CAxDialogImpl - Implements a dialog box that hosts ActiveX controls - -#ifndef _ATL_NO_HOSTING - - -template -class ATL_NO_VTABLE CAxDialogImpl : public CDialogImplBaseT< TBase > -{ -public: -#ifdef _DEBUG - bool m_bModal; - CAxDialogImpl() : m_bModal(false) { } -#endif //_DEBUG - int GetIDD() - { - return( static_cast(this)->IDD ); - } - virtual DLGPROC GetDialogProc() - { - return DialogProc; - } - static INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - // modal dialogs - INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow(), LPARAM dwInitParam = NULL) - { - ATLASSERT(m_hWnd == NULL); - _AtlWinModule.AddCreateWndData(&m_thunk.cd, (CDialogImplBaseT< TBase >*)this); -#ifdef _DEBUG - m_bModal = true; -#endif //_DEBUG - return AtlAxDialogBox(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(static_cast(this)->IDD), - hWndParent, T::StartDialogProc, dwInitParam); - } - BOOL EndDialog(int nRetCode) - { - ATLASSERT(::IsWindow(m_hWnd)); -#ifdef _DEBUG - ATLASSERT(m_bModal); // must be a modal dialog -#endif //_DEBUG - return ::EndDialog(m_hWnd, nRetCode); - } - // modeless dialogs - HWND Create(HWND hWndParent, LPARAM dwInitParam = NULL) - { - ATLASSERT(m_hWnd == NULL); - _AtlWinModule.AddCreateWndData(&m_thunk.cd, (CDialogImplBaseT< TBase >*)this); -#ifdef _DEBUG - m_bModal = false; -#endif //_DEBUG - HWND hWnd = AtlAxCreateDialog(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(static_cast(this)->IDD), - hWndParent, T::StartDialogProc, dwInitParam); - ATLASSERT(m_hWnd == hWnd); - return hWnd; - } - // for CComControl - HWND Create(HWND hWndParent, RECT&, LPARAM dwInitParam = NULL) - { - return Create(hWndParent, dwInitParam); - } - BOOL DestroyWindow() - { - ATLASSERT(::IsWindow(m_hWnd)); -#ifdef _DEBUG - ATLASSERT(!m_bModal); // must not be a modal dialog -#endif //_DEBUG - return ::DestroyWindow(m_hWnd); - } - -// Event handling support and Message map - HRESULT AdviseSinkMap(bool bAdvise) - { - if(!bAdvise && m_hWnd == NULL) - { - // window is gone, controls are already unadvised - ATLTRACE(atlTraceControls, 1, _T("CAxDialogImpl::AdviseSinkMap called after the window was destroyed\n")); - return S_OK; - } - HRESULT hRet = E_NOTIMPL; - __if_exists(T::_GetSinkMapFinder) - { - T* pT = static_cast(this); - hRet = AtlAdviseSinkMap(pT, bAdvise); - } - return hRet; - } - - typedef CAxDialogImpl< T, TBase > thisClass; - BEGIN_MSG_MAP(thisClass) - MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) - MESSAGE_HANDLER(WM_DESTROY, OnDestroy) - END_MSG_MAP() - - virtual HRESULT CreateActiveXControls(UINT nID) - { - // Load dialog template and InitData - HRSRC hDlgInit = ::FindResource(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(nID), (LPTSTR)_ATL_RT_DLGINIT); - BYTE* pInitData = NULL; - HGLOBAL hData = NULL; - HRESULT hr = S_OK; - if (hDlgInit != NULL) - { - hData = ::LoadResource(_AtlBaseModule.GetResourceInstance(), hDlgInit); - if (hData != NULL) - pInitData = (BYTE*) ::LockResource(hData); - } - - HRSRC hDlg = ::FindResource(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(nID), (LPTSTR)RT_DIALOG); - if (hDlg != NULL) - { - HGLOBAL hResource = ::LoadResource(_AtlBaseModule.GetResourceInstance(), hDlg); - DLGTEMPLATE* pDlg = NULL; - if (hResource != NULL) - { - pDlg = (DLGTEMPLATE*) ::LockResource(hResource); - if (pDlg != NULL) - { - // Get first control on the template - BOOL bDialogEx = _DialogSplitHelper::IsDialogEx(pDlg); - WORD nItems = _DialogSplitHelper::DlgTemplateItemCount(pDlg); - - // Get first control on the dialog - DLGITEMTEMPLATE* pItem = _DialogSplitHelper::FindFirstDlgItem(pDlg); - HWND hWndPrev = GetWindow(GW_CHILD); - - // Create all ActiveX cotnrols in the dialog template and place them in the correct tab order (z-order) - for (WORD nItem = 0; nItem < nItems; nItem++) - { - DWORD wID = bDialogEx ? ((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->id : pItem->id; - if (_DialogSplitHelper::IsActiveXControl(pItem, bDialogEx)) - { - BYTE* pData = NULL; - DWORD dwLen = _DialogSplitHelper::FindCreateData(wID, pInitData, &pData); - CComPtr spStream; - if (dwLen != 0) - { - HGLOBAL h = GlobalAlloc(GHND, dwLen); - if (h != NULL) - { - BYTE* pBytes = (BYTE*) GlobalLock(h); - BYTE* pSource = pData; - memcpy(pBytes, pSource, dwLen); - GlobalUnlock(h); - CreateStreamOnHGlobal(h, TRUE, &spStream); - } - else - { - hr = E_OUTOFMEMORY; - break; - } - } - - CComBSTR bstrLicKey; - hr = _DialogSplitHelper::ParseInitData(spStream, &bstrLicKey.m_str); - if (SUCCEEDED(hr)) - { - CAxWindow2 wnd; - // Get control caption. - LPWSTR pszClassName = - bDialogEx ? - (LPWSTR)(((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem) + 1) : - (LPWSTR)(pItem + 1); - // Get control rect. - RECT rect; - rect.left = - bDialogEx ? - ((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->x : - pItem->x; - rect.top = - bDialogEx ? - ((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->y : - pItem->y; - rect.right = rect.left + - (bDialogEx ? - ((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->cx : - pItem->cx); - rect.bottom = rect.top + - (bDialogEx ? - ((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->cy : - pItem->cy); - - // Convert from dialog units to screen units - MapDialogRect(&rect); - - // Create AxWindow with a NULL caption. - wnd.Create(m_hWnd, - &rect, - NULL, - (bDialogEx ? - ((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->style : - pItem->style) | WS_TABSTOP, - bDialogEx ? - ((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->exStyle : - 0, - bDialogEx ? - ((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->id : - pItem->id, - NULL); - - if (wnd != NULL) - { - // Set the Help ID - if (bDialogEx && ((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->helpID != 0) - wnd.SetWindowContextHelpId(((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->helpID); - // Try to create the ActiveX control. - hr = wnd.CreateControlLic(pszClassName, spStream, NULL, bstrLicKey); - if (FAILED(hr)) - break; - // Set the correct tab position. - if (nItem == 0) - hWndPrev = HWND_TOP; - wnd.SetWindowPos(hWndPrev, 0,0,0,0,SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); - hWndPrev = wnd; - } - else - { - hr = AtlHresultFromLastError(); - } - } - } - else - { - if (nItem != 0) - hWndPrev = ::GetWindow(hWndPrev, GW_HWNDNEXT); - } - pItem = _DialogSplitHelper::FindNextDlgItem(pItem, bDialogEx); - } - } - else - hr = AtlHresultFromLastError(); - } - else - hr = AtlHresultFromLastError(); - } - return hr; - } - - LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - // initialize controls in dialog with DLGINIT resource section - ExecuteDlgInit(static_cast(this)->IDD); - AdviseSinkMap(true); - bHandled = FALSE; - return 1; - } - - LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - AdviseSinkMap(false); - bHandled = FALSE; - return 1; - } - -// Accelerators handling - needs to be called from a message loop - BOOL IsDialogMessage(LPMSG pMsg) - { - if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) && - (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST)) - return FALSE; - - // find a direct child of the dialog from the window that has focus - HWND hWndCtl = ::GetFocus(); - if(IsChild(hWndCtl) && ::GetParent(hWndCtl) != m_hWnd) - { - do - { - hWndCtl = ::GetParent(hWndCtl); - } - while (::GetParent(hWndCtl) != m_hWnd); - } - // give controls a chance to translate this message - if (::SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)pMsg) == 1) - return TRUE; - - // do the Windows default thing - return CDialogImplBaseT< TBase >::IsDialogMessage(pMsg); - } -}; - -template -INT_PTR CALLBACK CAxDialogImpl< T, TBase >::DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - CAxDialogImpl< T, TBase >* pThis = (CAxDialogImpl< T, TBase >*)hWnd; - if (uMsg == WM_INITDIALOG) - { - HRESULT hr; - if (FAILED(hr = pThis->CreateActiveXControls(pThis->GetIDD()))) - { - pThis->DestroyWindow(); - SetLastError(hr & 0x0000FFFF); - return FALSE; - } - } - return CDialogImplBaseT< TBase >::DialogProc(hWnd, uMsg, wParam, lParam); -} -#endif //_ATL_NO_HOSTING - -///////////////////////////////////////////////////////////////////////////// -// CSimpleDialog - Prebuilt modal dialog that uses standard buttons - -template -class CSimpleDialog : public CDialogImplBase -{ -public: - INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow()) - { - ATLASSERT(m_hWnd == NULL); - _AtlWinModule.AddCreateWndData(&m_thunk.cd, (CDialogImplBase*)this); - int nRet = ::DialogBox(_AtlBaseModule.GetResourceInstance(), - MAKEINTRESOURCE(t_wDlgTemplateID), hWndParent, StartDialogProc); - m_hWnd = NULL; - return nRet; - } - - typedef CSimpleDialog thisClass; - BEGIN_MSG_MAP(thisClass) - MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) - COMMAND_RANGE_HANDLER(IDOK, IDNO, OnCloseCmd) - END_MSG_MAP() - - LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - // initialize controls in dialog with DLGINIT resource section - ExecuteDlgInit(t_wDlgTemplateID); - if(t_bCenter) - CenterWindow(GetParent()); - return TRUE; - } - - LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) - { - ::EndDialog(m_hWnd, wID); - return 0; - } -}; - -///////////////////////////////////////////////////////////////////////////// -// CContainedWindow - Implements a contained window - -template -class CContainedWindowT : public TBase -{ -public: - CWndProcThunk m_thunk; - LPCTSTR m_lpszClassName; - WNDPROC m_pfnSuperWindowProc; - CMessageMap* m_pObject; - DWORD m_dwMsgMapID; - const _ATL_MSG* m_pCurrentMsg; - - // If you use this constructor you must supply - // the Window Class Name, Object* and Message Map ID - // Later to the Create call - CContainedWindowT() : m_pCurrentMsg(NULL) - { } - - CContainedWindowT(LPTSTR lpszClassName, CMessageMap* pObject, DWORD dwMsgMapID = 0) - : m_lpszClassName(lpszClassName), - m_pfnSuperWindowProc(::DefWindowProc), - m_pObject(pObject), m_dwMsgMapID(dwMsgMapID), - m_pCurrentMsg(NULL) - { } - - CContainedWindowT(CMessageMap* pObject, DWORD dwMsgMapID = 0) - : m_lpszClassName(TBase::GetWndClassName()), - m_pfnSuperWindowProc(::DefWindowProc), - m_pObject(pObject), m_dwMsgMapID(dwMsgMapID), - m_pCurrentMsg(NULL) - { } - - void SwitchMessageMap(DWORD dwMsgMapID) - { - m_dwMsgMapID = dwMsgMapID; - } - - const _ATL_MSG* GetCurrentMessage() const - { - return m_pCurrentMsg; - } - - LRESULT DefWindowProc() - { - const _ATL_MSG* pMsg = m_pCurrentMsg; - LRESULT lRes = 0; - if (pMsg != NULL) - lRes = DefWindowProc(pMsg->message, pMsg->wParam, pMsg->lParam); - return lRes; - } - - LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) - { -#ifdef STRICT - return ::CallWindowProc(m_pfnSuperWindowProc, m_hWnd, uMsg, wParam, lParam); -#else - return ::CallWindowProc((FARPROC)m_pfnSuperWindowProc, m_hWnd, uMsg, wParam, lParam); -#endif - } - static LRESULT CALLBACK StartWindowProc(HWND hWnd, UINT uMsg, - WPARAM wParam, LPARAM lParam) - { - CContainedWindowT< TBase >* pThis = (CContainedWindowT< TBase >*)_AtlWinModule.ExtractCreateWndData(); - ATLASSERT(pThis != NULL); - pThis->m_hWnd = hWnd; - pThis->m_thunk.Init(WindowProc, pThis); - WNDPROC pProc = pThis->m_thunk.GetWNDPROC(); - WNDPROC pOldProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc); -#ifdef _DEBUG - // check if somebody has subclassed us already since we discard it - if(pOldProc != StartWindowProc) - ATLTRACE(atlTraceWindowing, 0, _T("Subclassing through a hook discarded.\n")); -#else - pOldProc; // avoid unused warning -#endif - return pProc(hWnd, uMsg, wParam, lParam); - } - - static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) - { - CContainedWindowT< TBase >* pThis = (CContainedWindowT< TBase >*)hWnd; - ATLASSERT(pThis->m_hWnd != NULL); - ATLASSERT(pThis->m_pObject != NULL); - // set a ptr to this message and save the old value - _ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam); - const _ATL_MSG* pOldMsg = pThis->m_pCurrentMsg; - pThis->m_pCurrentMsg = &msg; - // pass to the message map to process - LRESULT lRes; - BOOL bRet = pThis->m_pObject->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, pThis->m_dwMsgMapID); - // restore saved value for the current message - ATLASSERT(pThis->m_pCurrentMsg == &msg); - pThis->m_pCurrentMsg = pOldMsg; - // do the default processing if message was not handled - if(!bRet) - { - if(uMsg != WM_NCDESTROY) - lRes = pThis->DefWindowProc(uMsg, wParam, lParam); - else - { - // unsubclass, if needed - LONG_PTR pfnWndProc = ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC); - lRes = pThis->DefWindowProc(uMsg, wParam, lParam); - if(pThis->m_pfnSuperWindowProc != ::DefWindowProc && ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC) == pfnWndProc) - ::SetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC, (LONG_PTR)pThis->m_pfnSuperWindowProc); - // clear out window handle - pThis->m_hWnd = NULL; - } - } - return lRes; - } - - ATOM RegisterWndSuperclass() - { - ATOM atom = 0; - LPTSTR szBuff = (LPTSTR)_alloca((lstrlen(m_lpszClassName) + 14) * sizeof(TCHAR)); - - WNDCLASSEX wc; - wc.cbSize = sizeof(WNDCLASSEX); - - // Try global class - if(!::GetClassInfoEx(NULL, m_lpszClassName, &wc)) - { - // try local class - if(!::GetClassInfoEx(_AtlBaseModule.GetModuleInstance(), m_lpszClassName, &wc)) - return atom; - } - - m_pfnSuperWindowProc = wc.lpfnWndProc; - lstrcpy(szBuff, _T("ATL:")); - lstrcat(szBuff, m_lpszClassName); - - WNDCLASSEX wc1; - wc1.cbSize = sizeof(WNDCLASSEX); - atom = (ATOM)::GetClassInfoEx(_AtlBaseModule.GetModuleInstance(), szBuff, &wc1); - - if(atom == 0) // register class - { - wc.lpszClassName = szBuff; - wc.lpfnWndProc = StartWindowProc; - wc.hInstance = _AtlBaseModule.GetModuleInstance(); - wc.style &= ~CS_GLOBALCLASS; // we don't register global classes - - atom = AtlWinModuleRegisterClassEx(&_AtlWinModule, &wc); - } - return atom; - } - - HWND Create(HWND hWndParent, _U_RECT rect, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - ATLASSERT(m_hWnd == NULL); - - ATOM atom = RegisterWndSuperclass(); - if(atom == 0) - return NULL; - - _AtlWinModule.AddCreateWndData(&m_thunk.cd, this); - - if(MenuOrID.m_hMenu == NULL && (dwStyle & WS_CHILD)) - MenuOrID.m_hMenu = (HMENU)(UINT_PTR)this; - if(rect.m_lpRect == NULL) - rect.m_lpRect = &TBase::rcDefault; - - dwStyle = TWinTraits::GetWndStyle(dwStyle); - dwExStyle = TWinTraits::GetWndExStyle(dwExStyle); - - HWND hWnd = ::CreateWindowEx(dwExStyle, MAKEINTATOM(atom), szWindowName, - dwStyle, - rect.m_lpRect->left, rect.m_lpRect->top, - rect.m_lpRect->right - rect.m_lpRect->left, - rect.m_lpRect->bottom - rect.m_lpRect->top, - hWndParent, MenuOrID.m_hMenu, - _AtlBaseModule.GetModuleInstance(), lpCreateParam); - ATLASSERT(m_hWnd == hWnd); - return hWnd; - } - - HWND Create(CMessageMap* pObject, DWORD dwMsgMapID, HWND hWndParent, _U_RECT rect, - LPCTSTR szWindowName = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, - _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - m_lpszClassName = TBase::GetWndClassName(); - m_pfnSuperWindowProc = ::DefWindowProc; - m_pObject = pObject; - m_dwMsgMapID = dwMsgMapID; - return Create(hWndParent, rect, szWindowName, dwStyle, dwExStyle, MenuOrID, lpCreateParam); - } - - HWND Create(LPCTSTR lpszClassName, CMessageMap* pObject, DWORD dwMsgMapID, HWND hWndParent, _U_RECT rect, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - m_lpszClassName = lpszClassName; - m_pfnSuperWindowProc = ::DefWindowProc; - m_pObject = pObject; - m_dwMsgMapID = dwMsgMapID; - return Create(hWndParent, rect, szWindowName, dwStyle, dwExStyle, MenuOrID, lpCreateParam); - } - - BOOL SubclassWindow(HWND hWnd) - { - ATLASSERT(m_hWnd == NULL); - ATLASSERT(::IsWindow(hWnd)); - - m_thunk.Init(WindowProc, this); - WNDPROC pProc = m_thunk.GetWNDPROC(); - WNDPROC pfnWndProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc); - if(pfnWndProc == NULL) - return FALSE; - m_pfnSuperWindowProc = pfnWndProc; - m_hWnd = hWnd; - return TRUE; - } - - // Use only if you want to subclass before window is destroyed, - // WindowProc will automatically subclass when window goes away - HWND UnsubclassWindow(BOOL bForce = FALSE) - { - ATLASSERT(m_hWnd != NULL); - - WNDPROC pOurProc = m_thunk.GetWNDPROC(); - WNDPROC pActiveProc = (WNDPROC)::GetWindowLongPtr(m_hWnd, GWLP_WNDPROC); - - HWND hWnd = NULL; - if (bForce || pOurProc == pActiveProc) - { - if(!::SetWindowLongPtr(m_hWnd, GWLP_WNDPROC, (LONG_PTR)m_pfnSuperWindowProc)) - return NULL; - - m_pfnSuperWindowProc = ::DefWindowProc; - hWnd = m_hWnd; - m_hWnd = NULL; - } - return hWnd; - } - LRESULT ReflectNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - HWND hWndChild = NULL; - - switch(uMsg) - { - case WM_COMMAND: - if(lParam != NULL) // not from a menu - hWndChild = (HWND)lParam; - break; - case WM_NOTIFY: - hWndChild = ((LPNMHDR)lParam)->hwndFrom; - break; - case WM_PARENTNOTIFY: - switch(LOWORD(wParam)) - { - case WM_CREATE: - case WM_DESTROY: - hWndChild = (HWND)lParam; - break; - default: - hWndChild = GetDlgItem(HIWORD(wParam)); - break; - } - break; - case WM_DRAWITEM: - if(wParam) // not from a menu - hWndChild = ((LPDRAWITEMSTRUCT)lParam)->hwndItem; - break; - case WM_MEASUREITEM: - if(wParam) // not from a menu - hWndChild = GetDlgItem(((LPMEASUREITEMSTRUCT)lParam)->CtlID); - break; - case WM_COMPAREITEM: - if(wParam) // not from a menu - hWndChild = GetDlgItem(((LPCOMPAREITEMSTRUCT)lParam)->CtlID); - break; - case WM_DELETEITEM: - if(wParam) // not from a menu - hWndChild = GetDlgItem(((LPDELETEITEMSTRUCT)lParam)->CtlID); - break; - case WM_VKEYTOITEM: - case WM_CHARTOITEM: - case WM_HSCROLL: - case WM_VSCROLL: - hWndChild = (HWND)lParam; - break; - case WM_CTLCOLORBTN: - case WM_CTLCOLORDLG: - case WM_CTLCOLOREDIT: - case WM_CTLCOLORLISTBOX: - case WM_CTLCOLORMSGBOX: - case WM_CTLCOLORSCROLLBAR: - case WM_CTLCOLORSTATIC: - hWndChild = (HWND)lParam; - break; - default: - break; - } - - if(hWndChild == NULL) - { - bHandled = FALSE; - return 1; - } - - ATLASSERT(::IsWindow(hWndChild)); - return ::SendMessage(hWndChild, OCM__BASE + uMsg, wParam, lParam); - } -}; - -typedef CContainedWindowT CContainedWindow; - -///////////////////////////////////////////////////////////////////////////// -// _DialogSizeHelper - helpers for calculating the size of a dialog template - -class _DialogSizeHelper -{ -public: -//local struct used for implementation -#pragma pack(push, 1) - struct _ATL_DLGTEMPLATEEX - { - WORD dlgVer; - WORD signature; - DWORD helpID; - DWORD exStyle; - DWORD style; - WORD cDlgItems; - short x; - short y; - short cx; - short cy; - }; -#pragma pack(pop) - - static void GetDialogSize(const DLGTEMPLATE* pTemplate, SIZE* pSize, bool bPropertyPage = false) - { - // If the dialog has a font we use it otherwise we default - // to the system font. - TCHAR szFace[LF_FACESIZE]; - WORD wFontSize = 0; - GetSizeInDialogUnits(pTemplate, pSize); - BOOL bFont = GetFont(pTemplate, szFace, &wFontSize); - if (bFont) - { - ConvertDialogUnitsToPixels(szFace, wFontSize, pSize, bPropertyPage); - } - else - { - ConvertDialogUnitsToPixels(NULL, 0, pSize, bPropertyPage); - } - } - - static void GetFontDimensions(LPCTSTR pszFontFace, WORD wFontSize, SIZE* pSizeChar, LONG *ptmHeight) - { - if (pszFontFace != NULL) - { - // Attempt to create the font to be used in the dialog box - HDC hDC = ::GetDC(NULL); - if (hDC != NULL) - { - LOGFONT lf; - memset(&lf, 0, sizeof(LOGFONT)); - lf.lfHeight = -MulDiv(wFontSize, GetDeviceCaps(hDC, LOGPIXELSY), 72); - lf.lfWeight = FW_NORMAL; - lf.lfCharSet = DEFAULT_CHARSET; - lstrcpyn(lf.lfFaceName, pszFontFace, sizeof(lf.lfFaceName) / sizeof(lf.lfFaceName[0])); - - HFONT hNewFont = CreateFontIndirect(&lf); - if (hNewFont != NULL) - { - TEXTMETRIC tm; - SIZE size; - HFONT hFontOld = (HFONT)SelectObject(hDC, hNewFont); - GetTextMetrics(hDC, &tm); - ::GetTextExtentPoint(hDC, - _T("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"), 52, - &size); - SelectObject(hDC, hFontOld); - DeleteObject(hNewFont); - *ptmHeight = tm.tmHeight; - pSizeChar->cy = tm.tmHeight + tm.tmExternalLeading; - pSizeChar->cx = (size.cx + 26) / 52; - ::ReleaseDC(NULL, hDC); - return; - } - ::ReleaseDC(NULL, hDC); - } - } - // Could not create font or no font name was not specified - LONG nDlgBaseUnits = GetDialogBaseUnits(); - pSizeChar->cx = LOWORD(nDlgBaseUnits); - *ptmHeight = pSizeChar->cy = HIWORD(nDlgBaseUnits); - } - -// ID of the dialog template used for property sheet in comctl32.dll -#define IDD_PROPSHEET_ID 1006 - - static void ConvertDialogUnitsToPixels(LPCTSTR pszFontFace, WORD wFontSize, SIZE* pSizePixel, bool bPropertyPage = false) - { - LONG tmHeight; - SIZE sizeFontChar; - GetFontDimensions(pszFontFace, wFontSize, &sizeFontChar, &tmHeight); - if (bPropertyPage) - { - // Get the font used by the property sheet - HINSTANCE hInst = LoadLibrary(_T("COMCTL32.DLL")); - if (hInst != NULL) - { - HRSRC hResource = ::FindResource(hInst, - MAKEINTRESOURCE(IDD_PROPSHEET_ID), - RT_DIALOG); - if (hResource != NULL) - { - HGLOBAL hTemplate = LoadResource(hInst, hResource); - if (hTemplate != NULL) - { - TCHAR szFace[LF_FACESIZE]; - WORD wSize; - BOOL bFont; - bFont = _DialogSizeHelper::GetFont((DLGTEMPLATE*)hTemplate, szFace, &wSize); - FreeLibrary(hInst); - if (bFont) - { - SIZE sizeSheetFontChar; - LONG tmHeightSheetFont; - GetFontDimensions(szFace, wSize, &sizeSheetFontChar, &tmHeightSheetFont); - // Now translate to pixels compensating for the calculations made by OLEAUT32 and Dialog manager - - // Calculate the size of pixels using property sheet font. - pSizePixel->cx = MulDiv(pSizePixel->cx, sizeFontChar.cx, 4); - pSizePixel->cy = MulDiv(pSizePixel->cy, sizeSheetFontChar.cy, 8); - - // Inflate/Deflate the height to compensate for the correct font. - pSizePixel->cy = MulDiv(pSizePixel->cy, tmHeight, tmHeightSheetFont); - return ; - } - } - } - } - } - // Not property page or could not load Property sheet resource. - // Translate dialog units to pixels - pSizePixel->cx = MulDiv(pSizePixel->cx, sizeFontChar.cx, 4); - pSizePixel->cy = MulDiv(pSizePixel->cy, sizeFontChar.cy, 8); - } - - static BOOL IsDialogEx(const DLGTEMPLATE* pTemplate) - { - return ((_ATL_DLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF; - } - - static BOOL HasFont(const DLGTEMPLATE* pTemplate) - { - return (DS_SETFONT & - (IsDialogEx(pTemplate) ? - ((_ATL_DLGTEMPLATEEX*)pTemplate)->style : pTemplate->style)); - } - - static BYTE* GetFontSizeField(const DLGTEMPLATE* pTemplate) - { - BOOL bDialogEx = IsDialogEx(pTemplate); - WORD* pw; - - if (bDialogEx) - pw = (WORD*)((_ATL_DLGTEMPLATEEX*)pTemplate + 1); - else - pw = (WORD*)(pTemplate + 1); - - if (*pw == (WORD)-1) // Skip menu name string or ordinal - pw += 2; // WORDs - else - while(*pw++); - - if (*pw == (WORD)-1) // Skip class name string or ordinal - pw += 2; // WORDs - else - while(*pw++); - - while (*pw++); // Skip caption string - - return (BYTE*)pw; - } - - static BOOL GetFont(const DLGTEMPLATE* pTemplate, TCHAR* pszFace, WORD* pFontSize) - { - USES_CONVERSION; - if (!HasFont(pTemplate)) - return FALSE; - - BYTE* pb = GetFontSizeField(pTemplate); - *pFontSize = *(WORD*)pb; - // Skip over font attributes to get to the font name - pb += sizeof(WORD) * (IsDialogEx(pTemplate) ? 3 : 1); - - _tcsncpy(pszFace, W2T((WCHAR*)pb), LF_FACESIZE); - if (_tcslen(pszFace) >= LF_FACESIZE) - { // NUL not appended - pszFace[LF_FACESIZE-1] = _T('\0'); - } - return TRUE; - } - - static void GetSizeInDialogUnits(const DLGTEMPLATE* pTemplate, SIZE* pSize) - { - if (IsDialogEx(pTemplate)) - { - pSize->cx = ((_ATL_DLGTEMPLATEEX*)pTemplate)->cx; - pSize->cy = ((_ATL_DLGTEMPLATEEX*)pTemplate)->cy; - } - else - { - pSize->cx = pTemplate->cx; - pSize->cy = pTemplate->cy; - } - } -}; - -inline void AtlGetDialogSize(const DLGTEMPLATE* pTemplate, SIZE* pSize, bool bPropertyPage = false) -{ - ATLASSERT(pTemplate != NULL); - ATLASSERT(pSize != NULL); - _DialogSizeHelper::GetDialogSize(pTemplate, pSize, bPropertyPage); -} - -}; //namespace ATL - -#ifndef _ATL_NO_HOSTING - -#include - -#endif - -#endif // __ATLWIN_H__ - -//All exports go here -#ifndef _ATL_DLL - -namespace ATL -{ - -class AtlModuleRegisterWndClassInfoParamA -{ -public: - typedef LPSTR PXSTR; - typedef LPCSTR PCXSTR; - typedef _ATL_WNDCLASSINFOA _ATL_WNDCLASSINFO; - typedef WNDCLASSEXA WNDCLASSEX; - - static BOOL GetClassInfoEx(HINSTANCE hinst, PCXSTR lpszClass, WNDCLASSEX* lpwcx) - { - return ::GetClassInfoExA(hinst, lpszClass, lpwcx); - } - - static void FormatWindowClassName(PXSTR szBuffer, void* unique) - { -#if defined(_WIN64) // || or Windows 2000 - ::wsprintfA(szBuffer, "ATL:%p", unique); -#else - ::wsprintfA(szBuffer, "ATL:%8.8X", reinterpret_cast(unique)); -#endif - } - - static HCURSOR LoadCursor(HINSTANCE hInstance, PCXSTR lpCursorName) - { - return ::LoadCursorA(hInstance, lpCursorName); - } - - static ATOM RegisterClassEx(_ATL_WIN_MODULE* pWinModule, const WNDCLASSEX* lpwcx) - { - return AtlWinModuleRegisterClassExA(pWinModule, lpwcx); - } -}; - -class AtlModuleRegisterWndClassInfoParamW -{ -public: - typedef LPWSTR PXSTR; - typedef LPCWSTR PCXSTR; - typedef _ATL_WNDCLASSINFOW _ATL_WNDCLASSINFO; - typedef WNDCLASSEXW WNDCLASSEX; - - static BOOL GetClassInfoEx(HINSTANCE hinst, PCXSTR lpszClass, WNDCLASSEX* lpwcx) - { - return ::GetClassInfoExW(hinst, lpszClass, lpwcx); - } - - static void FormatWindowClassName(PXSTR szBuffer, void* unique) - { -#if defined(_WIN64) // || or Windows 2000 - ::wsprintfW(szBuffer, L"ATL:%p", unique); -#else - ::wsprintfW(szBuffer, L"ATL:%8.8X", reinterpret_cast(unique)); -#endif - } - - static HCURSOR LoadCursor(HINSTANCE hInstance, PCXSTR lpCursorName) - { - return ::LoadCursorW(hInstance, lpCursorName); - } - - static ATOM RegisterClassEx(_ATL_WIN_MODULE* pWinModule, const WNDCLASSEX* lpwcx) - { - return AtlWinModuleRegisterClassExW(pWinModule, lpwcx); - } -}; - -ATLINLINE ATLAPI_(ATOM) AtlWinModuleRegisterClassExA(_ATL_WIN_MODULE* pWinModule, const WNDCLASSEXA *lpwc) -{ - if (pWinModule == NULL || lpwc == NULL) - return 0; - ATOM atom = ::RegisterClassExA(lpwc); - BOOL bRet = pWinModule->m_rgWindowClassAtoms.Add(atom); - ATLASSERT(bRet); - (bRet); - return atom; -} - -ATLINLINE ATLAPI_(ATOM) AtlWinModuleRegisterClassExW(_ATL_WIN_MODULE* pWinModule, const WNDCLASSEXW *lpwc) -{ - if (pWinModule == NULL || lpwc == NULL) - return 0; - ATOM atom = ::RegisterClassExW(lpwc); - BOOL bRet = pWinModule->m_rgWindowClassAtoms.Add(atom); - ATLASSERT(bRet); - (bRet); - return atom; -} - - -template -ATLINLINE ATOM AtlModuleRegisterWndClassInfoT(_ATL_BASE_MODULE* pBaseModule, _ATL_WIN_MODULE* pWinModule, typename T::_ATL_WNDCLASSINFO* p, WNDPROC* pProc, T) -{ - if (pBaseModule == NULL || pWinModule == NULL || p == NULL || pProc == NULL) - { - ATLTRACE(atlTraceWindowing, 0, _T("ERROR : Invalid Arguments to AtlModuleRegisterWndClassInfoT\n")); - ATLASSERT(0); - return 0; - } - - if (p->m_atom == 0) - { - ATL::CComCritSecLock lock(pWinModule->m_csWindowCreate, false); - if (FAILED(lock.Lock())) - { - ATLTRACE(atlTraceWindowing, 0, _T("ERROR : Unable to lock critical section in AtlModuleRegisterWndClassInfoT\n")); - ATLASSERT(0); - return 0; - } - if(p->m_atom == 0) - { - if (p->m_lpszOrigName != NULL) - { - ATLASSERT(pProc != NULL); - T::PCXSTR lpsz = p->m_wc.lpszClassName; - WNDPROC proc = p->m_wc.lpfnWndProc; - - T::WNDCLASSEX wc; - wc.cbSize = sizeof(T::WNDCLASSEX); - // Try global class - if(!T::GetClassInfoEx(NULL, p->m_lpszOrigName, &wc)) - { - // try process local - if(!T::GetClassInfoEx(pBaseModule->m_hInst, p->m_lpszOrigName, &wc)) - { - ATLTRACE(atlTraceWindowing, 0, "ERROR : Could not obtain Window Class information for %s\n", p->m_lpszOrigName); - return 0; - } - } - p->m_wc = wc; - p->pWndProc = p->m_wc.lpfnWndProc; - p->m_wc.lpszClassName = lpsz; - p->m_wc.lpfnWndProc = proc; - } - else - { - p->m_wc.hCursor = T::LoadCursor(p->m_bSystemCursor ? NULL : pBaseModule->m_hInstResource, - p->m_lpszCursorID); - } - - p->m_wc.hInstance = pBaseModule->m_hInst; - p->m_wc.style &= ~CS_GLOBALCLASS; // we don't register global classes - if (p->m_wc.lpszClassName == NULL) - { - T::FormatWindowClassName(p->m_szAutoName, &p->m_wc); - p->m_wc.lpszClassName = p->m_szAutoName; - } - T::WNDCLASSEX wcTemp; - wcTemp = p->m_wc; - p->m_atom = static_cast(T::GetClassInfoEx(p->m_wc.hInstance, p->m_wc.lpszClassName, &wcTemp)); - if (p->m_atom == 0) - { - p->m_atom = T::RegisterClassEx(pWinModule, &p->m_wc); - } - } - } - - if (p->m_lpszOrigName != NULL) - { - ATLASSERT(pProc != NULL); - ATLASSERT(p->pWndProc != NULL); - *pProc = p->pWndProc; - } - return p->m_atom; -} - -ATLINLINE ATLAPI_(ATOM) AtlWinModuleRegisterWndClassInfoA(_ATL_WIN_MODULE* pWinModule, _ATL_BASE_MODULE* pBaseModule, _ATL_WNDCLASSINFOA* p, WNDPROC* pProc) -{ - AtlModuleRegisterWndClassInfoParamA templateParameter; - return AtlModuleRegisterWndClassInfoT(pBaseModule, pWinModule, p, pProc, templateParameter); -} - -ATLINLINE ATLAPI_(ATOM) AtlWinModuleRegisterWndClassInfoW(_ATL_WIN_MODULE* pWinModule, _ATL_BASE_MODULE* pBaseModule, _ATL_WNDCLASSINFOW* p, WNDPROC* pProc) -{ - AtlModuleRegisterWndClassInfoParamW templateParameter; - return AtlModuleRegisterWndClassInfoT(pBaseModule, pWinModule, p, pProc, templateParameter); -} - -ATLINLINE ATLAPI_(HDC) AtlCreateTargetDC(HDC hdc, DVTARGETDEVICE* ptd) -{ - USES_CONVERSION; - - // cases hdc, ptd, hdc is metafile, hic -// NULL, NULL, n/a, Display -// NULL, !NULL, n/a, ptd -// !NULL, NULL, FALSE, hdc -// !NULL, NULL, TRUE, display -// !NULL, !NULL, FALSE, ptd -// !NULL, !NULL, TRUE, ptd - - if (ptd != NULL) - { - LPDEVMODEOLE lpDevMode; - LPOLESTR lpszDriverName; - LPOLESTR lpszDeviceName; - LPOLESTR lpszPortName; - - if (ptd->tdExtDevmodeOffset == 0) - lpDevMode = NULL; - else - lpDevMode = (LPDEVMODEOLE) ((LPSTR)ptd + ptd->tdExtDevmodeOffset); - - lpszDriverName = (LPOLESTR)((BYTE*)ptd + ptd->tdDriverNameOffset); - lpszDeviceName = (LPOLESTR)((BYTE*)ptd + ptd->tdDeviceNameOffset); - lpszPortName = (LPOLESTR)((BYTE*)ptd + ptd->tdPortNameOffset); - - return ::CreateDC(OLE2CT(lpszDriverName), OLE2CT(lpszDeviceName), - OLE2CT(lpszPortName), DEVMODEOLE2T(lpDevMode)); - } - else if (hdc == NULL || GetDeviceCaps(hdc, TECHNOLOGY) == DT_METAFILE) - return ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL); - else - return hdc; -} - -///////////////////////////////////////////////////////////////////////////// -// Windowing : Conversion helpers - -ATLINLINE ATLAPI_(void) AtlHiMetricToPixel(const SIZEL * lpSizeInHiMetric, LPSIZEL lpSizeInPix) -{ - int nPixelsPerInchX; // Pixels per logical inch along width - int nPixelsPerInchY; // Pixels per logical inch along height - - HDC hDCScreen = GetDC(NULL); - ATLASSERT(hDCScreen != NULL); - nPixelsPerInchX = GetDeviceCaps(hDCScreen, LOGPIXELSX); - nPixelsPerInchY = GetDeviceCaps(hDCScreen, LOGPIXELSY); - ReleaseDC(NULL, hDCScreen); - - lpSizeInPix->cx = MAP_LOGHIM_TO_PIX(lpSizeInHiMetric->cx, nPixelsPerInchX); - lpSizeInPix->cy = MAP_LOGHIM_TO_PIX(lpSizeInHiMetric->cy, nPixelsPerInchY); -} - -ATLINLINE ATLAPI_(void) AtlPixelToHiMetric(const SIZEL * lpSizeInPix, LPSIZEL lpSizeInHiMetric) -{ - int nPixelsPerInchX; // Pixels per logical inch along width - int nPixelsPerInchY; // Pixels per logical inch along height - - HDC hDCScreen = GetDC(NULL); - ATLASSERT(hDCScreen != NULL); - nPixelsPerInchX = GetDeviceCaps(hDCScreen, LOGPIXELSX); - nPixelsPerInchY = GetDeviceCaps(hDCScreen, LOGPIXELSY); - ReleaseDC(NULL, hDCScreen); - - lpSizeInHiMetric->cx = MAP_PIX_TO_LOGHIM(lpSizeInPix->cx, nPixelsPerInchX); - lpSizeInHiMetric->cy = MAP_PIX_TO_LOGHIM(lpSizeInPix->cy, nPixelsPerInchY); -} - -} //namespace ATL - -#endif // !_ATL_DLL - -#ifndef _ATL_NO_PRAGMA_WARNINGS -#pragma warning (pop) -#endif diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/statreg.h b/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/statreg.h deleted file mode 100644 index 46fefe231..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc7_atl/statreg.h +++ /dev/null @@ -1,1408 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __STATREG_H__ -#define __STATREG_H__ - -#pragma once - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#ifndef __ATLBASE_H__ - #error statreg.h requires atlbase.h to be included first -#endif - -#define E_ATL_REGISTRAR_DESC 0x0201 -#define E_ATL_NOT_IN_MAP 0x0202 -#define E_ATL_UNEXPECTED_EOS 0x0203 -#define E_ATL_VALUE_SET_FAILED 0x0204 -#define E_ATL_RECURSE_DELETE_FAILED 0x0205 -#define E_ATL_EXPECTING_EQUAL 0x0206 -#define E_ATL_CREATE_KEY_FAILED 0x0207 -#define E_ATL_DELETE_KEY_FAILED 0x0208 -#define E_ATL_OPEN_KEY_FAILED 0x0209 -#define E_ATL_CLOSE_KEY_FAILED 0x020A -#define E_ATL_UNABLE_TO_COERCE 0x020B -#define E_ATL_BAD_HKEY 0x020C -#define E_ATL_MISSING_OPENKEY_TOKEN 0x020D -#define E_ATL_CONVERT_FAILED 0x020E -#define E_ATL_TYPE_NOT_SUPPORTED 0x020F -#define E_ATL_COULD_NOT_CONCAT 0x0210 -#define E_ATL_COMPOUND_KEY 0x0211 -#define E_ATL_INVALID_MAPKEY 0x0212 -#define E_ATL_UNSUPPORTED_VT 0x0213 -#define E_ATL_VALUE_GET_FAILED 0x0214 -#define E_ATL_VALUE_TOO_LARGE 0x0215 -#define E_ATL_MISSING_VALUE_DELIMETER 0x0216 -#define E_ATL_DATA_NOT_BYTE_ALIGNED 0x0217 - -namespace ATL -{ -const TCHAR chDirSep = _T('\\'); -const TCHAR chRightBracket = _T('}'); -const TCHAR chLeftBracket = _T('{'); -const TCHAR chQuote = _T('\''); -const TCHAR chEquals = _T('='); -const LPCTSTR szStringVal = _T("S"); -const LPCTSTR multiszStringVal = _T("M"); -const LPCTSTR szDwordVal = _T("D"); -const LPCTSTR szBinaryVal = _T("B"); -const LPCTSTR szValToken = _T("Val"); -const LPCTSTR szForceRemove = _T("ForceRemove"); -const LPCTSTR szNoRemove = _T("NoRemove"); -const LPCTSTR szDelete = _T("Delete"); - - -// Implementation helper -class CExpansionVectorEqualHelper -{ -public: - static bool IsEqualKey(const LPTSTR k1, const LPTSTR k2) - { - if (lstrcmpi(k1, k2) == 0) - return true; - return false; - } - - // Not used - static bool IsEqualValue(const LPCOLESTR /*v1*/, const LPCOLESTR /*v2*/) - { - return false; - } -}; - -// Implementation helper -class CExpansionVector : public CSimpleMap -{ -public: - ~CExpansionVector() - { - ClearReplacements(); - } - - BOOL Add(LPCTSTR lpszKey, LPCOLESTR lpszValue) - { - ATLASSERT(lpszKey != NULL && lpszValue != NULL); - if (lpszKey == NULL || lpszValue == NULL) - return FALSE; - - HRESULT hRes = S_OK; - - size_t cbKey = (lstrlen(lpszKey)+1)*sizeof(TCHAR); - TCHAR* szKey = NULL; - - ATLTRY(szKey = new TCHAR[cbKey];) - - size_t cbValue = (ocslen(lpszValue)+1)*sizeof(OLECHAR); - LPOLESTR szValue = NULL; - ATLTRY(szValue = new OLECHAR[cbValue];) - - if (szKey == NULL || szValue == NULL) - hRes = E_OUTOFMEMORY; - else - { - memcpy(szKey, lpszKey, cbKey); - memcpy(szValue, lpszValue, cbValue); - if (!CSimpleMap::Add(szKey, szValue)) - hRes = E_OUTOFMEMORY; - } - if (FAILED(hRes)) - { - delete []szKey; - delete []szValue; - } - return SUCCEEDED(hRes); - } - HRESULT ClearReplacements() - { - for (int i = 0; i < GetSize(); i++) - { - delete []GetKeyAt(i); - delete []GetValueAt(i); - } - RemoveAll(); - return S_OK; - } -}; - -class CRegObject; - -class CRegParser -{ -public: - CRegParser(CRegObject* pRegObj); - - HRESULT PreProcessBuffer(LPTSTR lpszReg, LPTSTR* ppszReg); - HRESULT RegisterBuffer(LPTSTR szReg, BOOL bRegister); - -protected: - - void SkipWhiteSpace(); - HRESULT NextToken(LPTSTR szToken); - HRESULT AddValue(CRegKey& rkParent,LPCTSTR szValueName, LPTSTR szToken); - BOOL CanForceRemoveKey(LPCTSTR szKey); - BOOL HasSubKeys(HKEY hkey); - BOOL HasValues(HKEY hkey); - HRESULT RegisterSubkeys(LPTSTR szToken, HKEY hkParent, BOOL bRegister, BOOL bInRecovery = FALSE); - BOOL IsSpace(TCHAR ch); - LPTSTR m_pchCur; - - CRegObject* m_pRegObj; - - HRESULT GenerateError(UINT) {return DISP_E_EXCEPTION;} - HRESULT HandleReplacements(LPTSTR& szToken); - HRESULT SkipAssignment(LPTSTR szToken); - - BOOL EndOfVar() { return chQuote == *m_pchCur && chQuote != *CharNext(m_pchCur); } - static LPTSTR StrChr(LPTSTR lpsz, TCHAR ch); - static HKEY HKeyFromString(LPTSTR szToken); - static BYTE ChToByte(const TCHAR ch); - static BOOL VTFromRegType(LPCTSTR szValueType, VARTYPE& vt); - static const TCHAR* const rgszNeverDelete[]; - static const int cbNeverDelete; - static const int MAX_VALUE = 4096; - static const int MAX_TYPE = 4096; - - // Implementation Helper - class CParseBuffer - { - public: - int nPos; - int nSize; - LPTSTR p; - CParseBuffer(int nInitial) - { - if (nInitial < 100) - nInitial = 1000; - nPos = 0; - nSize = nInitial; - p = (LPTSTR) CoTaskMemAlloc(nSize*sizeof(TCHAR)); - if (p != NULL) - *p = NULL; - } - ~CParseBuffer() - { - CoTaskMemFree(p); - } - BOOL Append(const TCHAR* pch, int nChars) - { - ATLASSERT(p != NULL); - if ((nPos + nChars + 1) >= nSize) - { - while ((nPos + nChars + 1) >= nSize) - nSize *=2; - LPTSTR pTemp = (LPTSTR) CoTaskMemRealloc(p, nSize*sizeof(TCHAR)); - if (pTemp == NULL) - return FALSE; - p = pTemp; - } - memcpy(p + nPos, pch, int(nChars * sizeof(TCHAR))); - nPos += nChars; - *(p + nPos) = NULL; - return TRUE; - } - - BOOL AddChar(const TCHAR* pch) - { -#ifndef _UNICODE - int nChars = int(CharNext(pch) - pch); -#else - int nChars = 1; -#endif - return Append(pch, nChars); - - } - BOOL AddString(LPCOLESTR lpsz) - { - if (lpsz == NULL) - return FALSE; - USES_CONVERSION_EX; - LPCTSTR lpszT = OLE2CT_EX(lpsz, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifdef _UNICODE - if (lpszT == NULL) - return FALSE; -#endif - return Append(lpszT, (int)lstrlen(lpszT)); - } - LPTSTR Detach() - { - LPTSTR lp = p; - p = NULL; - nSize = nPos = 0; - return lp; - } - - }; -}; - -#if defined(_ATL_DLL) || defined(_ATL_DLL_IMPL) -class ATL_NO_VTABLE CRegObject - : public IRegistrar -#else -class CRegObject : public IRegistrarBase -#endif -{ -public: - -#if defined(_ATL_DLL) || defined(_ATL_DLL_IMPL) - -#else - STDMETHOD(QueryInterface)(const IID &,void ** ) - { - ATLASSERT(_T("statically linked in CRegObject is not a com object. Do not callthis function")); - return E_NOTIMPL; - } - - STDMETHOD_(ULONG, AddRef)(void) - { - ATLASSERT(_T("statically linked in CRegObject is not a com object. Do not callthis function")); - return 1; - } - STDMETHOD_(ULONG, Release)(void) - { - ATLASSERT(_T("statically linked in CRegObject is not a com object. Do not callthis function")); - return 0; - } -#endif - virtual ~CRegObject(){ClearReplacements();} - HRESULT FinalConstruct() {return S_OK;} - void FinalRelease() {} - - - // Map based methods - HRESULT STDMETHODCALLTYPE AddReplacement(LPCOLESTR lpszKey, LPCOLESTR lpszItem); - HRESULT STDMETHODCALLTYPE ClearReplacements(); - LPCOLESTR StrFromMap(LPTSTR lpszKey); - - // Register via a given mechanism - HRESULT STDMETHODCALLTYPE ResourceRegister(LPCOLESTR pszFileName, UINT nID, LPCOLESTR pszType); - HRESULT STDMETHODCALLTYPE ResourceRegisterSz(LPCOLESTR pszFileName, LPCOLESTR pszID, LPCOLESTR pszType); - HRESULT STDMETHODCALLTYPE ResourceUnregister(LPCOLESTR pszFileName, UINT nID, LPCOLESTR pszType); - HRESULT STDMETHODCALLTYPE ResourceUnregisterSz(LPCOLESTR pszFileName, LPCOLESTR pszID, LPCOLESTR pszType); - HRESULT STDMETHODCALLTYPE FileRegister(LPCOLESTR bstrFileName) - { - return CommonFileRegister(bstrFileName, TRUE); - } - - HRESULT STDMETHODCALLTYPE FileUnregister(LPCOLESTR bstrFileName) - { - return CommonFileRegister(bstrFileName, FALSE); - } - - HRESULT STDMETHODCALLTYPE StringRegister(LPCOLESTR bstrData) - { - return RegisterWithString(bstrData, TRUE); - } - - HRESULT STDMETHODCALLTYPE StringUnregister(LPCOLESTR bstrData) - { - return RegisterWithString(bstrData, FALSE); - } - -protected: - - HRESULT CommonFileRegister(LPCOLESTR pszFileName, BOOL bRegister); - HRESULT RegisterFromResource(LPCOLESTR pszFileName, LPCTSTR pszID, LPCTSTR pszType, BOOL bRegister); - HRESULT RegisterWithString(LPCOLESTR pszData, BOOL bRegister); - - static HRESULT GenerateError(UINT) {return DISP_E_EXCEPTION;} - - CExpansionVector m_RepMap; - CComObjectThreadModel::AutoCriticalSection m_csMap; -}; - -inline HRESULT STDMETHODCALLTYPE CRegObject::AddReplacement(LPCOLESTR lpszKey, LPCOLESTR lpszItem) -{ - if (lpszKey == NULL || lpszItem == NULL) - return E_INVALIDARG; - m_csMap.Lock(); - USES_CONVERSION_EX; - - LPCTSTR lpszT = OLE2CT_EX(lpszKey, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); - -#ifndef _UNICODE - if(lpszT == NULL) - return E_OUTOFMEMORY; -#endif - - BOOL bRet = m_RepMap.Add(lpszT, lpszItem); - m_csMap.Unlock(); - return bRet ? S_OK : E_OUTOFMEMORY; -} - -inline HRESULT CRegObject::RegisterFromResource(LPCOLESTR bstrFileName, LPCTSTR szID, - LPCTSTR szType, BOOL bRegister) -{ - USES_CONVERSION_EX; - - HRESULT hr; - CRegParser parser(this); - HINSTANCE hInstResDll; - HRSRC hrscReg; - HGLOBAL hReg; - DWORD dwSize; - LPSTR szRegA; - CTempBuffer szReg; - - LPCTSTR lpszBSTRFileName = OLE2CT_EX(bstrFileName, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if (lpszBSTRFileName == NULL) - { - return E_OUTOFMEMORY; - } -#endif // _UNICODE - - hInstResDll = LoadLibraryEx(lpszBSTRFileName, NULL, LOAD_LIBRARY_AS_DATAFILE); - - if (NULL == hInstResDll) - { - ATLTRACE(atlTraceRegistrar, 0, _T("Failed to LoadLibrary on %s\n"), bstrFileName); - hr = AtlHresultFromLastError(); - goto ReturnHR; - } - - hrscReg = FindResource((HMODULE)hInstResDll, szID, szType); - - if (NULL == hrscReg) - { - ATLTRACE(atlTraceRegistrar, 0, (HIWORD(szID) == NULL) ? - _T("Failed to FindResource on ID:%d TYPE:%s\n") : - _T("Failed to FindResource on ID:%s TYPE:%s\n"), - szID, szType); - hr = AtlHresultFromLastError(); - goto ReturnHR; - } - - hReg = LoadResource((HMODULE)hInstResDll, hrscReg); - - if (NULL == hReg) - { - ATLTRACE(atlTraceRegistrar, 0, _T("Failed to LoadResource\n")); - hr = AtlHresultFromLastError(); - goto ReturnHR; - } - - dwSize = SizeofResource((HMODULE)hInstResDll, hrscReg); - szRegA = (LPSTR)hReg; - - // Allocate extra space for NULL. - ATLTRY(szReg.Allocate(dwSize + 1)); - if (szReg == NULL) - { - hr = E_OUTOFMEMORY; - goto ReturnHR; - } - -#ifdef _UNICODE - if (::MultiByteToWideChar(_AtlGetConversionACP(), 0, szRegA, dwSize, szReg, dwSize) == 0) - { - hr = AtlHresultFromLastError(); - goto ReturnHR; - } -#else - memcpy(szReg, szRegA, dwSize); -#endif - - // Append a NULL at the end. - szReg[dwSize] = NULL; - - hr = parser.RegisterBuffer(szReg, bRegister); - -ReturnHR: - - if (NULL != hInstResDll) - FreeLibrary((HMODULE)hInstResDll); - return hr; -} - -inline HRESULT STDMETHODCALLTYPE CRegObject::ResourceRegister(LPCOLESTR szFileName, UINT nID, LPCOLESTR szType) -{ - USES_CONVERSION_EX; - - LPCTSTR lpszT = OLE2CT_EX(szType, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if (lpszT == NULL) - { - return E_OUTOFMEMORY; - } -#endif // _UNICODE - - return RegisterFromResource(szFileName, MAKEINTRESOURCE(nID), lpszT, TRUE); -} - -inline HRESULT STDMETHODCALLTYPE CRegObject::ResourceRegisterSz(LPCOLESTR szFileName, LPCOLESTR szID, LPCOLESTR szType) -{ - USES_CONVERSION_EX; - if (szID == NULL || szType == NULL) - return E_INVALIDARG; - - LPCTSTR lpszID = OLE2CT_EX(szID, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); - LPCTSTR lpszType = OLE2CT_EX(szType, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if (lpszID == NULL || lpszType) - { - return E_OUTOFMEMORY; - } -#endif // _UNICODE - return RegisterFromResource(szFileName, lpszID, lpszType, TRUE); -} - -inline HRESULT STDMETHODCALLTYPE CRegObject::ResourceUnregister(LPCOLESTR szFileName, UINT nID, LPCOLESTR szType) -{ - USES_CONVERSION_EX; - - LPCTSTR lpszT = OLE2CT_EX(szType, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if (lpszT == NULL) - { - return E_OUTOFMEMORY; - } -#endif // _UNICODE - return RegisterFromResource(szFileName, MAKEINTRESOURCE(nID), lpszT, FALSE); -} - -inline HRESULT STDMETHODCALLTYPE CRegObject::ResourceUnregisterSz(LPCOLESTR szFileName, LPCOLESTR szID, LPCOLESTR szType) -{ - USES_CONVERSION_EX; - if (szID == NULL || szType == NULL) - return E_INVALIDARG; - - LPCTSTR lpszID = OLE2CT_EX(szID, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); - LPCTSTR lpszType = OLE2CT_EX(szType, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if (lpszID == NULL || lpszType == NULL) - { - return E_OUTOFMEMORY; - } -#endif // _UNICODE - - return RegisterFromResource(szFileName, lpszID, lpszType, FALSE); -} - -inline HRESULT CRegObject::RegisterWithString(LPCOLESTR bstrData, BOOL bRegister) -{ - USES_CONVERSION_EX; - CRegParser parser(this); - - LPCTSTR szReg = OLE2CT_EX(bstrData, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if (szReg == NULL) - { - return E_OUTOFMEMORY; - } -#endif // _UNICODE - - HRESULT hr = parser.RegisterBuffer((LPTSTR)szReg, bRegister); - - return hr; -} - -inline HRESULT CRegObject::ClearReplacements() -{ - m_csMap.Lock(); - HRESULT hr = m_RepMap.ClearReplacements(); - m_csMap.Unlock(); - return hr; -} - - -inline LPCOLESTR CRegObject::StrFromMap(LPTSTR lpszKey) -{ - m_csMap.Lock(); - LPCOLESTR lpsz = m_RepMap.Lookup(lpszKey); - if (lpsz == NULL) // not found!! - ATLTRACE(atlTraceRegistrar, 0, _T("Map Entry not found\n")); - m_csMap.Unlock(); - return lpsz; -} - -inline HRESULT CRegObject::CommonFileRegister(LPCOLESTR bstrFileName, BOOL bRegister) -{ - USES_CONVERSION_EX; - - CRegParser parser(this); - - LPCTSTR lpszBSTRFileName = OLE2CT_EX(bstrFileName, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if (lpszBSTRFileName == NULL) - { - return E_OUTOFMEMORY; - } -#endif // _UNICODE - - HANDLE hFile = CreateFile(lpszBSTRFileName, GENERIC_READ, 0, NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_READONLY, - NULL); - if (INVALID_HANDLE_VALUE == hFile) - { - ATLTRACE2(atlTraceRegistrar, 0, _T("Failed to CreateFile on %s\n"), lpszBSTRFileName); - return AtlHresultFromLastError(); - } - - HRESULT hRes = S_OK; - DWORD cbRead; - DWORD cbFile = GetFileSize(hFile, NULL); // No HiOrder DWORD required - - CTempBuffer szReg; - // Extra space for NULL. - ATLTRY(szReg.Allocate(cbFile + 1)); - if (szReg == NULL) - { - hRes = E_OUTOFMEMORY; - goto ReturnHR; - } - - if (ReadFile(hFile, szReg, cbFile, &cbRead, NULL) == 0) - { - ATLTRACE2(atlTraceRegistrar, 0, "Read Failed on file%s\n", lpszBSTRFileName); - hRes = AtlHresultFromLastError(); - } - if (SUCCEEDED(hRes)) - { - szReg[cbRead] = NULL; - -#ifdef _UNICODE - CTempBuffer szConverted; - ATLTRY(szConverted.Allocate(cbFile + 1)); - if (szConverted == NULL) - { - hRes = E_OUTOFMEMORY; - goto ReturnHR; - - } - if (::MultiByteToWideChar(_AtlGetConversionACP(), 0, szReg, cbFile + 1, szConverted, cbFile + 1) == 0) - { - hRes = AtlHresultFromLastError(); - goto ReturnHR; - } -#else - LPTSTR szConverted = szReg; -#endif - hRes = parser.RegisterBuffer(szConverted, bRegister); - } -ReturnHR: - CloseHandle(hFile); - return hRes; -} - -__declspec(selectany) const TCHAR* const CRegParser::rgszNeverDelete[] = -{ - _T("AppID"), - _T("CLSID"), - _T("Component Categories"), - _T("FileType"), - _T("Interface"), - _T("Hardware"), - _T("Mime"), - _T("SAM"), - _T("SECURITY"), - _T("SYSTEM"), - _T("Software"), - _T("TypeLib") -}; - -__declspec(selectany) const int CRegParser::cbNeverDelete = sizeof(rgszNeverDelete) / sizeof(LPCTSTR*); - - -inline BOOL CRegParser::VTFromRegType(LPCTSTR szValueType, VARTYPE& vt) -{ - struct typemap - { - LPCTSTR lpsz; - VARTYPE vt; - }; -#pragma warning (push) -#pragma warning (disable : 4640) // construction of local static object is not thread-safe - - static const typemap map[] = { - {szStringVal, VT_BSTR}, - {multiszStringVal, VT_BSTR | VT_BYREF}, - {szDwordVal, VT_UI4}, - {szBinaryVal, VT_UI1} - }; - -#pragma warning (pop) - - for (int i=0;i= MAX_VALUE + szOrig) - return GenerateError(E_ATL_VALUE_TOO_LARGE); - for (int i = 0; pchPrev+i < m_pchCur; i++, szToken++) - *szToken = *(pchPrev+i); - } - - if (NULL == *m_pchCur) - { - ATLTRACE(atlTraceRegistrar, 0, _T("NextToken : Unexpected End of File\n")); - return GenerateError(E_ATL_UNEXPECTED_EOS); - } - - *szToken = NULL; - m_pchCur = CharNext(m_pchCur); - } - - else - { - // Handle non-quoted ie parse up till first "White Space" - while (NULL != *m_pchCur && !IsSpace(*m_pchCur)) - { - LPTSTR pchPrev = m_pchCur; - m_pchCur = CharNext(m_pchCur); - if (szToken + sizeof(WORD) >= MAX_VALUE + szOrig) - return GenerateError(E_ATL_VALUE_TOO_LARGE); - for (int i = 0; pchPrev+i < m_pchCur; i++, szToken++) - *szToken = *(pchPrev+i); - } - - *szToken = NULL; - } - return S_OK; -} - -inline HRESULT CRegParser::AddValue(CRegKey& rkParent,LPCTSTR szValueName, LPTSTR szToken) -{ - HRESULT hr; - - TCHAR szValue[MAX_VALUE]; - VARTYPE vt = VT_EMPTY; - LONG lRes = ERROR_SUCCESS; - UINT nIDRes = 0; - - if (FAILED(hr = NextToken(szValue))) - return hr; - if (!VTFromRegType(szValue, vt)) - { - ATLTRACE(atlTraceRegistrar, 0, _T("%s Type not supported\n"), szValue); - return GenerateError(E_ATL_TYPE_NOT_SUPPORTED); - } - - SkipWhiteSpace(); - if (FAILED(hr = NextToken(szValue))) - return hr; - - switch (vt) - { - case VT_BSTR: - { - lRes = rkParent.SetStringValue(szValueName, szValue); - ATLTRACE(atlTraceRegistrar, 2, _T("Setting Value %s at %s\n"), szValue, !szValueName ? _T("default") : szValueName); - break; - } - case VT_BSTR | VT_BYREF: - { - ATLTRACE(atlTraceRegistrar, 2, _T("Setting Value %s at %s\n"), szValue, !szValueName ? _T("default") : szValueName); - int nLen = lstrlen(szValue) + 1; - CTempBuffer pszDestValue; - ATLTRY(pszDestValue.Allocate(nLen)); - if (pszDestValue != NULL) - { - TCHAR* p = pszDestValue; - TCHAR* q = szValue; - nLen = 0; - while (*q != NULL) - { - TCHAR* r = CharNext(q); - if (*q == '\\' && *r == '0') - { - *p++ = NULL; - q = CharNext(r); - } - else - { - *p = *q; -#ifndef _UNICODE - if (IsDBCSLeadByte(*q)) - { - p++; - q++; - *p = *q; - } -#endif - p++; - q++; - } - nLen ++; - } - *p = NULL; - lRes = rkParent.SetMultiStringValue(szValueName, pszDestValue); - } - else - { - lRes = ERROR_OUTOFMEMORY; - } - } - break; - case VT_UI4: - { - ULONG ulVal; - USES_CONVERSION_EX; - - LPOLESTR lpszV = T2OLE_EX(szValue, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); - #ifndef _UNICODE - if(lpszV == NULL) - return E_OUTOFMEMORY; - #endif - VarUI4FromStr(lpszV, 0, 0, &ulVal); - - lRes = rkParent.SetDWORDValue(szValueName, ulVal); - ATLTRACE(atlTraceRegistrar, 2, _T("Setting Value %d at %s\n"), ulVal, !szValueName ? _T("default") : szValueName); - break; - } - case VT_UI1: - { - int cbValue = lstrlen(szValue); - if (cbValue & 0x00000001) - { - ATLTRACE(atlTraceRegistrar, 0, _T("Binary Data does not fall on BYTE boundries\n")); - return E_FAIL; - } - int cbValDiv2 = cbValue/2; - CTempBuffer rgBinary; - ATLTRY(rgBinary.Allocate(cbValDiv2)); - if (rgBinary == NULL) - return E_FAIL; - memset(rgBinary, 0, cbValDiv2); - for (int irg = 0; irg < cbValue; irg++) - rgBinary[(irg/2)] |= (ChToByte(szValue[irg])) << (4*(1 - (irg & 0x00000001))); - lRes = RegSetValueEx(rkParent, szValueName, 0, REG_BINARY, rgBinary, cbValDiv2); - break; - } - } - - if (ERROR_SUCCESS != lRes) - { - nIDRes = E_ATL_VALUE_SET_FAILED; - return AtlHresultFromWin32(lRes); - } - - if (FAILED(hr = NextToken(szToken))) - return hr; - - return S_OK; -} - -inline BOOL CRegParser::CanForceRemoveKey(LPCTSTR szKey) -{ - for (int iNoDel = 0; iNoDel < cbNeverDelete; iNoDel++) - if (!lstrcmpi(szKey, rgszNeverDelete[iNoDel])) - return FALSE; // We cannot delete it - - return TRUE; -} - -inline BOOL CRegParser::HasSubKeys(HKEY hkey) -{ - DWORD cbSubKeys = 0; - - if (RegQueryInfoKey(hkey, NULL, NULL, NULL, - &cbSubKeys, NULL, NULL, - NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) - { - ATLTRACE(atlTraceRegistrar, 0, _T("Should not be here!!\n")); - ATLASSERT(FALSE); - return FALSE; - } - - return cbSubKeys > 0; -} - -inline BOOL CRegParser::HasValues(HKEY hkey) -{ - DWORD cbValues = 0; - - LONG lResult = RegQueryInfoKey(hkey, NULL, NULL, NULL, - NULL, NULL, NULL, - &cbValues, NULL, NULL, NULL, NULL); - if (ERROR_SUCCESS != lResult) - { - ATLTRACE(atlTraceRegistrar, 0, _T("RegQueryInfoKey Failed ")); - ATLASSERT(FALSE); - return FALSE; - } - - if (1 == cbValues) - { - DWORD cbMaxName= MAX_VALUE; - TCHAR szValueName[MAX_VALUE]; - // Check to see if the Value is default or named - lResult = RegEnumValue(hkey, 0, szValueName, &cbMaxName, NULL, NULL, NULL, NULL); - if (ERROR_SUCCESS == lResult && (szValueName[0] != NULL)) - return TRUE; // Named Value means we have a value - return FALSE; - } - - return cbValues > 0; // More than 1 means we have a non-default value -} - -inline HRESULT CRegParser::SkipAssignment(LPTSTR szToken) -{ - HRESULT hr; - TCHAR szValue[MAX_VALUE]; - - if (*szToken == chEquals) - { - if (FAILED(hr = NextToken(szToken))) - return hr; - // Skip assignment - SkipWhiteSpace(); - if (FAILED(hr = NextToken(szValue))) - return hr; - if (FAILED(hr = NextToken(szToken))) - return hr; - } - - return S_OK; -} - -inline HRESULT CRegParser::PreProcessBuffer(LPTSTR lpszReg, LPTSTR* ppszReg) -{ - ATLASSERT(lpszReg != NULL); - ATLASSERT(ppszReg != NULL); - - if (lpszReg == NULL || ppszReg == NULL) - return E_POINTER; - - *ppszReg = NULL; - int nSize = lstrlen(lpszReg)*2; - CParseBuffer pb(nSize); - if (pb.p == NULL) - return E_OUTOFMEMORY; - m_pchCur = lpszReg; - HRESULT hr = S_OK; - - while (*m_pchCur != NULL) // look for end - { - if (*m_pchCur == _T('%')) - { - m_pchCur = CharNext(m_pchCur); - if (*m_pchCur == _T('%')) - { - if (!pb.AddChar(m_pchCur)) - { - hr = E_OUTOFMEMORY; - break; - } - } - else - { - LPTSTR lpszNext = StrChr(m_pchCur, _T('%')); - if (lpszNext == NULL) - { - ATLTRACE(atlTraceRegistrar, 0, _T("Error no closing % found\n")); - hr = GenerateError(E_ATL_UNEXPECTED_EOS); - break; - } - if ((lpszNext-m_pchCur) > 31) - { - hr = E_FAIL; - break; - } - int nLength = int(lpszNext - m_pchCur); - TCHAR buf[32]; - lstrcpyn(buf, m_pchCur, nLength+1); - LPCOLESTR lpszVar = m_pRegObj->StrFromMap(buf); - if (lpszVar == NULL) - { - hr = GenerateError(E_ATL_NOT_IN_MAP); - break; - } - if (!pb.AddString(lpszVar)) - { - hr = E_OUTOFMEMORY; - break; - } - - while (m_pchCur != lpszNext) - m_pchCur = CharNext(m_pchCur); - } - } - else - { - if (!pb.AddChar(m_pchCur)) - { - hr = E_OUTOFMEMORY; - break; - } - } - - m_pchCur = CharNext(m_pchCur); - } - if (SUCCEEDED(hr)) - *ppszReg = pb.Detach(); - return hr; -} - -inline HRESULT CRegParser::RegisterBuffer(LPTSTR szBuffer, BOOL bRegister) -{ - TCHAR szToken[MAX_VALUE]; - HRESULT hr = S_OK; - - LPTSTR szReg = NULL; - hr = PreProcessBuffer(szBuffer, &szReg); - if (FAILED(hr)) - return hr; - - ATLTRACE(atlTraceRegistrar, 0, szReg); - ATLTRACE(atlTraceRegistrar, 0, _T("\n")); - - m_pchCur = szReg; - - // Preprocess szReg - - while (NULL != *m_pchCur) - { - if (FAILED(hr = NextToken(szToken))) - break; - HKEY hkBase; - if ((hkBase = HKeyFromString(szToken)) == NULL) - { - ATLTRACE(atlTraceRegistrar, 0, _T("HKeyFromString failed on %s\n"), szToken); - hr = GenerateError(E_ATL_BAD_HKEY); - break; - } - - if (FAILED(hr = NextToken(szToken))) - break; - - if (chLeftBracket != *szToken) - { - ATLTRACE(atlTraceRegistrar, 0, _T("Syntax error, expecting a {, found a %s\n"), szToken); - hr = GenerateError(E_ATL_MISSING_OPENKEY_TOKEN); - break; - } - if (bRegister) - { - LPTSTR szRegAtRegister = m_pchCur; - hr = RegisterSubkeys(szToken, hkBase, bRegister); - if (FAILED(hr)) - { - ATLTRACE(atlTraceRegistrar, 0, _T("Failed to register, cleaning up!\n")); - m_pchCur = szRegAtRegister; - RegisterSubkeys(szToken, hkBase, FALSE); - break; - } - } - else - { - if (FAILED(hr = RegisterSubkeys(szToken, hkBase, bRegister))) - break; - } - - SkipWhiteSpace(); - } - CoTaskMemFree(szReg); - return hr; -} - -inline HRESULT CRegParser::RegisterSubkeys(LPTSTR szToken, HKEY hkParent, BOOL bRegister, BOOL bRecover) -{ - CRegKey keyCur; - LONG lRes; - TCHAR szKey[_MAX_PATH]; - BOOL bDelete = TRUE; - BOOL bInRecovery = bRecover; - HRESULT hr = S_OK; - - ATLTRACE(atlTraceRegistrar, 2, _T("Num Els = %d\n"), cbNeverDelete); - if (FAILED(hr = NextToken(szToken))) - return hr; - - - while (*szToken != chRightBracket) // Continue till we see a } - { - bDelete = TRUE; - BOOL bTokenDelete = !lstrcmpi(szToken, szDelete); - - if (!lstrcmpi(szToken, szForceRemove) || bTokenDelete) - { - if (FAILED(hr = NextToken(szToken))) - break; - - if (bRegister) - { - CRegKey rkForceRemove; - - if (StrChr(szToken, chDirSep) != NULL) - return GenerateError(E_ATL_COMPOUND_KEY); - - if (CanForceRemoveKey(szToken)) - { - rkForceRemove.Attach(hkParent); - // Error not returned. We will overwrite the values any way. - rkForceRemove.RecurseDeleteKey(szToken); - rkForceRemove.Detach(); - } - if (bTokenDelete) - { - if (FAILED(hr = NextToken(szToken))) - break; - if (FAILED(hr = SkipAssignment(szToken))) - break; - goto EndCheck; - } - } - - } - - if (!lstrcmpi(szToken, szNoRemove)) - { - bDelete = FALSE; // set even for register - if (FAILED(hr = NextToken(szToken))) - break; - } - - if (!lstrcmpi(szToken, szValToken)) // need to add a value to hkParent - { - TCHAR szValueName[_MAX_PATH]; - - if (FAILED(hr = NextToken(szValueName))) - break; - if (FAILED(hr = NextToken(szToken))) - break; - - - if (*szToken != chEquals) - return GenerateError(E_ATL_EXPECTING_EQUAL); - - if (bRegister) - { - CRegKey rk; - - rk.Attach(hkParent); - hr = AddValue(rk, szValueName, szToken); - rk.Detach(); - - if (FAILED(hr)) - return hr; - - goto EndCheck; - } - else - { - if (!bRecover && bDelete) - { - ATLTRACE(atlTraceRegistrar, 1, _T("Deleting %s\n"), szValueName); - // We have to open the key for write to be able to delete. - CRegKey rkParent; - lRes = rkParent.Open(hkParent, NULL, KEY_WRITE); - if (lRes == ERROR_SUCCESS) - { - lRes = rkParent.DeleteValue(szValueName); - if (lRes != ERROR_SUCCESS && lRes != ERROR_FILE_NOT_FOUND) - { - // Key not present is not an error - hr = AtlHresultFromWin32(lRes); - break; - } - } - else - { - hr = AtlHresultFromWin32(lRes); - break; - } - } - if (FAILED(hr = SkipAssignment(szToken))) - break; - continue; // can never have a subkey - } - } - - if (StrChr(szToken, chDirSep) != NULL) - return GenerateError(E_ATL_COMPOUND_KEY); - - if (bRegister) - { - lRes = keyCur.Open(hkParent, szToken, KEY_READ | KEY_WRITE); - if (ERROR_SUCCESS != lRes) - { - // Failed all access try read only - lRes = keyCur.Open(hkParent, szToken, KEY_READ); - if (ERROR_SUCCESS != lRes) - { - // Finally try creating it - ATLTRACE(atlTraceRegistrar, 2, _T("Creating key %s\n"), szToken); - lRes = keyCur.Create(hkParent, szToken, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE); - if (lRes != ERROR_SUCCESS) - return AtlHresultFromWin32(lRes); - } - } - - if (FAILED(hr = NextToken(szToken))) - break; - - - if (*szToken == chEquals) - { - if (FAILED(hr = AddValue(keyCur, NULL, szToken))) // NULL == default - break; - } - } - else - { - if (!bRecover) - lRes = keyCur.Open(hkParent, szToken, KEY_READ); - else - lRes = ERROR_FILE_NOT_FOUND; - - - // Open failed set recovery mode - if (lRes != ERROR_SUCCESS) - bRecover = true; - - // TRACE out Key open status and if in recovery mode -#ifdef _DEBUG - if (!bRecover) - ATLTRACE(atlTraceRegistrar, 1, _T("Opened Key %s\n"), szToken); - else - ATLTRACE(atlTraceRegistrar, 0, _T("Ignoring Open key on %s : In Recovery mode\n"), szToken); -#endif //_DEBUG - - // Remember Subkey - lstrcpyn(szKey, szToken, _MAX_PATH); - - if (FAILED(hr = NextToken(szToken))) - break; - if (FAILED(hr = SkipAssignment(szToken))) - break; - - if (*szToken == chLeftBracket) - { - hr = RegisterSubkeys(szToken, keyCur.m_hKey, bRegister, bRecover); - // In recover mode ignore error - if (FAILED(hr) && !bRecover) - break; - // Skip the } - if (FAILED(hr = NextToken(szToken))) - break; - } - -#ifdef _DEBUG - if (bRecover != bInRecovery) - ATLTRACE(atlTraceRegistrar, 0, _T("Ending Recovery Mode\n")); -#endif - bRecover = bInRecovery; - - if (lRes == ERROR_FILE_NOT_FOUND) - // Key already not present so not an error. - continue; - - if (lRes != ERROR_SUCCESS) - { - // We are recovery mode continue on errors else break - if (bRecover) - continue; - else - { - hr = AtlHresultFromWin32(lRes); - break; - } - } - - // If in recovery mode - if (bRecover && HasSubKeys(keyCur)) - { - // See if the KEY is in the NeverDelete list and if so, don't - if (CanForceRemoveKey(szKey) && bDelete) - { - ATLTRACE(atlTraceRegistrar, 0, _T("Deleting non-empty subkey %s by force\n"), szKey); - // Error not returned since we are in recovery mode. The error that caused recovery mode is returned - keyCur.RecurseDeleteKey(szKey); - } - continue; - } - - lRes = keyCur.Close(); - if (lRes != ERROR_SUCCESS) - return AtlHresultFromWin32(lRes); - - if (bDelete) - { - ATLTRACE(atlTraceRegistrar, 0, _T("Deleting Key %s\n"), szKey); - CRegKey rkParent; - rkParent.Attach(hkParent); - lRes = rkParent.DeleteSubKey(szKey); - rkParent.Detach(); - if (lRes != ERROR_SUCCESS) - { - hr = AtlHresultFromWin32(lRes); - break; - } - } - } - -EndCheck: - - if (bRegister) - { - if (*szToken == chLeftBracket && lstrlen(szToken) == 1) - { - if (FAILED(hr = RegisterSubkeys(szToken, keyCur.m_hKey, bRegister, FALSE))) - break; - if (FAILED(hr = NextToken(szToken))) - break; - } - } - } - - return hr; -} - -}; //namespace ATL - -#endif //__STATREG_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/ATLComMem.h b/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/ATLComMem.h deleted file mode 100644 index c0bcd80ff..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/ATLComMem.h +++ /dev/null @@ -1,172 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLCOMMEM_H__ -#define __ATLCOMMEM_H__ - -#pragma once - -#ifndef __ATLMEM_H__ - #error ATLComMem.h requires atlmem.h to be included first -#endif // __ATLMEM_H__ - -#include - -#pragma pack(push,_ATL_PACKING) -namespace ATL -{ - -class CComHeap : - public IAtlMemMgr -{ -// IAtlMemMgr -public: - virtual void* Allocate( size_t nBytes ) throw() - { -#ifdef _WIN64 - if( nBytes > INT_MAX ) - { - return( NULL ); - } -#endif - return( ::CoTaskMemAlloc( ULONG( nBytes ) ) ); - } - virtual void Free( void* p ) throw() - { - ::CoTaskMemFree( p ); - } - virtual void* Reallocate( void* p, size_t nBytes ) throw() - { -#ifdef _WIN64 - if( nBytes > INT_MAX ) - { - return( NULL ); - } -#endif - return( ::CoTaskMemRealloc( p, ULONG( nBytes ) ) ); - } - virtual size_t GetSize( void* p ) throw() - { - CComPtr< IMalloc > pMalloc; - - HRESULT hr = ::CoGetMalloc( 1, &pMalloc ); - if (FAILED(hr)) - return 0; - - return( pMalloc->GetSize( p ) ); - } -}; - -///////////////////////////////////////////////////////////////////////////// -// OLE task memory allocation support - -inline LPWSTR AtlAllocTaskWideString(LPCWSTR lpszString) throw() -{ - if (lpszString == NULL) - { - return NULL; - } - UINT nSize = (UINT)((wcslen(lpszString)+1) * sizeof(WCHAR)); - LPWSTR lpszResult = (LPWSTR)CoTaskMemAlloc(nSize); -#if _SECURE_ATL - if (lpszResult == NULL) - { - return NULL; - } - - if(0 != memcpy_s(lpszResult, nSize, lpszString, nSize)) - { - CoTaskMemFree(lpszResult); - return NULL; - } -#else - if (lpszResult != NULL) - memcpy(lpszResult, lpszString, nSize); -#endif - - return lpszResult; -} - -inline LPWSTR AtlAllocTaskWideString(LPCSTR lpszString) throw() -{ - if (lpszString == NULL) - return NULL; - UINT nLen = lstrlenA(lpszString)+1; - LPWSTR lpszResult = (LPWSTR)::ATL::AtlCoTaskMemCAlloc(nLen, static_cast(sizeof(WCHAR))); - if (lpszResult != NULL) - { - int nRet = MultiByteToWideChar(CP_ACP, 0, lpszString, -1, lpszResult, nLen); - ATLASSERT(nRet != 0); - if (nRet == 0) - { - CoTaskMemFree(lpszResult); - lpszResult = NULL; - } - } - return lpszResult; -} - -inline LPSTR AtlAllocTaskAnsiString(LPCWSTR lpszString) throw() -{ - if (lpszString == NULL) - return NULL; - UINT nBytes = (UINT)((wcslen(lpszString)+1)*2); - LPSTR lpszResult = (LPSTR)CoTaskMemAlloc(nBytes); - if (lpszResult != NULL) - { - int nRet = WideCharToMultiByte(CP_ACP, 0, lpszString, -1, lpszResult, nBytes, NULL, NULL); - ATLASSERT(nRet != 0); - if (nRet == 0) - { - CoTaskMemFree(lpszResult); - lpszResult = NULL; - } - } - return lpszResult; -} - -inline LPSTR AtlAllocTaskAnsiString(LPCSTR lpszString) throw() -{ - if (lpszString == NULL) - { - return NULL; - } - UINT nSize = lstrlenA(lpszString)+1; - LPSTR lpszResult = (LPSTR)CoTaskMemAlloc(nSize); -#if _SECURE_ATL - if (lpszResult == NULL) - { - return NULL; - } - - if(0 != memcpy_s(lpszResult, nSize, lpszString, nSize)) - { - CoTaskMemFree(lpszResult); - return NULL; - } -#else - if (lpszResult != NULL) - memcpy(lpszResult, lpszString, nSize); -#endif - return lpszResult; -} - -#ifdef _UNICODE - #define AtlAllocTaskString(x) AtlAllocTaskWideString(x) -#else - #define AtlAllocTaskString(x) AtlAllocTaskAnsiString(x) -#endif - -#define AtlAllocTaskOleString(x) AtlAllocTaskWideString(x) - -} // namespace ATL -#pragma pack(pop) - -#endif // __ATLCOMMEM_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlalloc.h b/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlalloc.h deleted file mode 100644 index 461f5f269..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlalloc.h +++ /dev/null @@ -1,704 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#pragma once -#ifndef __ATLALLOC_H__ -#define __ATLALLOC_H__ -#endif - -#include -#include - -#pragma pack(push,_ATL_PACKING) -namespace ATL -{ - -/* -This is more than a little unsatisfying. /Wp64 warns when we convert a size_t to an int -because it knows such a conversion won't port. -But, when we have overloaded templates, there may well exist both conversions and we need -to fool the warning into not firing on 32 bit builds -*/ -#if !defined(_ATL_W64) -#if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) -#define _ATL_W64 __w64 -#else -#define _ATL_W64 -#endif -#endif - -/* Can't use ::std::numeric_limits here because we don't want to introduce a new - deprendency of this code on SCL -*/ - -template -class AtlLimits; - -template<> -class AtlLimits -{ -public: - static const int _Min=INT_MIN; - static const int _Max=INT_MAX; -}; - -template<> -class AtlLimits -{ -public: - static const unsigned int _Min=0; - static const unsigned int _Max=UINT_MAX; -}; - -template<> -class AtlLimits -{ -public: - static const long _Min=LONG_MIN; - static const long _Max=LONG_MAX; -}; - -template<> -class AtlLimits -{ -public: - static const unsigned long _Min=0; - static const unsigned long _Max=ULONG_MAX; -}; - -template<> -class AtlLimits -{ -public: - static const long long _Min=LLONG_MIN; - static const long long _Max=LLONG_MAX; -}; - -template<> -class AtlLimits -{ -public: - static const unsigned long long _Min=0; - static const unsigned long long _Max=ULLONG_MAX; -}; - -/* generic version */ -template -inline HRESULT AtlAdd(T* ptResult, T tLeft, T tRight) -{ - if(::ATL::AtlLimits::_Max-tLeft < tRight) - { - return E_INVALIDARG; - } - *ptResult= tLeft + tRight; - return S_OK; -} - -/* generic but compariatively slow version */ -template -inline HRESULT AtlMultiply(T* ptResult, T tLeft, T tRight) -{ - /* avoid divide 0 */ - if(tLeft==0) - { - *ptResult=0; - return S_OK; - } - if(::ATL::AtlLimits::_Max/tLeft < tRight) - { - return E_INVALIDARG; - } - *ptResult= tLeft * tRight; - return S_OK; -} - -/* fast version for 32 bit integers */ -template<> -inline HRESULT AtlMultiply(int _ATL_W64 *piResult, int _ATL_W64 iLeft, int _ATL_W64 iRight) -{ - __int64 i64Result=static_cast<__int64>(iLeft) * static_cast<__int64>(iRight); - if(i64Result>INT_MAX || i64Result < INT_MIN) - { - return E_INVALIDARG; - } - *piResult=static_cast(i64Result); - return S_OK; -} - -template<> -inline HRESULT AtlMultiply(unsigned int _ATL_W64 *piResult, unsigned int _ATL_W64 iLeft, unsigned int _ATL_W64 iRight) -{ - unsigned __int64 i64Result=static_cast(iLeft) * static_cast(iRight); - if(i64Result>UINT_MAX) - { - return E_INVALIDARG; - } - *piResult=static_cast(i64Result); - return S_OK; -} - -template<> -inline HRESULT AtlMultiply(long _ATL_W64 *piResult, long _ATL_W64 iLeft, long _ATL_W64 iRight) -{ - __int64 i64Result=static_cast<__int64>(iLeft) * static_cast<__int64>(iRight); - if(i64Result>LONG_MAX || i64Result < LONG_MIN) - { - return E_INVALIDARG; - } - *piResult=static_cast(i64Result); - return S_OK; -} - -template<> -inline HRESULT AtlMultiply(unsigned long _ATL_W64 *piResult, unsigned long _ATL_W64 iLeft, unsigned long _ATL_W64 iRight) -{ - unsigned __int64 i64Result=static_cast(iLeft) * static_cast(iRight); - if(i64Result>ULONG_MAX) - { - return E_INVALIDARG; - } - *piResult=static_cast(i64Result); - return S_OK; -} - -template -inline T AtlMultiplyThrow(T tLeft, T tRight) -{ - T tResult; - HRESULT hr=AtlMultiply(&tResult, tLeft, tRight); - if(FAILED(hr)) - { - AtlThrow(hr); - } - return tResult; -} - -template -inline T AtlAddThrow(T tLeft, T tRight) -{ - T tResult; - HRESULT hr=AtlAdd(&tResult, tLeft, tRight); - if(FAILED(hr)) - { - AtlThrow(hr); - } - return tResult; -} - -inline LPVOID AtlCoTaskMemCAlloc(ULONG nCount, ULONG nSize) -{ - HRESULT hr; - ULONG nBytes=0; - if( FAILED(hr=::ATL::AtlMultiply(&nBytes, nCount, nSize))) - { - return NULL; - } - return ::CoTaskMemAlloc(nBytes); -} - -inline LPVOID AtlCoTaskMemRecalloc(void *pvMemory, ULONG nCount, ULONG nSize) -{ - HRESULT hr; - ULONG nBytes=0; - if( FAILED(hr=::ATL::AtlMultiply(&nBytes, nCount, nSize))) - { - return NULL; - } - return ::CoTaskMemRealloc(pvMemory, nBytes); -} - -} // namespace ATL -#pragma pack(pop) - -#pragma pack(push,8) -namespace ATL -{ -// forward declaration of Checked::memcpy_s - -namespace Checked -{ - void __cdecl memcpy_s(void *s1, size_t s1max, const void *s2, size_t n); -} - -///////////////////////////////////////////////////////////////////////////// -// Allocation helpers - -class CCRTAllocator -{ -public: - static void* Reallocate(void* p, size_t nBytes) throw() - { - return realloc(p, nBytes); - } - - static void* Allocate(size_t nBytes) throw() - { - return malloc(nBytes); - } - - static void Free(void* p) throw() - { - free(p); - } -}; - -class CLocalAllocator -{ -public: - static void* Allocate(size_t nBytes) throw() - { - return ::LocalAlloc(LMEM_FIXED, nBytes); - } - static void* Reallocate(void* p, size_t nBytes) throw() - { - if (p==NULL){ - return ( Allocate(nBytes) ); - - } - if (nBytes==0){ - Free(p); - return NULL; - } - return ::LocalReAlloc(p, nBytes, 0); - - } - static void Free(void* p) throw() - { - ::LocalFree(p); - } -}; - -class CGlobalAllocator -{ -public: - static void* Allocate(size_t nBytes) throw() - { - return ::GlobalAlloc(GMEM_FIXED, nBytes); - } - static void* Reallocate(void* p, size_t nBytes) throw() - { - if (p==NULL){ - return ( Allocate(nBytes) ); - - } - if (nBytes==0){ - Free(p); - return NULL; - } - return ( ::GlobalReAlloc(p, nBytes, 0) ); - } - static void Free(void* p) throw() - { - ::GlobalFree(p); - } -}; - -template -class CHeapPtrBase -{ -protected: - CHeapPtrBase() throw() : - m_pData(NULL) - { - } - CHeapPtrBase(CHeapPtrBase& p) throw() - { - m_pData = p.Detach(); // Transfer ownership - } - explicit CHeapPtrBase(T* pData) throw() : - m_pData(pData) - { - } - -public: - ~CHeapPtrBase() throw() - { - Free(); - } - -protected: - CHeapPtrBase& operator=(CHeapPtrBase& p) throw() - { - if(m_pData != p.m_pData) - Attach(p.Detach()); // Transfer ownership - return *this; - } - -public: - operator T*() const throw() - { - return m_pData; - } - - T* operator->() const throw() - { - ATLASSERT(m_pData != NULL); - return m_pData; - } - - T** operator&() throw() - { - ATLASSUME(m_pData == NULL); - return &m_pData; - } - - // Allocate a buffer with the given number of bytes - bool AllocateBytes(size_t nBytes) throw() - { - ATLASSERT(m_pData == NULL); - m_pData = static_cast(Allocator::Allocate(nBytes)); - if (m_pData == NULL) - return false; - - return true; - } - - // Attach to an existing pointer (takes ownership) - void Attach(T* pData) throw() - { - Allocator::Free(m_pData); - m_pData = pData; - } - - // Detach the pointer (releases ownership) - T* Detach() throw() - { - T* pTemp = m_pData; - m_pData = NULL; - return pTemp; - } - - // Free the memory pointed to, and set the pointer to NULL - void Free() throw() - { - Allocator::Free(m_pData); - m_pData = NULL; - } - - // Reallocate the buffer to hold a given number of bytes - bool ReallocateBytes(size_t nBytes) throw() - { - T* pNew; - - pNew = static_cast(Allocator::Reallocate(m_pData, nBytes)); - if (pNew == NULL) - return false; - m_pData = pNew; - - return true; - } - -public: - T* m_pData; -}; - -template -class CHeapPtr : - public CHeapPtrBase -{ -public: - CHeapPtr() throw() - { - } - CHeapPtr(CHeapPtr& p) throw() : - CHeapPtrBase(p) - { - } - explicit CHeapPtr(T* p) throw() : - CHeapPtrBase(p) - { - } - - CHeapPtr& operator=(CHeapPtr& p) throw() - { - CHeapPtrBase::operator=(p); - - return *this; - } - - // Allocate a buffer with the given number of elements - bool Allocate(size_t nElements = 1) throw() - { - size_t nBytes=0; - if(FAILED(::ATL::AtlMultiply(&nBytes, nElements, sizeof(T)))) - { - return false; - } - return AllocateBytes(nBytes); - } - - // Reallocate the buffer to hold a given number of elements - bool Reallocate(size_t nElements) throw() - { - size_t nBytes=0; - if(FAILED(::ATL::AtlMultiply(&nBytes, nElements, sizeof(T)))) - { - return false; - } - return ReallocateBytes(nBytes); - } -}; - -template< typename T, int t_nFixedBytes = 128, class Allocator = CCRTAllocator > -class CTempBuffer -{ -public: - CTempBuffer() throw() : - m_p( NULL ) - { - } - CTempBuffer( size_t nElements ) throw( ... ) : - m_p( NULL ) - { - Allocate( nElements ); - } - - ~CTempBuffer() throw() - { - if( m_p != reinterpret_cast< T* >( m_abFixedBuffer ) ) - { - FreeHeap(); - } - } - - operator T*() const throw() - { - return( m_p ); - } - T* operator->() const throw() - { - ATLASSERT( m_p != NULL ); - return( m_p ); - } - - T* Allocate( size_t nElements ) throw( ... ) - { - return( AllocateBytes( ::ATL::AtlMultiplyThrow(nElements,sizeof( T )) ) ); - } - - T* Reallocate( size_t nElements ) throw( ... ) - { - ATLENSURE(nElements < size_t(-1)/sizeof(T) ); - size_t nNewSize = nElements*sizeof( T ) ; - - if (m_p == NULL) - return AllocateBytes(nNewSize); - - if (nNewSize > t_nFixedBytes) - { - if( m_p == reinterpret_cast< T* >( m_abFixedBuffer ) ) - { - // We have to allocate from the heap and copy the contents into the new buffer - AllocateHeap(nNewSize); - Checked::memcpy_s(m_p, nNewSize, m_abFixedBuffer, t_nFixedBytes); - } - else - { - ReAllocateHeap( nNewSize ); - } - } - else - { - m_p = reinterpret_cast< T* >( m_abFixedBuffer ); - } - - return m_p; - } - - T* AllocateBytes( size_t nBytes ) - { - ATLASSERT( m_p == NULL ); - if( nBytes > t_nFixedBytes ) - { - AllocateHeap( nBytes ); - } - else - { - m_p = reinterpret_cast< T* >( m_abFixedBuffer ); - } - - return( m_p ); - } - -private: - ATL_NOINLINE void AllocateHeap( size_t nBytes ) - { - T* p = static_cast< T* >( Allocator::Allocate( nBytes ) ); - if( p == NULL ) - { - AtlThrow( E_OUTOFMEMORY ); - } - m_p = p; - } - - ATL_NOINLINE void ReAllocateHeap( size_t nNewSize) - { - T* p = static_cast< T* >( Allocator::Reallocate(m_p, nNewSize) ); - if ( p == NULL ) - { - AtlThrow( E_OUTOFMEMORY ); - } - m_p = p; - } - - ATL_NOINLINE void FreeHeap() throw() - { - Allocator::Free( m_p ); - } - -private: - T* m_p; - BYTE m_abFixedBuffer[t_nFixedBytes]; -}; - - -// Allocating memory on the stack without causing stack overflow. -// Only use these through the _ATL_SAFE_ALLOCA_* macros -namespace _ATL_SAFE_ALLOCA_IMPL -{ - -#ifndef _ATL_STACK_MARGIN -#if defined(_M_IX86) -#define _ATL_STACK_MARGIN 0x2000 // Minimum stack available after call to _ATL_SAFE_ALLOCA -#else //_M_AMD64 _M_IA64 -#define _ATL_STACK_MARGIN 0x4000 -#endif -#endif //_ATL_STACK_MARGIN - -//Verifies if sufficient space is available on the stack. -//Note: This function should never be inlined, because the stack allocation -//may not be freed until the end of the calling function (instead of the end of _AtlVerifyStackAvailable). -//The use of __try/__except preverts inlining in this case. -inline bool _AtlVerifyStackAvailable(SIZE_T Size) -{ - bool bStackAvailable = true; - - __try - { - SIZE_T size=0; - HRESULT hrAdd=::ATL::AtlAdd(&size, Size, static_cast(_ATL_STACK_MARGIN)); - if(FAILED(hrAdd)) - { - ATLASSERT(FALSE); - bStackAvailable = false; - } - else - { - PVOID p = _alloca(size); - (p); - } - } - __except ((EXCEPTION_STACK_OVERFLOW == GetExceptionCode()) ? - EXCEPTION_EXECUTE_HANDLER : - EXCEPTION_CONTINUE_SEARCH) - { - bStackAvailable = false; - _resetstkoflw(); - } - return bStackAvailable; -} - - -// Helper Classes to manage heap buffers for _ATL_SAFE_ALLOCA -template < class Allocator> -class CAtlSafeAllocBufferManager -{ -private : - struct CAtlSafeAllocBufferNode - { - CAtlSafeAllocBufferNode* m_pNext; -#if defined(_M_IX86) - BYTE _pad[4]; -#elif defined(_M_IA64) - BYTE _pad[8]; -#elif defined(_M_AMD64) - BYTE _pad[8]; -#else - #error Only supported for X86, AMD64 and IA64 -#endif - void* GetData() - { - return (this + 1); - } - }; - - CAtlSafeAllocBufferNode* m_pHead; -public : - - CAtlSafeAllocBufferManager() : m_pHead(NULL) {}; - void* Allocate(SIZE_T nRequestedSize) - { - CAtlSafeAllocBufferNode *p = (CAtlSafeAllocBufferNode*)Allocator::Allocate(::ATL::AtlAddThrow(nRequestedSize, static_cast(sizeof(CAtlSafeAllocBufferNode)))); - if (p == NULL) - return NULL; - - // Add buffer to the list - p->m_pNext = m_pHead; - m_pHead = p; - - return p->GetData(); - } - ~CAtlSafeAllocBufferManager() - { - // Walk the list and free the buffers - while (m_pHead != NULL) - { - CAtlSafeAllocBufferNode* p = m_pHead; - m_pHead = m_pHead->m_pNext; - Allocator::Free(p); - } - } -}; - -} // namespace _ATL_SAFE_ALLOCA_IMPL - -} // namespace ATL - #pragma pack(pop) - -// Use one of the following macros before using _ATL_SAFE_ALLOCA -// EX version allows specifying a different heap allocator -#define USES_ATL_SAFE_ALLOCA_EX(x) ATL::_ATL_SAFE_ALLOCA_IMPL::CAtlSafeAllocBufferManager _AtlSafeAllocaManager - -#ifndef USES_ATL_SAFE_ALLOCA -#define USES_ATL_SAFE_ALLOCA USES_ATL_SAFE_ALLOCA_EX(ATL::CCRTAllocator) -#endif - -// nRequestedSize - requested size in bytes -// nThreshold - size in bytes beyond which memory is allocated from the heap. - -// Defining _ATL_SAFE_ALLOCA_ALWAYS_ALLOCATE_THRESHOLD_SIZE always allocates the size specified -// for threshold if the stack space is available irrespective of requested size. -// This available for testing purposes. It will help determine the max stack usage due to _alloca's -// Disable _alloca not within try-except prefast warning since we verify stack space is available before. -#ifdef _ATL_SAFE_ALLOCA_ALWAYS_ALLOCATE_THRESHOLD_SIZE -#define _ATL_SAFE_ALLOCA(nRequestedSize, nThreshold) \ - __pragma(warning(push))\ - __pragma(warning(disable:4616))\ - __pragma(warning(disable:6255))\ - ((nRequestedSize <= nThreshold && ATL::_ATL_SAFE_ALLOCA_IMPL::_AtlVerifyStackAvailable(nThreshold) ) ? \ - _alloca(nThreshold) : \ - ((ATL::_ATL_SAFE_ALLOCA_IMPL::_AtlVerifyStackAvailable(nThreshold)) ? _alloca(nThreshold) : 0), \ - _AtlSafeAllocaManager.Allocate(nRequestedSize))\ - __pragma(warning(pop)) -#else -#define _ATL_SAFE_ALLOCA(nRequestedSize, nThreshold) \ - __pragma(warning(push))\ - __pragma(warning(disable:4616))\ - __pragma(warning(disable:6255))\ - ((nRequestedSize <= nThreshold && ATL::_ATL_SAFE_ALLOCA_IMPL::_AtlVerifyStackAvailable(nRequestedSize) ) ? \ - _alloca(nRequestedSize) : \ - _AtlSafeAllocaManager.Allocate(nRequestedSize))\ - __pragma(warning(pop)) -#endif - -// Use 1024 bytes as the default threshold in ATL -#ifndef _ATL_SAFE_ALLOCA_DEF_THRESHOLD -#define _ATL_SAFE_ALLOCA_DEF_THRESHOLD 1024 -#endif diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlbase.h b/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlbase.h deleted file mode 100644 index 0f521c08d..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlbase.h +++ /dev/null @@ -1,7227 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLBASE_H__ -#define __ATLBASE_H__ - -#pragma once - -// Warnings outside of the push/pop sequence will be disabled for all user -// projects. The only warnings that should be disabled outside the push/pop -// are warnings that are a) benign and b) will show up in user projects -// without being directly caused by the user - -#pragma warning(disable: 4505) // unreferenced local function has been removed -#pragma warning(disable: 4710) // function couldn't be inlined -#pragma warning(disable: 4514) // unreferenced inlines are common - -// These two warnings will occur in any class that contains or derives from a -// class with a private copy constructor or copy assignment operator. -#pragma warning(disable: 4511) // copy constructor could not be generated -#pragma warning(disable: 4512) // assignment operator could not be generated - -// This is a very common pattern for us -#pragma warning(disable: 4355) // 'this' : used in base member initializer list - -// Warning 4702 is generated based on compiler backend data flow analysis. This means that for -// some specific instantiations of a template it can be generated even when the code branch is -// required for other instantiations. In future we should find a way to be more selective about this -#pragma warning(disable: 4702) // Unreachable code - -#ifdef _ATL_ALL_WARNINGS -#pragma warning( push ) -#endif - -#pragma warning(disable : 4668) // is not defined as a preprocessor macro, replacing with '0' for '#if/#elif -#pragma warning(disable : 4820) // padding added after member -#pragma warning(disable : 4917) // a GUID can only be associated with a class, interface or namespace - -#pragma warning(disable : 4217) // member template functions cannot be used for copy-assignment or copy-construction - -#pragma warning(disable: 4127) // constant expression -#pragma warning(disable: 4097) // typedef name used as synonym for class-name -#pragma warning(disable: 4786) // identifier was truncated in the debug information -#pragma warning(disable: 4291) // allow placement new -#pragma warning(disable: 4201) // nameless unions are part of C++ -#pragma warning(disable: 4103) // pragma pack -#pragma warning(disable: 4268) // const static/global data initialized to zeros - -#pragma warning (push) -#pragma warning(disable: 4571) //catch(...) blocks compiled with /EHs do NOT catch or re-throw Structured Exceptions -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif -#ifndef ATL_NO_LEAN_AND_MEAN -#define ATL_NO_LEAN_AND_MEAN -#endif - -#include - -#ifndef _WINSOCKAPI_ -#include -#endif - -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include - -#if !defined(_ATL_MIN_CRT) & defined(_MT) -#include -#include // for _beginthreadex, _endthreadex -#endif - -#include -#include - -#include -#include -#include -#include -#include - -#define _ATL_TYPELIB_INDEX_LENGTH 10 -#define _ATL_QUOTES_SPACE 2 - -#pragma pack(push, _ATL_PACKING) - -#ifndef _ATL_NO_DEFAULT_LIBS - -#if defined(_ATL_DLL) - #pragma comment(lib, "atl.lib") - -#if !defined(_ATL_NOFORCE_MANIFEST) && !defined(_VC_NODEFAULTLIB) - -#include - -#endif // !defined(_ATL_NOFORCE_MANIFEST) && !defined(_VC_NODEFAULTLIB) - -#endif // _ATL_DLL - -#ifdef _DEBUG - #pragma comment(lib, "atlsd.lib") -#else - #pragma comment(lib, "atls.lib") -#ifdef _ATL_MIN_CRT - #pragma comment(lib, "atlmincrt.lib") -#endif -#endif - -#endif // !_ATL_NO_DEFAULT_LIBS - -#if defined(_ATL_DLL) - // Pull in obj file with manifest directive for ATL dll - #if defined(_M_IX86) - #pragma comment(linker, "/include:__forceAtlDllManifest") - #else - #pragma comment(linker, "/include:_forceAtlDllManifest") - #endif -#endif - -extern "C" const __declspec(selectany) GUID LIBID_ATLLib = {0x44EC0535,0x400F,0x11D0,{0x9D,0xCD,0x00,0xA0,0xC9,0x03,0x91,0xD3}}; -extern "C" const __declspec(selectany) CLSID CLSID_Registrar = {0x44EC053A,0x400F,0x11D0,{0x9D,0xCD,0x00,0xA0,0xC9,0x03,0x91,0xD3}}; -extern "C" const __declspec(selectany) IID IID_IRegistrar = {0x44EC053B,0x400F,0x11D0,{0x9D,0xCD,0x00,0xA0,0xC9,0x03,0x91,0xD3}}; -extern "C" const __declspec(selectany) IID IID_IAxWinHostWindow = {0xb6ea2050,0x048a,0x11d1,{0x82,0xb9,0x00,0xc0,0x4f,0xb9,0x94,0x2e}}; -extern "C" const __declspec(selectany) IID IID_IAxWinAmbientDispatch = {0xb6ea2051,0x048a,0x11d1,{0x82,0xb9,0x00,0xc0,0x4f,0xb9,0x94,0x2e}}; -extern "C" const __declspec(selectany) IID IID_IInternalConnection = {0x72AD0770,0x6A9F,0x11d1,{0xBC,0xEC,0x00,0x60,0x08,0x8F,0x44,0x4E}}; -extern "C" const __declspec(selectany) IID IID_IDocHostUIHandlerDispatch = {0x425B5AF0,0x65F1,0x11d1,{0x96,0x11,0x00,0x00,0xF8,0x1E,0x0D,0x0D}}; -extern "C" const __declspec(selectany) IID IID_IAxWinHostWindowLic = {0x3935BDA8,0x4ED9,0x495c,{0x86,0x50,0xE0,0x1F,0xC1,0xE3,0x8A,0x4B}}; -extern "C" const __declspec(selectany) IID IID_IAxWinAmbientDispatchEx = {0xB2D0778B,0xAC99,0x4c58,{0xA5,0xC8,0xE7,0x72,0x4E,0x53,0x16,0xB5}}; - - -#ifndef _delayimp_h -extern "C" IMAGE_DOS_HEADER __ImageBase; -#endif - -#ifdef _AFX -void AFXAPI AfxOleLockApp(); -void AFXAPI AfxOleUnlockApp(); -#endif // _AFX - - - -namespace ATL -{ - -struct _ATL_CATMAP_ENTRY -{ - int iType; - const CATID* pcatid; -}; - -#define _ATL_CATMAP_ENTRY_END 0 -#define _ATL_CATMAP_ENTRY_IMPLEMENTED 1 -#define _ATL_CATMAP_ENTRY_REQUIRED 2 - -typedef HRESULT (WINAPI _ATL_CREATORFUNC)(void* pv, REFIID riid, LPVOID* ppv); -typedef HRESULT (WINAPI _ATL_CREATORARGFUNC)(void* pv, REFIID riid, LPVOID* ppv, DWORD_PTR dw); -typedef HRESULT (WINAPI _ATL_MODULEFUNC)(DWORD_PTR dw); -typedef LPCTSTR (WINAPI _ATL_DESCRIPTIONFUNC)(); -typedef const struct _ATL_CATMAP_ENTRY* (_ATL_CATMAPFUNC)(); -typedef void (__stdcall _ATL_TERMFUNC)(DWORD_PTR dw); - -struct _ATL_TERMFUNC_ELEM -{ - _ATL_TERMFUNC* pFunc; - DWORD_PTR dw; - _ATL_TERMFUNC_ELEM* pNext; -}; - -/* -struct _ATL_OBJMAP_ENTRY20 -{ - const CLSID* pclsid; - HRESULT (WINAPI *pfnUpdateRegistry)(BOOL bRegister); - _ATL_CREATORFUNC* pfnGetClassObject; - _ATL_CREATORFUNC* pfnCreateInstance; - IUnknown* pCF; - DWORD dwRegister; - _ATL_DESCRIPTIONFUNC* pfnGetObjectDescription; -}; -*/ - -// Can't inherit from _ATL_OBJMAP_ENTRY20 -// because it messes up the OBJECT_MAP macros -struct _ATL_OBJMAP_ENTRY30 -{ - const CLSID* pclsid; - HRESULT (WINAPI *pfnUpdateRegistry)(BOOL bRegister); - _ATL_CREATORFUNC* pfnGetClassObject; - _ATL_CREATORFUNC* pfnCreateInstance; - IUnknown* pCF; - DWORD dwRegister; - _ATL_DESCRIPTIONFUNC* pfnGetObjectDescription; - _ATL_CATMAPFUNC* pfnGetCategoryMap; - HRESULT WINAPI RevokeClassObject() - { - if (dwRegister == 0) - return S_OK; - return CoRevokeClassObject(dwRegister); - } - HRESULT WINAPI RegisterClassObject(DWORD dwClsContext, DWORD dwFlags) - { - IUnknown* p = NULL; - if (pfnGetClassObject == NULL) - return S_OK; - HRESULT hRes = pfnGetClassObject(pfnCreateInstance, __uuidof(IUnknown), (LPVOID*) &p); - if (SUCCEEDED(hRes)) - hRes = CoRegisterClassObject(*pclsid, p, dwClsContext, dwFlags, &dwRegister); - if (p != NULL) - p->Release(); - return hRes; - } -// Added in ATL 3.0 - void (WINAPI *pfnObjectMain)(bool bStarting); -}; - -typedef _ATL_OBJMAP_ENTRY30 _ATL_OBJMAP_ENTRY; - -// Auto Object Map - -#if defined(_M_IA64) || defined(_M_IX86) || defined (_M_AMD64) - -#pragma section("ATL$__a", read, shared) -#pragma section("ATL$__z", read, shared) -#pragma section("ATL$__m", read, shared) -extern "C" -{ -__declspec(selectany) __declspec(allocate("ATL$__a")) _ATL_OBJMAP_ENTRY* __pobjMapEntryFirst = NULL; -__declspec(selectany) __declspec(allocate("ATL$__z")) _ATL_OBJMAP_ENTRY* __pobjMapEntryLast = NULL; -} - -#if !defined(_M_IA64) -#pragma comment(linker, "/merge:ATL=.rdata") -#endif - -#else - -extern "C" -{ -__declspec(selectany) _ATL_OBJMAP_ENTRY* __pobjMapEntryFirst = NULL; -__declspec(selectany) _ATL_OBJMAP_ENTRY* __pobjMapEntryLast = NULL; -} - -#endif // defined(_M_IA64) || defined(_M_IX86) - -struct _ATL_REGMAP_ENTRY -{ - LPCOLESTR szKey; - LPCOLESTR szData; -}; - -struct _AtlCreateWndData -{ - void* m_pThis; - DWORD m_dwThreadID; - _AtlCreateWndData* m_pNext; -}; - - -// perfmon registration/unregistration function definitions -typedef HRESULT (*_ATL_PERFREGFUNC)(HINSTANCE hDllInstance); -typedef HRESULT (*_ATL_PERFUNREGFUNC)(); -__declspec(selectany) _ATL_PERFREGFUNC _pPerfRegFunc = NULL; -__declspec(selectany) _ATL_PERFUNREGFUNC _pPerfUnRegFunc = NULL; - -///////////////////////////////////////////////////////////////////////////// -// Threading Model Support - -template< class TLock > -class CComCritSecLock -{ -public: - CComCritSecLock( TLock& cs, bool bInitialLock = true ); - ~CComCritSecLock() throw(); - - HRESULT Lock() throw(); - void Unlock() throw(); - -// Implementation -private: - TLock& m_cs; - bool m_bLocked; - -// Private to avoid accidental use - CComCritSecLock( const CComCritSecLock& ) throw(); - CComCritSecLock& operator=( const CComCritSecLock& ) throw(); -}; - -template< class TLock > -inline CComCritSecLock< TLock >::CComCritSecLock( TLock& cs, bool bInitialLock ) : - m_cs( cs ), - m_bLocked( false ) -{ - if( bInitialLock ) - { - HRESULT hr; - - hr = Lock(); - if( FAILED( hr ) ) - { - AtlThrow( hr ); - } - } -} - -template< class TLock > -inline CComCritSecLock< TLock >::~CComCritSecLock() throw() -{ - if( m_bLocked ) - { - Unlock(); - } -} - -template< class TLock > -inline HRESULT CComCritSecLock< TLock >::Lock() throw() -{ - HRESULT hr; - - ATLASSERT( !m_bLocked ); - hr = m_cs.Lock(); - if( FAILED( hr ) ) - { - return( hr ); - } - m_bLocked = true; - - return( S_OK ); -} - -template< class TLock > -inline void CComCritSecLock< TLock >::Unlock() throw() -{ - ATLASSUME( m_bLocked ); - m_cs.Unlock(); - m_bLocked = false; -} - -class CComMultiThreadModelNoCS -{ -public: - static ULONG WINAPI Increment(LPLONG p) throw() {return InterlockedIncrement(p);} - static ULONG WINAPI Decrement(LPLONG p) throw() {return InterlockedDecrement(p);} - typedef CComFakeCriticalSection AutoCriticalSection; - typedef CComFakeCriticalSection AutoDeleteCriticalSection; - typedef CComFakeCriticalSection CriticalSection; - typedef CComMultiThreadModelNoCS ThreadModelNoCS; -}; - -class CComMultiThreadModel -{ -public: - static ULONG WINAPI Increment(LPLONG p) throw() {return InterlockedIncrement(p);} - static ULONG WINAPI Decrement(LPLONG p) throw() {return InterlockedDecrement(p);} - typedef CComAutoCriticalSection AutoCriticalSection; - typedef CComAutoDeleteCriticalSection AutoDeleteCriticalSection; - typedef CComCriticalSection CriticalSection; - typedef CComMultiThreadModelNoCS ThreadModelNoCS; -}; - -class CComSingleThreadModel -{ -public: - static ULONG WINAPI Increment(LPLONG p) throw() {return ++(*p);} - static ULONG WINAPI Decrement(LPLONG p) throw() {return --(*p);} - typedef CComFakeCriticalSection AutoCriticalSection; - typedef CComFakeCriticalSection AutoDeleteCriticalSection; - typedef CComFakeCriticalSection CriticalSection; - typedef CComSingleThreadModel ThreadModelNoCS; -}; - -#if defined(_ATL_SINGLE_THREADED) - -#if defined(_ATL_APARTMENT_THREADED) || defined(_ATL_FREE_THREADED) -#pragma message ("More than one global threading model defined.") -#endif - - typedef CComSingleThreadModel CComObjectThreadModel; - typedef CComSingleThreadModel CComGlobalsThreadModel; - -#elif defined(_ATL_APARTMENT_THREADED) - -#if defined(_ATL_SINGLE_THREADED) || defined(_ATL_FREE_THREADED) -#pragma message ("More than one global threading model defined.") -#endif - - typedef CComSingleThreadModel CComObjectThreadModel; - typedef CComMultiThreadModel CComGlobalsThreadModel; - -#elif defined(_ATL_FREE_THREADED) - -#if defined(_ATL_SINGLE_THREADED) || defined(_ATL_APARTMENT_THREADED) -#pragma message ("More than one global threading model defined.") -#endif - - typedef CComMultiThreadModel CComObjectThreadModel; - typedef CComMultiThreadModel CComGlobalsThreadModel; - -#else -#pragma message ("No global threading model defined") -#endif - -///////////////////////////////////////////////////////////////////////////// -// Module - - -// Used by COM related code in ATL -struct _ATL_COM_MODULE70 -{ - UINT cbSize; - HINSTANCE m_hInstTypeLib; - _ATL_OBJMAP_ENTRY** m_ppAutoObjMapFirst; - _ATL_OBJMAP_ENTRY** m_ppAutoObjMapLast; - CComCriticalSection m_csObjMap; -}; -typedef _ATL_COM_MODULE70 _ATL_COM_MODULE; - - -// Used by Windowing code in ATL -struct _ATL_WIN_MODULE70 -{ - UINT cbSize; - CComCriticalSection m_csWindowCreate; - _AtlCreateWndData* m_pCreateWndList; - CSimpleArray m_rgWindowClassAtoms; -}; -typedef _ATL_WIN_MODULE70 _ATL_WIN_MODULE; - - -struct _ATL_MODULE70 -{ - UINT cbSize; - LONG m_nLockCnt; - _ATL_TERMFUNC_ELEM* m_pTermFuncs; - CComCriticalSection m_csStaticDataInitAndTypeInfo; -}; -typedef _ATL_MODULE70 _ATL_MODULE; - - -///////////////////////////////////////////////////////////////////////////// -//This define makes debugging asserts easier. -#define _ATL_SIMPLEMAPENTRY ((ATL::_ATL_CREATORARGFUNC*)1) - -struct _ATL_INTMAP_ENTRY -{ - const IID* piid; // the interface id (IID) - DWORD_PTR dw; - _ATL_CREATORARGFUNC* pFunc; //NULL:end, 1:offset, n:ptr -}; - -///////////////////////////////////////////////////////////////////////////// -// Global Functions - -///////////////////////////////////////////////////////////////////////////// -// QI Support - -ATLAPI AtlInternalQueryInterface(void* pThis, - const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject); - -///////////////////////////////////////////////////////////////////////////// -// Inproc Marshaling helpers - -ATLAPI AtlFreeMarshalStream(IStream* pStream); -ATLAPI AtlMarshalPtrInProc(IUnknown* pUnk, const IID& iid, IStream** ppStream); -ATLAPI AtlUnmarshalPtr(IStream* pStream, const IID& iid, IUnknown** ppUnk); - -ATLAPI_(BOOL) AtlWaitWithMessageLoop(HANDLE hEvent); - -///////////////////////////////////////////////////////////////////////////// -// Connection Point Helpers - -ATLAPI AtlAdvise(IUnknown* pUnkCP, IUnknown* pUnk, const IID& iid, LPDWORD pdw); -ATLAPI AtlUnadvise(IUnknown* pUnkCP, const IID& iid, DWORD dw); - -///////////////////////////////////////////////////////////////////////////// -// IDispatch Error handling - -ATLAPI AtlSetErrorInfo(const CLSID& clsid, LPCOLESTR lpszDesc, - DWORD dwHelpID, LPCOLESTR lpszHelpFile, const IID& iid, HRESULT hRes, - HINSTANCE hInst); - -///////////////////////////////////////////////////////////////////////////// -// Module - -ATLAPI AtlComModuleRegisterClassObjects(_ATL_COM_MODULE* pComModule, DWORD dwClsContext, DWORD dwFlags); -ATLAPI AtlComModuleRevokeClassObjects(_ATL_COM_MODULE* pComModule); - -ATLAPI AtlComModuleGetClassObject(_ATL_COM_MODULE* pComModule, REFCLSID rclsid, REFIID riid, LPVOID* ppv); - -ATLAPI AtlComModuleRegisterServer(_ATL_COM_MODULE* pComModule, BOOL bRegTypeLib, const CLSID* pCLSID = NULL); -ATLAPI AtlComModuleUnregisterServer(_ATL_COM_MODULE* pComModule, BOOL bUnRegTypeLib, const CLSID* pCLSID = NULL); - -ATLAPI AtlRegisterClassCategoriesHelper( REFCLSID clsid, const struct _ATL_CATMAP_ENTRY* pCatMap, BOOL bRegister ); - -ATLAPI AtlUpdateRegistryFromResourceD(HINSTANCE hInst, LPCOLESTR lpszRes, - BOOL bRegister, struct _ATL_REGMAP_ENTRY* pMapEntries, IRegistrar* pReg = NULL); - -ATLAPI AtlRegisterTypeLib(HINSTANCE hInstTypeLib, LPCOLESTR lpszIndex); -ATLAPI AtlUnRegisterTypeLib(HINSTANCE hInstTypeLib, LPCOLESTR lpszIndex); -ATLAPI AtlLoadTypeLib(HINSTANCE hInstTypeLib, LPCOLESTR lpszIndex, BSTR* pbstrPath, ITypeLib** ppTypeLib); - -ATLAPI_(DWORD) AtlGetVersion(void* pReserved); - -ATLAPI AtlModuleAddTermFunc(_ATL_MODULE* pModule, _ATL_TERMFUNC* pFunc, DWORD_PTR dw); -ATLAPI_(void) AtlCallTermFunc(_ATL_MODULE* pModule); - -ATLAPI AtlWinModuleInit(_ATL_WIN_MODULE* pWinModule); -ATLAPIINL AtlWinModuleTerm(_ATL_WIN_MODULE* pWinModule, HINSTANCE hInst); - -ATLAPI_(void) AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE* pWinModule, _AtlCreateWndData* pData, void* pObject); -ATLAPI_(void*) AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE* pWinModule); - -///////////////////////////////////////////////////////////////////////////// -// Get Registrar object from ATL DLL. - -#if !defined(_ATL_STATIC_REGISTRY) -#ifdef _ATL_DLL_IMPL -extern "C" HRESULT __stdcall AtlCreateRegistrar(IRegistrar** ppReg); -#else -extern "C" __declspec(dllimport) HRESULT __stdcall AtlCreateRegistrar(IRegistrar** ppReg); -#endif -#endif - -///////////////////////////////////////////////////////////////////////////// -// GUID comparison -inline BOOL WINAPI InlineIsEqualUnknown(REFGUID rguid1) -{ - return ( - ((PLONG) &rguid1)[0] == 0 && - ((PLONG) &rguid1)[1] == 0 && -#ifdef _ATL_BYTESWAP - ((PLONG) &rguid1)[2] == 0xC0000000 && - ((PLONG) &rguid1)[3] == 0x00000046); -#else - ((PLONG) &rguid1)[2] == 0x000000C0 && - ((PLONG) &rguid1)[3] == 0x46000000); -#endif -} - - - -template -LPCTSTR AtlDebugGetClassName(T*) -{ -#ifdef _DEBUG - const _ATL_INTMAP_ENTRY* pEntries = T::_GetEntries(); - return (LPCTSTR)pEntries[-1].dw; -#else - return NULL; -#endif -} - -// Validation macro for OUT pointer -// Used in QI and CreateInstance -#define _ATL_VALIDATE_OUT_POINTER(x)\ - do { \ - ATLASSERT(x != NULL); \ - if (x == NULL) \ - return E_POINTER; \ - *x = NULL; \ - } while(0) - -///////////////////////////////////////////////////////////////////////////// -// Win32 libraries - -#ifndef _ATL_NO_DEFAULT_LIBS -#pragma comment(lib, "kernel32.lib") -#pragma comment(lib, "user32.lib") -#pragma comment(lib, "advapi32.lib") -#pragma comment(lib, "ole32.lib") -#pragma comment(lib, "shell32.lib") -#pragma comment(lib, "oleaut32.lib") -#pragma comment(lib, "uuid.lib") -#pragma comment(lib, "shlwapi.lib") -#endif // !_ATL_NO_DEFAULT_LIBS - -template< typename T > -class CAutoVectorPtr -{ -public: - CAutoVectorPtr() throw() : - m_p( NULL ) - { - } - CAutoVectorPtr( CAutoVectorPtr< T >& p ) throw() - { - m_p = p.Detach(); // Transfer ownership - } - explicit CAutoVectorPtr( T* p ) throw() : - m_p( p ) - { - } - ~CAutoVectorPtr() throw() - { - Free(); - } - - operator T*() const throw() - { - return( m_p ); - } - - CAutoVectorPtr< T >& operator=( CAutoVectorPtr< T >& p ) throw() - { - if(*this==p) - { - if(this!=&p) - { - // If this assert fires, it means you attempted to assign one CAutoVectorPtr to another when they both contained - // a pointer to the same underlying vector. This means a bug in your code, since your vector will get - // double-deleted. - ATLASSERT(FALSE); - - // For safety, we are going to detach the other CAutoVectorPtr to avoid a double-free. Your code still - // has a bug, though. - p.Detach(); - } - else - { - // Alternatively, this branch means that you are assigning a CAutoVectorPtr to itself, which is - // pointless but permissible - - // nothing to do - } - } - else - { - Free(); - Attach( p.Detach() ); // Transfer ownership - } - return( *this ); - } - - // basic comparison operators - bool operator!=(CAutoVectorPtr& p) const - { - return !operator==(p); - } - - bool operator==(CAutoVectorPtr& p) const - { - return m_p==p.m_p; - } - - // Allocate the vector - bool Allocate( size_t nElements ) throw() - { - ATLASSUME( m_p == NULL ); - ATLTRY( m_p = new T[nElements] ); - if( m_p == NULL ) - { - return( false ); - } - - return( true ); - } - // Attach to an existing pointer (takes ownership) - void Attach( T* p ) throw() - { - ATLASSUME( m_p == NULL ); - m_p = p; - } - // Detach the pointer (releases ownership) - T* Detach() throw() - { - T* p; - - p = m_p; - m_p = NULL; - - return( p ); - } - // Delete the vector pointed to, and set the pointer to NULL - void Free() throw() - { - delete[] m_p; - m_p = NULL; - } - -public: - T* m_p; -}; - -template< typename T > -class CAutoPtr -{ -public: - CAutoPtr() throw() : - m_p( NULL ) - { - } - template< typename TSrc > - CAutoPtr( CAutoPtr< TSrc >& p ) throw() - { - m_p = p.Detach(); // Transfer ownership - } - CAutoPtr( CAutoPtr< T >& p ) throw() - { - m_p = p.Detach(); // Transfer ownership - } - explicit CAutoPtr( T* p ) throw() : - m_p( p ) - { - } - ~CAutoPtr() throw() - { - Free(); - } - - // Templated version to allow pBase = pDerived - template< typename TSrc > - CAutoPtr< T >& operator=( CAutoPtr< TSrc >& p ) throw() - { - if(m_p==p.m_p) - { - // This means that two CAutoPtrs of two different types had the same m_p in them - // which is never correct - ATLASSERT(FALSE); - } - else - { - Free(); - Attach( p.Detach() ); // Transfer ownership - } - return( *this ); - } - CAutoPtr< T >& operator=( CAutoPtr< T >& p ) throw() - { - if(*this==p) - { - if(this!=&p) - { - // If this assert fires, it means you attempted to assign one CAutoPtr to another when they both contained - // a pointer to the same underlying object. This means a bug in your code, since your object will get - // double-deleted. -#ifdef ATL_AUTOPTR_ASSIGNMENT_ASSERT - ATLASSERT(FALSE); -#endif - - // For safety, we are going to detach the other CAutoPtr to avoid a double-free. Your code still - // has a bug, though. - p.Detach(); - } - else - { - // Alternatively, this branch means that you are assigning a CAutoPtr to itself, which is - // pointless but permissible - - // nothing to do - } - } - else - { - Free(); - Attach( p.Detach() ); // Transfer ownership - } - return( *this ); - } - - // basic comparison operators - bool operator!=(CAutoPtr& p) const - { - return !operator==(p); - } - - bool operator==(CAutoPtr& p) const - { - return m_p==p.m_p; - } - - operator T*() const throw() - { - return( m_p ); - } - T* operator->() const throw() - { - ATLASSUME( m_p != NULL ); - return( m_p ); - } - - // Attach to an existing pointer (takes ownership) - void Attach( T* p ) throw() - { - ATLASSUME( m_p == NULL ); - m_p = p; - } - // Detach the pointer (releases ownership) - T* Detach() throw() - { - T* p; - - p = m_p; - m_p = NULL; - - return( p ); - } - // Delete the object pointed to, and set the pointer to NULL - void Free() throw() - { - delete m_p; - m_p = NULL; - } - -public: - T* m_p; -}; - -/* Automatic cleanup for _malloca objects */ -template< typename T > -class CAutoStackPtr -{ -public: - CAutoStackPtr() throw() : - m_p( NULL ) - { - } - template< typename TSrc > - CAutoStackPtr( CAutoStackPtr< TSrc >& p ) throw() - { - m_p = p.Detach(); // Transfer ownership - } - CAutoStackPtr( CAutoStackPtr< T >& p ) throw() - { - m_p = p.Detach(); // Transfer ownership - } - explicit CAutoStackPtr( T* p ) throw() : - m_p( p ) - { - } - ~CAutoStackPtr() throw() - { - Free(); - } - - // Templated version to allow pBase = pDerived - template< typename TSrc > - CAutoStackPtr< T >& operator=( CAutoStackPtr< TSrc >& p ) throw() - { - if(m_p==p.m_p) - { - // This means that two CAutoPtrs of two different types had the same m_p in them - // which is never correct - ATLASSERT(FALSE); - } - else - { - Free(); - Attach( p.Detach() ); // Transfer ownership - } - return( *this ); - } - CAutoStackPtr< T >& operator=( CAutoStackPtr< T >& p ) throw() - { - if(*this==p) - { - if(this!=&p) - { - // If this assert fires, it means you attempted to assign one CAutoPtr to another when they both contained - // a pointer to the same underlying object. This means a bug in your code, since your object will get - // double-deleted. - ATLASSERT(FALSE); - - // For safety, we are going to detach the other CAutoPtr to avoid a double-free. Your code still - // has a bug, though. - p.Detach(); - } - else - { - // Alternatively, this branch means that you are assigning a CAutoPtr to itself, which is - // pointless but permissible - - // nothing to do - } - } - else - { - Free(); - Attach( p.Detach() ); // Transfer ownership - } - return( *this ); - } - - // basic comparison operators - bool operator!=(CAutoStackPtr& p) const - { - return !operator==(p); - } - - bool operator==(CAutoStackPtr& p) const - { - return m_p==p.m_p; - } - - operator T*() const throw() - { - return( m_p ); - } - T* operator->() const throw() - { - ATLASSUME( m_p != NULL ); - return( m_p ); - } - - // Attach to an existing pointer (takes ownership) - void Attach( T* p ) throw() - { - ATLASSUME( m_p == NULL ); - m_p = p; - } - // Detach the pointer (releases ownership) - T* Detach() throw() - { - T* p; - - p = m_p; - m_p = NULL; - - return( p ); - } - // Delete the object pointed to, and set the pointer to NULL - void Free() throw() - { - /* Note: _freea only actually does anything if m_p was heap allocated - If m_p was from the stack, it wouldn't be possible to actually free it here - [wrong function] unless we got inlined. But really all we do if m_p is - stack-based is ignore it and let its alloca storage disappear at the end - of the outer function. - */ - _freea(m_p); - m_p = NULL; - } - -public: - T* m_p; -}; - -// static_cast_auto template functions. Used like static_cast, only they work on CAutoPtr objects -template< class Dest, class Src > -Dest* static_cast_auto( const CAutoPtr< Src >& pSrc ) throw() -{ - return( static_cast< Dest* >( static_cast< Src* >( pSrc ) ) ); -} - - -class CComAllocator -{ -public: - static void* Reallocate(void* p, size_t nBytes) throw() - { -#ifdef _WIN64 - if( nBytes > INT_MAX ) - { - return( NULL ); - } -#endif - return ::CoTaskMemRealloc(p, ULONG(nBytes)); - } - static void* Allocate(size_t nBytes) throw() - { -#ifdef _WIN64 - if( nBytes > INT_MAX ) - { - return( NULL ); - } -#endif - return ::CoTaskMemAlloc(ULONG(nBytes)); - } - static void Free(void* p) throw() - { - ::CoTaskMemFree(p); - } -}; - -template -class CComHeapPtr : - public CHeapPtr -{ -public: - CComHeapPtr() throw() - { - } - - explicit CComHeapPtr(T* pData) throw() : - CHeapPtr(pData) - { - } -}; - -template -T* AtlSafeRealloc(T* pT, size_t cEls) throw() -{ - T* pTemp; - - size_t nBytes=0; - if(FAILED(::ATL::AtlMultiply(&nBytes, cEls, sizeof(T)))) - { - return NULL; - } - pTemp = static_cast(Reallocator::Reallocate(pT, nBytes)); - if (pTemp == NULL) - { - Reallocator::Free(pT); - return NULL; - } - pT = pTemp; - return pTemp; -} - -class CHandle -{ -public: - CHandle() throw(); - CHandle( CHandle& h ) throw(); - explicit CHandle( HANDLE h ) throw(); - ~CHandle() throw(); - - CHandle& operator=( CHandle& h ) throw(); - - operator HANDLE() const throw(); - - // Attach to an existing handle (takes ownership). - void Attach( HANDLE h ) throw(); - // Detach the handle from the object (releases ownership). - HANDLE Detach() throw(); - - // Close the handle. - void Close() throw(); - -public: - HANDLE m_h; -}; - -inline CHandle::CHandle() throw() : - m_h( NULL ) -{ -} - -inline CHandle::CHandle( CHandle& h ) throw() : - m_h( NULL ) -{ - Attach( h.Detach() ); -} - -inline CHandle::CHandle( HANDLE h ) throw() : - m_h( h ) -{ -} - -inline CHandle::~CHandle() throw() -{ - if( m_h != NULL ) - { - Close(); - } -} - -inline CHandle& CHandle::operator=( CHandle& h ) throw() -{ - if( this != &h ) - { - if( m_h != NULL ) - { - Close(); - } - Attach( h.Detach() ); - } - - return( *this ); -} - -inline CHandle::operator HANDLE() const throw() -{ - return( m_h ); -} - -inline void CHandle::Attach( HANDLE h ) throw() -{ - ATLASSUME( m_h == NULL ); - m_h = h; // Take ownership -} - -inline HANDLE CHandle::Detach() throw() -{ - HANDLE h; - - h = m_h; // Release ownership - m_h = NULL; - - return( h ); -} - -inline void CHandle::Close() throw() -{ - if( m_h != NULL ) - { - ::CloseHandle( m_h ); - m_h = NULL; - } -} - -class CCritSecLock -{ -public: - CCritSecLock( CRITICAL_SECTION& cs, bool bInitialLock = true ); - ~CCritSecLock() throw(); - - void Lock(); - void Unlock() throw(); - -// Implementation -private: - CRITICAL_SECTION& m_cs; - bool m_bLocked; - -// Private to avoid accidental use - CCritSecLock( const CCritSecLock& ) throw(); - CCritSecLock& operator=( const CCritSecLock& ) throw(); -}; - -inline CCritSecLock::CCritSecLock( CRITICAL_SECTION& cs, bool bInitialLock ) : - m_cs( cs ), - m_bLocked( false ) -{ - if( bInitialLock ) - { - Lock(); - } -} - -inline CCritSecLock::~CCritSecLock() throw() -{ - if( m_bLocked ) - { - Unlock(); - } -} - -inline void CCritSecLock::Lock() -{ - ATLASSERT( !m_bLocked ); - __try - { - ::EnterCriticalSection( &m_cs ); - } - __except( STATUS_NO_MEMORY == GetExceptionCode() ) - { - AtlThrow( E_OUTOFMEMORY ); - } - m_bLocked = true; -} - -inline void CCritSecLock::Unlock() throw() -{ - ATLASSUME( m_bLocked ); - ::LeaveCriticalSection( &m_cs ); - m_bLocked = false; -} - -///////////////////////////////////////////////////////////////////////////// -// Interface debugging -#if defined(_ATL_DEBUG_INTERFACES) || defined(_ATL_DEBUG_QI) -HRESULT WINAPI AtlDumpIID(REFIID iid, LPCTSTR pszClassName, HRESULT hr) throw(); -#endif // _ATL_DEBUG_INTERFACES || _ATL_DEBUG_QI - -#ifdef _ATL_DEBUG_INTERFACES - -struct _QIThunk -{ - STDMETHOD(QueryInterface)(REFIID iid, void** pp) - { - ATLASSUME(m_dwRef >= 0); - ATLASSUME(m_pUnk != NULL); - return m_pUnk->QueryInterface(iid, pp); - } - STDMETHOD_(ULONG, AddRef)() - { - ATLASSUME(m_pUnk != NULL); - if (m_bBreak) - DebugBreak(); - m_pUnk->AddRef(); - return InternalAddRef(); - } - ULONG InternalAddRef() - { - ATLASSUME(m_pUnk != NULL); - if (m_bBreak) - DebugBreak(); - ATLASSUME(m_dwRef >= 0); - long l = InterlockedIncrement(&m_dwRef); - - TCHAR buf[512+1]; -#if _SECURE_ATL && !defined(_ATL_MIN_CRT) - _stprintf_s(buf, _countof(buf), _T("QIThunk - %-10d\tAddRef :\tObject = 0x%p\tRefcount = %d\t"), - m_nIndex, m_pUnk, m_dwRef); -#else - wsprintf(buf, _T("QIThunk - %-10d\tAddRef :\tObject = 0x%p\tRefcount = %d\t"), m_nIndex, m_pUnk, m_dwRef); -#endif - buf[_countof(buf)-1] = 0; - OutputDebugString(buf); - AtlDumpIID(m_iid, m_lpszClassName, S_OK); - - if (l > m_dwMaxRef) - m_dwMaxRef = l; - return l; - } - STDMETHOD_(ULONG, Release)(); - - STDMETHOD(f3)(); - STDMETHOD(f4)(); - STDMETHOD(f5)(); - STDMETHOD(f6)(); - STDMETHOD(f7)(); - STDMETHOD(f8)(); - STDMETHOD(f9)(); - STDMETHOD(f10)(); - STDMETHOD(f11)(); - STDMETHOD(f12)(); - STDMETHOD(f13)(); - STDMETHOD(f14)(); - STDMETHOD(f15)(); - STDMETHOD(f16)(); - STDMETHOD(f17)(); - STDMETHOD(f18)(); - STDMETHOD(f19)(); - STDMETHOD(f20)(); - STDMETHOD(f21)(); - STDMETHOD(f22)(); - STDMETHOD(f23)(); - STDMETHOD(f24)(); - STDMETHOD(f25)(); - STDMETHOD(f26)(); - STDMETHOD(f27)(); - STDMETHOD(f28)(); - STDMETHOD(f29)(); - STDMETHOD(f30)(); - STDMETHOD(f31)(); - STDMETHOD(f32)(); - STDMETHOD(f33)(); - STDMETHOD(f34)(); - STDMETHOD(f35)(); - STDMETHOD(f36)(); - STDMETHOD(f37)(); - STDMETHOD(f38)(); - STDMETHOD(f39)(); - STDMETHOD(f40)(); - STDMETHOD(f41)(); - STDMETHOD(f42)(); - STDMETHOD(f43)(); - STDMETHOD(f44)(); - STDMETHOD(f45)(); - STDMETHOD(f46)(); - STDMETHOD(f47)(); - STDMETHOD(f48)(); - STDMETHOD(f49)(); - STDMETHOD(f50)(); - STDMETHOD(f51)(); - STDMETHOD(f52)(); - STDMETHOD(f53)(); - STDMETHOD(f54)(); - STDMETHOD(f55)(); - STDMETHOD(f56)(); - STDMETHOD(f57)(); - STDMETHOD(f58)(); - STDMETHOD(f59)(); - STDMETHOD(f60)(); - STDMETHOD(f61)(); - STDMETHOD(f62)(); - STDMETHOD(f63)(); - STDMETHOD(f64)(); - STDMETHOD(f65)(); - STDMETHOD(f66)(); - STDMETHOD(f67)(); - STDMETHOD(f68)(); - STDMETHOD(f69)(); - STDMETHOD(f70)(); - STDMETHOD(f71)(); - STDMETHOD(f72)(); - STDMETHOD(f73)(); - STDMETHOD(f74)(); - STDMETHOD(f75)(); - STDMETHOD(f76)(); - STDMETHOD(f77)(); - STDMETHOD(f78)(); - STDMETHOD(f79)(); - STDMETHOD(f80)(); - STDMETHOD(f81)(); - STDMETHOD(f82)(); - STDMETHOD(f83)(); - STDMETHOD(f84)(); - STDMETHOD(f85)(); - STDMETHOD(f86)(); - STDMETHOD(f87)(); - STDMETHOD(f88)(); - STDMETHOD(f89)(); - STDMETHOD(f90)(); - STDMETHOD(f91)(); - STDMETHOD(f92)(); - STDMETHOD(f93)(); - STDMETHOD(f94)(); - STDMETHOD(f95)(); - STDMETHOD(f96)(); - STDMETHOD(f97)(); - STDMETHOD(f98)(); - STDMETHOD(f99)(); - STDMETHOD(f100)(); - STDMETHOD(f101)(); - STDMETHOD(f102)(); - STDMETHOD(f103)(); - STDMETHOD(f104)(); - STDMETHOD(f105)(); - STDMETHOD(f106)(); - STDMETHOD(f107)(); - STDMETHOD(f108)(); - STDMETHOD(f109)(); - STDMETHOD(f110)(); - STDMETHOD(f111)(); - STDMETHOD(f112)(); - STDMETHOD(f113)(); - STDMETHOD(f114)(); - STDMETHOD(f115)(); - STDMETHOD(f116)(); - STDMETHOD(f117)(); - STDMETHOD(f118)(); - STDMETHOD(f119)(); - STDMETHOD(f120)(); - STDMETHOD(f121)(); - STDMETHOD(f122)(); - STDMETHOD(f123)(); - STDMETHOD(f124)(); - STDMETHOD(f125)(); - STDMETHOD(f126)(); - STDMETHOD(f127)(); - STDMETHOD(f128)(); - STDMETHOD(f129)(); - STDMETHOD(f130)(); - STDMETHOD(f131)(); - STDMETHOD(f132)(); - STDMETHOD(f133)(); - STDMETHOD(f134)(); - STDMETHOD(f135)(); - STDMETHOD(f136)(); - STDMETHOD(f137)(); - STDMETHOD(f138)(); - STDMETHOD(f139)(); - STDMETHOD(f140)(); - STDMETHOD(f141)(); - STDMETHOD(f142)(); - STDMETHOD(f143)(); - STDMETHOD(f144)(); - STDMETHOD(f145)(); - STDMETHOD(f146)(); - STDMETHOD(f147)(); - STDMETHOD(f148)(); - STDMETHOD(f149)(); - STDMETHOD(f150)(); - STDMETHOD(f151)(); - STDMETHOD(f152)(); - STDMETHOD(f153)(); - STDMETHOD(f154)(); - STDMETHOD(f155)(); - STDMETHOD(f156)(); - STDMETHOD(f157)(); - STDMETHOD(f158)(); - STDMETHOD(f159)(); - STDMETHOD(f160)(); - STDMETHOD(f161)(); - STDMETHOD(f162)(); - STDMETHOD(f163)(); - STDMETHOD(f164)(); - STDMETHOD(f165)(); - STDMETHOD(f166)(); - STDMETHOD(f167)(); - STDMETHOD(f168)(); - STDMETHOD(f169)(); - STDMETHOD(f170)(); - STDMETHOD(f171)(); - STDMETHOD(f172)(); - STDMETHOD(f173)(); - STDMETHOD(f174)(); - STDMETHOD(f175)(); - STDMETHOD(f176)(); - STDMETHOD(f177)(); - STDMETHOD(f178)(); - STDMETHOD(f179)(); - STDMETHOD(f180)(); - STDMETHOD(f181)(); - STDMETHOD(f182)(); - STDMETHOD(f183)(); - STDMETHOD(f184)(); - STDMETHOD(f185)(); - STDMETHOD(f186)(); - STDMETHOD(f187)(); - STDMETHOD(f188)(); - STDMETHOD(f189)(); - STDMETHOD(f190)(); - STDMETHOD(f191)(); - STDMETHOD(f192)(); - STDMETHOD(f193)(); - STDMETHOD(f194)(); - STDMETHOD(f195)(); - STDMETHOD(f196)(); - STDMETHOD(f197)(); - STDMETHOD(f198)(); - STDMETHOD(f199)(); - STDMETHOD(f200)(); - STDMETHOD(f201)(); - STDMETHOD(f202)(); - STDMETHOD(f203)(); - STDMETHOD(f204)(); - STDMETHOD(f205)(); - STDMETHOD(f206)(); - STDMETHOD(f207)(); - STDMETHOD(f208)(); - STDMETHOD(f209)(); - STDMETHOD(f210)(); - STDMETHOD(f211)(); - STDMETHOD(f212)(); - STDMETHOD(f213)(); - STDMETHOD(f214)(); - STDMETHOD(f215)(); - STDMETHOD(f216)(); - STDMETHOD(f217)(); - STDMETHOD(f218)(); - STDMETHOD(f219)(); - STDMETHOD(f220)(); - STDMETHOD(f221)(); - STDMETHOD(f222)(); - STDMETHOD(f223)(); - STDMETHOD(f224)(); - STDMETHOD(f225)(); - STDMETHOD(f226)(); - STDMETHOD(f227)(); - STDMETHOD(f228)(); - STDMETHOD(f229)(); - STDMETHOD(f230)(); - STDMETHOD(f231)(); - STDMETHOD(f232)(); - STDMETHOD(f233)(); - STDMETHOD(f234)(); - STDMETHOD(f235)(); - STDMETHOD(f236)(); - STDMETHOD(f237)(); - STDMETHOD(f238)(); - STDMETHOD(f239)(); - STDMETHOD(f240)(); - STDMETHOD(f241)(); - STDMETHOD(f242)(); - STDMETHOD(f243)(); - STDMETHOD(f244)(); - STDMETHOD(f245)(); - STDMETHOD(f246)(); - STDMETHOD(f247)(); - STDMETHOD(f248)(); - STDMETHOD(f249)(); - STDMETHOD(f250)(); - STDMETHOD(f251)(); - STDMETHOD(f252)(); - STDMETHOD(f253)(); - STDMETHOD(f254)(); - STDMETHOD(f255)(); - STDMETHOD(f256)(); - STDMETHOD(f257)(); - STDMETHOD(f258)(); - STDMETHOD(f259)(); - STDMETHOD(f260)(); - STDMETHOD(f261)(); - STDMETHOD(f262)(); - STDMETHOD(f263)(); - STDMETHOD(f264)(); - STDMETHOD(f265)(); - STDMETHOD(f266)(); - STDMETHOD(f267)(); - STDMETHOD(f268)(); - STDMETHOD(f269)(); - STDMETHOD(f270)(); - STDMETHOD(f271)(); - STDMETHOD(f272)(); - STDMETHOD(f273)(); - STDMETHOD(f274)(); - STDMETHOD(f275)(); - STDMETHOD(f276)(); - STDMETHOD(f277)(); - STDMETHOD(f278)(); - STDMETHOD(f279)(); - STDMETHOD(f280)(); - STDMETHOD(f281)(); - STDMETHOD(f282)(); - STDMETHOD(f283)(); - STDMETHOD(f284)(); - STDMETHOD(f285)(); - STDMETHOD(f286)(); - STDMETHOD(f287)(); - STDMETHOD(f288)(); - STDMETHOD(f289)(); - STDMETHOD(f290)(); - STDMETHOD(f291)(); - STDMETHOD(f292)(); - STDMETHOD(f293)(); - STDMETHOD(f294)(); - STDMETHOD(f295)(); - STDMETHOD(f296)(); - STDMETHOD(f297)(); - STDMETHOD(f298)(); - STDMETHOD(f299)(); - STDMETHOD(f300)(); - STDMETHOD(f301)(); - STDMETHOD(f302)(); - STDMETHOD(f303)(); - STDMETHOD(f304)(); - STDMETHOD(f305)(); - STDMETHOD(f306)(); - STDMETHOD(f307)(); - STDMETHOD(f308)(); - STDMETHOD(f309)(); - STDMETHOD(f310)(); - STDMETHOD(f311)(); - STDMETHOD(f312)(); - STDMETHOD(f313)(); - STDMETHOD(f314)(); - STDMETHOD(f315)(); - STDMETHOD(f316)(); - STDMETHOD(f317)(); - STDMETHOD(f318)(); - STDMETHOD(f319)(); - STDMETHOD(f320)(); - STDMETHOD(f321)(); - STDMETHOD(f322)(); - STDMETHOD(f323)(); - STDMETHOD(f324)(); - STDMETHOD(f325)(); - STDMETHOD(f326)(); - STDMETHOD(f327)(); - STDMETHOD(f328)(); - STDMETHOD(f329)(); - STDMETHOD(f330)(); - STDMETHOD(f331)(); - STDMETHOD(f332)(); - STDMETHOD(f333)(); - STDMETHOD(f334)(); - STDMETHOD(f335)(); - STDMETHOD(f336)(); - STDMETHOD(f337)(); - STDMETHOD(f338)(); - STDMETHOD(f339)(); - STDMETHOD(f340)(); - STDMETHOD(f341)(); - STDMETHOD(f342)(); - STDMETHOD(f343)(); - STDMETHOD(f344)(); - STDMETHOD(f345)(); - STDMETHOD(f346)(); - STDMETHOD(f347)(); - STDMETHOD(f348)(); - STDMETHOD(f349)(); - STDMETHOD(f350)(); - STDMETHOD(f351)(); - STDMETHOD(f352)(); - STDMETHOD(f353)(); - STDMETHOD(f354)(); - STDMETHOD(f355)(); - STDMETHOD(f356)(); - STDMETHOD(f357)(); - STDMETHOD(f358)(); - STDMETHOD(f359)(); - STDMETHOD(f360)(); - STDMETHOD(f361)(); - STDMETHOD(f362)(); - STDMETHOD(f363)(); - STDMETHOD(f364)(); - STDMETHOD(f365)(); - STDMETHOD(f366)(); - STDMETHOD(f367)(); - STDMETHOD(f368)(); - STDMETHOD(f369)(); - STDMETHOD(f370)(); - STDMETHOD(f371)(); - STDMETHOD(f372)(); - STDMETHOD(f373)(); - STDMETHOD(f374)(); - STDMETHOD(f375)(); - STDMETHOD(f376)(); - STDMETHOD(f377)(); - STDMETHOD(f378)(); - STDMETHOD(f379)(); - STDMETHOD(f380)(); - STDMETHOD(f381)(); - STDMETHOD(f382)(); - STDMETHOD(f383)(); - STDMETHOD(f384)(); - STDMETHOD(f385)(); - STDMETHOD(f386)(); - STDMETHOD(f387)(); - STDMETHOD(f388)(); - STDMETHOD(f389)(); - STDMETHOD(f390)(); - STDMETHOD(f391)(); - STDMETHOD(f392)(); - STDMETHOD(f393)(); - STDMETHOD(f394)(); - STDMETHOD(f395)(); - STDMETHOD(f396)(); - STDMETHOD(f397)(); - STDMETHOD(f398)(); - STDMETHOD(f399)(); - STDMETHOD(f400)(); - STDMETHOD(f401)(); - STDMETHOD(f402)(); - STDMETHOD(f403)(); - STDMETHOD(f404)(); - STDMETHOD(f405)(); - STDMETHOD(f406)(); - STDMETHOD(f407)(); - STDMETHOD(f408)(); - STDMETHOD(f409)(); - STDMETHOD(f410)(); - STDMETHOD(f411)(); - STDMETHOD(f412)(); - STDMETHOD(f413)(); - STDMETHOD(f414)(); - STDMETHOD(f415)(); - STDMETHOD(f416)(); - STDMETHOD(f417)(); - STDMETHOD(f418)(); - STDMETHOD(f419)(); - STDMETHOD(f420)(); - STDMETHOD(f421)(); - STDMETHOD(f422)(); - STDMETHOD(f423)(); - STDMETHOD(f424)(); - STDMETHOD(f425)(); - STDMETHOD(f426)(); - STDMETHOD(f427)(); - STDMETHOD(f428)(); - STDMETHOD(f429)(); - STDMETHOD(f430)(); - STDMETHOD(f431)(); - STDMETHOD(f432)(); - STDMETHOD(f433)(); - STDMETHOD(f434)(); - STDMETHOD(f435)(); - STDMETHOD(f436)(); - STDMETHOD(f437)(); - STDMETHOD(f438)(); - STDMETHOD(f439)(); - STDMETHOD(f440)(); - STDMETHOD(f441)(); - STDMETHOD(f442)(); - STDMETHOD(f443)(); - STDMETHOD(f444)(); - STDMETHOD(f445)(); - STDMETHOD(f446)(); - STDMETHOD(f447)(); - STDMETHOD(f448)(); - STDMETHOD(f449)(); - STDMETHOD(f450)(); - STDMETHOD(f451)(); - STDMETHOD(f452)(); - STDMETHOD(f453)(); - STDMETHOD(f454)(); - STDMETHOD(f455)(); - STDMETHOD(f456)(); - STDMETHOD(f457)(); - STDMETHOD(f458)(); - STDMETHOD(f459)(); - STDMETHOD(f460)(); - STDMETHOD(f461)(); - STDMETHOD(f462)(); - STDMETHOD(f463)(); - STDMETHOD(f464)(); - STDMETHOD(f465)(); - STDMETHOD(f466)(); - STDMETHOD(f467)(); - STDMETHOD(f468)(); - STDMETHOD(f469)(); - STDMETHOD(f470)(); - STDMETHOD(f471)(); - STDMETHOD(f472)(); - STDMETHOD(f473)(); - STDMETHOD(f474)(); - STDMETHOD(f475)(); - STDMETHOD(f476)(); - STDMETHOD(f477)(); - STDMETHOD(f478)(); - STDMETHOD(f479)(); - STDMETHOD(f480)(); - STDMETHOD(f481)(); - STDMETHOD(f482)(); - STDMETHOD(f483)(); - STDMETHOD(f484)(); - STDMETHOD(f485)(); - STDMETHOD(f486)(); - STDMETHOD(f487)(); - STDMETHOD(f488)(); - STDMETHOD(f489)(); - STDMETHOD(f490)(); - STDMETHOD(f491)(); - STDMETHOD(f492)(); - STDMETHOD(f493)(); - STDMETHOD(f494)(); - STDMETHOD(f495)(); - STDMETHOD(f496)(); - STDMETHOD(f497)(); - STDMETHOD(f498)(); - STDMETHOD(f499)(); - STDMETHOD(f500)(); - STDMETHOD(f501)(); - STDMETHOD(f502)(); - STDMETHOD(f503)(); - STDMETHOD(f504)(); - STDMETHOD(f505)(); - STDMETHOD(f506)(); - STDMETHOD(f507)(); - STDMETHOD(f508)(); - STDMETHOD(f509)(); - STDMETHOD(f510)(); - STDMETHOD(f511)(); - STDMETHOD(f512)(); - STDMETHOD(f513)(); - STDMETHOD(f514)(); - STDMETHOD(f515)(); - STDMETHOD(f516)(); - STDMETHOD(f517)(); - STDMETHOD(f518)(); - STDMETHOD(f519)(); - STDMETHOD(f520)(); - STDMETHOD(f521)(); - STDMETHOD(f522)(); - STDMETHOD(f523)(); - STDMETHOD(f524)(); - STDMETHOD(f525)(); - STDMETHOD(f526)(); - STDMETHOD(f527)(); - STDMETHOD(f528)(); - STDMETHOD(f529)(); - STDMETHOD(f530)(); - STDMETHOD(f531)(); - STDMETHOD(f532)(); - STDMETHOD(f533)(); - STDMETHOD(f534)(); - STDMETHOD(f535)(); - STDMETHOD(f536)(); - STDMETHOD(f537)(); - STDMETHOD(f538)(); - STDMETHOD(f539)(); - STDMETHOD(f540)(); - STDMETHOD(f541)(); - STDMETHOD(f542)(); - STDMETHOD(f543)(); - STDMETHOD(f544)(); - STDMETHOD(f545)(); - STDMETHOD(f546)(); - STDMETHOD(f547)(); - STDMETHOD(f548)(); - STDMETHOD(f549)(); - STDMETHOD(f550)(); - STDMETHOD(f551)(); - STDMETHOD(f552)(); - STDMETHOD(f553)(); - STDMETHOD(f554)(); - STDMETHOD(f555)(); - STDMETHOD(f556)(); - STDMETHOD(f557)(); - STDMETHOD(f558)(); - STDMETHOD(f559)(); - STDMETHOD(f560)(); - STDMETHOD(f561)(); - STDMETHOD(f562)(); - STDMETHOD(f563)(); - STDMETHOD(f564)(); - STDMETHOD(f565)(); - STDMETHOD(f566)(); - STDMETHOD(f567)(); - STDMETHOD(f568)(); - STDMETHOD(f569)(); - STDMETHOD(f570)(); - STDMETHOD(f571)(); - STDMETHOD(f572)(); - STDMETHOD(f573)(); - STDMETHOD(f574)(); - STDMETHOD(f575)(); - STDMETHOD(f576)(); - STDMETHOD(f577)(); - STDMETHOD(f578)(); - STDMETHOD(f579)(); - STDMETHOD(f580)(); - STDMETHOD(f581)(); - STDMETHOD(f582)(); - STDMETHOD(f583)(); - STDMETHOD(f584)(); - STDMETHOD(f585)(); - STDMETHOD(f586)(); - STDMETHOD(f587)(); - STDMETHOD(f588)(); - STDMETHOD(f589)(); - STDMETHOD(f590)(); - STDMETHOD(f591)(); - STDMETHOD(f592)(); - STDMETHOD(f593)(); - STDMETHOD(f594)(); - STDMETHOD(f595)(); - STDMETHOD(f596)(); - STDMETHOD(f597)(); - STDMETHOD(f598)(); - STDMETHOD(f599)(); - STDMETHOD(f600)(); - STDMETHOD(f601)(); - STDMETHOD(f602)(); - STDMETHOD(f603)(); - STDMETHOD(f604)(); - STDMETHOD(f605)(); - STDMETHOD(f606)(); - STDMETHOD(f607)(); - STDMETHOD(f608)(); - STDMETHOD(f609)(); - STDMETHOD(f610)(); - STDMETHOD(f611)(); - STDMETHOD(f612)(); - STDMETHOD(f613)(); - STDMETHOD(f614)(); - STDMETHOD(f615)(); - STDMETHOD(f616)(); - STDMETHOD(f617)(); - STDMETHOD(f618)(); - STDMETHOD(f619)(); - STDMETHOD(f620)(); - STDMETHOD(f621)(); - STDMETHOD(f622)(); - STDMETHOD(f623)(); - STDMETHOD(f624)(); - STDMETHOD(f625)(); - STDMETHOD(f626)(); - STDMETHOD(f627)(); - STDMETHOD(f628)(); - STDMETHOD(f629)(); - STDMETHOD(f630)(); - STDMETHOD(f631)(); - STDMETHOD(f632)(); - STDMETHOD(f633)(); - STDMETHOD(f634)(); - STDMETHOD(f635)(); - STDMETHOD(f636)(); - STDMETHOD(f637)(); - STDMETHOD(f638)(); - STDMETHOD(f639)(); - STDMETHOD(f640)(); - STDMETHOD(f641)(); - STDMETHOD(f642)(); - STDMETHOD(f643)(); - STDMETHOD(f644)(); - STDMETHOD(f645)(); - STDMETHOD(f646)(); - STDMETHOD(f647)(); - STDMETHOD(f648)(); - STDMETHOD(f649)(); - STDMETHOD(f650)(); - STDMETHOD(f651)(); - STDMETHOD(f652)(); - STDMETHOD(f653)(); - STDMETHOD(f654)(); - STDMETHOD(f655)(); - STDMETHOD(f656)(); - STDMETHOD(f657)(); - STDMETHOD(f658)(); - STDMETHOD(f659)(); - STDMETHOD(f660)(); - STDMETHOD(f661)(); - STDMETHOD(f662)(); - STDMETHOD(f663)(); - STDMETHOD(f664)(); - STDMETHOD(f665)(); - STDMETHOD(f666)(); - STDMETHOD(f667)(); - STDMETHOD(f668)(); - STDMETHOD(f669)(); - STDMETHOD(f670)(); - STDMETHOD(f671)(); - STDMETHOD(f672)(); - STDMETHOD(f673)(); - STDMETHOD(f674)(); - STDMETHOD(f675)(); - STDMETHOD(f676)(); - STDMETHOD(f677)(); - STDMETHOD(f678)(); - STDMETHOD(f679)(); - STDMETHOD(f680)(); - STDMETHOD(f681)(); - STDMETHOD(f682)(); - STDMETHOD(f683)(); - STDMETHOD(f684)(); - STDMETHOD(f685)(); - STDMETHOD(f686)(); - STDMETHOD(f687)(); - STDMETHOD(f688)(); - STDMETHOD(f689)(); - STDMETHOD(f690)(); - STDMETHOD(f691)(); - STDMETHOD(f692)(); - STDMETHOD(f693)(); - STDMETHOD(f694)(); - STDMETHOD(f695)(); - STDMETHOD(f696)(); - STDMETHOD(f697)(); - STDMETHOD(f698)(); - STDMETHOD(f699)(); - STDMETHOD(f700)(); - STDMETHOD(f701)(); - STDMETHOD(f702)(); - STDMETHOD(f703)(); - STDMETHOD(f704)(); - STDMETHOD(f705)(); - STDMETHOD(f706)(); - STDMETHOD(f707)(); - STDMETHOD(f708)(); - STDMETHOD(f709)(); - STDMETHOD(f710)(); - STDMETHOD(f711)(); - STDMETHOD(f712)(); - STDMETHOD(f713)(); - STDMETHOD(f714)(); - STDMETHOD(f715)(); - STDMETHOD(f716)(); - STDMETHOD(f717)(); - STDMETHOD(f718)(); - STDMETHOD(f719)(); - STDMETHOD(f720)(); - STDMETHOD(f721)(); - STDMETHOD(f722)(); - STDMETHOD(f723)(); - STDMETHOD(f724)(); - STDMETHOD(f725)(); - STDMETHOD(f726)(); - STDMETHOD(f727)(); - STDMETHOD(f728)(); - STDMETHOD(f729)(); - STDMETHOD(f730)(); - STDMETHOD(f731)(); - STDMETHOD(f732)(); - STDMETHOD(f733)(); - STDMETHOD(f734)(); - STDMETHOD(f735)(); - STDMETHOD(f736)(); - STDMETHOD(f737)(); - STDMETHOD(f738)(); - STDMETHOD(f739)(); - STDMETHOD(f740)(); - STDMETHOD(f741)(); - STDMETHOD(f742)(); - STDMETHOD(f743)(); - STDMETHOD(f744)(); - STDMETHOD(f745)(); - STDMETHOD(f746)(); - STDMETHOD(f747)(); - STDMETHOD(f748)(); - STDMETHOD(f749)(); - STDMETHOD(f750)(); - STDMETHOD(f751)(); - STDMETHOD(f752)(); - STDMETHOD(f753)(); - STDMETHOD(f754)(); - STDMETHOD(f755)(); - STDMETHOD(f756)(); - STDMETHOD(f757)(); - STDMETHOD(f758)(); - STDMETHOD(f759)(); - STDMETHOD(f760)(); - STDMETHOD(f761)(); - STDMETHOD(f762)(); - STDMETHOD(f763)(); - STDMETHOD(f764)(); - STDMETHOD(f765)(); - STDMETHOD(f766)(); - STDMETHOD(f767)(); - STDMETHOD(f768)(); - STDMETHOD(f769)(); - STDMETHOD(f770)(); - STDMETHOD(f771)(); - STDMETHOD(f772)(); - STDMETHOD(f773)(); - STDMETHOD(f774)(); - STDMETHOD(f775)(); - STDMETHOD(f776)(); - STDMETHOD(f777)(); - STDMETHOD(f778)(); - STDMETHOD(f779)(); - STDMETHOD(f780)(); - STDMETHOD(f781)(); - STDMETHOD(f782)(); - STDMETHOD(f783)(); - STDMETHOD(f784)(); - STDMETHOD(f785)(); - STDMETHOD(f786)(); - STDMETHOD(f787)(); - STDMETHOD(f788)(); - STDMETHOD(f789)(); - STDMETHOD(f790)(); - STDMETHOD(f791)(); - STDMETHOD(f792)(); - STDMETHOD(f793)(); - STDMETHOD(f794)(); - STDMETHOD(f795)(); - STDMETHOD(f796)(); - STDMETHOD(f797)(); - STDMETHOD(f798)(); - STDMETHOD(f799)(); - STDMETHOD(f800)(); - STDMETHOD(f801)(); - STDMETHOD(f802)(); - STDMETHOD(f803)(); - STDMETHOD(f804)(); - STDMETHOD(f805)(); - STDMETHOD(f806)(); - STDMETHOD(f807)(); - STDMETHOD(f808)(); - STDMETHOD(f809)(); - STDMETHOD(f810)(); - STDMETHOD(f811)(); - STDMETHOD(f812)(); - STDMETHOD(f813)(); - STDMETHOD(f814)(); - STDMETHOD(f815)(); - STDMETHOD(f816)(); - STDMETHOD(f817)(); - STDMETHOD(f818)(); - STDMETHOD(f819)(); - STDMETHOD(f820)(); - STDMETHOD(f821)(); - STDMETHOD(f822)(); - STDMETHOD(f823)(); - STDMETHOD(f824)(); - STDMETHOD(f825)(); - STDMETHOD(f826)(); - STDMETHOD(f827)(); - STDMETHOD(f828)(); - STDMETHOD(f829)(); - STDMETHOD(f830)(); - STDMETHOD(f831)(); - STDMETHOD(f832)(); - STDMETHOD(f833)(); - STDMETHOD(f834)(); - STDMETHOD(f835)(); - STDMETHOD(f836)(); - STDMETHOD(f837)(); - STDMETHOD(f838)(); - STDMETHOD(f839)(); - STDMETHOD(f840)(); - STDMETHOD(f841)(); - STDMETHOD(f842)(); - STDMETHOD(f843)(); - STDMETHOD(f844)(); - STDMETHOD(f845)(); - STDMETHOD(f846)(); - STDMETHOD(f847)(); - STDMETHOD(f848)(); - STDMETHOD(f849)(); - STDMETHOD(f850)(); - STDMETHOD(f851)(); - STDMETHOD(f852)(); - STDMETHOD(f853)(); - STDMETHOD(f854)(); - STDMETHOD(f855)(); - STDMETHOD(f856)(); - STDMETHOD(f857)(); - STDMETHOD(f858)(); - STDMETHOD(f859)(); - STDMETHOD(f860)(); - STDMETHOD(f861)(); - STDMETHOD(f862)(); - STDMETHOD(f863)(); - STDMETHOD(f864)(); - STDMETHOD(f865)(); - STDMETHOD(f866)(); - STDMETHOD(f867)(); - STDMETHOD(f868)(); - STDMETHOD(f869)(); - STDMETHOD(f870)(); - STDMETHOD(f871)(); - STDMETHOD(f872)(); - STDMETHOD(f873)(); - STDMETHOD(f874)(); - STDMETHOD(f875)(); - STDMETHOD(f876)(); - STDMETHOD(f877)(); - STDMETHOD(f878)(); - STDMETHOD(f879)(); - STDMETHOD(f880)(); - STDMETHOD(f881)(); - STDMETHOD(f882)(); - STDMETHOD(f883)(); - STDMETHOD(f884)(); - STDMETHOD(f885)(); - STDMETHOD(f886)(); - STDMETHOD(f887)(); - STDMETHOD(f888)(); - STDMETHOD(f889)(); - STDMETHOD(f890)(); - STDMETHOD(f891)(); - STDMETHOD(f892)(); - STDMETHOD(f893)(); - STDMETHOD(f894)(); - STDMETHOD(f895)(); - STDMETHOD(f896)(); - STDMETHOD(f897)(); - STDMETHOD(f898)(); - STDMETHOD(f899)(); - STDMETHOD(f900)(); - STDMETHOD(f901)(); - STDMETHOD(f902)(); - STDMETHOD(f903)(); - STDMETHOD(f904)(); - STDMETHOD(f905)(); - STDMETHOD(f906)(); - STDMETHOD(f907)(); - STDMETHOD(f908)(); - STDMETHOD(f909)(); - STDMETHOD(f910)(); - STDMETHOD(f911)(); - STDMETHOD(f912)(); - STDMETHOD(f913)(); - STDMETHOD(f914)(); - STDMETHOD(f915)(); - STDMETHOD(f916)(); - STDMETHOD(f917)(); - STDMETHOD(f918)(); - STDMETHOD(f919)(); - STDMETHOD(f920)(); - STDMETHOD(f921)(); - STDMETHOD(f922)(); - STDMETHOD(f923)(); - STDMETHOD(f924)(); - STDMETHOD(f925)(); - STDMETHOD(f926)(); - STDMETHOD(f927)(); - STDMETHOD(f928)(); - STDMETHOD(f929)(); - STDMETHOD(f930)(); - STDMETHOD(f931)(); - STDMETHOD(f932)(); - STDMETHOD(f933)(); - STDMETHOD(f934)(); - STDMETHOD(f935)(); - STDMETHOD(f936)(); - STDMETHOD(f937)(); - STDMETHOD(f938)(); - STDMETHOD(f939)(); - STDMETHOD(f940)(); - STDMETHOD(f941)(); - STDMETHOD(f942)(); - STDMETHOD(f943)(); - STDMETHOD(f944)(); - STDMETHOD(f945)(); - STDMETHOD(f946)(); - STDMETHOD(f947)(); - STDMETHOD(f948)(); - STDMETHOD(f949)(); - STDMETHOD(f950)(); - STDMETHOD(f951)(); - STDMETHOD(f952)(); - STDMETHOD(f953)(); - STDMETHOD(f954)(); - STDMETHOD(f955)(); - STDMETHOD(f956)(); - STDMETHOD(f957)(); - STDMETHOD(f958)(); - STDMETHOD(f959)(); - STDMETHOD(f960)(); - STDMETHOD(f961)(); - STDMETHOD(f962)(); - STDMETHOD(f963)(); - STDMETHOD(f964)(); - STDMETHOD(f965)(); - STDMETHOD(f966)(); - STDMETHOD(f967)(); - STDMETHOD(f968)(); - STDMETHOD(f969)(); - STDMETHOD(f970)(); - STDMETHOD(f971)(); - STDMETHOD(f972)(); - STDMETHOD(f973)(); - STDMETHOD(f974)(); - STDMETHOD(f975)(); - STDMETHOD(f976)(); - STDMETHOD(f977)(); - STDMETHOD(f978)(); - STDMETHOD(f979)(); - STDMETHOD(f980)(); - STDMETHOD(f981)(); - STDMETHOD(f982)(); - STDMETHOD(f983)(); - STDMETHOD(f984)(); - STDMETHOD(f985)(); - STDMETHOD(f986)(); - STDMETHOD(f987)(); - STDMETHOD(f988)(); - STDMETHOD(f989)(); - STDMETHOD(f990)(); - STDMETHOD(f991)(); - STDMETHOD(f992)(); - STDMETHOD(f993)(); - STDMETHOD(f994)(); - STDMETHOD(f995)(); - STDMETHOD(f996)(); - STDMETHOD(f997)(); - STDMETHOD(f998)(); - STDMETHOD(f999)(); - STDMETHOD(f1000)(); - STDMETHOD(f1001)(); - STDMETHOD(f1002)(); - STDMETHOD(f1003)(); - STDMETHOD(f1004)(); - STDMETHOD(f1005)(); - STDMETHOD(f1006)(); - STDMETHOD(f1007)(); - STDMETHOD(f1008)(); - STDMETHOD(f1009)(); - STDMETHOD(f1010)(); - STDMETHOD(f1011)(); - STDMETHOD(f1012)(); - STDMETHOD(f1013)(); - STDMETHOD(f1014)(); - STDMETHOD(f1015)(); - STDMETHOD(f1016)(); - STDMETHOD(f1017)(); - STDMETHOD(f1018)(); - STDMETHOD(f1019)(); - STDMETHOD(f1020)(); - STDMETHOD(f1021)(); - STDMETHOD(f1022)(); - STDMETHOD(f1023)(); - _QIThunk(IUnknown* pOrig, LPCTSTR p, const IID& i, UINT n, bool b) - { - m_lpszClassName = p; - m_iid = i; - m_nIndex = n; - m_dwRef = 0; - m_dwMaxRef = 0; - ATLENSURE(pOrig); - m_pUnk = pOrig; - m_bBreak = b; - m_bNonAddRefThunk = false; - } - IUnknown* m_pUnk; - long m_dwRef; - long m_dwMaxRef; - LPCTSTR m_lpszClassName; - IID m_iid; - UINT m_nIndex; - bool m_bBreak; - bool m_bNonAddRefThunk; - void Dump() throw(); -}; - -#endif - -///////////////////////////////////////////////////////////////////////////// -// Module Classes - - -#ifdef _ATL_STATIC_REGISTRY -#define UpdateRegistryFromResource UpdateRegistryFromResourceS -#else -#define UpdateRegistryFromResource UpdateRegistryFromResourceD -#endif // _ATL_STATIC_REGISTRY - - -class CAtlComModule : public _ATL_COM_MODULE -{ -public: - - CAtlComModule() throw() - { - cbSize = 0; - - m_hInstTypeLib = reinterpret_cast(&__ImageBase); - - m_ppAutoObjMapFirst = &__pobjMapEntryFirst + 1; - m_ppAutoObjMapLast = &__pobjMapEntryLast; - - if (FAILED(m_csObjMap.Init())) - { - ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to initialize critical section in CAtlComModule\n")); - ATLASSERT(0); - CAtlBaseModule::m_bInitFailed = true; - return; - } - // Set cbSize on success. - cbSize = sizeof(_ATL_COM_MODULE); - } - - ~CAtlComModule() - { - Term(); - } - - // Called from ~CAtlComModule or from ~CAtlExeModule. - void Term() - { - if (cbSize == 0) - return; - - for (_ATL_OBJMAP_ENTRY** ppEntry = m_ppAutoObjMapFirst; ppEntry < m_ppAutoObjMapLast; ppEntry++) - { - if (*ppEntry != NULL) - { - _ATL_OBJMAP_ENTRY* pEntry = *ppEntry; - if (pEntry->pCF != NULL) - pEntry->pCF->Release(); - pEntry->pCF = NULL; - } - } - m_csObjMap.Term(); - // Set to 0 to indicate that this function has been called - // At this point no one should be concerned about cbsize - // having the correct value - cbSize = 0; - } - - // Registry support (helpers) - HRESULT RegisterTypeLib() - { - return AtlRegisterTypeLib(m_hInstTypeLib, NULL); - } - HRESULT RegisterTypeLib(LPCTSTR lpszIndex) - { - USES_CONVERSION_EX; - LPCOLESTR pwszTemp = NULL; - if( lpszIndex != NULL ) - { - pwszTemp = T2COLE_EX(lpszIndex, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if( pwszTemp == NULL ) - return E_OUTOFMEMORY; -#endif - } - return AtlRegisterTypeLib(m_hInstTypeLib, pwszTemp); - } - HRESULT UnRegisterTypeLib() - { - return AtlUnRegisterTypeLib(m_hInstTypeLib, NULL); - } - HRESULT UnRegisterTypeLib(LPCTSTR lpszIndex) - { - USES_CONVERSION_EX; - LPCOLESTR pwszTemp = NULL; - if( lpszIndex != NULL ) - { - pwszTemp = T2COLE_EX(lpszIndex, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if( pwszTemp == NULL ) - return E_OUTOFMEMORY; -#endif - } - return AtlUnRegisterTypeLib(m_hInstTypeLib, pwszTemp); - } - - // RegisterServer walks the ATL Autogenerated object map and registers each object in the map - // If pCLSID is not NULL then only the object referred to by pCLSID is registered (The default case) - // otherwise all the objects are registered - HRESULT RegisterServer(BOOL bRegTypeLib = FALSE, const CLSID* pCLSID = NULL) - { - return AtlComModuleRegisterServer(this, bRegTypeLib, pCLSID); - } - - // UnregisterServer walks the ATL Autogenerated object map and unregisters each object in the map - // If pCLSID is not NULL then only the object referred to by pCLSID is unregistered (The default case) - // otherwise all the objects are unregistered. - HRESULT UnregisterServer(BOOL bRegTypeLib = FALSE, const CLSID* pCLSID = NULL) - { - return AtlComModuleUnregisterServer(this, bRegTypeLib, pCLSID); - } - - // Implementation - - // Call ObjectMain for all the objects. - void ExecuteObjectMain(bool bStarting) - { - for (_ATL_OBJMAP_ENTRY** ppEntry = m_ppAutoObjMapFirst; ppEntry < m_ppAutoObjMapLast; ppEntry++) - { - if (*ppEntry != NULL) - (*ppEntry)->pfnObjectMain(bStarting); - } - } -}; - -extern CAtlComModule _AtlComModule; - -#ifdef _ATL_DEBUG_INTERFACES - -class CAtlDebugInterfacesModule -{ -public: - CAtlDebugInterfacesModule() throw() : - m_nIndexQI( 0 ), - m_nIndexBreakAt( 0 ) - { - if (FAILED(m_cs.Init())) - { - ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to initialize critical section in CAtlDebugInterfacesModule\n")); - ATLASSERT(0); - CAtlBaseModule::m_bInitFailed = true; - } - } - ~CAtlDebugInterfacesModule() throw() - { - // Release all class factories. - _AtlComModule.Term(); - DumpLeakedThunks(); - } - - HRESULT AddThunk(IUnknown** pp, LPCTSTR lpsz, REFIID iid) throw() - { - if ((pp == NULL) || (*pp == NULL)) - return E_POINTER; - IUnknown* p = *pp; - _QIThunk* pThunk = NULL; - CComCritSecLock lock(m_cs, false); - HRESULT hr = lock.Lock(); - if (FAILED(hr)) - { - ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to lock critical section in CAtlDebugInterfacesModule\n")); - ATLASSERT(0); - return hr; - } - - // Check if exists for identity - if (InlineIsEqualUnknown(iid)) - { - for (int i = 0; i < m_aThunks.GetSize(); i++) - { - if (m_aThunks[i]->m_pUnk == p && InlineIsEqualGUID(m_aThunks[i]->m_iid, iid)) - { - m_aThunks[i]->InternalAddRef(); - pThunk = m_aThunks[i]; - break; - } - } - } - if (pThunk == NULL) - { - ++m_nIndexQI; - if (m_nIndexBreakAt == m_nIndexQI) - DebugBreak(); - ATLTRY(pThunk = new _QIThunk(p, lpsz, iid, m_nIndexQI, (m_nIndexBreakAt == m_nIndexQI))); - if (pThunk == NULL) - { - return E_OUTOFMEMORY; - } - pThunk->InternalAddRef(); - m_aThunks.Add(pThunk); - } - *pp = (IUnknown*)pThunk; - return S_OK; - } - HRESULT AddNonAddRefThunk(IUnknown* p, LPCTSTR lpsz, IUnknown** ppThunkRet) throw() - { - if (ppThunkRet == NULL) - return E_POINTER; - *ppThunkRet = NULL; - - _QIThunk* pThunk = NULL; - CComCritSecLock lock(m_cs, false); - HRESULT hr = lock.Lock(); - if (FAILED(hr)) - { - ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to lock critical section in CAtlDebugInterfacesModule\n")); - ATLASSERT(0); - return hr; - } - - // Check if exists already for identity - for (int i = 0; i < m_aThunks.GetSize(); i++) - { - if (m_aThunks[i]->m_pUnk == p) - { - m_aThunks[i]->m_bNonAddRefThunk = true; - pThunk = m_aThunks[i]; - break; - } - } - if (pThunk == NULL) - { - ++m_nIndexQI; - if (m_nIndexBreakAt == m_nIndexQI) - DebugBreak(); - ATLTRY(pThunk = new _QIThunk(p, lpsz, __uuidof(IUnknown), m_nIndexQI, (m_nIndexBreakAt == m_nIndexQI))); - if (pThunk == NULL) - { - return E_OUTOFMEMORY; - } - pThunk->m_bNonAddRefThunk = true; - m_aThunks.Add(pThunk); - } - *ppThunkRet = (IUnknown*)pThunk; - return S_OK;; - } - void DeleteNonAddRefThunk(IUnknown* pUnk) throw() - { - CComCritSecLock lock(m_cs, false); - HRESULT hr = lock.Lock(); - if (FAILED(hr)) - { - ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to lock critical section in CAtlDebugInterfacesModule\n")); - ATLASSERT(0); - return; - } - - for (int i = 0; i < m_aThunks.GetSize(); i++) - { - if (m_aThunks[i]->m_bNonAddRefThunk && m_aThunks[i]->m_pUnk == pUnk) - { - delete m_aThunks[i]; - m_aThunks.RemoveAt(i); - break; - } - } - } - void DeleteThunk(_QIThunk* p) throw() - { - CComCritSecLock lock(m_cs, false); - HRESULT hr = lock.Lock(); - if (FAILED(hr)) - { - ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to lock critical section in CAtlDebugInterfacesModule\n")); - ATLASSERT(0); - return; - } - - int nIndex = m_aThunks.Find(p); - if (nIndex != -1) - { - m_aThunks[nIndex]->m_pUnk = NULL; - delete m_aThunks[nIndex]; - m_aThunks.RemoveAt(nIndex); - } - } - bool DumpLeakedThunks() - { - bool b = false; - for (int i = 0; i < m_aThunks.GetSize(); i++) - { - b = true; - m_aThunks[i]->Dump(); - delete m_aThunks[i]; - } - m_aThunks.RemoveAll(); - return b; - } - -public: - UINT m_nIndexQI; - UINT m_nIndexBreakAt; - CSimpleArray<_QIThunk*> m_aThunks; - CComAutoDeleteCriticalSection m_cs; -}; - -extern CAtlDebugInterfacesModule _AtlDebugInterfacesModule; - -#ifndef _ATL_STATIC_LIB_IMPL -// Should not be pulled into the static lib -__declspec (selectany) CAtlDebugInterfacesModule _AtlDebugInterfacesModule; -#endif - -inline ULONG _QIThunk::Release() -{ - ATLASSUME(m_pUnk != NULL); - if (m_bBreak) - DebugBreak(); - ATLASSUME(m_dwRef > 0); - - // save copies of member variables we wish to use after the InterlockedDecrement - UINT nIndex = m_nIndex; - IUnknown* pUnk = m_pUnk; - IID iid = m_iid; - LPCTSTR lpszClassName = m_lpszClassName; - bool bNonAddRefThunk = m_bNonAddRefThunk; - - ULONG l = InterlockedDecrement(&m_dwRef); - - TCHAR buf[512+1]; -#if _SECURE_ATL && !defined(_ATL_MIN_CRT) - _stprintf_s(buf, _countof(buf), _T("QIThunk - %-10d\tRelease :\tObject = 0x%p\tRefcount = %d\t"), nIndex, pUnk, l); -#else - wsprintf(buf, _T("QIThunk - %-10d\tRelease :\tObject = 0x%p\tRefcount = %d\t"), nIndex, pUnk, l); -#endif - buf[_countof(buf)-1] = 0; - OutputDebugString(buf); - AtlDumpIID(iid, lpszClassName, S_OK); - - bool bDeleteThunk = (l == 0 && !bNonAddRefThunk); - pUnk->Release(); - if (bDeleteThunk) - _AtlDebugInterfacesModule.DeleteThunk(this); - return l; -} - -#endif // _ATL_DEBUG_INTERFACES - - -class CAtlWinModule : public _ATL_WIN_MODULE -{ -public: - CAtlWinModule() - { - cbSize = sizeof(_ATL_WIN_MODULE); - HRESULT hr = AtlWinModuleInit(this); - if (FAILED(hr)) - { - ATLASSERT(0); - CAtlBaseModule::m_bInitFailed = true; - cbSize = 0; - return; - } - } - - ~CAtlWinModule() - { - Term(); - } - - void Term() - { - AtlWinModuleTerm(this, _AtlBaseModule.GetModuleInstance()); - } - - void AddCreateWndData(_AtlCreateWndData* pData, void* pObject) - { - AtlWinModuleAddCreateWndData(this, pData, pObject); - } - - void* ExtractCreateWndData() - { - return AtlWinModuleExtractCreateWndData(this); - } -}; - -extern CAtlWinModule _AtlWinModule; - -class CAtlModule; -__declspec(selectany) CAtlModule* _pAtlModule = NULL; - -#if defined(_M_CEE) && !defined(_ATL_MIXED) - -// This small class takes care of releasing the class factories at managed -// shutdown when we are compiling /clr. We can't wait to call _AtlComModule.Term() -// in _AtlComModule destructor, since _AtlComModule is a native global object, and it -// will be destructed after the managed runtime has been shutdown. - -// Notice that if the user defines _ATL_MIXED, he/she will need to take care -// of releasing the eventual managed class factories at the right time. - -class CAtlReleaseManagedClassFactories -{ -public: - CAtlReleaseManagedClassFactories() { } - ~CAtlReleaseManagedClassFactories() - { - _AtlComModule.Term(); - } -}; - -__declspec (selectany) CAtlReleaseManagedClassFactories _AtlReleaseManagedClassFactories; - -extern "C" -{ -__declspec (selectany) void *_pAtlReleaseManagedClassFactories = &_AtlReleaseManagedClassFactories; -} -#if defined(_M_IX86) - #pragma comment(linker, "/include:__pAtlReleaseManagedClassFactories") -#else - #pragma comment(linker, "/include:_pAtlReleaseManagedClassFactories") -#endif - -#endif - -class ATL_NO_VTABLE CAtlModule : public _ATL_MODULE -{ -public : - static GUID m_libid; - IGlobalInterfaceTable* m_pGIT; - - CAtlModule() throw() - { - // Should have only one instance of a class - // derived from CAtlModule in a project. - ATLASSERT(_pAtlModule == NULL); - cbSize = 0; - m_pTermFuncs = NULL; - - m_nLockCnt = 0; - _pAtlModule = this; - m_pGIT = NULL; - - if (FAILED(m_csStaticDataInitAndTypeInfo.Init())) - { - ATLTRACE(atlTraceGeneral, 0, _T("ERROR : Unable to initialize critical section in CAtlModule\n")); - ATLASSERT(0); - CAtlBaseModule::m_bInitFailed = true; - return; - } - - // Set cbSize on success. - cbSize = sizeof(_ATL_MODULE); - } - - void Term() throw() - { - // cbSize == 0 indicates that Term has already been called - if (cbSize == 0) - return; - - // Call term functions - if (m_pTermFuncs != NULL) - { - AtlCallTermFunc(this); - m_pTermFuncs = NULL; - } - - if (m_pGIT != NULL) - m_pGIT->Release(); - - m_csStaticDataInitAndTypeInfo.Term(); - - cbSize = 0; - } - - virtual ~CAtlModule() throw() - { - Term(); - } - - virtual LONG Lock() throw() - { - return CComGlobalsThreadModel::Increment(&m_nLockCnt); - } - - virtual LONG Unlock() throw() - { - return CComGlobalsThreadModel::Decrement(&m_nLockCnt); - } - - virtual LONG GetLockCount() throw() - { - return m_nLockCnt; - } - - HRESULT AddTermFunc(_ATL_TERMFUNC* pFunc, DWORD_PTR dw) throw() - { - return AtlModuleAddTermFunc(this, pFunc, dw); - } - - virtual HRESULT GetGITPtr(IGlobalInterfaceTable** ppGIT) throw() - { - ATLASSERT(ppGIT != NULL); - - if (ppGIT == NULL) - return E_POINTER; - - HRESULT hr = S_OK; - if (m_pGIT == NULL) - { - hr = ::CoCreateInstance(CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, - __uuidof(IGlobalInterfaceTable), (void**)&m_pGIT); - } - - if (SUCCEEDED(hr)) - { - ATLASSUME(m_pGIT != NULL); - *ppGIT = m_pGIT; - m_pGIT->AddRef(); - } - return hr; - } - - virtual HRESULT AddCommonRGSReplacements(IRegistrarBase* /*pRegistrar*/) throw() = 0; - - // Resource-based Registration -#ifdef _ATL_STATIC_REGISTRY - // Statically linking to Registry Ponent - HRESULT WINAPI UpdateRegistryFromResourceS(LPCTSTR lpszRes, BOOL bRegister, - struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw(); - HRESULT WINAPI UpdateRegistryFromResourceS(UINT nResID, BOOL bRegister, - struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw(); -#else - HRESULT WINAPI UpdateRegistryFromResourceD(LPCTSTR lpszRes, BOOL bRegister, - struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw() - { - if(lpszRes == NULL) - return E_INVALIDARG; - - USES_CONVERSION_EX; - LPCOLESTR pwszTemp = T2COLE_EX(lpszRes, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifdef _UNICODE - if(pwszTemp == NULL) - return E_OUTOFMEMORY; -#endif - return UpdateRegistryFromResourceDHelper(pwszTemp, bRegister, pMapEntries); - } - HRESULT WINAPI UpdateRegistryFromResourceD(UINT nResID, BOOL bRegister, - struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw() - { - return UpdateRegistryFromResourceDHelper((LPCOLESTR)MAKEINTRESOURCE(nResID), bRegister, pMapEntries); - } -#endif - - // Implementation -#if !defined(_ATL_STATIC_REGISTRY) - inline HRESULT WINAPI UpdateRegistryFromResourceDHelper(LPCOLESTR lpszRes, BOOL bRegister, - struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw() - { - CComPtr spRegistrar; - HRESULT hr = AtlCreateRegistrar(&spRegistrar); - if (FAILED(hr)) - return hr; - - if (NULL != pMapEntries) - { - while (NULL != pMapEntries->szKey) - { - ATLASSERT(NULL != pMapEntries->szData); - spRegistrar->AddReplacement(pMapEntries->szKey, pMapEntries->szData); - pMapEntries++; - } - } - - hr = AddCommonRGSReplacements(spRegistrar); - if (FAILED(hr)) - return hr; - - return AtlUpdateRegistryFromResourceD(_AtlBaseModule.GetModuleInstance(), lpszRes, bRegister, - NULL, spRegistrar); - } -#endif - - static void EscapeSingleQuote(__out_ecount_z(destSizeInChars) LPOLESTR lpDest,__in size_t destSizeInChars, __in_z LPCOLESTR lp) throw() - { - if (destSizeInChars == 0) - { - return; - } - UINT i = 0; - // copy charecters to the destination buffer but leave the last char to be NULL. - for (i=0; i < destSizeInChars-1 && *lp; i++) - { - *lpDest++ = *lp; - // make sure we won't promote lpDest behind the buffer limit. - if (*lp == '\'' && ++i < destSizeInChars-1) - *lpDest++ = *lp; - lp++; - } - *lpDest = NULL; - } - - ATL_DEPRECATED("CAtlModule::EscapeSingleQuote(dest, src) is unsafe. Instead, use CAtlModule::EscapeSingleQuote(dest, size, src)") - static void EscapeSingleQuote(LPOLESTR lpDest, LPCOLESTR lp) throw() - { - EscapeSingleQuote(lpDest, SIZE_MAX/sizeof(OLECHAR), lp); - } - - // search for an occurence of string p2 in string p1 - static LPCTSTR FindOneOf(LPCTSTR p1, LPCTSTR p2) throw() - { - while (p1 != NULL && *p1 != NULL) - { - LPCTSTR p = p2; - while (p != NULL && *p != NULL) - { - if (*p1 == *p) - return CharNext(p1); - p = CharNext(p); - } - p1 = CharNext(p1); - } - return NULL; - } -#pragma warning(push) -#pragma warning(disable : 4302) // 'type cast' : truncation from 'LPSTR' to 'TCHAR' - - static int WordCmpI(LPCTSTR psz1, LPCTSTR psz2) throw() - { - TCHAR c1 = (TCHAR)CharUpper((LPTSTR)*psz1); - TCHAR c2 = (TCHAR)CharUpper((LPTSTR)*psz2); - while (c1 != NULL && c1 == c2 && c1 != ' ' && c1 != '\t') - { - psz1 = CharNext(psz1); - psz2 = CharNext(psz2); - c1 = (TCHAR)CharUpper((LPTSTR)*psz1); - c2 = (TCHAR)CharUpper((LPTSTR)*psz2); - } - if ((c1 == NULL || c1 == ' ' || c1 == '\t') && (c2 == NULL || c2 == ' ' || c2 == '\t')) - return 0; - - return (c1 < c2) ? -1 : 1; - } - -#pragma warning (pop) -}; - -__declspec(selectany) GUID CAtlModule::m_libid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} }; - -#define DECLARE_LIBID(libid) \ - static void InitLibId() throw() \ - { \ - ATL::CAtlModule::m_libid = libid; \ - } - -#define DECLARE_REGISTRY_APPID_RESOURCEID(resid, appid) \ - static LPCOLESTR GetAppId() throw() \ - { \ - return OLESTR(appid); \ - } \ - static TCHAR* GetAppIdT() throw() \ - { \ - return _T(appid); \ - } \ - static HRESULT WINAPI UpdateRegistryAppId(BOOL bRegister) throw() \ - { \ - ATL::_ATL_REGMAP_ENTRY aMapEntries [] = \ - { \ - { OLESTR("APPID"), GetAppId() }, \ - { NULL, NULL } \ - }; \ - return ATL::_pAtlModule->UpdateRegistryFromResource(resid, bRegister, aMapEntries); \ - } - -inline HRESULT AtlGetGITPtr(IGlobalInterfaceTable** ppGIT) throw() -{ - if (ppGIT == NULL) - return E_POINTER; - - if (_pAtlModule == NULL) - { - return CoCreateInstance(CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, - __uuidof(IGlobalInterfaceTable), (void**)ppGIT); - } - else - { - return _pAtlModule->GetGITPtr(ppGIT); - } -} - -template -class ATL_NO_VTABLE CAtlModuleT : public CAtlModule -{ -public : - CAtlModuleT() throw() - { - T::InitLibId(); - } - - static void InitLibId() throw() - { - } - - HRESULT RegisterServer(BOOL bRegTypeLib = FALSE, const CLSID* pCLSID = NULL) throw() - { - (pCLSID); - (bRegTypeLib); - - HRESULT hr = S_OK; - -#ifndef _ATL_NO_COM_SUPPORT - - hr = _AtlComModule.RegisterServer(bRegTypeLib, pCLSID); - -#endif // _ATL_NO_COM_SUPPORT - - -#ifndef _ATL_NO_PERF_SUPPORT - - if (SUCCEEDED(hr) && _pPerfRegFunc != NULL) - hr = (*_pPerfRegFunc)(_AtlBaseModule.m_hInst); - -#endif - - return hr; - } - - HRESULT UnregisterServer(BOOL bUnRegTypeLib, const CLSID* pCLSID = NULL) throw() - { - (bUnRegTypeLib); - (pCLSID); - - HRESULT hr = S_OK; - -#ifndef _ATL_NO_PERF_SUPPORT - - if (_pPerfUnRegFunc != NULL) - hr = (*_pPerfUnRegFunc)(); - -#endif - -#ifndef _ATL_NO_COM_SUPPORT - - if (SUCCEEDED(hr)) - hr = _AtlComModule.UnregisterServer(bUnRegTypeLib, pCLSID); - -#endif // _ATL_NO_COM_SUPPORT - - return hr; - - } - - static HRESULT WINAPI UpdateRegistryAppId(BOOL /*bRegister*/) throw() - { - return S_OK; - } - HRESULT RegisterAppId() throw() - { - return T::UpdateRegistryAppId(TRUE); - } - - HRESULT UnregisterAppId() throw() - { - return T::UpdateRegistryAppId(FALSE); - } - - virtual HRESULT AddCommonRGSReplacements(IRegistrarBase* pRegistrar) throw() - { - return pRegistrar->AddReplacement(L"APPID", T::GetAppId()); - } - static LPCOLESTR GetAppId() throw() - { - return OLESTR(""); - } -}; - -#if !defined(_ATL_NATIVE_INITIALIZATION) -#pragma warning(push) -#pragma warning(disable:4483) -namespace __identifier("") -#pragma warning(pop) -{ - __declspec(selectany) bool DllModuleInitialized = false; -} - -#endif - -template -class ATL_NO_VTABLE CAtlDllModuleT : public CAtlModuleT -{ -public : - CAtlDllModuleT() throw() - { - _AtlComModule.ExecuteObjectMain(true); -#if !defined(_ATL_NATIVE_INITIALIZATION) -#pragma warning(push) -#pragma warning(disable:4483) - using namespace __identifier(""); -#pragma warning(pop) - ATLASSERT(DllModuleInitialized == false); - DllModuleInitialized = true; - _DllMain(DLL_PROCESS_ATTACH, NULL); -#endif - } - - ~CAtlDllModuleT() throw() - { -#if !defined(_ATL_NATIVE_INITIALIZATION) -#pragma warning(push) -#pragma warning(disable:4483) - using namespace __identifier(""); -#pragma warning(pop) - ATLASSERT(DllModuleInitialized == true); - _DllMain(DLL_PROCESS_DETACH, NULL); -#endif - _AtlComModule.ExecuteObjectMain(false); - } - - BOOL WINAPI DllMain(DWORD dwReason, LPVOID lpReserved) throw(); - - BOOL WINAPI _DllMain(DWORD dwReason, LPVOID /* lpReserved */) throw() - { - if (dwReason == DLL_PROCESS_ATTACH) - { - if (CAtlBaseModule::m_bInitFailed) - { - ATLASSERT(0); - return FALSE; - } - -#ifdef _ATL_MIN_CRT - DisableThreadLibraryCalls(_AtlBaseModule.GetModuleInstance()); -#endif - } -#ifdef _DEBUG - else if (dwReason == DLL_PROCESS_DETACH) - { - // Prevent false memory leak reporting. ~CAtlWinModule may be too late. - _AtlWinModule.Term(); - } -#endif // _DEBUG - return TRUE; // ok - } - - HRESULT DllCanUnloadNow() throw() - { - T* pT = static_cast(this); - return (pT->GetLockCount()==0) ? S_OK : S_FALSE; - } - - HRESULT DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) throw() - { - T* pT = static_cast(this); - return pT->GetClassObject(rclsid, riid, ppv); - } - - HRESULT DllRegisterServer(BOOL bRegTypeLib = TRUE) throw() - { - LCID lcid = GetThreadLocale(); - SetThreadLocale(LOCALE_SYSTEM_DEFAULT); - // registers object, typelib and all interfaces in typelib - T* pT = static_cast(this); - HRESULT hr = pT->RegisterAppId(); - if (SUCCEEDED(hr)) - hr = pT->RegisterServer(bRegTypeLib); - SetThreadLocale(lcid); - return hr; - } - - HRESULT DllUnregisterServer(BOOL bUnRegTypeLib = TRUE) throw() - { - LCID lcid = GetThreadLocale(); - SetThreadLocale(LOCALE_SYSTEM_DEFAULT); - T* pT = static_cast(this); - HRESULT hr = pT->UnregisterServer(bUnRegTypeLib); - if (SUCCEEDED(hr)) - hr = pT->UnregisterAppId(); - SetThreadLocale(lcid); - return hr; - } - - // Obtain a Class Factory - HRESULT GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) throw() - { - -#ifndef _ATL_OLEDB_CONFORMANCE_TESTS - ATLASSERT(ppv != NULL); -#endif - - return AtlComModuleGetClassObject(&_AtlComModule, rclsid, riid, ppv); - } -}; - -#pragma managed(push, off) - -template -inline BOOL WINAPI CAtlDllModuleT::DllMain(DWORD dwReason, LPVOID lpReserved) throw() -{ -#if !defined(_ATL_NATIVE_INITIALIZATION) - dwReason; lpReserved; -#pragma warning(push) -#pragma warning(disable:4483) - using namespace __identifier(""); -#pragma warning(pop) - if (dwReason == DLL_PROCESS_ATTACH) - { - ATLASSERT(DllModuleInitialized == false); - } - return TRUE; -#else - return _DllMain(dwReason, lpReserved); -#endif -} - -#pragma managed(pop) - -#ifndef _AFX - - -template -class ATL_NO_VTABLE CAtlExeModuleT : public CAtlModuleT -{ -public : -#ifndef _ATL_NO_COM_SUPPORT - - DWORD m_dwMainThreadID; - HANDLE m_hEventShutdown; - DWORD m_dwTimeOut; - DWORD m_dwPause; - bool m_bDelayShutdown; - bool m_bActivity; - bool m_bComInitialized; // Flag that indicates if ATL initialized COM - -#endif // _ATL_NO_COM_SUPPORT - - CAtlExeModuleT() throw() - -#ifndef _ATL_NO_COM_SUPPORT - - : m_dwMainThreadID(::GetCurrentThreadId()), - m_dwTimeOut(5000), - m_dwPause(1000), - m_hEventShutdown(NULL), - m_bDelayShutdown(true), - m_bComInitialized(false) - -#endif // _ATL_NO_COM_SUPPORT - - { -#if !defined(_ATL_NO_COM_SUPPORT) - HRESULT hr = T::InitializeCom(); - if (FAILED(hr)) - { - // Ignore RPC_E_CHANGED_MODE if CLR is loaded. Error is due to CLR initializing - // COM and InitializeCOM trying to initialize COM with different flags. - if (hr != RPC_E_CHANGED_MODE || GetModuleHandle(_T("Mscoree.dll")) == NULL) - { - ATLASSERT(0); - CAtlBaseModule::m_bInitFailed = true; - return; - } - } - else - { - m_bComInitialized = true; - } - - - _AtlComModule.ExecuteObjectMain(true); - -#endif // !defined(_ATL_NO_COM_SUPPORT) - - } - - ~CAtlExeModuleT() throw() - { -#ifndef _ATL_NO_COM_SUPPORT - - _AtlComModule.ExecuteObjectMain(false); - -#endif - - // Call term functions before COM is uninitialized - Term(); - -#ifndef _ATL_NO_COM_SUPPORT - - // Clean up AtlComModule before COM is uninitialized - _AtlComModule.Term(); - - if (m_bComInitialized) - T::UninitializeCom(); -#endif // _ATL_NO_COM_SUPPORT - } - - static HRESULT InitializeCom() throw() - { - -#if ((_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM)) & defined(_ATL_FREE_THREADED) - return CoInitializeEx(NULL, COINIT_MULTITHREADED); -#else - return CoInitialize(NULL); -#endif - } - - static void UninitializeCom() throw() - { - CoUninitialize(); - } - - LONG Unlock() throw() - { - LONG lRet = CComGlobalsThreadModel::Decrement(&m_nLockCnt); - -#ifndef _ATL_NO_COM_SUPPORT - - if (lRet == 0) - { - if (m_bDelayShutdown) - { - m_bActivity = true; - ::SetEvent(m_hEventShutdown); // tell monitor that we transitioned to zero - } - else - { - ::PostThreadMessage(m_dwMainThreadID, WM_QUIT, 0, 0); - } - } - -#endif // _ATL_NO_COM_SUPPORT - - return lRet; - } -#ifndef _ATL_NO_COM_SUPPORT - - void MonitorShutdown() throw() - { - while (1) - { - ::WaitForSingleObject(m_hEventShutdown, INFINITE); - DWORD dwWait = 0; - do - { - m_bActivity = false; - dwWait = ::WaitForSingleObject(m_hEventShutdown, m_dwTimeOut); - } while (dwWait == WAIT_OBJECT_0); - // timed out - if (!m_bActivity && m_nLockCnt == 0) // if no activity let's really bail - { -#if ((_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM)) & defined(_ATL_FREE_THREADED) - ::CoSuspendClassObjects(); - if (m_nLockCnt == 0) -#endif - break; - } - } - ::CloseHandle(m_hEventShutdown); - ::PostThreadMessage(m_dwMainThreadID, WM_QUIT, 0, 0); - } - - HANDLE StartMonitor() throw() - { - m_hEventShutdown = ::CreateEvent(NULL, false, false, NULL); - if (m_hEventShutdown == NULL) - { - return NULL; - } - DWORD dwThreadID; - HANDLE hThread = ::CreateThread(NULL, 0, MonitorProc, this, 0, &dwThreadID); - if(hThread==NULL) - { - ::CloseHandle(m_hEventShutdown); - } - return hThread; - } - - static DWORD WINAPI MonitorProc(void* pv) throw() - { - CAtlExeModuleT* p = static_cast*>(pv); - p->MonitorShutdown(); - return 0; - } -#endif // _ATL_NO_COM_SUPPORT - - int WinMain(int nShowCmd) throw() - { - if (CAtlBaseModule::m_bInitFailed) - { - ATLASSERT(0); - return -1; - } - T* pT = static_cast(this); - HRESULT hr = S_OK; - - LPTSTR lpCmdLine = GetCommandLine(); //this line necessary for _ATL_MIN_CRT - if (pT->ParseCommandLine(lpCmdLine, &hr) == true) - hr = pT->Run(nShowCmd); - -#ifdef _DEBUG - // Prevent false memory leak reporting. ~CAtlWinModule may be too late. - _AtlWinModule.Term(); -#endif // _DEBUG - return hr; - } - - // Scan command line and perform registration - // Return value specifies if server should run - - // Parses the command line and registers/unregisters the rgs file if necessary - bool ParseCommandLine(LPCTSTR lpCmdLine, HRESULT* pnRetCode) throw() - { - *pnRetCode = S_OK; - - TCHAR szTokens[] = _T("-/"); - - T* pT = static_cast(this); - LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens); - while (lpszToken != NULL) - { - if (WordCmpI(lpszToken, _T("UnregServer"))==0) - { - *pnRetCode = pT->UnregisterServer(TRUE); - if (SUCCEEDED(*pnRetCode)) - *pnRetCode = pT->UnregisterAppId(); - return false; - } - - // Register as Local Server - if (WordCmpI(lpszToken, _T("RegServer"))==0) - { - *pnRetCode = pT->RegisterAppId(); - if (SUCCEEDED(*pnRetCode)) - *pnRetCode = pT->RegisterServer(TRUE); - return false; - } - - lpszToken = FindOneOf(lpszToken, szTokens); - } - - return true; - } - - HRESULT PreMessageLoop(int /*nShowCmd*/) throw() - { - HRESULT hr = S_OK; - T* pT = static_cast(this); - pT; - -#ifndef _ATL_NO_COM_SUPPORT - -#if ((_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM)) & defined(_ATL_FREE_THREADED) - - hr = pT->RegisterClassObjects(CLSCTX_LOCAL_SERVER, - REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED); - - if (FAILED(hr)) - return hr; - - if (hr == S_OK) - { - if (m_bDelayShutdown) - { - CHandle h(pT->StartMonitor()); - if (h.m_h == NULL) - { - hr = E_FAIL; - } - else - { - hr = CoResumeClassObjects(); - ATLASSERT(SUCCEEDED(hr)); - if (FAILED(hr)) - { - ::SetEvent(m_hEventShutdown); // tell monitor to shutdown - ::WaitForSingleObject(h, m_dwTimeOut * 2); - } - } - } - else - { - hr = CoResumeClassObjects(); - ATLASSERT(SUCCEEDED(hr)); - } - - if (FAILED(hr)) - pT->RevokeClassObjects(); - } - else - { - m_bDelayShutdown = false; - } - -#else - - hr = pT->RegisterClassObjects(CLSCTX_LOCAL_SERVER, - REGCLS_MULTIPLEUSE); - if (hr == S_OK) - { - if (m_bDelayShutdown && !pT->StartMonitor()) - { - hr = E_FAIL; - } - } - else - { - m_bDelayShutdown = false; - } - - -#endif - -#endif // _ATL_NO_COM_SUPPORT - - ATLASSERT(SUCCEEDED(hr)); - return hr; - } - - HRESULT PostMessageLoop() throw() - { - HRESULT hr = S_OK; - -#ifndef _ATL_NO_COM_SUPPORT - - T* pT = static_cast(this); - hr = pT->RevokeClassObjects(); - if (m_bDelayShutdown) - Sleep(m_dwPause); //wait for any threads to finish - -#endif // _ATL_NO_COM_SUPPORT - - return hr; - } - - void RunMessageLoop() throw() - { - MSG msg; - while (GetMessage(&msg, 0, 0, 0) > 0) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - - HRESULT Run(int nShowCmd = SW_HIDE) throw() - { - HRESULT hr = S_OK; - - T* pT = static_cast(this); - hr = pT->PreMessageLoop(nShowCmd); - - // Call RunMessageLoop only if PreMessageLoop returns S_OK. - if (hr == S_OK) - { - pT->RunMessageLoop(); - } - - // Call PostMessageLoop if PreMessageLoop returns success. - if (SUCCEEDED(hr)) - { - hr = pT->PostMessageLoop(); - } - - ATLASSERT(SUCCEEDED(hr)); - return hr; - } - - // Register/Revoke All Class Factories with the OS (EXE only) - HRESULT RegisterClassObjects(DWORD dwClsContext, DWORD dwFlags) throw() - { - return AtlComModuleRegisterClassObjects(&_AtlComModule, dwClsContext, dwFlags); - } - HRESULT RevokeClassObjects() throw() - { - return AtlComModuleRevokeClassObjects(&_AtlComModule); - } -}; - -#ifndef _ATL_NO_SERVICE -template -class ATL_NO_VTABLE CAtlServiceModuleT : public CAtlExeModuleT -{ -public : - - CAtlServiceModuleT() throw() - { - m_bService = TRUE; - LoadString(_AtlBaseModule.GetModuleInstance(), nServiceNameID, m_szServiceName, sizeof(m_szServiceName) / sizeof(TCHAR)); - - // set up the initial service status - m_hServiceStatus = NULL; - m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - m_status.dwCurrentState = SERVICE_STOPPED; - m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP; - m_status.dwWin32ExitCode = 0; - m_status.dwServiceSpecificExitCode = 0; - m_status.dwCheckPoint = 0; - m_status.dwWaitHint = 0; - } - - int WinMain(int nShowCmd) throw() - { - if (CAtlBaseModule::m_bInitFailed) - { - ATLASSERT(0); - return -1; - } - - T* pT = static_cast(this); - HRESULT hr = S_OK; - - LPTSTR lpCmdLine = GetCommandLine(); //this line necessary for _ATL_MIN_CRT - if (pT->ParseCommandLine(lpCmdLine, &hr) == true) - hr = pT->Start(nShowCmd); - -#ifdef _DEBUG - // Prevent false memory leak reporting. ~CAtlWinModule may be too late. - _AtlWinModule.Term(); -#endif // _DEBUG - return hr; - } - - HRESULT Start(int nShowCmd) throw() - { - T* pT = static_cast(this); - // Are we Service or Local Server - CRegKey keyAppID; - LONG lRes = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_READ); - if (lRes != ERROR_SUCCESS) - { - m_status.dwWin32ExitCode = lRes; - return m_status.dwWin32ExitCode; - } - - CRegKey key; - lRes = key.Open(keyAppID, pT->GetAppIdT(), KEY_READ); - if (lRes != ERROR_SUCCESS) - { - m_status.dwWin32ExitCode = lRes; - return m_status.dwWin32ExitCode; - } - - TCHAR szValue[MAX_PATH]; - DWORD dwLen = MAX_PATH; - lRes = key.QueryStringValue(_T("LocalService"), szValue, &dwLen); - - m_bService = FALSE; - if (lRes == ERROR_SUCCESS) - m_bService = TRUE; - - if (m_bService) - { - SERVICE_TABLE_ENTRY st[] = - { - { m_szServiceName, _ServiceMain }, - { NULL, NULL } - }; - if (::StartServiceCtrlDispatcher(st) == 0) - m_status.dwWin32ExitCode = GetLastError(); - return m_status.dwWin32ExitCode; - } - // local server - call Run() directly, rather than - // from ServiceMain() - m_status.dwWin32ExitCode = pT->Run(nShowCmd); - return m_status.dwWin32ExitCode; - } - - inline HRESULT RegisterAppId(bool bService = false) throw() - { - if (!Uninstall()) - return E_FAIL; - - HRESULT hr = T::UpdateRegistryAppId(TRUE); - if (FAILED(hr)) - return hr; - - CRegKey keyAppID; - LONG lRes = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_WRITE); - if (lRes != ERROR_SUCCESS) - return AtlHresultFromWin32(lRes); - - CRegKey key; - - lRes = key.Create(keyAppID, T::GetAppIdT()); - if (lRes != ERROR_SUCCESS) - return AtlHresultFromWin32(lRes); - - key.DeleteValue(_T("LocalService")); - - if (!bService) - return S_OK; - - key.SetStringValue(_T("LocalService"), m_szServiceName); - - // Create service - if (!Install()) - return E_FAIL; - return S_OK; - } - - HRESULT UnregisterAppId() throw() - { - if (!Uninstall()) - return E_FAIL; - // First remove entries not in the RGS file. - CRegKey keyAppID; - LONG lRes = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_WRITE); - if (lRes != ERROR_SUCCESS) - return AtlHresultFromWin32(lRes); - - CRegKey key; - lRes = key.Open(keyAppID, T::GetAppIdT(), KEY_WRITE); - if (lRes != ERROR_SUCCESS) - return AtlHresultFromWin32(lRes); - key.DeleteValue(_T("LocalService")); - - return T::UpdateRegistryAppId(FALSE); - } - - // Parses the command line and registers/unregisters the rgs file if necessary - bool ParseCommandLine(LPCTSTR lpCmdLine, HRESULT* pnRetCode) throw() - { - if (!CAtlExeModuleT::ParseCommandLine(lpCmdLine, pnRetCode)) - return false; - - TCHAR szTokens[] = _T("-/"); - *pnRetCode = S_OK; - - T* pT = static_cast(this); - LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens); - while (lpszToken != NULL) - { - if (WordCmpI(lpszToken, _T("Service"))==0) - { - *pnRetCode = pT->RegisterAppId(true); - if (SUCCEEDED(*pnRetCode)) - *pnRetCode = pT->RegisterServer(TRUE); - return false; - } - lpszToken = FindOneOf(lpszToken, szTokens); - } - return true; - } - - void ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv) throw() - { - lpszArgv; - dwArgc; - // Register the control request handler - m_status.dwCurrentState = SERVICE_START_PENDING; - m_hServiceStatus = RegisterServiceCtrlHandler(m_szServiceName, _Handler); - if (m_hServiceStatus == NULL) - { - LogEvent(_T("Handler not installed")); - return; - } - SetServiceStatus(SERVICE_START_PENDING); - - m_status.dwWin32ExitCode = S_OK; - m_status.dwCheckPoint = 0; - m_status.dwWaitHint = 0; - - T* pT = static_cast(this); -#ifndef _ATL_NO_COM_SUPPORT - - HRESULT hr = E_FAIL; - hr = T::InitializeCom(); - if (FAILED(hr)) - { - // Ignore RPC_E_CHANGED_MODE if CLR is loaded. Error is due to CLR initializing - // COM and InitializeCOM trying to initialize COM with different flags. - if (hr != RPC_E_CHANGED_MODE || GetModuleHandle(_T("Mscoree.dll")) == NULL) - { - return; - } - } - else - { - m_bComInitialized = true; - } - - m_bDelayShutdown = false; -#endif //_ATL_NO_COM_SUPPORT - // When the Run function returns, the service has stopped. - m_status.dwWin32ExitCode = pT->Run(SW_HIDE); - -#ifndef _ATL_NO_COM_SUPPORT - if (m_bService && m_bComInitialized) - T::UninitializeCom(); -#endif - - SetServiceStatus(SERVICE_STOPPED); - LogEvent(_T("Service stopped")); - } - - HRESULT Run(int nShowCmd = SW_HIDE) throw() - { - HRESULT hr = S_OK; - T* pT = static_cast(this); - - hr = pT->PreMessageLoop(nShowCmd); - - if (hr == S_OK) - { - if (m_bService) - { - LogEvent(_T("Service started")); - SetServiceStatus(SERVICE_RUNNING); - } - - pT->RunMessageLoop(); - } - - if (SUCCEEDED(hr)) - { - hr = pT->PostMessageLoop(); - } - - return hr; - } - - HRESULT PreMessageLoop(int nShowCmd) throw() - { - HRESULT hr = S_OK; - if (m_bService) - { - m_dwThreadID = GetCurrentThreadId(); - - T* pT = static_cast(this); - hr = pT->InitializeSecurity(); - - if (FAILED(hr)) - return hr; - } - - hr = CAtlExeModuleT::PreMessageLoop(nShowCmd); - if (FAILED(hr)) - return hr; - - return hr; - } - - void OnStop() throw() - { - SetServiceStatus(SERVICE_STOP_PENDING); - PostThreadMessage(m_dwThreadID, WM_QUIT, 0, 0); - } - - void OnPause() throw() - { - } - - void OnContinue() throw() - { - } - - void OnInterrogate() throw() - { - } - - void OnShutdown() throw() - { - } - - void OnUnknownRequest(DWORD /*dwOpcode*/) throw() - { - LogEvent(_T("Bad service request")); - } - - void Handler(DWORD dwOpcode) throw() - { - T* pT = static_cast(this); - - switch (dwOpcode) - { - case SERVICE_CONTROL_STOP: - pT->OnStop(); - break; - case SERVICE_CONTROL_PAUSE: - pT->OnPause(); - break; - case SERVICE_CONTROL_CONTINUE: - pT->OnContinue(); - break; - case SERVICE_CONTROL_INTERROGATE: - pT->OnInterrogate(); - break; - case SERVICE_CONTROL_SHUTDOWN: - pT->OnShutdown(); - break; - default: - pT->OnUnknownRequest(dwOpcode); - } - } - - BOOL IsInstalled() throw() - { - BOOL bResult = FALSE; - - SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); - - if (hSCM != NULL) - { - SC_HANDLE hService = ::OpenService(hSCM, m_szServiceName, SERVICE_QUERY_CONFIG); - if (hService != NULL) - { - bResult = TRUE; - ::CloseServiceHandle(hService); - } - ::CloseServiceHandle(hSCM); - } - return bResult; - } - BOOL Install() throw() - { - if (IsInstalled()) - return TRUE; - - // Get the executable file path - TCHAR szFilePath[MAX_PATH + _ATL_QUOTES_SPACE]; - DWORD dwFLen = ::GetModuleFileName(NULL, szFilePath + 1, MAX_PATH); - if( dwFLen == 0 || dwFLen == MAX_PATH ) - return FALSE; - - // Quote the FilePath before calling CreateService - szFilePath[0] = _T('\"'); - szFilePath[dwFLen + 1] = _T('\"'); - szFilePath[dwFLen + 2] = 0; - - SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); - if (hSCM == NULL) - { - TCHAR szBuf[1024]; - if (AtlLoadString(ATL_SERVICE_MANAGER_OPEN_ERROR, szBuf, 1024) == 0) -#ifdef UNICODE - Checked::wcscpy_s(szBuf, _countof(szBuf), _T("Could not open Service Manager")); -#else - Checked::strcpy_s(szBuf, _countof(szBuf), _T("Could not open Service Manager")); -#endif - MessageBox(NULL, szBuf, m_szServiceName, MB_OK); - return FALSE; - } - - SC_HANDLE hService = ::CreateService( - hSCM, m_szServiceName, m_szServiceName, - SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, - SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, - szFilePath, NULL, NULL, _T("RPCSS\0"), NULL, NULL); - - if (hService == NULL) - { - ::CloseServiceHandle(hSCM); - TCHAR szBuf[1024]; - if (AtlLoadString(ATL_SERVICE_START_ERROR, szBuf, 1024) == 0) -#ifdef UNICODE - Checked::wcscpy_s(szBuf, _countof(szBuf), _T("Could not start service")); -#else - Checked::strcpy_s(szBuf, _countof(szBuf), _T("Could not start service")); -#endif - MessageBox(NULL, szBuf, m_szServiceName, MB_OK); - return FALSE; - } - - ::CloseServiceHandle(hService); - ::CloseServiceHandle(hSCM); - return TRUE; - } - - BOOL Uninstall() throw() - { - if (!IsInstalled()) - return TRUE; - - SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); - - if (hSCM == NULL) - { - TCHAR szBuf[1024]; - if (AtlLoadString(ATL_SERVICE_MANAGER_OPEN_ERROR, szBuf, 1024) == 0) -#ifdef UNICODE - Checked::wcscpy_s(szBuf, _countof(szBuf), _T("Could not open Service Manager")); -#else - Checked::strcpy_s(szBuf, _countof(szBuf), _T("Could not open Service Manager")); -#endif - MessageBox(NULL, szBuf, m_szServiceName, MB_OK); - return FALSE; - } - - SC_HANDLE hService = ::OpenService(hSCM, m_szServiceName, SERVICE_STOP | DELETE); - - if (hService == NULL) - { - ::CloseServiceHandle(hSCM); - TCHAR szBuf[1024]; - if (AtlLoadString(ATL_SERVICE_OPEN_ERROR, szBuf, 1024) == 0) -#ifdef UNICODE - Checked::wcscpy_s(szBuf, _countof(szBuf), _T("Could not open service")); -#else - Checked::strcpy_s(szBuf, _countof(szBuf), _T("Could not open service")); -#endif - MessageBox(NULL, szBuf, m_szServiceName, MB_OK); - return FALSE; - } - SERVICE_STATUS status; - BOOL bRet = ::ControlService(hService, SERVICE_CONTROL_STOP, &status); - if (!bRet) - { - DWORD dwError = GetLastError(); - if (!((dwError == ERROR_SERVICE_NOT_ACTIVE) || (dwError == ERROR_SERVICE_CANNOT_ACCEPT_CTRL && status.dwCurrentState == SERVICE_STOP_PENDING))) - { - TCHAR szBuf[1024]; - if (AtlLoadString(ATL_SERVICE_STOP_ERROR, szBuf, 1024) == 0) -#ifdef UNICODE - Checked::wcscpy_s(szBuf, _countof(szBuf), _T("Could not stop service")); -#else - Checked::strcpy_s(szBuf, _countof(szBuf), _T("Could not stop service")); -#endif - MessageBox(NULL, szBuf, m_szServiceName, MB_OK); - } - } - - - BOOL bDelete = ::DeleteService(hService); - ::CloseServiceHandle(hService); - ::CloseServiceHandle(hSCM); - - if (bDelete) - return TRUE; - - TCHAR szBuf[1024]; - if (AtlLoadString(ATL_SERVICE_DELETE_ERROR, szBuf, 1024) == 0) -#ifdef UNICODE - Checked::wcscpy_s(szBuf, _countof(szBuf), _T("Could not delete service")); -#else - Checked::strcpy_s(szBuf, _countof(szBuf), _T("Could not delete service")); -#endif - MessageBox(NULL, szBuf, m_szServiceName, MB_OK); - return FALSE; - } - - LONG Unlock() throw() - { - LONG lRet; - if (m_bService) - { - // We are running as a service, therefore transition to zero does not - // unload the process - lRet = CAtlModuleT::Unlock(); - } - else - { - // We are running as EXE, use MonitorShutdown logic provided by CExeModule - lRet = CAtlExeModuleT::Unlock(); - } - return lRet; - } - - void LogEventEx(int id, LPCTSTR pszMessage=NULL, WORD type = EVENTLOG_INFORMATION_TYPE) throw() - { - HANDLE hEventSource; - if (m_szServiceName) - { - /* Get a handle to use with ReportEvent(). */ - hEventSource = RegisterEventSource(NULL, m_szServiceName); - if (hEventSource != NULL) - { - /* Write to event log. */ - ReportEvent(hEventSource, - type, - (WORD)0, - id, - NULL, - (WORD)(pszMessage != NULL ? 1 : 0), - 0, - pszMessage != NULL ? &pszMessage : NULL, - NULL); - DeregisterEventSource(hEventSource); - } - } - } - -#pragma warning(push) -#pragma warning(disable : 4793) - void __cdecl LogEvent(LPCTSTR pszFormat, ...) throw() - { - const int LOG_EVENT_MSG_SIZE = 256; - - TCHAR chMsg[LOG_EVENT_MSG_SIZE]; - HANDLE hEventSource; - LPTSTR lpszStrings[1]; - va_list pArg; - - va_start(pArg, pszFormat); -#if _SECURE_ATL - _vsntprintf_s(chMsg, LOG_EVENT_MSG_SIZE, LOG_EVENT_MSG_SIZE-1, pszFormat, pArg); -#else - _vsntprintf(chMsg, LOG_EVENT_MSG_SIZE, pszFormat, pArg); -#endif - va_end(pArg); - - chMsg[LOG_EVENT_MSG_SIZE - 1] = 0; - - lpszStrings[0] = chMsg; - - if (!m_bService) - { - // Not running as a service, so print out the error message - // to the console if possible - _putts(chMsg); - } - - /* Get a handle to use with ReportEvent(). */ - hEventSource = RegisterEventSource(NULL, m_szServiceName); - if (hEventSource != NULL) - { - /* Write to event log. */ - ReportEvent(hEventSource, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (LPCTSTR*) &lpszStrings[0], NULL); - DeregisterEventSource(hEventSource); - } - } -#pragma warning(pop) - - void SetServiceStatus(DWORD dwState) throw() - { - m_status.dwCurrentState = dwState; - ::SetServiceStatus(m_hServiceStatus, &m_status); - } - -//Implementation -protected: - static void WINAPI _ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv) throw() - { - ((T*)_pAtlModule)->ServiceMain(dwArgc, lpszArgv); - } - static void WINAPI _Handler(DWORD dwOpcode) throw() - { - ((T*)_pAtlModule)->Handler(dwOpcode); - } - -// data members -public: - TCHAR m_szServiceName[256]; - SERVICE_STATUS_HANDLE m_hServiceStatus; - SERVICE_STATUS m_status; - BOOL m_bService; - DWORD m_dwThreadID; -}; - -#endif // _ATL_NO_SERVICE - -#endif // !_AFX - -#ifdef _AFX - -class CAtlMfcModule : public ATL::CAtlModuleT -{ -public : - virtual LONG Lock() throw() - { -#ifdef _USRDLL - AFX_MANAGE_STATE(AfxGetStaticModuleState()); -#endif - AfxOleLockApp(); - return AfxGetModuleState()->m_nObjectCount; - } - - virtual LONG Unlock() throw() - { -#ifdef _USRDLL - AFX_MANAGE_STATE(AfxGetStaticModuleState()); -#endif - AfxOleUnlockApp(); - return AfxGetModuleState()->m_nObjectCount; - } - - virtual LONG GetLockCount() throw() - { -#ifdef _USRDLL - AFX_MANAGE_STATE(AfxGetStaticModuleState()); -#endif - return AfxGetModuleState()->m_nObjectCount; - } - - // Obtain a Class Factory (DLL only) - HRESULT GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) - { - return ATL::AtlComModuleGetClassObject(&ATL::_AtlComModule, rclsid, riid, ppv); - } - - // Register/Revoke All Class Factories with the OS (EXE only) - HRESULT RegisterClassObjects(DWORD dwClsContext, DWORD dwFlags) - { - return ATL::AtlComModuleRegisterClassObjects(&ATL::_AtlComModule, dwClsContext, dwFlags); - } - - HRESULT RevokeClassObjects() - { - return ATL::AtlComModuleRevokeClassObjects(&ATL::_AtlComModule); - } -}; - -#endif // _AFX - -///////////////////////////////////////////////////////////////////////////// -// CComModule - Uses the functionality provided by other modules - -#define THREADFLAGS_APARTMENT 0x1 -#define THREADFLAGS_BOTH 0x2 -#define AUTPRXFLAG 0x4 - -#ifndef _ATL_NO_COMMODULE - -class CComModule; - -#if !defined(_ATL_NATIVE_INITIALIZATION) - -#pragma managed(push, off) - -#pragma warning(push) -#pragma warning(disable:4483) -namespace __identifier("") -#pragma warning(pop) -{ - struct CComModuleHelper - { - CComModule* Module; - HINSTANCE Instance; - _ATL_OBJMAP_ENTRY* ObjectMap; - const GUID* LibraryId; - - // Must NOT have any constructors - // We initialize the object in DllMain *before* - // the constructors would run. - - void Initialize(CComModule* pModule, HINSTANCE hInstance, _ATL_OBJMAP_ENTRY* pObjMap, const GUID* pLibID) - { - Module = pModule; - Instance = hInstance; - ObjectMap = pObjMap; - LibraryId = pLibID; - } - }; - - __declspec(selectany) CComModuleHelper ComModuleHelper; - __declspec(selectany) bool ComModuleInitialized = false; -} - -#pragma managed(pop) - -#endif - - -__declspec(selectany) CComModule* _pModule = NULL; -class CComModule : public CAtlModuleT -{ -public : - - CComModule() - { - // Should have only one instance of a class - // derived from CComModule in a project. - ATLASSERT(_pModule == NULL); - _pModule = this; -#if !defined(_ATL_NATIVE_INITIALIZATION) -#pragma warning(push) -#pragma warning(disable:4483) - using namespace __identifier(""); -#pragma warning(pop) - ATLASSERT(ComModuleInitialized == false); - // If ComModuleHelper.Module == NULL it mean that DllMain has not been called, so we assume CComModule lives in - // an exe and not in a dll - if (ComModuleHelper.Module != NULL) - { - ATLASSERT(ComModuleHelper.Module == this); - _DllMain(ComModuleHelper.Instance, DLL_PROCESS_ATTACH, NULL, ComModuleHelper.ObjectMap, ComModuleHelper.LibraryId); - } - ComModuleInitialized = true; -#endif - } - - ~CComModule() - { -#if !defined(_ATL_NATIVE_INITIALIZATION) -#pragma warning(push) -#pragma warning(disable:4483) - using namespace __identifier(""); -#pragma warning(pop) - ATLASSERT(ComModuleInitialized == true); - // If ComModuleHelper.Module == NULL it mean that DllMain has not been called, so we assume CComModule lives in - // an exe and not in a dll - if (ComModuleHelper.Module != NULL) - { - ATLASSERT(ComModuleHelper.Module == this); - _DllMain(ComModuleHelper.Instance, DLL_PROCESS_DETACH, NULL, ComModuleHelper.ObjectMap, ComModuleHelper.LibraryId); - } -#endif - } - - __declspec(property(get = get_m_hInst)) HINSTANCE m_hInst; - HINSTANCE& get_m_hInst() const throw() - { - return _AtlBaseModule.m_hInst; - } - - __declspec(property(get = get_m_hInstResource, put = put_m_hInstResource)) HINSTANCE m_hInstResource; - HINSTANCE& get_m_hInstResource() const throw() - { - return _AtlBaseModule.m_hInstResource; - } - void put_m_hInstResource(HINSTANCE h) throw() - { - _AtlBaseModule.SetResourceInstance(h); - } - HINSTANCE SetResourceInstance(HINSTANCE h) throw() - { - return _AtlBaseModule.SetResourceInstance(h); - } - - HINSTANCE GetModuleInstance() throw() - { - return _AtlBaseModule.m_hInst; - } - HINSTANCE GetResourceInstance() throw() - { - return _AtlBaseModule.m_hInstResource; - } - - __declspec(property(get = get_m_hInstTypeLib, put = put_m_hInstTypeLib)) HINSTANCE m_hInstTypeLib; - HINSTANCE& get_m_hInstTypeLib() const throw() - { - return _AtlComModule.m_hInstTypeLib; - } - void put_m_hInstTypeLib(HINSTANCE h) throw() - { - _AtlComModule.m_hInstTypeLib = h; - } - - HINSTANCE GetTypeLibInstance() const throw() - { - return _AtlComModule.m_hInstTypeLib; - } - - // For Backward compatibility - _ATL_OBJMAP_ENTRY* m_pObjMap; - - __declspec(property(get = get_m_csWindowCreate)) CRITICAL_SECTION m_csWindowCreate; - CRITICAL_SECTION& get_m_csWindowCreate() throw(); - - __declspec(property(get = get_m_csObjMap)) CRITICAL_SECTION m_csObjMap; - CRITICAL_SECTION& get_m_csObjMap() throw(); - - __declspec(property(get = get_m_csStaticDataInit)) CRITICAL_SECTION m_csTypeInfoHolder; - __declspec(property(get = get_m_csStaticDataInit)) CRITICAL_SECTION m_csStaticDataInit; - CRITICAL_SECTION& get_m_csStaticDataInit() throw(); - void EnterStaticDataCriticalSection() throw() - { - EnterCriticalSection(&m_csStaticDataInit); - } - - void LeaveStaticDataCriticalSection() throw() - { - LeaveCriticalSection(&m_csStaticDataInit); - } - - __declspec(property(get = get_dwAtlBuildVer)) DWORD dwAtlBuildVer; - DWORD& get_dwAtlBuildVer() throw() - { - return _AtlBaseModule.dwAtlBuildVer; - } - - __declspec(property(get = get_m_pCreateWndList, put = put_m_pCreateWndList)) _AtlCreateWndData* m_pCreateWndList; - _AtlCreateWndData*& get_m_pCreateWndList() throw(); - void put_m_pCreateWndList(_AtlCreateWndData* p) throw(); - - __declspec(property(get = get_pguidVer)) const GUID* pguidVer; - const GUID*& get_pguidVer() throw() - { - return _AtlBaseModule.pguidVer; - } - -#ifdef _ATL_DEBUG_INTERFACES - - __declspec(property(get = get_m_nIndexQI, put = put_m_nIndexQI)) UINT m_nIndexQI; - UINT& get_m_nIndexQI() throw(); - void put_m_nIndexQI(UINT nIndex) throw(); - - __declspec(property(get = get_m_nIndexBreakAt, put = put_m_nIndexBreakAt)) UINT m_nIndexBreakAt; - UINT& get_m_nIndexBreakAt() throw(); - void put_m_nIndexBreakAt(UINT nIndex) throw(); - - __declspec(property(get = get_m_paThunks)) CSimpleArray<_QIThunk*>* m_paThunks; - CSimpleArray<_QIThunk*>* get_m_paThunks() throw(); - HRESULT AddThunk(IUnknown** pp, LPCTSTR lpsz, REFIID iid) throw(); - - HRESULT AddNonAddRefThunk(IUnknown* p, LPCTSTR lpsz, IUnknown** ppThunkRet) throw(); - void DeleteNonAddRefThunk(IUnknown* pUnk) throw(); - void DeleteThunk(_QIThunk* p) throw(); - bool DumpLeakedThunks() throw(); -#endif // _ATL_DEBUG_INTERFACES - - HRESULT Init(_ATL_OBJMAP_ENTRY* p, HINSTANCE h, const GUID* plibid = NULL) throw(); - void Term() throw(); - - HRESULT GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) throw(); - // Register/Revoke All Class Factories with the OS (EXE only) - HRESULT RegisterClassObjects(DWORD dwClsContext, DWORD dwFlags) throw(); - HRESULT RevokeClassObjects() throw(); - // Registry support (helpers) - HRESULT RegisterTypeLib() throw(); - HRESULT RegisterTypeLib(LPCTSTR lpszIndex) throw(); - HRESULT UnRegisterTypeLib() throw(); - HRESULT UnRegisterTypeLib(LPCTSTR lpszIndex) throw(); - HRESULT RegisterServer(BOOL bRegTypeLib = FALSE, const CLSID* pCLSID = NULL) throw(); - HRESULT UnregisterServer(BOOL bUnRegTypeLib, const CLSID* pCLSID = NULL) throw(); - HRESULT UnregisterServer(const CLSID* pCLSID = NULL) throw(); - - void AddCreateWndData(_AtlCreateWndData* pData, void* pObject) throw() - { - _AtlWinModule.AddCreateWndData(pData, pObject); - } - - void* ExtractCreateWndData() throw() - { - return _AtlWinModule.ExtractCreateWndData(); - } - - // Only used in CComAutoThreadModule - HRESULT CreateInstance(void* /*pfnCreateInstance*/, REFIID /*riid*/, void** /*ppvObj*/) throw() - { - ATLASSERT(0); - ATLTRACENOTIMPL(_T("CComModule::CreateInstance")); - } - - HRESULT RegisterAppId(LPCTSTR pAppId); - HRESULT UnregisterAppId(LPCTSTR pAppId); - - // Resource-based Registration - virtual HRESULT WINAPI UpdateRegistryFromResourceD(LPCTSTR lpszRes, BOOL bRegister, - struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw() - { -#if defined(_ATL_STATIC_REGISTRY) - (lpszRes); - (bRegister); - (pMapEntries); - return E_FAIL; -#else - return CAtlModuleT::UpdateRegistryFromResourceD(lpszRes, bRegister, pMapEntries); -#endif - } - virtual HRESULT WINAPI UpdateRegistryFromResourceD(UINT nResID, BOOL bRegister, - struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw() - { -#if defined(_ATL_STATIC_REGISTRY) - (nResID); - (bRegister); - (pMapEntries); - return E_FAIL; -#else - return CAtlModuleT::UpdateRegistryFromResourceD(nResID, bRegister, pMapEntries); -#endif - } - - - // Statically linking to Registry Ponent - virtual HRESULT WINAPI UpdateRegistryFromResourceS(LPCTSTR lpszRes, BOOL bRegister, - struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw() - { -#ifdef _ATL_STATIC_REGISTRY - return CAtlModuleT::UpdateRegistryFromResourceS(lpszRes, bRegister, pMapEntries); -#else - (lpszRes); - (bRegister); - (pMapEntries); - return E_FAIL; -#endif - } - virtual HRESULT WINAPI UpdateRegistryFromResourceS(UINT nResID, BOOL bRegister, - struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw() - { -#ifdef _ATL_STATIC_REGISTRY - return CAtlModuleT::UpdateRegistryFromResourceS(nResID, bRegister, pMapEntries); -#else - (nResID); - (bRegister); - (pMapEntries); - return E_FAIL; -#endif - } - - - // Use RGS file for registration - - ATL_DEPRECATED("CComModule::RegisterProgID is no longer recommended. Instead, use an RGS file for registration.") - static HRESULT RegisterProgID(LPCTSTR lpszCLSID, LPCTSTR lpszProgID, LPCTSTR lpszUserDesc); - // Standard Registration - ATL_DEPRECATED("CComModule::UpdateRegistryClass is no longer recommended. Instead, use an RGS file for registration.") - HRESULT WINAPI UpdateRegistryClass(const CLSID& clsid, LPCTSTR lpszProgID, LPCTSTR lpszVerIndProgID, UINT nDescID, DWORD dwFlags, BOOL bRegister); - ATL_DEPRECATED("CComModule::UpdateRegistryClass is no longer recommended. Instead, use an RGS file for registration.") - HRESULT WINAPI UpdateRegistryClass(const CLSID& clsid, LPCTSTR lpszProgID, LPCTSTR lpszVerIndProgID, LPCTSTR szDesc, DWORD dwFlags, BOOL bRegister); - ATL_DEPRECATED("CComModule::RegisterClassHelper is no longer recommended. Instead, use an RGS file for registration.") - HRESULT WINAPI RegisterClassHelper(const CLSID& clsid, LPCTSTR lpszProgID, LPCTSTR lpszVerIndProgID, LPCTSTR szDesc, DWORD dwFlags); - ATL_DEPRECATED("CComModule::UnregisterClassHelper is no longer recommended. Instead, use an RGS file for registration.") - HRESULT WINAPI UnregisterClassHelper(const CLSID& clsid, LPCTSTR lpszProgID, LPCTSTR lpszVerIndProgID); - - BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /* lpReserved */, _ATL_OBJMAP_ENTRY* pObjMap, const GUID* pLibID); - - BOOL WINAPI _DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /* lpReserved */, _ATL_OBJMAP_ENTRY* pObjMap, const GUID* pLibID) - { - if (dwReason == DLL_PROCESS_ATTACH) - { - if (CAtlBaseModule::m_bInitFailed) - { - ATLASSERT(0); - return FALSE; - } - - if (FAILED(Init(pObjMap, hInstance, pLibID))) - { - Term(); - return FALSE; - } -#ifdef _ATL_MIN_CRT - DisableThreadLibraryCalls(hInstance); -#endif - } - else if (dwReason == DLL_PROCESS_DETACH) - Term(); - return TRUE; // ok - } - - HRESULT DllCanUnloadNow() throw() - { - return (GetLockCount()==0) ? S_OK : S_FALSE; - } - HRESULT DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) throw() - { - return GetClassObject(rclsid, riid, ppv); - } - - HRESULT DllRegisterServer(BOOL bRegTypeLib = TRUE) throw() - { - // registers object, typelib and all interfaces in typelib - return RegisterServer(bRegTypeLib); - } - - HRESULT DllUnregisterServer(BOOL bUnRegTypeLib = TRUE) throw() - { - return UnregisterServer(bUnRegTypeLib); - } - -}; - -#pragma managed(push, off) -inline BOOL WINAPI CComModule::DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved, _ATL_OBJMAP_ENTRY* pObjMap, const GUID* pLibID) -{ -#if !defined(_ATL_NATIVE_INITIALIZATION) -#pragma warning(push) -#pragma warning(disable:4483) - using namespace __identifier(""); -#pragma warning(pop) - lpReserved; - if (dwReason == DLL_PROCESS_ATTACH) - { - ATLASSERT(ComModuleInitialized == false); - ComModuleHelper.Initialize(this, hInstance, pObjMap, pLibID); - } - return TRUE; -#else - return _DllMain(hInstance, dwReason, lpReserved, pObjMap, pLibID); -#endif -} -#pragma managed(pop) - -#endif // !_ATL_NO_COMMODULE - -///////////////////////////////////////////////////////////////////////////// -// Thread creation helpers - -#if !defined(_ATL_MIN_CRT) && defined(_MT) -// CRTThreadTraits -// This class is for use with CThreadPool or CWorkerThread -// It should be used if the worker class will use CRT -// functions. -class CRTThreadTraits -{ -public: - static HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpsa, DWORD dwStackSize, LPTHREAD_START_ROUTINE pfnThreadProc, void *pvParam, DWORD dwCreationFlags, DWORD *pdwThreadId) throw() - { - ATLASSERT(sizeof(DWORD) == sizeof(unsigned int)); // sanity check for pdwThreadId - - // _beginthreadex calls CreateThread which will set the last error value before it returns. - return (HANDLE) _beginthreadex(lpsa, dwStackSize, (unsigned int (__stdcall *)(void *)) pfnThreadProc, pvParam, dwCreationFlags, (unsigned int *) pdwThreadId); - } -}; - -#endif - -// Win32ThreadTraits -// This class is for use with CThreadPool or CWorkerThread -// It should be used if the worker class will not use CRT -// functions. -class Win32ThreadTraits -{ -public: - static HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpsa, DWORD dwStackSize, LPTHREAD_START_ROUTINE pfnThreadProc, void *pvParam, DWORD dwCreationFlags, DWORD *pdwThreadId) throw() - { - return ::CreateThread(lpsa, dwStackSize, pfnThreadProc, pvParam, dwCreationFlags, pdwThreadId); - } -}; - -#if !defined(_ATL_MIN_CRT) && defined(_MT) - typedef CRTThreadTraits DefaultThreadTraits; -#else - typedef Win32ThreadTraits DefaultThreadTraits; -#endif - -template -HANDLE CreateThreadT(LPSECURITY_ATTRIBUTES lpsa, DWORD dwStackSize, DWORD (WINAPI * pfn)(T *pparam), - T *pparam, DWORD dwCreationFlags, LPDWORD pdw) -{ - return DefaultThreadTraits::CreateThread(lpsa, - dwStackSize, - (LPTHREAD_START_ROUTINE)pfn, - pparam, - dwCreationFlags, - pdw); -} - -template -HANDLE AtlCreateThread(DWORD (WINAPI* pfn)(T *pparam), T *pparam) -{ - return CreateThreadT(0, 0, pfn, pparam, 0, 0); -} - -///////////////////////////////////////////////////////////////////////////////////////////// -// Thread Pooling classes - -class _AtlAptCreateObjData -{ -public: - _ATL_CREATORFUNC* pfnCreateInstance; - const IID* piid; - HANDLE hEvent; - LPSTREAM pStream; - HRESULT hRes; -}; - -class CComApartment -{ -public: - CComApartment() - { - m_nLockCnt = 0; - m_hThread = NULL; - } - static UINT ATL_CREATE_OBJECT; - static DWORD WINAPI _Apartment(__in void* pv) - { - ATLENSURE(pv != NULL); - return ((CComApartment*)pv)->Apartment(); - } - DWORD Apartment() - { - CoInitialize(NULL); - MSG msg; - while(GetMessage(&msg, 0, 0, 0) > 0) - { - if (msg.message == ATL_CREATE_OBJECT) - { - _AtlAptCreateObjData* pdata = (_AtlAptCreateObjData*)msg.lParam; - IUnknown* pUnk = NULL; - pdata->hRes = pdata->pfnCreateInstance(NULL, __uuidof(IUnknown), (void**)&pUnk); - if (SUCCEEDED(pdata->hRes)) - pdata->hRes = CoMarshalInterThreadInterfaceInStream(*pdata->piid, pUnk, &pdata->pStream); - if (SUCCEEDED(pdata->hRes)) - { - pUnk->Release(); - ATLTRACE(atlTraceCOM, 2, _T("Object created on thread = %d\n"), GetCurrentThreadId()); - } -#ifdef _DEBUG - else - { - ATLTRACE(atlTraceCOM, 2, _T("Failed to create Object on thread = %d\n"), GetCurrentThreadId()); - } -#endif - SetEvent(pdata->hEvent); - } - DispatchMessage(&msg); - } - CoUninitialize(); - - return 0; - } - LONG Lock() {return CComGlobalsThreadModel::Increment(&m_nLockCnt);} - LONG Unlock(){return CComGlobalsThreadModel::Decrement(&m_nLockCnt); - } - LONG GetLockCount() {return m_nLockCnt;} - - DWORD m_dwThreadID; - HANDLE m_hThread; - LONG m_nLockCnt; -}; - -__declspec(selectany) UINT CComApartment::ATL_CREATE_OBJECT = 0; - -class CComSimpleThreadAllocator -{ -public: - CComSimpleThreadAllocator() - { - m_nThread = 0; - } - int GetThread(CComApartment* /*pApt*/, int nThreads) - { - if (++m_nThread == nThreads) - m_nThread = 0; - return m_nThread; - } - int m_nThread; -}; - -__interface IAtlAutoThreadModule -{ - virtual HRESULT CreateInstance(void* pfnCreateInstance, REFIID riid, void** ppvObj); -}; - -__declspec(selectany) IAtlAutoThreadModule* _pAtlAutoThreadModule; - -template -class ATL_NO_VTABLE CAtlAutoThreadModuleT : public IAtlAutoThreadModule -{ -// This class is not for use in a DLL. -// If this class were used in a DLL, there will be a deadlock when the DLL is unloaded. -// because of dwWait's default value of INFINITE -public: - CAtlAutoThreadModuleT(int nThreads = T::GetDefaultThreads()) - { - ATLASSERT(_pAtlAutoThreadModule == NULL); - _pAtlAutoThreadModule = this; - m_pApartments = NULL; - m_nThreads= 0; - - ATLTRY(m_pApartments = new CComApartment[nThreads]); - ATLASSERT(m_pApartments != NULL); - if(m_pApartments == NULL) - { - CAtlBaseModule::m_bInitFailed = true; - ATLENSURE(0); - } - - memset(m_pApartments, 0, sizeof(CComApartment) * nThreads); - - m_nThreads = nThreads; - for (int i = 0; i < nThreads; i++) - { - -#if !defined(_ATL_MIN_CRT) && defined(_MT) - typedef unsigned ( __stdcall *pfnThread )( void * ); - m_pApartments[i].m_hThread = (HANDLE)_beginthreadex(NULL, 0, (pfnThread)CComApartment::_Apartment, &m_pApartments[i], 0, (UINT*)&m_pApartments[i].m_dwThreadID); - if (m_pApartments[i].m_hThread == NULL) - { - HRESULT hr = E_FAIL; - switch (Checked::get_errno()) - { - case EAGAIN: - hr = HRESULT_FROM_WIN32(ERROR_TOO_MANY_TCBS); - break; - case EINVAL: - hr = E_INVALIDARG; - break; - } - ATLASSERT(0); - CAtlBaseModule::m_bInitFailed = true; - break; - } - -#else - m_pApartments[i].m_hThread = ::CreateThread(NULL, 0, CComApartment::_Apartment, (void*)&m_pApartments[i], 0, &m_pApartments[i].m_dwThreadID); - // clean up allocated threads - if (m_pApartments[i].m_hThread == NULL) - { - ATLASSERT(0); - CAtlBaseModule::m_bInitFailed = true; - break; - } - -#endif - - } - if (!CAtlBaseModule::m_bInitFailed) - CComApartment::ATL_CREATE_OBJECT = RegisterWindowMessage(_T("ATL_CREATE_OBJECT")); - } - - virtual ~CAtlAutoThreadModuleT() - { - if (m_pApartments == NULL) - return; - - DWORD dwCurrentThreadId = GetCurrentThreadId(); - int nCurrentThread = -1; - for (int i=0; i < m_nThreads; i++) - { - if (m_pApartments[i].m_hThread == NULL) - continue; - if (m_pApartments[i].m_dwThreadID == dwCurrentThreadId) - { - nCurrentThread = i; - continue; - } - while (::PostThreadMessage(m_pApartments[i].m_dwThreadID, WM_QUIT, 0, 0) == 0) - { - if (GetLastError() == ERROR_INVALID_THREAD_ID) - { - ATLASSERT(FALSE); - break; - } - ::Sleep(100); - } - ::WaitForSingleObject(m_pApartments[i].m_hThread, dwWait); - CloseHandle(m_pApartments[i].m_hThread); - } - if (nCurrentThread != -1) - CloseHandle(m_pApartments[nCurrentThread].m_hThread); - - delete [] m_pApartments; - m_pApartments = NULL; - } - - HRESULT CreateInstance(void* pfnCreateInstance, REFIID riid, void** ppvObj) - { - ATLASSERT(ppvObj != NULL); - if (ppvObj == NULL) - return E_POINTER; - *ppvObj = NULL; - - _ATL_CREATORFUNC* pFunc = (_ATL_CREATORFUNC*) pfnCreateInstance; - _AtlAptCreateObjData data; - data.pfnCreateInstance = pFunc; - data.piid = &riid; - data.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - data.hRes = S_OK; - int nThread = m_Allocator.GetThread(m_pApartments, m_nThreads); - int nIterations = 0; - while(::PostThreadMessage(m_pApartments[nThread].m_dwThreadID, CComApartment::ATL_CREATE_OBJECT, 0, (LPARAM)&data) == 0 && ++nIterations < 100) - { - Sleep(100); - } - if (nIterations < 100) - { - AtlWaitWithMessageLoop(data.hEvent); - } - else - { - data.hRes = AtlHresultFromLastError(); - } - CloseHandle(data.hEvent); - if (SUCCEEDED(data.hRes)) - data.hRes = CoGetInterfaceAndReleaseStream(data.pStream, riid, ppvObj); - return data.hRes; - } - DWORD dwThreadID; - int m_nThreads; - CComApartment* m_pApartments; - ThreadAllocator m_Allocator; - static int GetDefaultThreads() - { - SYSTEM_INFO si; - GetSystemInfo(&si); - return si.dwNumberOfProcessors * 4; - } -}; - -class CAtlAutoThreadModule : public CAtlAutoThreadModuleT -{ -public : -}; - -#ifndef _ATL_NO_COMMODULE - -template -class CComAutoThreadModule : - public CComModule, - public CAtlAutoThreadModuleT, ThreadAllocator, dwWait> -{ -public: - CComAutoThreadModule(int nThreads = GetDefaultThreads()) : - CAtlAutoThreadModuleT, ThreadAllocator, dwWait>(nThreads) - { - } - HRESULT Init(_ATL_OBJMAP_ENTRY* p, HINSTANCE h, const GUID* plibid = NULL, int nThreads = GetDefaultThreads()) - { - nThreads; - ATLASSERT(nThreads == GetDefaultThreads() && _T("Set number of threads through the constructor")); - return CComModule::Init(p, h, plibid); - } -}; - -#endif // !_ATL_NO_COMMODULE - -// Used in CThreadPool -class Win32WaitTraits -{ -public: - static DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwTimeout) - { - return ::WaitForSingleObject(hHandle, dwTimeout); - } -}; - -typedef Win32WaitTraits DefaultWaitTraits; - -///////////////////////////////////////////////////////////////////////////// -// GIT Pointer - -template -class CComGITPtr -{ -public: - CComGITPtr() throw() - { - m_dwCookie = 0; - } - CComGITPtr(T* p) - { - m_dwCookie = 0; - HRESULT hr = Attach(p); - - if (FAILED(hr)) - AtlThrow(hr); - } - CComGITPtr(const CComGITPtr& git) - { - m_dwCookie = 0; - CComPtr spT; - - HRESULT hr = git.CopyTo(&spT); - if (SUCCEEDED(hr)) - hr = Attach(spT); - - if (FAILED(hr)) - AtlThrow(hr); - } - explicit CComGITPtr(DWORD dwCookie) throw() - { - ATLASSUME(m_dwCookie != NULL); - m_dwCookie = dwCookie; - -#ifdef _DEBUG - CComPtr spT; - HRESULT hr = CopyTo(&spT); - ATLASSERT(SUCCEEDED(hr)); -#endif - } - - ~CComGITPtr() throw() - { - Revoke(); - } - CComGITPtr& operator=(const CComGITPtr& git) - { - if(*this!=git) - { - CComPtr spT; - - HRESULT hr = git.CopyTo(&spT); - if (SUCCEEDED(hr)) - { - hr = Attach(spT); - } - - if (FAILED(hr)) - { - AtlThrow(hr); - } - } - return *this; - } - CComGITPtr& operator=(T* p) - { - HRESULT hr = Attach(p); - if (FAILED(hr)) - AtlThrow(hr); - return *this; - } - CComGITPtr& operator=(DWORD dwCookie) - { - if(*this!=dwCookie) - { - HRESULT hr = Attach(dwCookie); - if (FAILED(hr)) - { - AtlThrow(hr); - } - - m_dwCookie = dwCookie; - -#ifdef _DEBUG - CComPtr spT; - hr = CopyTo(&spT); - ATLASSERT(SUCCEEDED(hr)); -#endif - } - return *this; - } - - // basic comparison operators - bool operator!=(CComGITPtr& git) const - { - return !operator==(git); - } - - bool operator!=(DWORD dwCookie) const - { - return !operator==(dwCookie); - } - - bool operator==(CComGITPtr& git) const - { - return m_dwCookie==git.GetCookie(); - } - - bool operator==(DWORD dwCookie) const - { - return m_dwCookie==dwCookie; - } - - // Get the cookie from the class - operator DWORD() const - { - return m_dwCookie; - } - // Get the cookie from the class - DWORD GetCookie() const - { - return m_dwCookie; - } - // Register the passed interface pointer in the GIT - HRESULT Attach(T* p) throw() - { - CComPtr spGIT; - HRESULT hr = E_FAIL; - hr = AtlGetGITPtr(&spGIT); - ATLASSERT(spGIT != NULL); - ATLASSERT(SUCCEEDED(hr)); - if (FAILED(hr)) - return hr; - - if (m_dwCookie != 0) - hr = spGIT->RevokeInterfaceFromGlobal(m_dwCookie); - if (FAILED(hr)) - return hr; - - return spGIT->RegisterInterfaceInGlobal(p, __uuidof(T), &m_dwCookie); - } - - HRESULT Attach(DWORD dwCookie) throw() - { - ATLASSERT(dwCookie != NULL); - HRESULT hr = Revoke(); - if (FAILED(hr)) - return hr; - m_dwCookie = dwCookie; - return S_OK; - } - - // Detach - DWORD Detach() throw() - { - DWORD dwCookie = m_dwCookie; - m_dwCookie = NULL; - return dwCookie; - } - - // Remove the interface from the GIT - HRESULT Revoke() throw() - { - HRESULT hr = S_OK; - if (m_dwCookie != 0) - { - CComPtr spGIT; - HRESULT hr = E_FAIL; - hr = AtlGetGITPtr(&spGIT); - - ATLASSERT(spGIT != NULL); - ATLASSERT(SUCCEEDED(hr)); - if (FAILED(hr)) - return hr; - - hr = spGIT->RevokeInterfaceFromGlobal(m_dwCookie); - if (SUCCEEDED(hr)) - m_dwCookie = 0; - } - return hr; - } - // Get's the interface from the GIT and copies it to the passed pointer. The pointer - // must be released by the caller when finished. - HRESULT CopyTo(T** pp) const throw() - { - CComPtr spGIT; - HRESULT hr = E_FAIL; - hr = AtlGetGITPtr(&spGIT); - - ATLASSERT(spGIT != NULL); - ATLASSERT(SUCCEEDED(hr)); - if (FAILED(hr)) - return hr; - - ATLASSUME(m_dwCookie!=NULL); - return spGIT->GetInterfaceFromGlobal(m_dwCookie, __uuidof(T), (void**)pp); - } - DWORD m_dwCookie; -}; - -///////////////////////////////////////////////////////////////////////////// -// CRegKey - -class CRegKey -{ -public: - CRegKey() throw(); - CRegKey( CRegKey& key ) throw(); - explicit CRegKey(HKEY hKey) throw(); - ~CRegKey() throw(); - - CRegKey& operator=( CRegKey& key ) throw(); - -// Attributes -public: - operator HKEY() const throw(); - HKEY m_hKey; - -// Operations -public: - ATL_DEPRECATED("CRegKey::SetValue(DWORD, TCHAR *valueName) has been superseded by CRegKey::SetDWORDValue") - LONG SetValue(DWORD dwValue, LPCTSTR lpszValueName); - ATL_DEPRECATED("CRegKey::SetValue(TCHAR *value, TCHAR *valueName) has been superseded by CRegKey::SetStringValue and CRegKey::SetMultiStringValue") - LONG SetValue(LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL, bool bMulti = false, int nValueLen = -1); - LONG SetValue(LPCTSTR pszValueName, DWORD dwType, const void* pValue, ULONG nBytes) throw(); - LONG SetGUIDValue(LPCTSTR pszValueName, REFGUID guidValue) throw(); - LONG SetBinaryValue(LPCTSTR pszValueName, const void* pValue, ULONG nBytes) throw(); - LONG SetDWORDValue(LPCTSTR pszValueName, DWORD dwValue) throw(); - LONG SetQWORDValue(LPCTSTR pszValueName, ULONGLONG qwValue) throw(); - LONG SetStringValue(LPCTSTR pszValueName, LPCTSTR pszValue, DWORD dwType = REG_SZ) throw(); - LONG SetMultiStringValue(LPCTSTR pszValueName, LPCTSTR pszValue) throw(); - - ATL_DEPRECATED("CRegKey::QueryValue(DWORD, TCHAR *valueName) has been superseded by CRegKey::QueryDWORDValue") - LONG QueryValue(__out DWORD& dwValue, __in_z_opt LPCTSTR lpszValueName); - ATL_DEPRECATED("CRegKey::QueryValue(TCHAR *value, TCHAR *valueName) has been superseded by CRegKey::QueryStringValue and CRegKey::QueryMultiStringValue") - LONG QueryValue(__out_ecount_part_z_opt(*pdwCount, *pdwCount) LPTSTR szValue, __in_z_opt LPCTSTR lpszValueName, __inout DWORD* pdwCount); - LONG QueryValue(__in_z_opt LPCTSTR pszValueName, DWORD* pdwType, void* pData, ULONG* pnBytes) throw(); - LONG QueryGUIDValue(__in_z_opt LPCTSTR pszValueName, GUID& guidValue) throw(); - LONG QueryBinaryValue(__in_z_opt LPCTSTR pszValueName, void* pValue, ULONG* pnBytes) throw(); - LONG QueryDWORDValue(__in_z_opt LPCTSTR pszValueName, DWORD& dwValue) throw(); - LONG QueryQWORDValue(__in_z_opt LPCTSTR pszValueName, ULONGLONG& qwValue) throw(); - LONG QueryStringValue(__in_z_opt LPCTSTR pszValueName, __out_ecount_part_z_opt(*pnChars, *pnChars) __out_z LPTSTR pszValue, __inout ULONG* pnChars) throw(); - LONG QueryMultiStringValue(__in_z_opt LPCTSTR pszValueName, __out_ecount_part_z_opt(*pnChars, *pnChars) __out_z LPTSTR pszValue, __inout ULONG* pnChars) throw(); - - // Get the key's security attributes. - LONG GetKeySecurity(SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR psd, LPDWORD pnBytes) throw(); - // Set the key's security attributes. - LONG SetKeySecurity(SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR psd) throw(); - - LONG SetKeyValue(LPCTSTR lpszKeyName, LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL) throw(); - static LONG WINAPI SetValue(HKEY hKeyParent, LPCTSTR lpszKeyName, - LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL); - - // Create a new registry key (or open an existing one). - LONG Create(__in HKEY hKeyParent, __in_z LPCTSTR lpszKeyName, - __in_z LPTSTR lpszClass = REG_NONE, __in DWORD dwOptions = REG_OPTION_NON_VOLATILE, - __in REGSAM samDesired = KEY_READ | KEY_WRITE, - __in_opt LPSECURITY_ATTRIBUTES lpSecAttr = NULL, - __in_opt LPDWORD lpdwDisposition = NULL) throw(); - // Open an existing registry key. - LONG Open(HKEY hKeyParent, LPCTSTR lpszKeyName, - REGSAM samDesired = KEY_READ | KEY_WRITE) throw(); - // Close the registry key. - LONG Close() throw(); - // Flush the key's data to disk. - LONG Flush() throw(); - - // Detach the CRegKey object from its HKEY. Releases ownership. - HKEY Detach() throw(); - // Attach the CRegKey object to an existing HKEY. Takes ownership. - void Attach(HKEY hKey) throw(); - - // Enumerate the subkeys of the key. - LONG EnumKey(__in DWORD iIndex, __out_ecount_part_z(*pnNameLength, *pnNameLength) LPTSTR pszName, __inout LPDWORD pnNameLength, __out_opt FILETIME* pftLastWriteTime = NULL) throw(); - LONG NotifyChangeKeyValue(BOOL bWatchSubtree, DWORD dwNotifyFilter, HANDLE hEvent, BOOL bAsync = TRUE) throw(); - - LONG DeleteSubKey(LPCTSTR lpszSubKey) throw(); - LONG RecurseDeleteKey(LPCTSTR lpszKey) throw(); - LONG DeleteValue(LPCTSTR lpszValue) throw(); -}; - -inline CRegKey::CRegKey() throw() : - m_hKey( NULL ) -{ -} - -inline CRegKey::CRegKey( CRegKey& key ) throw() : - m_hKey( NULL ) -{ - Attach( key.Detach() ); -} - -inline CRegKey::CRegKey(HKEY hKey) throw() : - m_hKey(hKey) -{ -} - -inline CRegKey::~CRegKey() throw() -{Close();} - -inline CRegKey& CRegKey::operator=( CRegKey& key ) throw() -{ - if(m_hKey!=key.m_hKey) - { - Close(); - Attach( key.Detach() ); - } - return( *this ); -} - -inline CRegKey::operator HKEY() const throw() -{return m_hKey;} - -inline HKEY CRegKey::Detach() throw() -{ - HKEY hKey = m_hKey; - m_hKey = NULL; - return hKey; -} - -inline void CRegKey::Attach(HKEY hKey) throw() -{ - ATLASSUME(m_hKey == NULL); - m_hKey = hKey; -} - -inline LONG CRegKey::DeleteSubKey(LPCTSTR lpszSubKey) throw() -{ - ATLASSUME(m_hKey != NULL); - return RegDeleteKey(m_hKey, lpszSubKey); -} - -inline LONG CRegKey::DeleteValue(LPCTSTR lpszValue) throw() -{ - ATLASSUME(m_hKey != NULL); - return RegDeleteValue(m_hKey, (LPTSTR)lpszValue); -} - -inline LONG CRegKey::Close() throw() -{ - LONG lRes = ERROR_SUCCESS; - if (m_hKey != NULL) - { - lRes = RegCloseKey(m_hKey); - m_hKey = NULL; - } - return lRes; -} - -inline LONG CRegKey::Flush() throw() -{ - ATLASSUME(m_hKey != NULL); - - return ::RegFlushKey(m_hKey); -} - -inline LONG CRegKey::EnumKey(__in DWORD iIndex, __out_ecount_part_z(*pnNameLength, *pnNameLength) LPTSTR pszName, __inout LPDWORD pnNameLength, __out_opt FILETIME* pftLastWriteTime) throw() -{ - FILETIME ftLastWriteTime; - - ATLASSUME(m_hKey != NULL); - if (pftLastWriteTime == NULL) - { - pftLastWriteTime = &ftLastWriteTime; - } - - return ::RegEnumKeyEx(m_hKey, iIndex, pszName, pnNameLength, NULL, NULL, NULL, pftLastWriteTime); -} - -inline LONG CRegKey::NotifyChangeKeyValue(BOOL bWatchSubtree, DWORD dwNotifyFilter, HANDLE hEvent, BOOL bAsync) throw() -{ - ATLASSUME(m_hKey != NULL); - ATLASSERT((hEvent != NULL) || !bAsync); - - return ::RegNotifyChangeKeyValue(m_hKey, bWatchSubtree, dwNotifyFilter, hEvent, bAsync); -} - -inline LONG CRegKey::Create(__in HKEY hKeyParent, __in_z LPCTSTR lpszKeyName, - __in_z LPTSTR lpszClass, __in DWORD dwOptions, __in REGSAM samDesired, - __in_opt LPSECURITY_ATTRIBUTES lpSecAttr, __in_opt LPDWORD lpdwDisposition) throw() -{ - ATLASSERT(hKeyParent != NULL); - DWORD dw; - HKEY hKey = NULL; - LONG lRes = RegCreateKeyEx(hKeyParent, lpszKeyName, 0, - lpszClass, dwOptions, samDesired, lpSecAttr, &hKey, &dw); - if (lpdwDisposition != NULL) - *lpdwDisposition = dw; - if (lRes == ERROR_SUCCESS) - { - lRes = Close(); - m_hKey = hKey; - } - return lRes; -} - -inline LONG CRegKey::Open(HKEY hKeyParent, LPCTSTR lpszKeyName, REGSAM samDesired) throw() -{ - ATLASSERT(hKeyParent != NULL); - HKEY hKey = NULL; - LONG lRes = RegOpenKeyEx(hKeyParent, lpszKeyName, 0, samDesired, &hKey); - if (lRes == ERROR_SUCCESS) - { - lRes = Close(); - ATLASSERT(lRes == ERROR_SUCCESS); - m_hKey = hKey; - } - return lRes; -} - -#pragma warning(push) -#pragma warning(disable: 4996) -inline LONG CRegKey::QueryValue(DWORD& dwValue, LPCTSTR lpszValueName) -{ - DWORD dwType = NULL; - DWORD dwCount = sizeof(DWORD); - LONG lRes = RegQueryValueEx(m_hKey, lpszValueName, NULL, &dwType, - (LPBYTE)&dwValue, &dwCount); - ATLASSERT((lRes!=ERROR_SUCCESS) || (dwType == REG_DWORD)); - ATLASSERT((lRes!=ERROR_SUCCESS) || (dwCount == sizeof(DWORD))); - if (dwType != REG_DWORD) - return ERROR_INVALID_DATA; - return lRes; -} - -#pragma warning(disable: 6053) -inline LONG CRegKey::QueryValue(__out_ecount_part_z_opt(*pdwCount, *pdwCount) LPTSTR pszValue, __in_z_opt LPCTSTR lpszValueName, __inout DWORD* pdwCount) -{ - ATLENSURE(pdwCount != NULL); - DWORD dwType = NULL; - LONG lRes = RegQueryValueEx(m_hKey, lpszValueName, NULL, &dwType, (LPBYTE)pszValue, pdwCount); - ATLASSERT((lRes!=ERROR_SUCCESS) || (dwType == REG_SZ) || - (dwType == REG_MULTI_SZ) || (dwType == REG_EXPAND_SZ)); - if (pszValue != NULL) - { - if(*pdwCount>0) - { - switch(dwType) - { - case REG_SZ: - case REG_EXPAND_SZ: - if ((*pdwCount) % sizeof(TCHAR) != 0 || pszValue[(*pdwCount) / sizeof(TCHAR) - 1] != 0) - { - pszValue[0]=_T('\0'); - return ERROR_INVALID_DATA; - } - break; - case REG_MULTI_SZ: - if ((*pdwCount) % sizeof(TCHAR) != 0 || (*pdwCount) / sizeof(TCHAR) < 1 || pszValue[(*pdwCount) / sizeof(TCHAR) -1] != 0 || (((*pdwCount) / sizeof(TCHAR))>1 && pszValue[(*pdwCount) / sizeof(TCHAR) - 2] != 0) ) - { - pszValue[0]=_T('\0'); - return ERROR_INVALID_DATA; - } - break; - default: - // Ensure termination - pszValue[0]=_T('\0'); - return ERROR_INVALID_DATA; - } - } - else - { - // this is a blank one with no data yet - // Ensure termination - pszValue[0]=_T('\0'); - } - } - return lRes; -} -#pragma warning(pop) - -inline LONG CRegKey::QueryValue(LPCTSTR pszValueName, DWORD* pdwType, void* pData, ULONG* pnBytes) throw() -{ - ATLASSUME(m_hKey != NULL); - - return( ::RegQueryValueEx(m_hKey, pszValueName, NULL, pdwType, static_cast< LPBYTE >( pData ), pnBytes) ); -} - -inline LONG CRegKey::QueryDWORDValue(LPCTSTR pszValueName, DWORD& dwValue) throw() -{ - LONG lRes; - ULONG nBytes; - DWORD dwType; - - ATLASSUME(m_hKey != NULL); - - nBytes = sizeof(DWORD); - lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast(&dwValue), - &nBytes); - if (lRes != ERROR_SUCCESS) - return lRes; - if (dwType != REG_DWORD) - return ERROR_INVALID_DATA; - - return ERROR_SUCCESS; -} -inline LONG CRegKey::QueryQWORDValue(LPCTSTR pszValueName, ULONGLONG& qwValue) throw() -{ - LONG lRes; - ULONG nBytes; - DWORD dwType; - - ATLASSUME(m_hKey != NULL); - - nBytes = sizeof(ULONGLONG); - lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast(&qwValue), - &nBytes); - if (lRes != ERROR_SUCCESS) - return lRes; - if (dwType != REG_QWORD) - return ERROR_INVALID_DATA; - - return ERROR_SUCCESS; -} - -inline LONG CRegKey::QueryBinaryValue(LPCTSTR pszValueName, void* pValue, ULONG* pnBytes) throw() -{ - LONG lRes; - DWORD dwType; - - ATLASSERT(pnBytes != NULL); - ATLASSUME(m_hKey != NULL); - - lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast(pValue), - pnBytes); - if (lRes != ERROR_SUCCESS) - return lRes; - if (dwType != REG_BINARY) - return ERROR_INVALID_DATA; - - return ERROR_SUCCESS; -} - -#pragma warning(push) -#pragma warning(disable: 6053) -/* prefast noise VSW 496818 */ -inline LONG CRegKey::QueryStringValue(LPCTSTR pszValueName, LPTSTR pszValue, ULONG* pnChars) throw() -{ - LONG lRes; - DWORD dwType; - ULONG nBytes; - - ATLASSUME(m_hKey != NULL); - ATLASSERT(pnChars != NULL); - - nBytes = (*pnChars)*sizeof(TCHAR); - *pnChars = 0; - lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast(pszValue), - &nBytes); - - if (lRes != ERROR_SUCCESS) - { - return lRes; - } - - if(dwType != REG_SZ && dwType != REG_EXPAND_SZ) - { - return ERROR_INVALID_DATA; - } - - if (pszValue != NULL) - { - if(nBytes!=0) - { - if ((nBytes % sizeof(TCHAR) != 0) || (pszValue[nBytes / sizeof(TCHAR) -1] != 0)) - { - return ERROR_INVALID_DATA; - } - } - else - { - pszValue[0]=_T('\0'); - } - } - - *pnChars = nBytes/sizeof(TCHAR); - - return ERROR_SUCCESS; -} -#pragma warning(pop) - -#pragma warning(push) -#pragma warning(disable: 6053) -/* prefast noise VSW 496818 */ -inline LONG CRegKey::QueryMultiStringValue(LPCTSTR pszValueName, LPTSTR pszValue, ULONG* pnChars) throw() -{ - LONG lRes; - DWORD dwType; - ULONG nBytes; - - ATLASSUME(m_hKey != NULL); - ATLASSERT(pnChars != NULL); - - if (pszValue != NULL && *pnChars < 2) - return ERROR_INSUFFICIENT_BUFFER; - - nBytes = (*pnChars)*sizeof(TCHAR); - *pnChars = 0; - - lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast(pszValue), - &nBytes); - if (lRes != ERROR_SUCCESS) - return lRes; - if (dwType != REG_MULTI_SZ) - return ERROR_INVALID_DATA; - if (pszValue != NULL && (nBytes % sizeof(TCHAR) != 0 || nBytes / sizeof(TCHAR) < 1 || pszValue[nBytes / sizeof(TCHAR) -1] != 0 || ((nBytes/sizeof(TCHAR))>1 && pszValue[nBytes / sizeof(TCHAR) - 2] != 0))) - return ERROR_INVALID_DATA; - - *pnChars = nBytes/sizeof(TCHAR); - - return ERROR_SUCCESS; -} -#pragma warning(pop) - -inline LONG CRegKey::QueryGUIDValue(LPCTSTR pszValueName, GUID& guidValue) throw() -{ - TCHAR szGUID[64]; - LONG lRes; - ULONG nCount; - HRESULT hr; - - ATLASSUME(m_hKey != NULL); - - guidValue = GUID_NULL; - - nCount = 64; - lRes = QueryStringValue(pszValueName, szGUID, &nCount); - - if (lRes != ERROR_SUCCESS) - return lRes; - - if(szGUID[0] != _T('{')) - return ERROR_INVALID_DATA; - - USES_CONVERSION_EX; - LPOLESTR lpstr = T2OLE_EX(szGUID, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if(lpstr == NULL) - return E_OUTOFMEMORY; -#endif - - hr = ::CLSIDFromString(lpstr, &guidValue); - if (FAILED(hr)) - return ERROR_INVALID_DATA; - - return ERROR_SUCCESS; -} - -inline LONG WINAPI CRegKey::SetValue(HKEY hKeyParent, LPCTSTR lpszKeyName, LPCTSTR lpszValue, LPCTSTR lpszValueName) -{ - ATLASSERT(lpszValue != NULL); - CRegKey key; - LONG lRes = key.Create(hKeyParent, lpszKeyName); - if (lRes == ERROR_SUCCESS) - lRes = key.SetStringValue(lpszValueName, lpszValue); - return lRes; -} - -inline LONG CRegKey::SetKeyValue(LPCTSTR lpszKeyName, LPCTSTR lpszValue, LPCTSTR lpszValueName) throw() -{ - ATLASSERT(lpszValue != NULL); - CRegKey key; - LONG lRes = key.Create(m_hKey, lpszKeyName); - if (lRes == ERROR_SUCCESS) - lRes = key.SetStringValue(lpszValueName, lpszValue); - return lRes; -} - -#pragma warning(push) -#pragma warning(disable: 4996) -inline LONG CRegKey::SetValue(DWORD dwValue, LPCTSTR pszValueName) -{ - ATLASSUME(m_hKey != NULL); - return SetDWORDValue(pszValueName, dwValue); -} - -inline LONG CRegKey::SetValue(LPCTSTR lpszValue, LPCTSTR lpszValueName, bool bMulti, int nValueLen) -{ - ATLENSURE(lpszValue != NULL); - ATLASSUME(m_hKey != NULL); - - if (bMulti && nValueLen == -1) - return ERROR_INVALID_PARAMETER; - - if (nValueLen == -1) - nValueLen = lstrlen(lpszValue) + 1; - - DWORD dwType = bMulti ? REG_MULTI_SZ : REG_SZ; - - return ::RegSetValueEx(m_hKey, lpszValueName, NULL, dwType, - reinterpret_cast(lpszValue), nValueLen*sizeof(TCHAR)); -} -#pragma warning(pop) - -inline LONG CRegKey::SetValue(LPCTSTR pszValueName, DWORD dwType, const void* pValue, ULONG nBytes) throw() -{ - ATLASSUME(m_hKey != NULL); - return ::RegSetValueEx(m_hKey, pszValueName, NULL, dwType, static_cast(pValue), nBytes); -} - -inline LONG CRegKey::SetBinaryValue(LPCTSTR pszValueName, const void* pData, ULONG nBytes) throw() -{ - ATLASSUME(m_hKey != NULL); - return ::RegSetValueEx(m_hKey, pszValueName, NULL, REG_BINARY, reinterpret_cast(pData), nBytes); -} - -inline LONG CRegKey::SetDWORDValue(LPCTSTR pszValueName, DWORD dwValue) throw() -{ - ATLASSUME(m_hKey != NULL); - return ::RegSetValueEx(m_hKey, pszValueName, NULL, REG_DWORD, reinterpret_cast(&dwValue), sizeof(DWORD)); -} - -inline LONG CRegKey::SetQWORDValue(LPCTSTR pszValueName, ULONGLONG qwValue) throw() -{ - ATLASSUME(m_hKey != NULL); - return ::RegSetValueEx(m_hKey, pszValueName, NULL, REG_QWORD, reinterpret_cast(&qwValue), sizeof(ULONGLONG)); -} - -inline LONG CRegKey::SetStringValue(__in_z_opt LPCTSTR pszValueName, __in_z LPCTSTR pszValue, __in DWORD dwType) throw() -{ - ATLASSUME(m_hKey != NULL); - ATLENSURE(pszValue != NULL); - ATLASSERT((dwType == REG_SZ) || (dwType == REG_EXPAND_SZ)); - - return ::RegSetValueEx(m_hKey, pszValueName, NULL, dwType, reinterpret_cast(pszValue), (lstrlen(pszValue)+1)*sizeof(TCHAR)); -} - -inline LONG CRegKey::SetMultiStringValue(LPCTSTR pszValueName, LPCTSTR pszValue) throw() -{ - LPCTSTR pszTemp; - ULONG nBytes; - ULONG nLength; - - ATLASSUME(m_hKey != NULL); - ATLENSURE(pszValue != NULL); - - // Find the total length (in bytes) of all of the strings, including the - // terminating '\0' of each string, and the second '\0' that terminates - // the list. - nBytes = 0; - pszTemp = pszValue; - do - { - nLength = lstrlen(pszTemp)+1; - pszTemp += nLength; - nBytes += nLength*sizeof(TCHAR); - } while (nLength != 1); - - return ::RegSetValueEx(m_hKey, pszValueName, NULL, REG_MULTI_SZ, reinterpret_cast(pszValue), - nBytes); -} - -inline LONG CRegKey::SetGUIDValue(LPCTSTR pszValueName, REFGUID guidValue) throw() -{ - OLECHAR szGUID[64]; - - ATLASSUME(m_hKey != NULL); - - ::StringFromGUID2(guidValue, szGUID, 64); - - USES_CONVERSION_EX; - LPCTSTR lpstr = OLE2CT_EX(szGUID, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if(lpstr == NULL) - return E_OUTOFMEMORY; -#endif - return SetStringValue(pszValueName, lpstr); -} - -inline LONG CRegKey::GetKeySecurity(SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR psd, LPDWORD pnBytes) throw() -{ - ATLASSUME(m_hKey != NULL); - ATLASSERT(pnBytes != NULL); - - return ::RegGetKeySecurity(m_hKey, si, psd, pnBytes); -} - -inline LONG CRegKey::SetKeySecurity(SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR psd) throw() -{ - ATLASSUME(m_hKey != NULL); - ATLASSERT(psd != NULL); - - return ::RegSetKeySecurity(m_hKey, si, psd); -} - -inline LONG CRegKey::RecurseDeleteKey(LPCTSTR lpszKey) throw() -{ - CRegKey key; - LONG lRes = key.Open(m_hKey, lpszKey, KEY_READ | KEY_WRITE); - if (lRes != ERROR_SUCCESS) - { - if (lRes != ERROR_FILE_NOT_FOUND && lRes != ERROR_PATH_NOT_FOUND) - { - ATLTRACE(atlTraceCOM, 0, _T("CRegKey::RecurseDeleteKey : Failed to Open Key %s(Error = %d)\n"), lpszKey, lRes); - } - return lRes; - } - FILETIME time; - DWORD dwSize = 256; - TCHAR szBuffer[256]; - while (RegEnumKeyEx(key.m_hKey, 0, szBuffer, &dwSize, NULL, NULL, NULL, - &time)==ERROR_SUCCESS) - { - lRes = key.RecurseDeleteKey(szBuffer); - if (lRes != ERROR_SUCCESS) - return lRes; - dwSize = 256; - } - key.Close(); - return DeleteSubKey(lpszKey); -} - -#ifndef _ATL_NO_COMMODULE - -inline HRESULT CComModule::RegisterProgID(LPCTSTR lpszCLSID, LPCTSTR lpszProgID, LPCTSTR lpszUserDesc) -{ - CRegKey keyProgID; - LONG lRes = keyProgID.Create(HKEY_CLASSES_ROOT, lpszProgID, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE); - if (lRes == ERROR_SUCCESS) - { - lRes = keyProgID.SetStringValue(NULL, lpszUserDesc); - if (lRes == ERROR_SUCCESS) - { - lRes = keyProgID.SetKeyValue(_T("CLSID"), lpszCLSID); - if (lRes == ERROR_SUCCESS) - return S_OK; - } - } - return AtlHresultFromWin32(lRes); -} - -inline HRESULT CComModule::RegisterAppId(LPCTSTR pAppId) -{ - CRegKey keyAppID; - HRESULT hr = S_OK; - LONG lRet; - - if ( (lRet = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_WRITE)) == ERROR_SUCCESS) - { - TCHAR szModule1[MAX_PATH]; - TCHAR szModule2[MAX_PATH]; - TCHAR* pszFileName; - - DWORD dwFLen = ::GetModuleFileName(GetModuleInstance(), szModule1, MAX_PATH); - if ( dwFLen != 0 && dwFLen != MAX_PATH ) - { - if (::GetFullPathName(szModule1, MAX_PATH, szModule2, &pszFileName) != 0) - { - CRegKey keyAppIDEXE; - if ( (lRet = keyAppIDEXE.Create(keyAppID, pszFileName, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE)) == ERROR_SUCCESS) - { - lRet = keyAppIDEXE.SetStringValue(_T("AppID"), pAppId); - if (lRet != ERROR_SUCCESS) - { - ATLTRACE(atlTraceCOM, 0, _T("CComModule::RegisterAppId : Failed to set app id string value\n")); - hr = AtlHresultFromWin32(lRet); - return hr; - } - } - else - { - ATLTRACE(atlTraceCOM, 0, _T("CComModule::RegisterAppId : Failed to create file name key\n")); - hr = AtlHresultFromWin32(lRet); - return hr; - } - if ( (lRet = keyAppIDEXE.Create(keyAppID, pAppId, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE)) == ERROR_SUCCESS) - { - lRet = keyAppIDEXE.SetStringValue(NULL, pszFileName); - if (lRet != ERROR_SUCCESS) - { - ATLTRACE(atlTraceCOM, 0, _T("CComModule::RegisterAppId : Failed to set file name string value\n")); - hr = AtlHresultFromWin32(lRet); - return hr; - } - } - else - { - ATLTRACE(atlTraceCOM, 0, _T("CComModule::RegisterAppId : Failed to create app id key\n")); - hr = AtlHresultFromWin32(lRet); - return hr; - } - } - else - { - ATLTRACE(atlTraceCOM, 0, _T("CComModule::RegisterAppId : Failed to get full path name for file %s\n"), szModule1); - hr = AtlHresultFromLastError(); - } - } - else - { - ATLTRACE(atlTraceCOM, 0, _T("CComModule::RegisterAppId : Failed to get module name\n")); - if( dwFLen == 0 ) - hr = AtlHresultFromLastError(); - else if( dwFLen == MAX_PATH ) - hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - } - } - else - { - ATLTRACE(atlTraceCOM, 0, _T("CComModule::RegisterAppId : Failed to open registry key\n")); - hr = AtlHresultFromWin32(lRet); - } - return hr; -} - -inline HRESULT CComModule::UnregisterAppId(LPCTSTR pAppId) -{ - CRegKey keyAppID; - HRESULT hr = S_OK; - LONG lRet = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_READ | KEY_WRITE); - - if (lRet == ERROR_SUCCESS) - { - TCHAR szModule1[MAX_PATH]; - TCHAR szModule2[MAX_PATH]; - TCHAR* pszFileName; - - DWORD dwFLen = ::GetModuleFileName(GetModuleInstance(), szModule1, MAX_PATH); - if ( dwFLen != 0 && dwFLen != MAX_PATH ) - { - if (::GetFullPathName(szModule1, MAX_PATH, szModule2, &pszFileName) != 0) - { - if ((lRet = keyAppID.RecurseDeleteKey(pAppId)) != ERROR_SUCCESS) - { - if (lRet != ERROR_FILE_NOT_FOUND) - hr = AtlHresultFromWin32(lRet); - } - if ((lRet = keyAppID.RecurseDeleteKey(pszFileName)) != ERROR_SUCCESS) - { - if (lRet != ERROR_FILE_NOT_FOUND) - hr = AtlHresultFromWin32(lRet); - } - } - else - { - ATLTRACE(atlTraceCOM, 0, _T("CComModule::UnregisterAppId : Failed to get full path name for file %s\n"), szModule1); - hr = AtlHresultFromLastError(); - } - } - else - { - ATLTRACE(atlTraceCOM, 0, _T("CComModule::UnregisterAppId : Failed to get module name\n")); - if( dwFLen == 0 ) - hr = AtlHresultFromLastError(); - else if( dwFLen == MAX_PATH ) - hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - } - } - else - { - if (lRet != ERROR_FILE_NOT_FOUND && lRet != ERROR_PATH_NOT_FOUND) - { - ATLTRACE(atlTraceCOM, 0, _T("CComModule::UnregisterAppId : Failed to open registry key\n")); - hr = AtlHresultFromWin32(lRet); - } - } - return hr; -} -#endif // !_ATL_NO_COMMODULE - -#ifdef _ATL_STATIC_REGISTRY -} // namespace ATL - - -#include - - - -namespace ATL -{ - -// Statically linking to Registry Ponent -inline HRESULT WINAPI CAtlModule::UpdateRegistryFromResourceS(LPCTSTR lpszRes, BOOL bRegister, - struct _ATL_REGMAP_ENTRY* pMapEntries /*= NULL*/) throw() -{ - CRegObject ro; - HRESULT hr = ro.FinalConstruct(); - if (FAILED(hr)) - { - return hr; - } - - if (pMapEntries != NULL) - { - while (pMapEntries->szKey != NULL) - { - ATLASSERT(NULL != pMapEntries->szData); - ro.AddReplacement(pMapEntries->szKey, pMapEntries->szData); - pMapEntries++; - } - } - - hr = AddCommonRGSReplacements(&ro); - if (FAILED(hr)) - return hr; - - USES_CONVERSION_EX; - TCHAR szModule[MAX_PATH]; - HINSTANCE hInst = _AtlBaseModule.GetModuleInstance(); - DWORD dwFLen = GetModuleFileName(hInst, szModule, MAX_PATH); - if( dwFLen == 0 ) - return AtlHresultFromLastError(); - else if( dwFLen == MAX_PATH ) - return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - - - LPOLESTR pszModule; - pszModule = T2OLE_EX(szModule, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if(pszModule == NULL) - return E_OUTOFMEMORY; -#endif - - OLECHAR pszModuleUnquoted[_MAX_PATH * 2]; - EscapeSingleQuote(pszModuleUnquoted, _countof(pszModuleUnquoted), pszModule); - - HRESULT hRes; - if ((hInst == NULL) || (hInst == GetModuleHandle(NULL))) // register as EXE - { - // If Registering as an EXE, then we quote the resultant path. - // We don't do it for a DLL, because LoadLibrary fails if the path is - // quoted - OLECHAR pszModuleQuote[(_MAX_PATH + _ATL_QUOTES_SPACE)*2]; - pszModuleQuote[0] = OLESTR('\"'); - if(!ocscpy_s(pszModuleQuote + 1, (_MAX_PATH + _ATL_QUOTES_SPACE)*2 - 1, pszModuleUnquoted)) - { - return E_FAIL; - } - size_t nLen = ocslen(pszModuleQuote); - pszModuleQuote[nLen] = OLESTR('\"'); - pszModuleQuote[nLen + 1] = 0; - - hRes = ro.AddReplacement(OLESTR("Module"), pszModuleQuote); - } - else - { - hRes = ro.AddReplacement(OLESTR("Module"), pszModuleUnquoted); - } - - if(FAILED(hRes)) - return hRes; - - hRes = ro.AddReplacement(OLESTR("Module_Raw"), pszModuleUnquoted); - if(FAILED(hRes)) - return hRes; - - LPCOLESTR szType = OLESTR("REGISTRY"); - LPCOLESTR pszRes = T2COLE_EX(lpszRes, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if(pszRes == NULL) - return E_OUTOFMEMORY; -#endif - hr = (bRegister) ? ro.ResourceRegisterSz(pszModule, pszRes, szType) : - ro.ResourceUnregisterSz(pszModule, pszRes, szType); - return hr; -} -inline HRESULT WINAPI CAtlModule::UpdateRegistryFromResourceS(UINT nResID, BOOL bRegister, - struct _ATL_REGMAP_ENTRY* pMapEntries /*= NULL*/) throw() -{ - CRegObject ro; - HRESULT hr = ro.FinalConstruct(); - if (FAILED(hr)) - { - return hr; - } - - if (pMapEntries != NULL) - { - while (pMapEntries->szKey != NULL) - { - ATLASSERT(NULL != pMapEntries->szData); - ro.AddReplacement(pMapEntries->szKey, pMapEntries->szData); - pMapEntries++; - } - } - - hr = AddCommonRGSReplacements(&ro); - if (FAILED(hr)) - return hr; - - USES_CONVERSION_EX; - TCHAR szModule[MAX_PATH]; - HINSTANCE hInst = _AtlBaseModule.GetModuleInstance(); - DWORD dwFLen = GetModuleFileName(hInst, szModule, MAX_PATH); - if( dwFLen == 0 ) - return AtlHresultFromLastError(); - else if( dwFLen == MAX_PATH ) - return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - - LPOLESTR pszModule; - pszModule = T2OLE_EX(szModule, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if(pszModule == NULL) - return E_OUTOFMEMORY; -#endif - - OLECHAR pszModuleUnquoted[_MAX_PATH * 2]; - EscapeSingleQuote(pszModuleUnquoted, _countof(pszModuleUnquoted), pszModule); - - HRESULT hRes; - if ((hInst == NULL) || (hInst == GetModuleHandle(NULL))) // register as EXE - { - // If Registering as an EXE, then we quote the resultant path. - // We don't do it for a DLL, because LoadLibrary fails if the path is - // quoted - OLECHAR pszModuleQuote[(_MAX_PATH + _ATL_QUOTES_SPACE)*2]; - pszModuleQuote[0] = OLESTR('\"'); - if(!ocscpy_s(pszModuleQuote + 1, (_MAX_PATH + _ATL_QUOTES_SPACE)*2 - 1, pszModuleUnquoted)) - { - return E_FAIL; - } - size_t nLen = ocslen(pszModuleQuote); - pszModuleQuote[nLen] = OLESTR('\"'); - pszModuleQuote[nLen + 1] = 0; - - hRes = ro.AddReplacement(OLESTR("Module"), pszModuleQuote); - } - else - { - hRes = ro.AddReplacement(OLESTR("Module"), pszModuleUnquoted); - } - - if(FAILED(hRes)) - return hRes; - - hRes = ro.AddReplacement(OLESTR("Module_Raw"), pszModuleUnquoted); - if(FAILED(hRes)) - return hRes; - - LPCOLESTR szType = OLESTR("REGISTRY"); - hr = (bRegister) ? ro.ResourceRegister(pszModule, nResID, szType) : - ro.ResourceUnregister(pszModule, nResID, szType); - return hr; -} -#endif //_ATL_STATIC_REGISTRY - -#ifndef _ATL_NO_COMMODULE - -#pragma warning( push ) -#pragma warning( disable: 4996 ) // Disable "deprecated symbol" warning - -inline HRESULT WINAPI CComModule::UpdateRegistryClass(const CLSID& clsid, LPCTSTR lpszProgID, - LPCTSTR lpszVerIndProgID, UINT nDescID, DWORD dwFlags, BOOL bRegister) -{ - if (bRegister) - { - TCHAR szDesc[256]; - LoadString(m_hInst, nDescID, szDesc, 256); - return RegisterClassHelper(clsid, lpszProgID, lpszVerIndProgID, szDesc, dwFlags); - } - return UnregisterClassHelper(clsid, lpszProgID, lpszVerIndProgID); -} - -inline HRESULT WINAPI CComModule::UpdateRegistryClass(const CLSID& clsid, LPCTSTR lpszProgID, - LPCTSTR lpszVerIndProgID, LPCTSTR szDesc, DWORD dwFlags, BOOL bRegister) -{ - if (bRegister) - return RegisterClassHelper(clsid, lpszProgID, lpszVerIndProgID, szDesc, dwFlags); - return UnregisterClassHelper(clsid, lpszProgID, lpszVerIndProgID); -} - -inline HRESULT WINAPI CComModule::RegisterClassHelper(const CLSID& clsid, LPCTSTR lpszProgID, - LPCTSTR lpszVerIndProgID, LPCTSTR szDesc, DWORD dwFlags) -{ - static const TCHAR szProgID[] = _T("ProgID"); - static const TCHAR szVIProgID[] = _T("VersionIndependentProgID"); - static const TCHAR szLS32[] = _T("LocalServer32"); - static const TCHAR szIPS32[] = _T("InprocServer32"); - static const TCHAR szThreadingModel[] = _T("ThreadingModel"); - static const TCHAR szAUTPRX32[] = _T("AUTPRX32.DLL"); - static const TCHAR szApartment[] = _T("Apartment"); - static const TCHAR szBoth[] = _T("both"); - USES_CONVERSION_EX; - TCHAR szModule[_MAX_PATH + _ATL_QUOTES_SPACE]; - - ATLENSURE(lpszProgID && lpszVerIndProgID || !lpszProgID && !lpszVerIndProgID); - - if (!szDesc) - { - szDesc = _T(""); - } - - // If the ModuleFileName's length is equal or greater than the 3rd parameter - // (length of the buffer passed),GetModuleFileName fills the buffer (truncates - // if neccessary), but doesn't null terminate it. It returns the same value as - // the 3rd parameter passed. So if the return value is the same as the 3rd param - // then you have a non null terminated buffer (which may or may not be truncated) - // We pass (szModule + 1) because in case it's an EXE we need to quote the PATH - // The quote is done later in this method before the SetKeyValue is called - DWORD dwLen = GetModuleFileName(m_hInst, szModule + 1, MAX_PATH); - if (dwLen == 0) - { - return AtlHresultFromLastError(); - } - else if( dwLen == MAX_PATH ) - { - return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - } - - LPOLESTR lpOleStr; - HRESULT hRes = StringFromCLSID(clsid, &lpOleStr); - if (FAILED(hRes)) - return hRes; - - LPTSTR lpszCLSID = OLE2T_EX(lpOleStr, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if(lpszCLSID == NULL) - { - CoTaskMemFree(lpOleStr); - return E_OUTOFMEMORY; - } -#endif - - hRes = lpszProgID ? RegisterProgID(lpszCLSID, lpszProgID, szDesc) : S_OK; - if (hRes == S_OK) - hRes = lpszVerIndProgID ? RegisterProgID(lpszCLSID, lpszVerIndProgID, szDesc) : S_OK; - LONG lRes = ERROR_SUCCESS; - if (hRes == S_OK) - { - CRegKey key; - lRes = key.Open(HKEY_CLASSES_ROOT, _T("CLSID"), KEY_READ | KEY_WRITE); - if (lRes == ERROR_SUCCESS) - { - lRes = key.Create(key, lpszCLSID, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE); - if (lRes == ERROR_SUCCESS) - { - lRes = key.SetStringValue(NULL, szDesc); - if (lRes == ERROR_SUCCESS) - { - lRes = lpszProgID ? key.SetKeyValue(szProgID, lpszProgID) : ERROR_SUCCESS; - if (lRes == ERROR_SUCCESS) - { - lRes = lpszVerIndProgID ? key.SetKeyValue(szVIProgID, lpszVerIndProgID) : ERROR_SUCCESS; - if (lRes == ERROR_SUCCESS) - { - if ((m_hInst == NULL) || (m_hInst == GetModuleHandle(NULL))) // register as EXE - { - // If Registering as an EXE, then we quote the resultant path. - // We don't do it for a DLL, because LoadLibrary fails if the path is - // quoted - szModule[0] = _T('\"'); - szModule[dwLen + 1] = _T('\"'); - szModule[dwLen + 2] = 0; - - lRes = key.SetKeyValue(szLS32, szModule); - } - else - { - lRes = key.SetKeyValue(szIPS32, (dwFlags & AUTPRXFLAG) ? szAUTPRX32 : szModule + 1); - if (lRes == ERROR_SUCCESS) - { - LPCTSTR lpszModel = (dwFlags & THREADFLAGS_BOTH) ? szBoth : - (dwFlags & THREADFLAGS_APARTMENT) ? szApartment : NULL; - if (lpszModel != NULL) - lRes = key.SetKeyValue(szIPS32, lpszModel, szThreadingModel); - } - } - } - } - } - } - } - } - CoTaskMemFree(lpOleStr); - if (lRes != ERROR_SUCCESS) - hRes = AtlHresultFromWin32(lRes); - return hRes; -} - -inline HRESULT WINAPI CComModule::UnregisterClassHelper(const CLSID& clsid, LPCTSTR lpszProgID, - LPCTSTR lpszVerIndProgID) -{ - USES_CONVERSION_EX; - CRegKey key; - LONG lRet; - - key.Attach(HKEY_CLASSES_ROOT); - if (lpszProgID != NULL && lpszProgID[0]!=_T('\0')) - { - lRet = key.RecurseDeleteKey(lpszProgID); - if (lRet != ERROR_SUCCESS && lRet != ERROR_FILE_NOT_FOUND && lRet != ERROR_PATH_NOT_FOUND) - { - ATLTRACE(atlTraceCOM, 0, _T("Failed to Unregister ProgID : %s\n"), lpszProgID); - key.Detach(); - return AtlHresultFromWin32(lRet); - } - } - if (lpszVerIndProgID != NULL && lpszVerIndProgID[0]!=_T('\0')) - { - lRet = key.RecurseDeleteKey(lpszVerIndProgID); - if (lRet != ERROR_SUCCESS && lRet != ERROR_FILE_NOT_FOUND && lRet != ERROR_PATH_NOT_FOUND) - { - ATLTRACE(atlTraceCOM, 0, _T("Failed to Unregister Version Independent ProgID : %s\n"), lpszVerIndProgID); - key.Detach(); - return AtlHresultFromWin32(lRet); - } - } - LPOLESTR lpOleStr; - HRESULT hr = StringFromCLSID(clsid, &lpOleStr); - if (SUCCEEDED(hr)) - { - LPTSTR lpsz = OLE2T_EX(lpOleStr, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if(lpsz == NULL) - { - CoTaskMemFree(lpOleStr); - return E_OUTOFMEMORY; - } -#endif - - lRet = key.Open(key, _T("CLSID"), KEY_READ | KEY_WRITE); - if (lRet == ERROR_SUCCESS) - lRet = key.RecurseDeleteKey(lpsz); - if (lRet != ERROR_SUCCESS && lRet != ERROR_FILE_NOT_FOUND && lRet != ERROR_PATH_NOT_FOUND) - { - ATLTRACE(atlTraceCOM, 0, _T("Failed to delete CLSID : %s\n"), lpsz); - hr = AtlHresultFromWin32(lRet); - } - CoTaskMemFree(lpOleStr); - } - else - { - ATLTRACE(atlTraceCOM, 0, _T("Failed to delete CLSID : {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"), - clsid.Data1, - clsid.Data2, - clsid.Data3, - clsid.Data4[0], - clsid.Data4[1], - clsid.Data4[2], - clsid.Data4[3], - clsid.Data4[4], - clsid.Data4[5], - clsid.Data4[6], - clsid.Data4[7] - ); - } - key.Detach(); - return hr; -} - -#pragma warning( pop ) // Disable "deprecated symbol" warning - -#endif // !_ATL_NO_COMMODULE - -#ifdef _ATL_DEBUG_INTERFACES - -inline void _QIThunk::Dump() throw() -{ - TCHAR buf[512+1]; - if (m_dwRef != 0) - { -#if _SECURE_ATL && !defined(_ATL_MIN_CRT) - _stprintf_s(buf, _countof(buf), _T("ATL: QIThunk - %-10d\tLEAK :\tObject = 0x%p\tRefcount = %d\tMaxRefCount = %d\t"), - m_nIndex, m_pUnk, m_dwRef, m_dwMaxRef); -#else - wsprintf(buf, _T("ATL: QIThunk - %-10d\tLEAK :\tObject = 0x%p\tRefcount = %d\tMaxRefCount = %d\t"), m_nIndex, m_pUnk, m_dwRef, m_dwMaxRef); -#endif - buf[_countof(buf)-1] = 0; - OutputDebugString(buf); - AtlDumpIID(m_iid, m_lpszClassName, S_OK); - } - else - { -#if _SECURE_ATL && !defined(_ATL_MIN_CRT) - _stprintf_s(buf, _countof(buf), _T("ATL: QIThunk - %-10d\tNonAddRef LEAK :\tObject = 0x%p\t"), m_nIndex, m_pUnk); -#else - wsprintf(buf, _T("ATL: QIThunk - %-10d\tNonAddRef LEAK :\tObject = 0x%p\t"), m_nIndex, m_pUnk); -#endif - buf[_countof(buf)-1] = 0; - OutputDebugString(buf); - AtlDumpIID(m_iid, m_lpszClassName, S_OK); - } -} - -#endif // _ATL_DEBUG_INTERFACES - -#if defined(_ATL_DEBUG_INTERFACES) || defined(_ATL_DEBUG_QI) -__forceinline HRESULT WINAPI AtlDumpIID(REFIID iid, LPCTSTR pszClassName, HRESULT hr) throw() -{ - USES_CONVERSION_EX; - CRegKey key; - TCHAR szName[100]; - DWORD dwType; - DWORD dw = sizeof(szName); - - LPOLESTR pszGUID = NULL; - if (FAILED(StringFromCLSID(iid, &pszGUID))) - return hr; - - OutputDebugString(pszClassName); - OutputDebugString(_T(" - ")); - - LPTSTR lpszGUID = OLE2T_EX(pszGUID, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if(lpszGUID == NULL) - { - CoTaskMemFree(pszGUID); - return hr; - } -#endif - // Attempt to find it in the interfaces section - if (key.Open(HKEY_CLASSES_ROOT, _T("Interface"), KEY_READ) == ERROR_SUCCESS) - { - if (key.Open(key, lpszGUID, KEY_READ) == ERROR_SUCCESS) - { - *szName = 0; - if (RegQueryValueEx(key.m_hKey, (LPTSTR)NULL, NULL, &dwType, (LPBYTE)szName, &dw) == ERROR_SUCCESS) - { - OutputDebugString(szName); - } - } - } - // Attempt to find it in the clsid section - if (key.Open(HKEY_CLASSES_ROOT, _T("CLSID"), KEY_READ) == ERROR_SUCCESS) - { - if (key.Open(key, lpszGUID, KEY_READ) == ERROR_SUCCESS) - { - *szName = 0; - if (RegQueryValueEx(key.m_hKey, (LPTSTR)NULL, NULL, &dwType, (LPBYTE)szName, &dw) == ERROR_SUCCESS) - { - OutputDebugString(_T("(CLSID\?\?\?) ")); - OutputDebugString(szName); - } - } - } - else - OutputDebugString(lpszGUID); - - if (hr != S_OK) - OutputDebugString(_T(" - failed")); - OutputDebugString(_T("\n")); - CoTaskMemFree(pszGUID); - - return hr; -} -#endif // _ATL_DEBUG_INTERFACES || _ATL_DEBUG_QI - - - -// WM_FORWARDMSG - used to forward a message to another window for processing -// WPARAM - DWORD dwUserData - defined by user -// LPARAM - LPMSG pMsg - a pointer to the MSG structure -// return value - 0 if the message was not processed, nonzero if it was -#define WM_FORWARDMSG 0x037F - -}; //namespace ATL - - -#ifndef _ATL_NO_AUTOMATIC_NAMESPACE -using namespace ATL; -#endif //!_ATL_NO_AUTOMATIC_NAMESPACE - -#ifdef _ATL_ATTRIBUTES -#include -#endif - - - -namespace ATL -{ - -// All exports go here -// Pull in if building ATL DLL or not linking to ATL DLL -#ifndef _ATL_DLL - -///////////////////////////////////////////////////////////////////////////// -// statics - -static inline UINT WINAPI AtlGetDirLen(LPCOLESTR lpszPathName) throw() -{ - ATLASSERT(lpszPathName != NULL); - if(lpszPathName == NULL) - return 0; - - // always capture the complete file name including extension (if present) - LPCOLESTR lpszTemp = lpszPathName; - for (LPCOLESTR lpsz = lpszPathName; *lpsz != NULL; ) - { - LPCOLESTR lp = CharNextO(lpsz); - // remember last directory/drive separator - if (*lpsz == OLESTR('\\') || *lpsz == OLESTR('/') || *lpsz == OLESTR(':')) - lpszTemp = lp; - lpsz = lp; - } - - return UINT( lpszTemp-lpszPathName ); -} - -static inline LPTSTR AtlFindExtension(LPCTSTR psz) -{ - if (psz == NULL) - return NULL; - LPCTSTR pszRemember = NULL; - while (*psz != NULL) - { - switch(*psz) - { - case _T('\\'): - pszRemember = NULL; - break; - case _T('.'): - pszRemember = psz; - break; - default: - break; - } - psz = CharNext(psz); - } - return (LPTSTR)((pszRemember == NULL) ? psz : pszRemember); -} - - -///////////////////////////////////////////////////////////////////////////// -// TypeLib registration - -#define _ATL_MAX_PATH_PLUS_INDEX (_MAX_PATH + _ATL_TYPELIB_INDEX_LENGTH) - -ATLINLINE ATLAPI AtlLoadTypeLib(HINSTANCE hInstTypeLib, LPCOLESTR lpszIndex, BSTR* pbstrPath, ITypeLib** ppTypeLib) -{ - ATLASSERT(pbstrPath != NULL && ppTypeLib != NULL); - if (pbstrPath == NULL || ppTypeLib == NULL) - return E_POINTER; - - *pbstrPath = NULL; - *ppTypeLib = NULL; - - USES_CONVERSION_EX; - ATLASSERT(hInstTypeLib != NULL); - TCHAR szModule[_ATL_MAX_PATH_PLUS_INDEX]; - - DWORD dwFLen = GetModuleFileName(hInstTypeLib, szModule, MAX_PATH); - if( dwFLen == 0 ) - return AtlHresultFromLastError(); - else if( dwFLen == MAX_PATH ) - return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - - // get the extension pointer in case of fail - LPTSTR lpszExt = NULL; - - lpszExt = AtlFindExtension(szModule); - - if (lpszIndex != NULL) - { - LPCTSTR lpcszIndex = OLE2CT_EX(lpszIndex, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); - if(lpcszIndex == NULL) - { - return E_OUTOFMEMORY; - } - DWORD nIndexLen = lstrlen(lpcszIndex); - - DWORD newLen = dwFLen + nIndexLen; - if ((newLen < dwFLen) || (newLen < nIndexLen) || (newLen >= _ATL_MAX_PATH_PLUS_INDEX)) - return E_FAIL; -#ifdef UNICODE - Checked::wcscpy_s(szModule + dwFLen, _countof(szModule) - dwFLen, lpcszIndex); -#else - Checked::strcpy_s(szModule + dwFLen, _countof(szModule) - dwFLen, lpcszIndex); -#endif - } - LPOLESTR lpszModule = T2OLE_EX(szModule, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if(lpszModule == NULL) - return E_OUTOFMEMORY; -#endif - HRESULT hr = LoadTypeLib(lpszModule, ppTypeLib); - if (!SUCCEEDED(hr)) - { - // typelib not in module, try .tlb instead - TCHAR szExt[] = _T(".tlb"); - if ((lpszExt - szModule + sizeof(szExt)/sizeof(TCHAR)) > _MAX_PATH) - return E_FAIL; - -#ifdef UNICODE - Checked::wcscpy_s(lpszExt, _countof(szModule) - (lpszExt - szModule), szExt); -#else - Checked::strcpy_s(lpszExt, _countof(szModule) - (lpszExt - szModule), szExt); -#endif - lpszModule = T2OLE_EX(szModule, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if(lpszModule == NULL) - return E_OUTOFMEMORY; -#endif - hr = LoadTypeLib(lpszModule, ppTypeLib); - } - if (SUCCEEDED(hr)) - { - *pbstrPath = ::SysAllocString(lpszModule); - if (*pbstrPath == NULL) - hr = E_OUTOFMEMORY; - } - return hr; -} - -ATLINLINE ATLAPI AtlUnRegisterTypeLib(HINSTANCE hInstTypeLib, LPCOLESTR lpszIndex) -{ - CComBSTR bstrPath; - CComPtr pTypeLib; - HRESULT hr = AtlLoadTypeLib(hInstTypeLib, lpszIndex, &bstrPath, &pTypeLib); - if (SUCCEEDED(hr)) - { - TLIBATTR* ptla; - hr = pTypeLib->GetLibAttr(&ptla); - if (SUCCEEDED(hr)) - { - hr = UnRegisterTypeLib(ptla->guid, ptla->wMajorVerNum, ptla->wMinorVerNum, ptla->lcid, ptla->syskind); - pTypeLib->ReleaseTLibAttr(ptla); - } - } - return hr; -} - -ATLINLINE ATLAPI AtlRegisterTypeLib(HINSTANCE hInstTypeLib, LPCOLESTR lpszIndex) -{ - CComBSTR bstrPath; - CComPtr pTypeLib; - HRESULT hr = AtlLoadTypeLib(hInstTypeLib, lpszIndex, &bstrPath, &pTypeLib); - if (SUCCEEDED(hr)) - { - OLECHAR szDir[MAX_PATH]; - Checked::wcsncpy_s(szDir, MAX_PATH, bstrPath.m_str, bstrPath.Length()); - - szDir[MAX_PATH - 1] = 0; - // If index is specified remove it from the path - if (lpszIndex != NULL) - { - size_t nLenPath = ocslen(szDir); - size_t nLenIndex = ocslen(lpszIndex); - if (memcmp(szDir + nLenPath - nLenIndex, lpszIndex, nLenIndex) == 0) - szDir[nLenPath - nLenIndex] = 0; - } - szDir[AtlGetDirLen(szDir)] = 0; - hr = ::RegisterTypeLib(pTypeLib, bstrPath, szDir); - } - return hr; -} - -///////////////////////////////////////////////////////////////////////////// -// Registration - -// AtlComModuleRegisterServer walks the ATL Autogenerated Object Map and registers each object in the map -// If pCLSID is not NULL then only the object referred to by pCLSID is registered (The default case) -// otherwise all the objects are registered -ATLINLINE ATLAPI AtlComModuleRegisterServer(_ATL_COM_MODULE* pComModule, BOOL bRegTypeLib, const CLSID* pCLSID) -{ - ATLASSERT(pComModule != NULL); - if (pComModule == NULL) - return E_INVALIDARG; - ATLASSERT(pComModule->m_hInstTypeLib != NULL); - - HRESULT hr = S_OK; - - for (_ATL_OBJMAP_ENTRY** ppEntry = pComModule->m_ppAutoObjMapFirst; ppEntry < pComModule->m_ppAutoObjMapLast; ppEntry++) - { - if (*ppEntry != NULL) - { - _ATL_OBJMAP_ENTRY* pEntry = *ppEntry; - if (pCLSID != NULL) - { - if (!IsEqualGUID(*pCLSID, *pEntry->pclsid)) - continue; - } - hr = pEntry->pfnUpdateRegistry(TRUE); - if (FAILED(hr)) - break; - hr = AtlRegisterClassCategoriesHelper( *pEntry->pclsid, - pEntry->pfnGetCategoryMap(), TRUE ); - if (FAILED(hr)) - break; - } - } - - if (SUCCEEDED(hr) && bRegTypeLib) - hr = AtlRegisterTypeLib(pComModule->m_hInstTypeLib, 0); - - return hr; -} - -// AtlComUnregisterServer walks the ATL Object Map and unregisters each object in the map -// If pCLSID is not NULL then only the object referred to by pCLSID is unregistered (The default case) -// otherwise all the objects are unregistered. -ATLINLINE ATLAPI AtlComModuleUnregisterServer(_ATL_COM_MODULE* pComModule, BOOL bUnRegTypeLib, const CLSID* pCLSID) -{ - ATLASSERT(pComModule != NULL); - if (pComModule == NULL) - return E_INVALIDARG; - - HRESULT hr = S_OK; - - for (_ATL_OBJMAP_ENTRY** ppEntry = pComModule->m_ppAutoObjMapFirst; ppEntry < pComModule->m_ppAutoObjMapLast; ppEntry++) - { - if (*ppEntry != NULL) - { - _ATL_OBJMAP_ENTRY* pEntry = *ppEntry; - if (pCLSID != NULL) - { - if (!IsEqualGUID(*pCLSID, *pEntry->pclsid)) - continue; - } - hr = AtlRegisterClassCategoriesHelper( *pEntry->pclsid, pEntry->pfnGetCategoryMap(), FALSE ); - if (FAILED(hr)) - break; - hr = pEntry->pfnUpdateRegistry(FALSE); //unregister - if (FAILED(hr)) - break; - } - } - if (SUCCEEDED(hr) && bUnRegTypeLib) - hr = AtlUnRegisterTypeLib(pComModule->m_hInstTypeLib, 0); - - return hr; -} - -ATLINLINE ATLAPI AtlRegisterClassCategoriesHelper( REFCLSID clsid, - const struct _ATL_CATMAP_ENTRY* pCatMap, BOOL bRegister ) -{ - CComPtr< ICatRegister > pCatRegister; - HRESULT hResult; - const struct _ATL_CATMAP_ENTRY* pEntry; - CATID catid; - - if( pCatMap == NULL ) - { - return( S_OK ); - } - - if (InlineIsEqualGUID(clsid, GUID_NULL)) - { - ATLASSERT(0 && _T("Use OBJECT_ENTRY_NON_CREATEABLE_EX macro if you want to register class categories for non creatable objects.")); - return S_OK; - } - - hResult = CoCreateInstance( CLSID_StdComponentCategoriesMgr, NULL, - CLSCTX_INPROC_SERVER, __uuidof(ICatRegister), (void**)&pCatRegister ); - if( FAILED( hResult ) ) - { - // Since not all systems have the category manager installed, we'll allow - // the registration to succeed even though we didn't register our - // categories. If you really want to register categories on a system - // without the category manager, you can either manually add the - // appropriate entries to your registry script (.rgs), or you can - // redistribute comcat.dll. - return( S_OK ); - } - - hResult = S_OK; - pEntry = pCatMap; - while( pEntry->iType != _ATL_CATMAP_ENTRY_END ) - { - catid = *pEntry->pcatid; - if( bRegister ) - { - if( pEntry->iType == _ATL_CATMAP_ENTRY_IMPLEMENTED ) - { - hResult = pCatRegister->RegisterClassImplCategories( clsid, 1, - &catid ); - } - else - { - ATLASSERT( pEntry->iType == _ATL_CATMAP_ENTRY_REQUIRED ); - hResult = pCatRegister->RegisterClassReqCategories( clsid, 1, - &catid ); - } - if( FAILED( hResult ) ) - { - return( hResult ); - } - } - else - { - if( pEntry->iType == _ATL_CATMAP_ENTRY_IMPLEMENTED ) - { - pCatRegister->UnRegisterClassImplCategories( clsid, 1, &catid ); - } - else - { - ATLASSERT( pEntry->iType == _ATL_CATMAP_ENTRY_REQUIRED ); - pCatRegister->UnRegisterClassReqCategories( clsid, 1, &catid ); - } - } - pEntry++; - } - - // When unregistering remove "Implemented Categories" and "Required Categories" subkeys if they are empty. - if (!bRegister) - { - OLECHAR szGUID[64]; - ::StringFromGUID2(clsid, szGUID, 64); - USES_CONVERSION_EX; - TCHAR* pszGUID = OLE2T_EX(szGUID, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); - if (pszGUID != NULL) - { - TCHAR szKey[128]; -#ifdef UNICODE - Checked::wcscpy_s(szKey, _countof(szKey), _T("CLSID\\")); - Checked::wcscat_s(szKey, _countof(szKey), pszGUID); - Checked::wcscat_s(szKey, _countof(szKey), _T("\\Required Categories")); -#else - Checked::strcpy_s(szKey, _countof(szKey), _T("CLSID\\")); - Checked::strcat_s(szKey, _countof(szKey), pszGUID); - Checked::strcat_s(szKey, _countof(szKey), _T("\\Required Categories")); -#endif - - CRegKey root(HKEY_CLASSES_ROOT); - CRegKey key; - DWORD cbSubKeys = 0; - - LRESULT lRes = key.Open(root, szKey, KEY_READ); - if (lRes == ERROR_SUCCESS) - { - lRes = RegQueryInfoKey(key, NULL, NULL, NULL, &cbSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - key.Close(); - if (lRes == ERROR_SUCCESS && cbSubKeys == 0) - { - root.DeleteSubKey(szKey); - } - } - -#ifdef UNICODE - Checked::wcscpy_s(szKey, _countof(szKey), _T("CLSID\\")); - Checked::wcscat_s(szKey, _countof(szKey), pszGUID); - Checked::wcscat_s(szKey, _countof(szKey), _T("\\Implemented Categories")); -#else - Checked::strcpy_s(szKey, _countof(szKey), _T("CLSID\\")); - Checked::strcat_s(szKey, _countof(szKey), pszGUID); - Checked::strcat_s(szKey, _countof(szKey), _T("\\Implemented Categories")); -#endif - lRes = key.Open(root, szKey, KEY_READ); - if (lRes == ERROR_SUCCESS) - { - lRes = RegQueryInfoKey(key, NULL, NULL, NULL, &cbSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - key.Close(); - if (lRes == ERROR_SUCCESS && cbSubKeys == 0) - { - root.DeleteSubKey(szKey); - } - } - } - } - return( S_OK ); -} - -#endif // _ATL_DLL - -ATLINLINE ATLAPIINL -AtlWinModuleTerm(_ATL_WIN_MODULE* pWinModule, HINSTANCE hInst) -{ - if (pWinModule == NULL) - return E_INVALIDARG; - if (pWinModule->cbSize == 0) - return S_OK; - if (pWinModule->cbSize != sizeof(_ATL_WIN_MODULE)) - return E_INVALIDARG; - - for (int i = 0; i < pWinModule->m_rgWindowClassAtoms.GetSize(); i++) - UnregisterClass((LPCTSTR)pWinModule->m_rgWindowClassAtoms[i], hInst); - pWinModule->m_rgWindowClassAtoms.RemoveAll(); - pWinModule->m_csWindowCreate.Term(); - pWinModule->cbSize = 0; - return S_OK; -} - - - -///////////////////////////////////////////////////////////////////////////// -// General DLL Version Helpers - -#pragma warning(push) -#pragma warning(disable : 4191) // 'type cast' : unsafe conversion from 'FARPROC' to 'DLLGETVERSIONPROC' - -inline HRESULT AtlGetDllVersion(HINSTANCE hInstDLL, DLLVERSIONINFO* pDllVersionInfo) -{ - ATLENSURE(pDllVersionInfo != NULL); - - // We must get this function explicitly because some DLLs don't implement it. - DLLGETVERSIONPROC pfnDllGetVersion = (DLLGETVERSIONPROC)::GetProcAddress(hInstDLL, "DllGetVersion"); - - if(pfnDllGetVersion == NULL) - { - return E_NOTIMPL; - } - - return (*pfnDllGetVersion)(pDllVersionInfo); -} - -#pragma warning(pop) - -inline HRESULT AtlGetDllVersion(LPCTSTR lpstrDllName, DLLVERSIONINFO* pDllVersionInfo) -{ - HINSTANCE hInstDLL = ::LoadLibrary(lpstrDllName); - if(hInstDLL == NULL) - { - return AtlHresultFromLastError(); - } - HRESULT hRet = AtlGetDllVersion(hInstDLL, pDllVersionInfo); - ::FreeLibrary(hInstDLL); - return hRet; -} - -// Common Control Versions: -// Win95/WinNT 4.0 maj=4 min=00 -// IE 3.x maj=4 min=70 -// IE 4.0 maj=4 min=71 -// IE 5.0 maj=5 min=80 -// Win2000 maj=5 min=81 -inline HRESULT AtlGetCommCtrlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor) -{ - ATLENSURE(( pdwMajor != NULL ) && ( pdwMinor != NULL )); - - DLLVERSIONINFO dvi; - memset(&dvi, 0, sizeof(dvi)); - dvi.cbSize = sizeof(dvi); - - HRESULT hRet = AtlGetDllVersion(_T("comctl32.dll"), &dvi); - - if(SUCCEEDED(hRet)) - { - *pdwMajor = dvi.dwMajorVersion; - *pdwMinor = dvi.dwMinorVersion; - } - else if(hRet == E_NOTIMPL) - { - // If DllGetVersion is not there, then the DLL is a version - // previous to the one shipped with IE 3.x - *pdwMajor = 4; - *pdwMinor = 0; - hRet = S_OK; - } - - return hRet; -} - -// Shell Versions: -// Win95/WinNT 4.0 maj=4 min=00 -// IE 3.x, IE 4.0 without Web Integrated Desktop maj=4 min=00 -// IE 4.0 with Web Integrated Desktop maj=4 min=71 -// IE 4.01 with Web Integrated Desktop maj=4 min=72 -// Win2000 maj=5 min=00 -inline HRESULT AtlGetShellVersion(LPDWORD pdwMajor, LPDWORD pdwMinor) -{ - ATLENSURE(( pdwMajor != NULL) && ( pdwMinor != NULL )); - - DLLVERSIONINFO dvi; - memset(&dvi, 0, sizeof(dvi)); - dvi.cbSize = sizeof(dvi); - HRESULT hRet = AtlGetDllVersion(_T("shell32.dll"), &dvi); - - if(SUCCEEDED(hRet)) - { - *pdwMajor = dvi.dwMajorVersion; - *pdwMinor = dvi.dwMinorVersion; - } - else if(hRet == E_NOTIMPL) - { - // If DllGetVersion is not there, then the DLL is a version - // previous to the one shipped with IE 4.x - *pdwMajor = 4; - *pdwMinor = 0; - hRet = S_OK; - } - - return hRet; -} - -inline ATL_DEPRECATED("AtlModuleRegisterClassObjects has been replaced by AtlComModuleRegisterClassObjects") -HRESULT AtlModuleRegisterClassObjects(_ATL_MODULE* /*pM*/, DWORD dwClsContext, DWORD dwFlags) -{ - return AtlComModuleRegisterClassObjects(&_AtlComModule, dwClsContext, dwFlags); -} - -inline ATL_DEPRECATED("AtlModuleRevokeClassObjects has been replaced by AtlComModuleRevokeClassObjects") -HRESULT AtlModuleRevokeClassObjects(_ATL_MODULE* /*pM*/) -{ - return AtlComModuleRevokeClassObjects(&_AtlComModule); -} - -inline ATL_DEPRECATED("AtlModuleGetClassObject has been replaced by AtlComModuleGetClassObject") -HRESULT AtlModuleGetClassObject(_ATL_MODULE* /*pM*/, REFCLSID rclsid, REFIID riid, LPVOID* ppv) -{ -#ifndef _ATL_OLEDB_CONFORMANCE_TESTS - ATLASSERT(ppv != NULL); -#endif - - return AtlComModuleGetClassObject(&_AtlComModule, rclsid, riid, ppv); -} - -inline ATL_DEPRECATED("AtlModuleRegisterServer has been replaced by AtlComModuleRegisterServer") -HRESULT AtlModuleRegisterServer(_ATL_MODULE* /*pM*/, BOOL bRegTypeLib, const CLSID* pCLSID = NULL) -{ - return AtlComModuleRegisterServer(&_AtlComModule, bRegTypeLib, pCLSID); -} - -inline ATL_DEPRECATED("AtlModuleUnregisterServer has been replaced by AtlComModuleUnregisterServer") -HRESULT AtlModuleUnregisterServer(_ATL_MODULE* /*pM*/, const CLSID* pCLSID = NULL) -{ - return AtlComModuleUnregisterServer(&_AtlComModule, FALSE, pCLSID); -} - -inline ATL_DEPRECATED("AtlModuleUnregisterServerEx has been replaced by AtlComModuleUnregisterServer") -HRESULT AtlModuleUnregisterServerEx(_ATL_MODULE* /*pM*/, BOOL bUnRegTypeLib, const CLSID* pCLSID = NULL) -{ - return AtlComModuleUnregisterServer(&_AtlComModule, bUnRegTypeLib, pCLSID); -} - -inline ATL_DEPRECATED("AtlModuleUpdateRegistryFromResourceD has been replaced by AtlUpdateRegistryFromResourceD") -HRESULT AtlModuleUpdateRegistryFromResourceD(_ATL_MODULE* /*pM*/, LPCOLESTR lpszRes, - BOOL bRegister, struct _ATL_REGMAP_ENTRY* pMapEntries, IRegistrar* pReg = NULL) -{ - return AtlUpdateRegistryFromResourceD(_AtlBaseModule.GetModuleInstance(), lpszRes, bRegister, pMapEntries, pReg); -} - -inline ATL_DEPRECATED("AtlModuleRegisterTypeLib has been replaced by AtlRegisterTypeLib") -HRESULT AtlModuleRegisterTypeLib(_ATL_MODULE* /*pM*/, LPCOLESTR lpszIndex) -{ - return AtlRegisterTypeLib(_AtlComModule.m_hInstTypeLib, lpszIndex); -} - -inline ATL_DEPRECATED("AtlModuleUnRegisterTypeLib has been replaced by AtlUnRegisterTypeLib") -HRESULT AtlModuleUnRegisterTypeLib(_ATL_MODULE* /*pM*/, LPCOLESTR lpszIndex) -{ - return AtlUnRegisterTypeLib(_AtlComModule.m_hInstTypeLib, lpszIndex); -} - -inline ATL_DEPRECATED("AtlModuleLoadTypeLib has been replaced by AtlLoadTypeLib") -HRESULT AtlModuleLoadTypeLib(_ATL_MODULE* /*pM*/, LPCOLESTR lpszIndex, BSTR* pbstrPath, ITypeLib** ppTypeLib) -{ - return AtlLoadTypeLib(_AtlComModule.m_hInstTypeLib, lpszIndex, pbstrPath, ppTypeLib); -} - -inline ATL_DEPRECATED("AtlModuleInit is no longer required") -HRESULT AtlModuleInit(_ATL_MODULE* /*pM*/, _ATL_OBJMAP_ENTRY* /*p*/, HINSTANCE /*h*/) -{ - return S_OK; -} - -inline ATL_DEPRECATED("AtlModuleTerm is no longer required") -HRESULT AtlModuleTerm(_ATL_MODULE* /*pM*/) -{ - return S_OK; -} - -inline ATL_DEPRECATED("AtlModuleAddCreateWndData has been replaced by AtlWinModuleAddCreateWndData") -void AtlModuleAddCreateWndData(_ATL_MODULE* /*pM*/, _AtlCreateWndData* pData, void* pObject) -{ - AtlWinModuleAddCreateWndData(&_AtlWinModule, pData, pObject); -} - -inline ATL_DEPRECATED("AtlModuleExtractCreateWndData has been replaced by AtlWinModuleExtractCreateWndData") -void* AtlModuleExtractCreateWndData(_ATL_MODULE* /*pM*/) -{ - return AtlWinModuleExtractCreateWndData(&_AtlWinModule); -} - -#ifndef _ATL_NO_COMMODULE - -inline CRITICAL_SECTION& CComModule::get_m_csWindowCreate() throw() -{ - return _AtlWinModule.m_csWindowCreate.m_sec; -} - -inline CRITICAL_SECTION& CComModule::get_m_csObjMap() throw() -{ - return _AtlComModule.m_csObjMap.m_sec; -} - -inline CRITICAL_SECTION& CComModule::get_m_csStaticDataInit() throw() -{ - return m_csStaticDataInitAndTypeInfo.m_sec; -} - -inline _AtlCreateWndData*& CComModule::get_m_pCreateWndList() throw() -{ - return _AtlWinModule.m_pCreateWndList; -} -inline void CComModule::put_m_pCreateWndList(_AtlCreateWndData* p) throw() -{ - _AtlWinModule.m_pCreateWndList = p; -} -#ifdef _ATL_DEBUG_INTERFACES -inline UINT& CComModule::get_m_nIndexQI() throw() -{ - return _AtlDebugInterfacesModule.m_nIndexQI; -} -inline void CComModule::put_m_nIndexQI(UINT nIndex) throw() -{ - _AtlDebugInterfacesModule.m_nIndexQI = nIndex; -} -inline UINT& CComModule::get_m_nIndexBreakAt() throw() -{ - return _AtlDebugInterfacesModule.m_nIndexBreakAt; -} -inline void CComModule::put_m_nIndexBreakAt(UINT nIndex) throw() -{ - _AtlDebugInterfacesModule.m_nIndexBreakAt = nIndex; -} -inline CSimpleArray<_QIThunk*>* CComModule::get_m_paThunks() throw() -{ - return &_AtlDebugInterfacesModule.m_aThunks; -} -inline HRESULT CComModule::AddThunk(IUnknown** pp, LPCTSTR lpsz, REFIID iid) throw() -{ - return _AtlDebugInterfacesModule.AddThunk(pp, lpsz, iid); -} -inline HRESULT CComModule::AddNonAddRefThunk(IUnknown* p, LPCTSTR lpsz, IUnknown** ppThunkRet) throw() -{ - return _AtlDebugInterfacesModule.AddNonAddRefThunk(p, lpsz, ppThunkRet); -} - -inline void CComModule::DeleteNonAddRefThunk(IUnknown* pUnk) throw() -{ - _AtlDebugInterfacesModule.DeleteNonAddRefThunk(pUnk); -} - -inline void CComModule::DeleteThunk(_QIThunk* p) throw() -{ - _AtlDebugInterfacesModule.DeleteThunk(p); -} - -inline bool CComModule::DumpLeakedThunks() throw() -{ - return _AtlDebugInterfacesModule.DumpLeakedThunks(); -} -#endif // _ATL_DEBUG_INTERFACES - -inline HRESULT CComModule::Init(_ATL_OBJMAP_ENTRY* p, HINSTANCE /*h*/, const GUID* plibid) throw() -{ - if (plibid != NULL) - m_libid = *plibid; - - _ATL_OBJMAP_ENTRY* pEntry; - if (p != (_ATL_OBJMAP_ENTRY*)-1) - { - m_pObjMap = p; - if (m_pObjMap != NULL) - { - pEntry = m_pObjMap; - while (pEntry->pclsid != NULL) - { - pEntry->pfnObjectMain(true); //initialize class resources - pEntry++; - } - } - } - for (_ATL_OBJMAP_ENTRY** ppEntry = _AtlComModule.m_ppAutoObjMapFirst; ppEntry < _AtlComModule.m_ppAutoObjMapLast; ppEntry++) - { - if (*ppEntry != NULL) - (*ppEntry)->pfnObjectMain(true); //initialize class resources - } - return S_OK; -} - -inline void CComModule::Term() throw() -{ - _ATL_OBJMAP_ENTRY* pEntry; - if (m_pObjMap != NULL) - { - pEntry = m_pObjMap; - while (pEntry->pclsid != NULL) - { - if (pEntry->pCF != NULL) - pEntry->pCF->Release(); - pEntry->pCF = NULL; - pEntry->pfnObjectMain(false); //cleanup class resources - pEntry++; - } - } - - for (_ATL_OBJMAP_ENTRY** ppEntry = _AtlComModule.m_ppAutoObjMapFirst; ppEntry < _AtlComModule.m_ppAutoObjMapLast; ppEntry++) - { - if (*ppEntry != NULL) - (*ppEntry)->pfnObjectMain(false); //cleanup class resources - } -#ifdef _DEBUG - // Prevent false memory leak reporting. ~CAtlWinModule may be too late. - _AtlWinModule.Term(); -#endif // _DEBUG - - CAtlModuleT::Term(); -} - -inline HRESULT CComModule::GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) throw() -{ - if (ppv == NULL) - return E_POINTER; - HRESULT hr = S_OK; - _ATL_OBJMAP_ENTRY* pEntry; - if (m_pObjMap != NULL) - { - pEntry = m_pObjMap; - while (pEntry->pclsid != NULL) - { - if ((pEntry->pfnGetClassObject != NULL) && InlineIsEqualGUID(rclsid, *pEntry->pclsid)) - { - if (pEntry->pCF == NULL) - { - CComCritSecLock lock(_AtlComModule.m_csObjMap, false); - hr = lock.Lock(); - if (FAILED(hr)) - { - ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to lock critical section in CComModule::GetClassObject\n")); - ATLASSERT(0); - break; - } - if (pEntry->pCF == NULL) - hr = pEntry->pfnGetClassObject(pEntry->pfnCreateInstance, __uuidof(IUnknown), (LPVOID*)&pEntry->pCF); - } - if (pEntry->pCF != NULL) - hr = pEntry->pCF->QueryInterface(riid, ppv); - break; - } - pEntry++; - } - } - if (*ppv == NULL && hr == S_OK) - hr = AtlComModuleGetClassObject(&_AtlComModule, rclsid, riid, ppv); - return hr; -} - -// Register/Revoke All Class Factories with the OS (EXE only) -inline HRESULT CComModule::RegisterClassObjects(DWORD dwClsContext, DWORD dwFlags) throw() -{ - HRESULT hr = S_OK; - _ATL_OBJMAP_ENTRY* pEntry; - if (m_pObjMap != NULL) - { - pEntry = m_pObjMap; - while (pEntry->pclsid != NULL && hr == S_OK) - { - hr = pEntry->RegisterClassObject(dwClsContext, dwFlags); - pEntry++; - } - } - if (hr == S_OK) - hr = AtlComModuleRegisterClassObjects(&_AtlComModule, dwClsContext, dwFlags); - return hr; -} -inline HRESULT CComModule::RevokeClassObjects() throw() -{ - HRESULT hr = S_OK; - _ATL_OBJMAP_ENTRY* pEntry; - if (m_pObjMap != NULL) - { - pEntry = m_pObjMap; - while (pEntry->pclsid != NULL && hr == S_OK) - { - hr = pEntry->RevokeClassObject(); - pEntry++; - } - } - if (hr == S_OK) - hr = AtlComModuleRevokeClassObjects(&_AtlComModule); - return hr; -} - -// Registry support (helpers) -inline HRESULT CComModule::RegisterTypeLib() throw() -{ - return _AtlComModule.RegisterTypeLib(); -} -inline HRESULT CComModule::RegisterTypeLib(LPCTSTR lpszIndex) throw() -{ - return _AtlComModule.RegisterTypeLib(lpszIndex); -} -inline HRESULT CComModule::UnRegisterTypeLib() throw() -{ - return _AtlComModule.UnRegisterTypeLib(); -} -inline HRESULT CComModule::UnRegisterTypeLib(LPCTSTR lpszIndex) throw() -{ - return _AtlComModule.UnRegisterTypeLib(lpszIndex); -} - -inline HRESULT CComModule::RegisterServer(BOOL bRegTypeLib /*= FALSE*/, const CLSID* pCLSID /*= NULL*/) throw() -{ - HRESULT hr = S_OK; - _ATL_OBJMAP_ENTRY* pEntry = m_pObjMap; - if (pEntry != NULL) - { - for (;pEntry->pclsid != NULL; pEntry++) - { - if (pCLSID != NULL) - { - if (!IsEqualGUID(*pCLSID, *pEntry->pclsid)) - continue; - } - hr = pEntry->pfnUpdateRegistry(TRUE); - if (FAILED(hr)) - break; - hr = AtlRegisterClassCategoriesHelper( *pEntry->pclsid, - pEntry->pfnGetCategoryMap(), TRUE ); - if (FAILED(hr)) - break; - } - } - if (SUCCEEDED(hr)) - hr = CAtlModuleT::RegisterServer(bRegTypeLib, pCLSID); - return hr; -} - -inline HRESULT CComModule::UnregisterServer(BOOL bUnRegTypeLib, const CLSID* pCLSID /*= NULL*/) throw() -{ - HRESULT hr = S_OK; - _ATL_OBJMAP_ENTRY* pEntry = m_pObjMap; - if (pEntry != NULL) - { - for (;pEntry->pclsid != NULL; pEntry++) - { - if (pCLSID != NULL) - { - if (!IsEqualGUID(*pCLSID, *pEntry->pclsid)) - continue; - } - hr = AtlRegisterClassCategoriesHelper( *pEntry->pclsid, - pEntry->pfnGetCategoryMap(), FALSE ); - if (FAILED(hr)) - break; - hr = pEntry->pfnUpdateRegistry(FALSE); //unregister - if (FAILED(hr)) - break; - } - } - if (SUCCEEDED(hr)) - hr = CAtlModuleT::UnregisterServer(bUnRegTypeLib, pCLSID); - return hr; -} - -inline HRESULT CComModule::UnregisterServer(const CLSID* pCLSID /*= NULL*/) throw() -{ - return UnregisterServer(FALSE, pCLSID); -} - -#endif // !_ATL_NO_COMMODULE - -} // namespace ATL - - -#pragma warning( pop ) - -#if !defined(_ATL_DLL) && !defined(_DEBUG) - -#include - -#endif // !_ATL_DLL && !_DEBUG - -#pragma pack(pop) -#ifdef _ATL_ALL_WARNINGS -#pragma warning( pop ) -#endif - -///////////////////////////////////////////////////////////////////////////// - -#endif // __ATLBASE_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlbase.inl b/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlbase.inl deleted file mode 100644 index 0d337b1cf..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlbase.inl +++ /dev/null @@ -1,427 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLBASE_INL__ -#define __ATLBASE_INL__ - -#pragma once - -#ifndef __ATLBASE_H__ - #error atlbase.inl requires atlbase.h to be included first -#endif -#pragma warning(push) -#pragma warning(disable:4571) //catch(...) blocks compiled with /EHs do NOT catch or re-throw Structured Exceptions -namespace ATL -{ - -///////////////////////////////////////////////////////////////////////////// -// Connection Point Helpers - -ATLINLINE ATLAPI AtlAdvise(IUnknown* pUnkCP, IUnknown* pUnk, const IID& iid, LPDWORD pdw) -{ - if(pUnkCP == NULL) - return E_INVALIDARG; - - CComPtr pCPC; - CComPtr pCP; - HRESULT hRes = pUnkCP->QueryInterface(__uuidof(IConnectionPointContainer), (void**)&pCPC); - if (SUCCEEDED(hRes)) - hRes = pCPC->FindConnectionPoint(iid, &pCP); - if (SUCCEEDED(hRes)) - hRes = pCP->Advise(pUnk, pdw); - return hRes; -} - -ATLINLINE ATLAPI AtlUnadvise(IUnknown* pUnkCP, const IID& iid, DWORD dw) -{ - if(pUnkCP == NULL) - return E_INVALIDARG; - - CComPtr pCPC; - CComPtr pCP; - HRESULT hRes = pUnkCP->QueryInterface(__uuidof(IConnectionPointContainer), (void**)&pCPC); - if (SUCCEEDED(hRes)) - hRes = pCPC->FindConnectionPoint(iid, &pCP); - if (SUCCEEDED(hRes)) - hRes = pCP->Unadvise(dw); - return hRes; -} - -///////////////////////////////////////////////////////////////////////////// -// Inproc Marshaling helpers - -//This API should be called from the same thread that called -//AtlMarshalPtrInProc -ATLINLINE ATLAPI AtlFreeMarshalStream(IStream* pStream) -{ - HRESULT hRes=S_OK; - if (pStream != NULL) - { - LARGE_INTEGER l; - l.QuadPart = 0; - pStream->Seek(l, STREAM_SEEK_SET, NULL); - hRes=CoReleaseMarshalData(pStream); - pStream->Release(); - } - return hRes; -} - -ATLINLINE ATLAPI AtlMarshalPtrInProc(IUnknown* pUnk, const IID& iid, IStream** ppStream) -{ - ATLASSERT(ppStream != NULL); - if (ppStream == NULL) - return E_POINTER; - - HRESULT hRes = CreateStreamOnHGlobal(NULL, TRUE, ppStream); - if (SUCCEEDED(hRes)) - { - hRes = CoMarshalInterface(*ppStream, iid, - pUnk, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLESTRONG); - if (FAILED(hRes)) - { - (*ppStream)->Release(); - *ppStream = NULL; - } - } - return hRes; -} - -ATLINLINE ATLAPI AtlUnmarshalPtr(IStream* pStream, const IID& iid, IUnknown** ppUnk) -{ - ATLASSERT(ppUnk != NULL); - if (ppUnk == NULL) - return E_POINTER; - - *ppUnk = NULL; - HRESULT hRes = E_INVALIDARG; - if (pStream != NULL) - { - LARGE_INTEGER l; - l.QuadPart = 0; - pStream->Seek(l, STREAM_SEEK_SET, NULL); - hRes = CoUnmarshalInterface(pStream, iid, (void**)ppUnk); - } - return hRes; -} - -///////////////////////////////////////////////////////////////////////////// -// Module - -ATLINLINE ATLAPI AtlComModuleGetClassObject(_ATL_COM_MODULE* pComModule, REFCLSID rclsid, REFIID riid, LPVOID* ppv) -{ - ATLASSERT(pComModule != NULL); - if (pComModule == NULL) - return E_INVALIDARG; - if (pComModule->cbSize == 0) // Module hasn't been initialized - return E_UNEXPECTED; - - if (ppv == NULL) - return E_POINTER; - *ppv = NULL; - - HRESULT hr = S_OK; - - for (_ATL_OBJMAP_ENTRY** ppEntry = pComModule->m_ppAutoObjMapFirst; ppEntry < pComModule->m_ppAutoObjMapLast; ppEntry++) - { - if (*ppEntry != NULL) - { - _ATL_OBJMAP_ENTRY* pEntry = *ppEntry; - if ((pEntry->pfnGetClassObject != NULL) && InlineIsEqualGUID(rclsid, *pEntry->pclsid)) - { - if (pEntry->pCF == NULL) - { - CComCritSecLock lock(pComModule->m_csObjMap, false); - hr = lock.Lock(); - if (FAILED(hr)) - { - ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to lock critical section in AtlComModuleGetClassObject\n")); - ATLASSERT(0); - break; - } - if (pEntry->pCF == NULL) - hr = pEntry->pfnGetClassObject(pEntry->pfnCreateInstance, __uuidof(IUnknown), (LPVOID*)&pEntry->pCF); - } - if (pEntry->pCF != NULL) - hr = pEntry->pCF->QueryInterface(riid, ppv); - break; - } - } - } - - if (*ppv == NULL && hr == S_OK) - hr = CLASS_E_CLASSNOTAVAILABLE; - return hr; -} - -ATLINLINE ATLAPI AtlComModuleRegisterClassObjects(_ATL_COM_MODULE* pComModule, DWORD dwClsContext, DWORD dwFlags) -{ - ATLASSERT(pComModule != NULL); - if (pComModule == NULL) - return E_INVALIDARG; - - HRESULT hr = S_FALSE; - for (_ATL_OBJMAP_ENTRY** ppEntry = pComModule->m_ppAutoObjMapFirst; ppEntry < pComModule->m_ppAutoObjMapLast && SUCCEEDED(hr); ppEntry++) - { - if (*ppEntry != NULL) - hr = (*ppEntry)->RegisterClassObject(dwClsContext, dwFlags); - } - return hr; -} - -ATLINLINE ATLAPI AtlComModuleRevokeClassObjects(_ATL_COM_MODULE* pComModule) -{ - ATLASSERT(pComModule != NULL); - if (pComModule == NULL) - return E_INVALIDARG; - - HRESULT hr = S_OK; - for (_ATL_OBJMAP_ENTRY** ppEntry = pComModule->m_ppAutoObjMapFirst; ppEntry < pComModule->m_ppAutoObjMapLast && hr == S_OK; ppEntry++) - { - if (*ppEntry != NULL) - hr = (*ppEntry)->RevokeClassObject(); - } - return hr; -} - -ATLINLINE ATLAPI_(BOOL) AtlWaitWithMessageLoop(HANDLE hEvent) -{ - DWORD dwRet; - MSG msg; - - while(1) - { - dwRet = MsgWaitForMultipleObjects(1, &hEvent, FALSE, INFINITE, QS_ALLINPUT); - - if (dwRet == WAIT_OBJECT_0) - return TRUE; // The event was signaled - - if (dwRet != WAIT_OBJECT_0 + 1) - break; // Something else happened - - // There is one or more window message available. Dispatch them - while(PeekMessage(&msg,0,0,0,PM_NOREMOVE)) - { - // check for unicode window so we call the appropriate functions - BOOL bUnicode = ::IsWindowUnicode(msg.hwnd); - BOOL bRet; - - if (bUnicode) - bRet = ::GetMessageW(&msg, NULL, 0, 0); - else - bRet = ::GetMessageA(&msg, NULL, 0, 0); - - if (bRet > 0) - { - ::TranslateMessage(&msg); - - if (bUnicode) - ::DispatchMessageW(&msg); - else - ::DispatchMessageA(&msg); - } - - if (WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0) - return TRUE; // Event is now signaled. - } - } - return FALSE; -} - -///////////////////////////////////////////////////////////////////////////// -// QI support - -ATLINLINE ATLAPI AtlInternalQueryInterface(void* pThis, - const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject) -{ - ATLASSERT(pThis != NULL); - ATLASSERT(pEntries!= NULL); - - if(pThis == NULL || pEntries == NULL) - return E_INVALIDARG ; - - // First entry in the com map should be a simple map entry - ATLASSERT(pEntries->pFunc == _ATL_SIMPLEMAPENTRY); - if (ppvObject == NULL) - return E_POINTER; - *ppvObject = NULL; - if (InlineIsEqualUnknown(iid)) // use first interface - { - IUnknown* pUnk = (IUnknown*)((INT_PTR)pThis+pEntries->dw); - pUnk->AddRef(); - *ppvObject = pUnk; - return S_OK; - } - while (pEntries->pFunc != NULL) - { - BOOL bBlind = (pEntries->piid == NULL); - if (bBlind || InlineIsEqualGUID(*(pEntries->piid), iid)) - { - if (pEntries->pFunc == _ATL_SIMPLEMAPENTRY) //offset - { - ATLASSERT(!bBlind); - IUnknown* pUnk = (IUnknown*)((INT_PTR)pThis+pEntries->dw); - pUnk->AddRef(); - *ppvObject = pUnk; - return S_OK; - } - else //actual function call - { - HRESULT hRes = pEntries->pFunc(pThis, - iid, ppvObject, pEntries->dw); - if (hRes == S_OK || (!bBlind && FAILED(hRes))) - return hRes; - } - } - pEntries++; - } - return E_NOINTERFACE; -} - -ATLINLINE ATLAPI_(DWORD) AtlGetVersion(void* /* pReserved */) -{ - return _ATL_VER; -} - -///////////////////////////////////////////////////////////////////////////// -// Windowing - -ATLINLINE ATLAPI_(void) AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE* pWinModule, _AtlCreateWndData* pData, void* pObject) -{ - if (pWinModule == NULL) - _AtlRaiseException((DWORD)EXCEPTION_ACCESS_VIOLATION); - - ATLASSERT(pData != NULL && pObject != NULL); - if(pData == NULL || pObject == NULL) - _AtlRaiseException((DWORD)EXCEPTION_ACCESS_VIOLATION); - - pData->m_pThis = pObject; - pData->m_dwThreadID = ::GetCurrentThreadId(); - CComCritSecLock lock(pWinModule->m_csWindowCreate, false); - if (FAILED(lock.Lock())) - { - ATLTRACE(atlTraceWindowing, 0, _T("ERROR : Unable to lock critical section in AtlWinModuleAddCreateWndData\n")); - ATLASSERT(0); - return; - } - pData->m_pNext = pWinModule->m_pCreateWndList; - pWinModule->m_pCreateWndList = pData; -} - -ATLINLINE ATLAPI_(void*) AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE* pWinModule) -{ - if (pWinModule == NULL) - return NULL; - - void* pv = NULL; - CComCritSecLock lock(pWinModule->m_csWindowCreate, false); - if (FAILED(lock.Lock())) - { - ATLTRACE(atlTraceWindowing, 0, _T("ERROR : Unable to lock critical section in AtlWinModuleExtractCreateWndData\n")); - ATLASSERT(0); - return pv; - } - _AtlCreateWndData* pEntry = pWinModule->m_pCreateWndList; - if(pEntry != NULL) - { - DWORD dwThreadID = ::GetCurrentThreadId(); - _AtlCreateWndData* pPrev = NULL; - while(pEntry != NULL) - { - if(pEntry->m_dwThreadID == dwThreadID) - { - if(pPrev == NULL) - pWinModule->m_pCreateWndList = pEntry->m_pNext; - else - pPrev->m_pNext = pEntry->m_pNext; - pv = pEntry->m_pThis; - break; - } - pPrev = pEntry; - pEntry = pEntry->m_pNext; - } - } - return pv; -} - - -ATLINLINE ATLAPI AtlWinModuleInit(_ATL_WIN_MODULE* pWinModule) -{ - if (pWinModule == NULL) - return E_INVALIDARG; - - // check only in the DLL - if (pWinModule->cbSize != sizeof(_ATL_WIN_MODULE)) - return E_INVALIDARG; - - pWinModule->m_pCreateWndList = NULL; - - HRESULT hr = pWinModule->m_csWindowCreate.Init(); - if (FAILED(hr)) - { - ATLTRACE(atlTraceWindowing, 0, _T("ERROR : Unable to initialize critical section in AtlWinModuleInit\n")); - ATLASSERT(0); - } - return hr; -} - -///////////////////////////////////////////////////////////////////////////// -// Module - -ATLINLINE ATLAPI AtlModuleAddTermFunc(_ATL_MODULE* pModule, _ATL_TERMFUNC* pFunc, DWORD_PTR dw) -{ - if (pModule == NULL) - return E_INVALIDARG; - - HRESULT hr = S_OK; - _ATL_TERMFUNC_ELEM* pNew = NULL; - ATLTRY(pNew = new _ATL_TERMFUNC_ELEM); - if (pNew == NULL) - hr = E_OUTOFMEMORY; - else - { - pNew->pFunc = pFunc; - pNew->dw = dw; - CComCritSecLock lock(pModule->m_csStaticDataInitAndTypeInfo, false); - hr = lock.Lock(); - if (SUCCEEDED(hr)) - { - pNew->pNext = pModule->m_pTermFuncs; - pModule->m_pTermFuncs = pNew; - } - else - { - delete pNew; - ATLTRACE(atlTraceGeneral, 0, _T("ERROR : Unable to lock critical section in AtlModuleAddTermFunc\n")); - ATLASSERT(0); - } - } - return hr; -} - -ATLINLINE ATLAPI_(void) AtlCallTermFunc(_ATL_MODULE* pModule) -{ - if (pModule == NULL) - _AtlRaiseException((DWORD)EXCEPTION_ACCESS_VIOLATION); - - _ATL_TERMFUNC_ELEM* pElem = pModule->m_pTermFuncs; - _ATL_TERMFUNC_ELEM* pNext = NULL; - while (pElem != NULL) - { - pElem->pFunc(pElem->dw); - pNext = pElem->pNext; - delete pElem; - pElem = pNext; - } - pModule->m_pTermFuncs = NULL; -} - -} // namespace ATL -#pragma warning(pop) -#endif // __ATLBASE_INL__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlchecked.h b/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlchecked.h deleted file mode 100644 index 42e82751b..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlchecked.h +++ /dev/null @@ -1,597 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLCHECKED_H__ -#define __ATLCHECKED_H__ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - - -#pragma pack(push,_ATL_PACKING) -namespace ATL -{ - -inline errno_t AtlCrtErrorCheck(errno_t nError) -{ - switch(nError) - { - case ENOMEM: - AtlThrow(E_OUTOFMEMORY); - break; - case EINVAL: - case ERANGE: - AtlThrow(E_INVALIDARG); - break; - case 0: - case STRUNCATE: - break; - default: - AtlThrow(E_FAIL); - break; - } - return nError; -} - -///////////////////////////////////////////////////////////////////////////// -// Secure (Checked) CRT functions - -namespace Checked -{ - -#if _SECURE_ATL - -#ifdef _AFX -#define ATLMFC_CRT_ERRORCHECK(expr) AFX_CRT_ERRORCHECK(expr) -#else -#define ATLMFC_CRT_ERRORCHECK(expr) ATL_CRT_ERRORCHECK(expr) -#endif - -inline void __cdecl memcpy_s(__out_bcount_part(_S1max,_N) void *_S1, __in size_t _S1max, __in_bcount(_N) const void *_S2, __in size_t _N) -{ - ATLMFC_CRT_ERRORCHECK(::memcpy_s(_S1, _S1max, _S2, _N)); -} - -inline void __cdecl wmemcpy_s(__out_ecount_part(_N1,_N) wchar_t *_S1, __in size_t _N1, __in_ecount(_N) const wchar_t *_S2, __in size_t _N) -{ - ATLMFC_CRT_ERRORCHECK(::wmemcpy_s(_S1, _N1, _S2, _N)); -} - -inline void __cdecl memmove_s(__out_bcount_part(_S1max,_N) void *_S1, __in size_t _S1max, __in_bcount(_N) const void *_S2, size_t _N) -{ - ATLMFC_CRT_ERRORCHECK(::memmove_s(_S1, _S1max, _S2, _N)); -} - -inline void __cdecl strcpy_s(__out_ecount(_S1max) char *_S1, __in size_t _S1max, __in_z const char *_S2) -{ - ATLMFC_CRT_ERRORCHECK(::strcpy_s(_S1, _S1max, _S2)); -} - -inline void __cdecl wcscpy_s(__out_ecount(_S1max) wchar_t *_S1, __in size_t _S1max, __in_z const wchar_t *_S2) -{ - ATLMFC_CRT_ERRORCHECK(::wcscpy_s(_S1, _S1max, _S2)); -} - -inline void __cdecl tcscpy_s(__out_ecount(_SizeInChars) TCHAR * _Dst, __in size_t _SizeInChars, __in_z const TCHAR * _Src) -{ -#ifndef _ATL_MIN_CRT - ATLMFC_CRT_ERRORCHECK(::_tcscpy_s(_Dst, _SizeInChars, _Src)); -#else -#ifdef UNICODE - ATLMFC_CRT_ERRORCHECK(::wcscpy_s(_Dst, _SizeInChars, _Src)); -#else - ATLMFC_CRT_ERRORCHECK(::strcpy_s(_Dst, _SizeInChars, _Src)); -#endif -#endif -} - -inline errno_t __cdecl strncpy_s(__out_ecount(_SizeInChars) char *_Dest, __in size_t _SizeInChars, __in_z const char *_Source, __in size_t _Count) -{ - return ATLMFC_CRT_ERRORCHECK(::strncpy_s(_Dest, _SizeInChars, _Source,_Count)); -} - -inline errno_t __cdecl wcsncpy_s(__out_ecount(_SizeInChars) wchar_t *_Dest, __in size_t _SizeInChars, __in_z const wchar_t *_Source, __in size_t _Count) -{ - return ATLMFC_CRT_ERRORCHECK(::wcsncpy_s(_Dest, _SizeInChars, _Source,_Count)); -} - -inline errno_t __cdecl tcsncpy_s(__out_ecount(_SizeInChars) TCHAR *_Dest, __in size_t _SizeInChars, __in_z const TCHAR *_Source, __in size_t _Count) -{ -#ifndef _ATL_MIN_CRT - return ATLMFC_CRT_ERRORCHECK(::_tcsncpy_s(_Dest, _SizeInChars, _Source,_Count)); -#else -#ifdef UNICODE - return ATLMFC_CRT_ERRORCHECK(::wcsncpy_s(_Dest, _SizeInChars, _Source,_Count)); -#else - return ATLMFC_CRT_ERRORCHECK(::strncpy_s(_Dest, _SizeInChars, _Source,_Count)); -#endif -#endif -} - -inline void __cdecl strcat_s(__inout_ecount_z(_SizeInChars) char * _Dst, __in size_t _SizeInChars, __in_z const char * _Src) -{ - ATLMFC_CRT_ERRORCHECK(::strcat_s(_Dst, _SizeInChars, _Src)); -} - -inline void __cdecl wcscat_s(__inout_ecount_z(_SizeInChars) wchar_t * _Dst, __in size_t _SizeInChars, __in_z const wchar_t * _Src) -{ - ATLMFC_CRT_ERRORCHECK(::wcscat_s(_Dst, _SizeInChars, _Src)); -} - -inline void __cdecl tcscat_s(__inout_ecount_z(_SizeInChars) TCHAR * _Dst, __in size_t _SizeInChars, __in_z const TCHAR * _Src) -{ -#ifndef _ATL_MIN_CRT - ATLMFC_CRT_ERRORCHECK(::_tcscat_s(_Dst, _SizeInChars, _Src)); -#else -#ifdef UNICODE - ATLMFC_CRT_ERRORCHECK(::wcscat_s(_Dst, _SizeInChars, _Src)); -#else - ATLMFC_CRT_ERRORCHECK(::strcat_s(_Dst, _SizeInChars, _Src)); -#endif -#endif -} - -inline void __cdecl strlwr_s(__inout_ecount_z(_SizeInChars) char * _Str, __in size_t _SizeInChars) -{ - ATLMFC_CRT_ERRORCHECK(::_strlwr_s(_Str, _SizeInChars)); -} - -inline void __cdecl wcslwr_s(__inout_ecount_z(_SizeInChars) wchar_t * _Str, __in size_t _SizeInChars) -{ - ATLMFC_CRT_ERRORCHECK(::_wcslwr_s(_Str, _SizeInChars)); -} - -inline void __cdecl mbslwr_s(__inout_bcount_z(_SizeInChars) unsigned char * _Str, __in size_t _SizeInChars) -{ - ATLMFC_CRT_ERRORCHECK(::_mbslwr_s(_Str, _SizeInChars)); -} - -inline void __cdecl tcslwr_s(__inout_ecount_z(_SizeInChars) TCHAR * _Str, __in size_t _SizeInChars) -{ -#ifndef _ATL_MIN_CRT - ATLMFC_CRT_ERRORCHECK(::_tcslwr_s(_Str, _SizeInChars)); -#else -#ifdef UNICODE - ATLMFC_CRT_ERRORCHECK(::_wcslwr_s(_Str, _SizeInChars)); -#else - ATLMFC_CRT_ERRORCHECK(::_strlwr_s(_Str, _SizeInChars)); -#endif -#endif -} - -inline void __cdecl strupr_s(__inout_ecount_z(_SizeInChars) char * _Str, __in size_t _SizeInChars) -{ - ATLMFC_CRT_ERRORCHECK(::_strupr_s(_Str, _SizeInChars)); -} - -inline void __cdecl wcsupr_s(__inout_ecount_z(_SizeInChars) wchar_t * _Str, __in size_t _SizeInChars) -{ - ATLMFC_CRT_ERRORCHECK(::_wcsupr_s(_Str, _SizeInChars)); -} - -inline void __cdecl mbsupr_s(__inout_bcount_z(_SizeInChars) unsigned char * _Str, __in size_t _SizeInChars) -{ - ATLMFC_CRT_ERRORCHECK(::_mbsupr_s(_Str, _SizeInChars)); -} - -inline void __cdecl tcsupr_s(__inout_ecount_z(_SizeInChars) TCHAR * _Str, __in size_t _SizeInChars) -{ - ATLMFC_CRT_ERRORCHECK(::_tcsupr_s(_Str, _SizeInChars)); -} - -inline void __cdecl itoa_s(__in int _Val, __out_ecount_z(_SizeInChars) char *_Buf, __in size_t _SizeInChars, __in int _Radix) -{ - ATLMFC_CRT_ERRORCHECK(::_itoa_s(_Val, _Buf, _SizeInChars, _Radix)); -} - -inline void __cdecl itot_s(__in int _Val, __out_ecount_z(_SizeInChars) TCHAR *_Buf, __in size_t _SizeInChars, __in int _Radix) -{ - ATLMFC_CRT_ERRORCHECK(::_itot_s(_Val, _Buf, _SizeInChars, _Radix)); -} - -inline void __cdecl ltoa_s(__in long _Val, __out_ecount_z(_SizeInChars) char *_Buf, __in size_t _SizeInChars, __in int _Radix) -{ - ATLMFC_CRT_ERRORCHECK(::_ltoa_s(_Val, _Buf, _SizeInChars, _Radix)); -} - -inline void __cdecl ltot_s(__in long _Val, __out_ecount_z(_SizeInChars) TCHAR *_Buf, __in size_t _SizeInChars, __in int _Radix) -{ - ATLMFC_CRT_ERRORCHECK(::_ltot_s(_Val, _Buf, _SizeInChars, _Radix)); -} - -inline void __cdecl ultoa_s(__in unsigned long _Val, __out_ecount_z(_SizeInChars) char *_Buf, __in size_t _SizeInChars, __in int _Radix) -{ - ATLMFC_CRT_ERRORCHECK(::_ultoa_s(_Val, _Buf, _SizeInChars, _Radix)); -} - -inline void __cdecl ultow_s(__in unsigned long _Val, __out_ecount_z(_SizeInChars) wchar_t *_Buf, __in size_t _SizeInChars, __in int _Radix) -{ - ATLMFC_CRT_ERRORCHECK(::_ultow_s(_Val, _Buf, _SizeInChars, _Radix)); -} - -inline void __cdecl ultot_s(__in unsigned long _Val, __out_ecount_z(_SizeInChars) TCHAR *_Buf, __in size_t _SizeInChars, __in int _Radix) -{ - ATLMFC_CRT_ERRORCHECK(::_ultot_s(_Val, _Buf, _SizeInChars, _Radix)); -} - -inline void __cdecl i64toa_s(__in __int64 _Val, __out_ecount_z(_SizeInChars) char *_Buf, __in size_t _SizeInChars, __in int _Radix) -{ - ATLMFC_CRT_ERRORCHECK(::_i64toa_s(_Val, _Buf, _SizeInChars, _Radix)); -} - -inline void __cdecl i64tow_s(__in __int64 _Val, __out_ecount_z(_SizeInChars) wchar_t *_Buf, __in size_t _SizeInChars, __in int _Radix) -{ - ATLMFC_CRT_ERRORCHECK(::_i64tow_s(_Val, _Buf, _SizeInChars, _Radix)); -} - -inline void __cdecl ui64toa_s(__in unsigned __int64 _Val, __out_ecount_z(_SizeInChars) char *_Buf, __in size_t _SizeInChars, __in int _Radix) -{ - ATLMFC_CRT_ERRORCHECK(::_ui64toa_s(_Val, _Buf, _SizeInChars, _Radix)); -} - -inline void __cdecl ui64tow_s(__in unsigned __int64 _Val, __out_ecount_z(_SizeInChars) wchar_t *_Buf, __in size_t _SizeInChars, __in int _Radix) -{ - ATLMFC_CRT_ERRORCHECK(::_ui64tow_s(_Val, _Buf, _SizeInChars, _Radix)); -} - -inline void __cdecl gcvt_s(__out_ecount_z(_SizeInChars) char *_Buffer, __in size_t _SizeInChars, __in double _Value, __in int _Ndec) -{ - ATLMFC_CRT_ERRORCHECK(::_gcvt_s(_Buffer, _SizeInChars, _Value, _Ndec)); -} - -inline void __cdecl tsplitpath_s(__in_z const TCHAR *_Path, __out_ecount_z_opt(_Drive_len) TCHAR *_Drive, __in size_t _Drive_len, - __out_ecount_z_opt(_Dir_len) TCHAR *_Dir, __in size_t _Dir_len, - __out_ecount_z_opt(_Fname_len) TCHAR *_Fname, __in size_t _Fname_len, - __out_ecount_z_opt(_Ext_len) TCHAR *_Ext, __in size_t _Ext_len) -{ - ATLMFC_CRT_ERRORCHECK(::_tsplitpath_s(_Path, _Drive, _Drive_len, _Dir, _Dir_len, _Fname, _Fname_len, _Ext, _Ext_len)); -} - -inline void __cdecl tmakepath_s(__out_ecount_z(_SizeInChars) TCHAR *_Path, __in size_t _SizeInChars, __in_z const TCHAR *_Drive, - __in_z const TCHAR *_Dir, __in_z const TCHAR *_Fname, __in_z const TCHAR *_Ext) -{ - ATLMFC_CRT_ERRORCHECK(::_tmakepath_s(_Path, _SizeInChars, _Drive, _Dir, _Fname, _Ext)); -} - -inline size_t __cdecl strnlen(__in_ecount(_Maxsize) const char *_Str, __in size_t _Maxsize) -{ - return ::strnlen(_Str, _Maxsize); -} - -inline size_t __cdecl wcsnlen(__in_ecount(_Maxsize) const wchar_t *_Wcs, __in size_t _Maxsize) -{ - return ::wcsnlen(_Wcs, _Maxsize); -} - -inline size_t __cdecl tcsnlen(__in_ecount(_Maxsize) const TCHAR *_Str, __in size_t _Maxsize) -{ - return ::_tcsnlen(_Str, _Maxsize); -} - -inline int get_errno() -{ - int nErrNo; - ATLMFC_CRT_ERRORCHECK(::_get_errno(&nErrNo)); - return nErrNo; -} - -inline void set_errno(__in int _Value) -{ - ATLMFC_CRT_ERRORCHECK(::_set_errno(_Value)); -} - -#else // !_SECURE_ATL - -#define ATLMFC_CRT_ERRORCHECK(expr) do { expr; } while (0) - -inline void __cdecl memcpy_s(__out_bcount(_S1max) void *_S1, __in size_t _S1max, __in_bcount(_N) const void *_S2, size_t _N) -{ - (_S1max); - memcpy(_S1, _S2, _N); -} - -inline void __cdecl wmemcpy_s(__out_ecount(_N1) wchar_t *_S1, __in size_t _N1, __in_ecount(_N) const wchar_t *_S2, __in size_t _N) -{ - (_N1); - ::wmemcpy(_S1, _S2, _N); -} - -inline void __cdecl memmove_s(__out_bcount(_S1max) void *_S1, __in size_t _S1max, __in_bcount(_N) const void *_S2, __in size_t _N) -{ - (_S1max); - memmove(_S1, _S2, _N); -} - -inline void __cdecl strcpy_s(__out_ecount_z(_S1max) char *_S1, __in size_t _S1max, __in_z const char *_S2) -{ - (_S1max); - ::strcpy(_S1, _S2); -} - -inline void __cdecl wcscpy_s(__out_ecount_z(_S1max) wchar_t *_S1, __in size_t _S1max, __in_z const wchar_t *_S2) -{ - (_S1max); - ::wcscpy(_S1, _S2); -} - -inline void __cdecl tcscpy_s(__out_ecount_z(_SizeInChars) TCHAR * _Dst, __in size_t _SizeInChars, __in_z const TCHAR * _Src) -{ - (_SizeInChars); -#ifndef _ATL_MIN_CRT - ::_tcscpy(_Dst, _Src); -#else -#ifdef UNICODE - ::wcscpy(_Dst, _Src); -#else - ::strcpy(_Dst, _Src); -#endif -#endif -} - -/* ensure that strncpy_s null-terminate the dest string */ -inline errno_t __cdecl strncpy_s(__out_ecount_z(_SizeInChars) char *_Dest, __in size_t _SizeInChars, __in_z const char *_Source,__in size_t _Count) -{ - if (_Count == _TRUNCATE) - { - _Count = _SizeInChars - 1; - } - while (_Count > 0 && *_Source != 0) - { - *_Dest++ = *_Source++; - --_Count; - } - *_Dest = 0; - - return (*_Source!=0) ? STRUNCATE : 0; -} - -inline errno_t __cdecl wcsncpy_s(__out_ecount_z(_SizeInChars) wchar_t *_Dest, __in size_t _SizeInChars, __in_z const wchar_t *_Source, __in size_t _Count) -{ - if (_Count == _TRUNCATE) - { - _Count = _SizeInChars - 1; - } - while (_Count > 0 && *_Source != 0) - { - *_Dest++ = *_Source++; - --_Count; - } - *_Dest = 0; - - return (*_Source!=0) ? STRUNCATE : 0; -} - -inline errno_t __cdecl tcsncpy_s(__out_ecount_z(_SizeInChars) TCHAR *_Dest, __in size_t _SizeInChars, __in_z const TCHAR *_Source,__in size_t _Count) -{ - if (_Count == _TRUNCATE) - { - if(_SizeInChars>0) - { - _Count = _SizeInChars - 1; - } - else - { - _Count =0; - } - } - -#ifndef _ATL_MIN_CRT -#pragma warning(push) -#pragma warning(disable: 6535) - ::_tcsncpy(_Dest,_Source,_Count); -#pragma warning(pop) - if(_SizeInChars>0) - { - _Dest[_SizeInChars-1] = 0; - } -#else - while (_Count > 0 && *_Source != 0) - { - *_Dest++ = *_Source++; - --_Count; - } - *_Dest = 0; -#endif - - return (*_Source!=0) ? STRUNCATE : 0; -} - -inline void __cdecl strcat_s(__inout_ecount_z(_SizeInChars) char * _Dst, __in size_t _SizeInChars, __in_z const char * _Src) -{ - (_SizeInChars); - ::strcat(_Dst, _Src); -} - -inline void __cdecl wcscat_s(__inout_ecount_z(_SizeInChars) wchar_t * _Dst, __in size_t _SizeInChars, __in_z const wchar_t * _Src) -{ - (_SizeInChars); - ::wcscat(_Dst, _Src); -} - -inline void __cdecl tcscat_s(__inout_ecount_z(_SizeInChars) TCHAR * _Dst, __in size_t _SizeInChars, __in_z const TCHAR * _Src) -{ - (_SizeInChars); -#ifndef _ATL_MIN_CRT - ::_tcscat(_Dst, _Src); -#else -#ifdef UNICODE - ::wcscat(_Dst, _Src); -#else - ::strcat(_Dst, _Src); -#endif -#endif -} - -inline void __cdecl strlwr_s(__inout_ecount_z(_SizeInChars) char * _Str, size_t _SizeInChars) -{ - (_SizeInChars); - ::_strlwr(_Str); -} - -inline void __cdecl wcslwr_s(__inout_ecount_z(_SizeInChars) wchar_t * _Str, size_t _SizeInChars) -{ - (_SizeInChars); - ::_wcslwr(_Str); -} - -inline void __cdecl mbslwr_s(__inout_bcount_z(_SizeInChars) unsigned char * _Str, size_t _SizeInChars) -{ - (_SizeInChars); - ::_mbslwr(_Str); -} - -inline void __cdecl tcslwr_s(__inout_ecount_z(_SizeInChars) TCHAR * _Str, size_t _SizeInChars) -{ - (_SizeInChars); -#ifndef _ATL_MIN_CRT - ::_tcslwr(_Str); -#else -#ifdef UNICODE - ::_wcslwr(_Str); -#else - ::_strlwr(_Str); -#endif -#endif -} - -inline void __cdecl itoa_s(__in int _Val, __out_ecount_z(_SizeInChars) char *_Buf, __in size_t _SizeInChars, __in int _Radix) -{ - (_SizeInChars); - ::_itoa_s(_Val, _Buf, _SizeInChars, _Radix); -} - -inline void __cdecl itot_s(__in int _Val, __out_ecount_z(_SizeInChars) TCHAR *_Buf, __in size_t _SizeInChars, __in int _Radix) -{ - (_SizeInChars); - ::_itot(_Val, _Buf, _Radix); -} - -inline void __cdecl ltoa_s(__in long _Val, __out_ecount_z(_SizeInChars) char *_Buf, __in size_t _SizeInChars, __in int _Radix) -{ - (_SizeInChars); - ::_ltoa(_Val, _Buf, _Radix); -} - -inline void __cdecl ltot_s(__in long _Val, __out_ecount_z(_SizeInChars) TCHAR *_Buf, __in size_t _SizeInChars, __in int _Radix) -{ - (_SizeInChars); - ::_ltot(_Val, _Buf, _Radix); -} - -inline void __cdecl ultoa_s(__in unsigned long _Val, __out_ecount_z(_SizeInChars) char *_Buf, __in size_t _SizeInChars, __in int _Radix) -{ - (_SizeInChars); - ::_ultoa(_Val, _Buf, _Radix); -} - -inline void __cdecl ultow_s(__in unsigned long _Val, __out_ecount_z(_SizeInChars) wchar_t *_Buf, __in size_t _SizeInChars, __in int _Radix) -{ - (_SizeInChars); - ::_ultow(_Val, _Buf, _Radix); -} - -inline void __cdecl ultot_s(__in unsigned long _Val, __out_ecount_z(_SizeInChars) TCHAR *_Buf, __in size_t _SizeInChars, __in int _Radix) -{ - (_SizeInChars); - ::_ultot(_Val, _Buf, _Radix); -} - -inline void __cdecl i64toa_s(__in __int64 _Val, __out_ecount_z(_SizeInChars) char *_Buf, __in size_t _SizeInChars, __in int _Radix) -{ - (_SizeInChars); - ::_i64toa(_Val, _Buf, _Radix); -} - -inline void __cdecl i64tow_s(__in __int64 _Val, __out_ecount_z(_SizeInChars) wchar_t *_Buf, __in size_t _SizeInChars, __in int _Radix) -{ - (_SizeInChars); - ::_i64tow(_Val, _Buf, _Radix); -} - -inline void __cdecl ui64toa_s(__in unsigned __int64 _Val, __out_ecount_z(_SizeInChars) char *_Buf, __in size_t _SizeInChars, __in int _Radix) -{ - (_SizeInChars); - ::_ui64toa(_Val, _Buf, _Radix); -} - -inline void __cdecl ui64tow_s(__in unsigned __int64 _Val, __out_ecount_z(_SizeInChars) wchar_t *_Buf, __in size_t _SizeInChars, __in int _Radix) -{ - (_SizeInChars); - ::_ui64tow(_Val, _Buf, _Radix); -} - -inline void __cdecl gcvt_s(__out_ecount_z(_SizeInChars) char *_Buffer, __in size_t _SizeInChars, __in double _Value, __in int _Ndec) -{ - (_SizeInChars); - ::_gcvt(_Value, _Ndec, _Buffer); -} - -inline void __cdecl tsplitpath_s(__in_z const TCHAR *_Path, __out_ecount_z_opt(_Drive_len) TCHAR *_Drive, __in size_t _Drive_len, - __out_ecount_z_opt(_Dir_len) TCHAR *_Dir, __in size_t _Dir_len, - __out_ecount_z_opt(_Fname_ext) TCHAR *_Fname, __in size_t _Fname_len, - __out_ecount_z_opt(_Ext_len) TCHAR *_Ext, __in size_t _Ext_len) -{ - (_Drive_len, _Dir_len, _Fname_len, _Ext_len); - ::_tsplitpath(_Path, _Drive, _Dir, _Fname, _Ext); -} - -inline void __cdecl tmakepath_s(__out_ecount_z(_SizeInChars) TCHAR *_Path, __in size_t _SizeInChars, __in_z const TCHAR *_Drive, - __in_z const TCHAR *_Dir, __in_z const TCHAR *_Fname, __in_z const TCHAR *_Ext) -{ - (_SizeInChars); - ::_tmakepath(_Path, _Drive, _Dir, _Fname, _Ext); -} - -inline size_t __cdecl strnlen(__in_ecount(_Maxsize) const char *_Str, __in size_t _Maxsize) -{ - (_Maxsize); - return ::strlen(_Str); -} - -inline size_t __cdecl wcsnlen(__in_ecount(_Maxsize) const wchar_t *_Wcs, __in size_t _Maxsize) -{ - (_Maxsize); - return ::wcslen(_Wcs); -} - -inline size_t __cdecl tcsnlen(__in_ecount(_Maxsize) const TCHAR *_Str, __in size_t _Maxsize) -{ - (_Maxsize); - return ::_tcslen(_Str); -} - -inline int get_errno() -{ - return errno; -} - -inline void set_errno(__in int _Value) -{ - errno = _Value; -} - -#endif // _SECURE_ATL - -} // namespace Checked - -} // namespace ATL -#pragma pack(pop) - -#endif // __ATLCHECKED_H__ - -///////////////////////////////////////////////////////////////////////////// diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlcom.h b/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlcom.h deleted file mode 100644 index e0363780d..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlcom.h +++ /dev/null @@ -1,6378 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLCOM_H__ -#define __ATLCOM_H__ - -#pragma once - -#ifndef _ATL_NO_PRAGMA_WARNINGS -#pragma warning (push) -#pragma warning(disable: 4702) // unreachable code -#pragma warning(disable: 4355) // 'this' used in initializer list -#pragma warning(disable: 4511) // copy constructor could not be generated -#pragma warning(disable: 4512) // assignment operator could not be generated -#pragma warning(disable : 4668) // is not defined as a preprocessor macro, replacing with '0' for '#if/#elif -#pragma warning(disable : 4820) // padding added after member -#pragma warning(disable : 4571) //catch(...) blocks compiled with /EHs do NOT catch or re-throw Structured Exceptions -#endif //!_ATL_NO_PRAGMA_WARNINGS - -#ifdef _ATL_ALL_WARNINGS -#pragma warning( push ) -#endif -#pragma warning(disable: 4127) // constant expression -#pragma warning(disable: 4786) // avoid 255-character limit warnings - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#ifndef __ATLBASE_H__ - #error atlcom.h requires atlbase.h to be included first -#endif - -#include -#pragma pack(push, _ATL_PACKING) - -EXTERN_C const IID IID_ITargetFrame; - -#include - -#pragma pack(push, _ATL_PACKING) -namespace ATL -{ - -#define CComConnectionPointContainerImpl ATL::IConnectionPointContainerImpl -#define CComISupportErrorInfoImpl ATL::ISupportErrorInfoImpl -#define CComProvideClassInfo2Impl ATL::IProvideClassInfoImpl -#define CComDualImpl ATL::IDispatchImpl - -#ifdef _ATL_DEBUG_QI -#ifndef _ATL_DEBUG -#define _ATL_DEBUG -#endif // _ATL_DEBUG -#endif // _ATL_DEBUG_QI - -#ifdef _ATL_DEBUG_QI -#define _ATLDUMPIID(iid, name, hr) AtlDumpIID(iid, name, hr) -#else -#define _ATLDUMPIID(iid, name, hr) hr -#endif - -#define _ATL_DEBUG_ADDREF_RELEASE_IMPL(className)\ - virtual ULONG STDMETHODCALLTYPE AddRef(void) = 0;\ - virtual ULONG STDMETHODCALLTYPE Release(void) = 0; - -///////////////////////////////////////////////////////////////////////////// -// AtlReportError - -inline HRESULT WINAPI AtlReportError(const CLSID& clsid, UINT nID, const IID& iid = GUID_NULL, - HRESULT hRes = 0, HINSTANCE hInst = _AtlBaseModule.GetResourceInstance()) -{ - return AtlSetErrorInfo(clsid, (LPCOLESTR)MAKEINTRESOURCE(nID), 0, NULL, iid, hRes, hInst); -} - -inline HRESULT WINAPI AtlReportError(const CLSID& clsid, UINT nID, DWORD dwHelpID, - LPCOLESTR lpszHelpFile, const IID& iid = GUID_NULL, HRESULT hRes = 0, - HINSTANCE hInst = _AtlBaseModule.GetResourceInstance()) -{ - return AtlSetErrorInfo(clsid, (LPCOLESTR)MAKEINTRESOURCE(nID), dwHelpID, - lpszHelpFile, iid, hRes, hInst); -} - -inline HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCSTR lpszDesc, - DWORD dwHelpID, LPCSTR lpszHelpFile, const IID& iid = GUID_NULL, HRESULT hRes = 0) -{ - ATLASSERT(lpszDesc != NULL); - if (lpszDesc == NULL) - return E_POINTER; - USES_CONVERSION_EX; - LPCOLESTR pwszDesc = A2COLE_EX(lpszDesc, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); - if(pwszDesc == NULL) - return E_OUTOFMEMORY; - - LPCWSTR pwzHelpFile = NULL; - if(lpszHelpFile != NULL) - { - pwzHelpFile = A2CW_EX(lpszHelpFile, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); - if(pwzHelpFile == NULL) - return E_OUTOFMEMORY; - } - - return AtlSetErrorInfo(clsid, pwszDesc, dwHelpID, pwzHelpFile, iid, hRes, NULL); -} - -inline HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCSTR lpszDesc, - const IID& iid = GUID_NULL, HRESULT hRes = 0) -{ - return AtlReportError(clsid, lpszDesc, 0, NULL, iid, hRes); -} - -inline HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCOLESTR lpszDesc, - const IID& iid = GUID_NULL, HRESULT hRes = 0) -{ - return AtlSetErrorInfo(clsid, lpszDesc, 0, NULL, iid, hRes, NULL); -} - -inline HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCOLESTR lpszDesc, DWORD dwHelpID, - LPCOLESTR lpszHelpFile, const IID& iid = GUID_NULL, HRESULT hRes = 0) -{ - return AtlSetErrorInfo(clsid, lpszDesc, dwHelpID, lpszHelpFile, iid, hRes, NULL); -} - -// Returns the apartment type that the current thread is in. false is returned -// if the thread isn't in an apartment. -inline bool AtlGetApartmentType(DWORD* pApartmentType) -{ - HRESULT hr = CoInitialize(NULL); - if (SUCCEEDED(hr)) - CoUninitialize(); - - if (hr == S_FALSE) - { - *pApartmentType = COINIT_APARTMENTTHREADED; - return true; - } -#if ((_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM)) - else - if (hr == RPC_E_CHANGED_MODE) - { - *pApartmentType = COINIT_MULTITHREADED; - return true; - } -#endif - return false; -} - -///////////////////////////////////////////////////////////////////////////// -// CComTypeAttr - -class CComTypeAttr -{ -// Construction -public: - CComTypeAttr( ITypeInfo* pTypeInfo ) throw() : - m_pTypeAttr( NULL ), - m_pTypeInfo( pTypeInfo ) - { - } - ~CComTypeAttr() throw() - { - Release(); - } - -// Operators -public: - TYPEATTR* operator->() throw() - { - ATLASSUME( m_pTypeAttr != NULL ); - - return m_pTypeAttr; - } - TYPEATTR** operator&() throw() - { - ATLASSUME( m_pTypeAttr == NULL ); - - return &m_pTypeAttr; - } - - operator const TYPEATTR*() const throw() - { - return m_pTypeAttr; - } - -// Operations -public: - void Release() throw() - { - if( m_pTypeAttr != NULL ) - { - ATLASSUME( m_pTypeInfo != NULL ); - m_pTypeInfo->ReleaseTypeAttr( m_pTypeAttr ); - m_pTypeAttr = NULL; - } - } - -public: - TYPEATTR* m_pTypeAttr; - CComPtr< ITypeInfo > m_pTypeInfo; -}; - - -///////////////////////////////////////////////////////////////////////////// -// CComVarDesc - -class CComVarDesc -{ -// Construction -public: - CComVarDesc( ITypeInfo* pTypeInfo ) throw() : - m_pVarDesc( NULL ), - m_pTypeInfo( pTypeInfo ) - { - } - ~CComVarDesc() throw() - { - Release(); - } - -// Operators -public: - VARDESC* operator->() throw() - { - ATLASSUME( m_pVarDesc != NULL ); - - return m_pVarDesc; - } - VARDESC** operator&() throw() - { - ATLASSUME( m_pVarDesc == NULL ); - - return &m_pVarDesc; - } - - operator const VARDESC*() const throw() - { - return m_pVarDesc; - } - -// Operations -public: - void Release() throw() - { - if( m_pVarDesc != NULL ) - { - ATLASSUME( m_pTypeInfo != NULL ); - m_pTypeInfo->ReleaseVarDesc( m_pVarDesc ); - m_pVarDesc = NULL; - } - } - -public: - VARDESC* m_pVarDesc; - CComPtr< ITypeInfo > m_pTypeInfo; -}; - - -///////////////////////////////////////////////////////////////////////////// -// CComFuncDesc - -class CComFuncDesc -{ -// Construction -public: - CComFuncDesc( ITypeInfo* pTypeInfo ) throw() : - m_pFuncDesc( NULL ), - m_pTypeInfo( pTypeInfo ) - { - } - ~CComFuncDesc() throw() - { - Release(); - } - -// Operators -public: - FUNCDESC* operator->() throw() - { - ATLASSUME( m_pFuncDesc != NULL ); - - return m_pFuncDesc; - } - FUNCDESC** operator&() throw() - { - ATLASSUME( m_pFuncDesc == NULL ); - - return &m_pFuncDesc; - } - - operator const FUNCDESC*() const throw() - { - return m_pFuncDesc; - } - -// Operations -public: - void Release() throw() - { - if( m_pFuncDesc != NULL ) - { - ATLASSUME( m_pTypeInfo != NULL ); - m_pTypeInfo->ReleaseFuncDesc( m_pFuncDesc ); - m_pFuncDesc = NULL; - } - } - -public: - FUNCDESC* m_pFuncDesc; - CComPtr< ITypeInfo > m_pTypeInfo; -}; - - -///////////////////////////////////////////////////////////////////////////// -// CComExcepInfo - -class CComExcepInfo : - public EXCEPINFO -{ -// Construction -public: - CComExcepInfo() - { - memset( this, 0, sizeof( *this ) ); - } - ~CComExcepInfo() - { - Clear(); - } - -// Operations -public: - void Clear() - { - ::SysFreeString(bstrSource); - ::SysFreeString(bstrDescription); - ::SysFreeString(bstrHelpFile); - - memset(this, 0, sizeof(*this)); - } -}; - - -////////////////////////////////////////////////////////////////////////////// -// IPersistImpl -template -class ATL_NO_VTABLE IPersistImpl : public IPersist -{ -public: - STDMETHOD(GetClassID)(CLSID *pClassID) - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistImpl::GetClassID\n")); - if (pClassID == NULL) - return E_FAIL; - *pClassID = T::GetObjectCLSID(); - return S_OK; - } -}; - -////////////////////////////////////////////////////////////////////////////// -// CFakeFirePropNotifyEvent -class CFakeFirePropNotifyEvent -{ -public: - static HRESULT FireOnRequestEdit(IUnknown* /*pUnk*/, DISPID /*dispID*/) - { - return S_OK; - } - static HRESULT FireOnChanged(IUnknown* /*pUnk*/, DISPID /*dispID*/) - { - return S_OK; - } -}; -typedef CFakeFirePropNotifyEvent _ATL_PROP_NOTIFY_EVENT_CLASS; - - -////////////////////////////////////////////////////////////////////////////// -// ALT_PROP_VAL_MAP - -struct ATL_PROPVALMAP_ENTRY -{ - DISPID dispid; - VARIANT val; - LPCOLESTR szDesc; -}; - -#define BEGIN_PROP_VAL_MAP(theClass) \ - static ATL::ATL_PROPVALMAP_ENTRY* GetPropValMap(int *cnt)\ - {\ - static ATL::ATL_PROPVALMAP_ENTRY pPropMap[] = \ - { - -#define PROP_VAL_INT(dispid, ival, str) \ - {dispid, {VT_I4, 0, 0, 0, ival}, OLESTR(str)}, - - -#define END_PROP_VAL_MAP() \ - }; \ - if (cnt) \ - *cnt = sizeof(pPropMap)/sizeof(pPropMap[0]); \ - return pPropMap; \ - } - -#define DECLARE_EMPTY_PROP_VAL_MAP() \ -public: \ - static ATL::ATL_PROPVALMAP_ENTRY* GetPropValMap(int *cnt)\ - { \ - if (cnt) \ - *cnt = 0; \ - return NULL; \ - } - -////////////////////////////////////////////////////////////////////////////// -// ATL Persistence - -struct ATL_PROPMAP_ENTRY -{ - LPCOLESTR szDesc; - DISPID dispid; - const CLSID* pclsidPropPage; - const IID* piidDispatch; - DWORD dwOffsetData; - DWORD dwSizeData; - VARTYPE vt; -}; - -// This one is DEPRECATED and is used for ATL 2.X controls -// it includes an implicit m_sizeExtent -#define BEGIN_PROPERTY_MAP(theClass) \ - __if_not_exists(__ATL_PROP_NOTIFY_EVENT_CLASS) \ - { \ - typedef ATL::_ATL_PROP_NOTIFY_EVENT_CLASS __ATL_PROP_NOTIFY_EVENT_CLASS; \ - } \ - typedef theClass _PropMapClass; \ - static ATL::ATL_PROPMAP_ENTRY* GetPropertyMap()\ - {\ - static ATL::ATL_PROPMAP_ENTRY pPropMap[] = \ - { \ - {OLESTR("_cx"), 0, &CLSID_NULL, NULL, offsetof(_PropMapClass, m_sizeExtent.cx), sizeof(long), VT_UI4}, \ - {OLESTR("_cy"), 0, &CLSID_NULL, NULL, offsetof(_PropMapClass, m_sizeExtent.cy), sizeof(long), VT_UI4}, - -// This one can be used on any type of object, but does not -// include the implicit m_sizeExtent -#define BEGIN_PROP_MAP(theClass) \ - __if_not_exists(__ATL_PROP_NOTIFY_EVENT_CLASS) \ - { \ - typedef ATL::_ATL_PROP_NOTIFY_EVENT_CLASS __ATL_PROP_NOTIFY_EVENT_CLASS; \ - } \ - typedef theClass _PropMapClass; \ - static ATL::ATL_PROPMAP_ENTRY* GetPropertyMap()\ - {\ - static ATL::ATL_PROPMAP_ENTRY pPropMap[] = \ - { - -#define PROP_ENTRY(szDesc, dispid, clsid) \ - {OLESTR(szDesc), dispid, &clsid, &__uuidof(IDispatch), 0, 0, 0}, - -#define PROP_ENTRY_EX(szDesc, dispid, clsid, iidDispatch) \ - {OLESTR(szDesc), dispid, &clsid, &iidDispatch, 0, 0, 0}, - -#define PROP_PAGE(clsid) \ - {NULL, NULL, &clsid, &IID_NULL, 0, 0, 0}, - -#define PROP_DATA_ENTRY(szDesc, member, vt) \ - {OLESTR(szDesc), 0, &CLSID_NULL, NULL, offsetof(_PropMapClass, member), sizeof(((_PropMapClass*)0)->member), vt}, - -#define END_PROPERTY_MAP() \ - {NULL, 0, NULL, &IID_NULL, 0, 0, 0} \ - }; \ - return pPropMap; \ - } - -#define END_PROP_MAP() \ - {NULL, 0, NULL, &IID_NULL, 0, 0, 0} \ - }; \ - return pPropMap; \ - } - -////////////////////////////////////////////////////////////////////////////// -// IPersist* Helpers - -ATLAPI AtlIPersistStreamInit_Load(LPSTREAM pStm, ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk); -ATLAPI AtlIPersistStreamInit_Save(LPSTREAM pStm, BOOL fClearDirty, ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk); -ATLAPI AtlIPersistPropertyBag_Load(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog, ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk); -ATLAPI AtlIPersistPropertyBag_Save(LPPROPERTYBAG pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties, ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk); - -////////////////////////////////////////////////////////////////////////////// -// IPersistStreamInitImpl -template -class ATL_NO_VTABLE IPersistStreamInitImpl : public IPersistStreamInit -{ -public: - // IPersist - STDMETHOD(GetClassID)(CLSID *pClassID) - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistStreamInitImpl::GetClassID\n")); - if (pClassID == NULL) - return E_POINTER; - *pClassID = T::GetObjectCLSID(); - return S_OK; - } - - // IPersistStream - STDMETHOD(IsDirty)() - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistStreamInitImpl::IsDirty\n")); - T* pT = static_cast(this); - return (pT->m_bRequiresSave) ? S_OK : S_FALSE; - } - STDMETHOD(Load)(LPSTREAM pStm) - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistStreamInitImpl::Load\n")); - - T* pT = static_cast(this); - return pT->IPersistStreamInit_Load(pStm, T::GetPropertyMap()); - } - STDMETHOD(Save)(LPSTREAM pStm, BOOL fClearDirty) - { - T* pT = static_cast(this); - ATLTRACE(atlTraceCOM, 2, _T("IPersistStreamInitImpl::Save\n")); - return pT->IPersistStreamInit_Save(pStm, fClearDirty, T::GetPropertyMap()); - } - STDMETHOD(GetSizeMax)(ULARGE_INTEGER* pcbSize) - { - HRESULT hr = S_OK; - T* pT = static_cast(this); - ATLTRACE(atlTraceCOM, 2, _T("IPersistStreamInitImpl::GetSizeMax\n")); - - if (pcbSize == NULL) - return E_POINTER; - - ATL_PROPMAP_ENTRY* pMap = T::GetPropertyMap(); - ATLENSURE(pMap != NULL); - - // Start the size with the size of the ATL version we write out. - ULARGE_INTEGER nSize; - nSize.HighPart = 0; - nSize.LowPart = sizeof(DWORD); - - CComPtr pDispatch; - const IID* piidOld = NULL; - for (int i = 0; pMap[i].pclsidPropPage != NULL; i++) - { - if (pMap[i].szDesc == NULL) - continue; - - // check if raw data entry - if (pMap[i].dwSizeData != 0) - { - ULONG ulSize=0; - //Calculate stream size for BSTRs special case - if (pMap[i].vt == VT_BSTR) - { - void* pData = (void*) (pMap[i].dwOffsetData + (DWORD_PTR)pT); - ATLENSURE( pData >= (void*)(DWORD_PTR)pMap[i].dwOffsetData - && pData >= (void*)(DWORD_PTR)pT ); - BSTR bstr=*reinterpret_cast(pData); - ulSize=CComBSTR::GetStreamSize(bstr); - } else - { - ulSize = pMap[i].dwSizeData; - } - nSize.QuadPart += ulSize; - continue; - } - - CComVariant var; - if (pMap[i].piidDispatch != piidOld) - { - pDispatch.Release(); - if (FAILED(pT->GetUnknown()->QueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch))) - { - ATLTRACE(atlTraceCOM, 0, _T("Failed to get a dispatch pointer for property #%i\n"), i); - hr = E_FAIL; - break; - } - piidOld = pMap[i].piidDispatch; - } - - if (FAILED(pDispatch.GetProperty(pMap[i].dispid, &var))) - { - ATLTRACE(atlTraceCOM, 0, _T("Invoked failed on DISPID %x\n"), pMap[i].dispid); - hr = E_FAIL; - break; - } - nSize.QuadPart += var.GetSize(); - } - *pcbSize = nSize; - return hr; - } - - // IPersistStreamInit - STDMETHOD(InitNew)() - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistStreamInitImpl::InitNew\n")); - T* pT = static_cast(this); - pT->m_bRequiresSave = TRUE; - return S_OK; - } - - HRESULT IPersistStreamInit_Load(LPSTREAM pStm, ATL_PROPMAP_ENTRY* pMap) - { - T* pT = static_cast(this); - HRESULT hr = AtlIPersistStreamInit_Load(pStm, pMap, pT, pT->GetUnknown()); - if (SUCCEEDED(hr)) - pT->m_bRequiresSave = FALSE; - return hr; - - } - HRESULT IPersistStreamInit_Save(LPSTREAM pStm, BOOL fClearDirty, ATL_PROPMAP_ENTRY* pMap) - { - T* pT = static_cast(this); - HRESULT hr; - hr = AtlIPersistStreamInit_Save(pStm, fClearDirty, pMap, pT, pT->GetUnknown()); - if (fClearDirty && SUCCEEDED(hr)) - { - pT->m_bRequiresSave=FALSE; - } - return hr; - - } -}; - -////////////////////////////////////////////////////////////////////////////// -// IPersistStorageImpl -template -class ATL_NO_VTABLE IPersistStorageImpl : public IPersistStorage -{ -public: - // IPersist - STDMETHOD(GetClassID)(CLSID *pClassID) - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistStorageImpl::GetClassID\n")); - if (pClassID == NULL) - return E_POINTER; - *pClassID = T::GetObjectCLSID(); - return S_OK; - } - - // IPersistStorage - STDMETHOD(IsDirty)(void) - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistStorageImpl::IsDirty\n")); - CComPtr p; - p.p = IPSI_GetIPersistStreamInit(); - return (p != NULL) ? p->IsDirty() : E_FAIL; - } - STDMETHOD(InitNew)(IStorage*) - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistStorageImpl::InitNew\n")); - CComPtr p; - p.p = IPSI_GetIPersistStreamInit(); - return (p != NULL) ? p->InitNew() : E_FAIL; - } - STDMETHOD(Load)(IStorage* pStorage) - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistStorageImpl::Load\n")); - if (pStorage == NULL) - return E_INVALIDARG; - CComPtr p; - p.p = IPSI_GetIPersistStreamInit(); - HRESULT hr = E_FAIL; - if (p != NULL) - { - CComPtr spStream; - hr = pStorage->OpenStream(OLESTR("Contents"), NULL, - STGM_DIRECT | STGM_SHARE_EXCLUSIVE, 0, &spStream); - if (SUCCEEDED(hr)) - hr = p->Load(spStream); - } - return hr; - } - STDMETHOD(Save)(IStorage* pStorage, BOOL fSameAsLoad) - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistStorageImpl::Save\n")); - if (pStorage == NULL) - return E_INVALIDARG; - CComPtr p; - p.p = IPSI_GetIPersistStreamInit(); - HRESULT hr = E_FAIL; - if (p != NULL) - { - CComPtr spStream; - static LPCOLESTR vszContents = OLESTR("Contents"); - hr = pStorage->CreateStream(vszContents, - STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, - 0, 0, &spStream); - if (SUCCEEDED(hr)) - hr = p->Save(spStream, fSameAsLoad); - } - return hr; - } - STDMETHOD(SaveCompleted)(IStorage* /* pStorage */) - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistStorageImpl::SaveCompleted\n")); - return S_OK; - } - STDMETHOD(HandsOffStorage)(void) - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistStorageImpl::HandsOffStorage\n")); - return S_OK; - } -private: - IPersistStreamInit* IPSI_GetIPersistStreamInit(); -}; - -template -IPersistStreamInit* IPersistStorageImpl::IPSI_GetIPersistStreamInit() -{ - T* pT = static_cast(this); - IPersistStreamInit* p; - if (FAILED(pT->GetUnknown()->QueryInterface(__uuidof(IPersistStreamInit), (void**)&p))) - pT->_InternalQueryInterface(__uuidof(IPersistStreamInit), (void**)&p); - return p; -} - - -////////////////////////////////////////////////////////////////////////////// -// IPersistPropertyBagImpl -template -class ATL_NO_VTABLE IPersistPropertyBagImpl : public IPersistPropertyBag -{ -public: - // IPersist - STDMETHOD(GetClassID)(CLSID *pClassID) - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistPropertyBagImpl::GetClassID\n")); - if (pClassID == NULL) - return E_POINTER; - *pClassID = T::GetObjectCLSID(); - return S_OK; - } - - // IPersistPropertyBag - // - STDMETHOD(InitNew)() - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistPropertyBagImpl::InitNew\n")); - T* pT = static_cast(this); - pT->m_bRequiresSave = TRUE; - return S_OK; - } - STDMETHOD(Load)(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog) - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistPropertyBagImpl::Load\n")); - T* pT = static_cast(this); - ATL_PROPMAP_ENTRY* pMap = T::GetPropertyMap(); - ATLASSERT(pMap != NULL); - return pT->IPersistPropertyBag_Load(pPropBag, pErrorLog, pMap); - } - STDMETHOD(Save)(LPPROPERTYBAG pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties) - { - ATLTRACE(atlTraceCOM, 2, _T("IPersistPropertyBagImpl::Save\n")); - T* pT = static_cast(this); - ATL_PROPMAP_ENTRY* pMap = T::GetPropertyMap(); - ATLASSERT(pMap != NULL); - return pT->IPersistPropertyBag_Save(pPropBag, fClearDirty, fSaveAllProperties, pMap); - } - HRESULT IPersistPropertyBag_Load(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog, ATL_PROPMAP_ENTRY* pMap) - { - T* pT = static_cast(this); - HRESULT hr = AtlIPersistPropertyBag_Load(pPropBag, pErrorLog, pMap, pT, pT->GetUnknown()); - if (SUCCEEDED(hr)) - pT->m_bRequiresSave = FALSE; - return hr; - } - HRESULT IPersistPropertyBag_Save(LPPROPERTYBAG pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties, ATL_PROPMAP_ENTRY* pMap) - { - T* pT = static_cast(this); - HRESULT hr; - hr = AtlIPersistPropertyBag_Save(pPropBag, fClearDirty, fSaveAllProperties, pMap, pT, pT->GetUnknown()); - if (fClearDirty && SUCCEEDED(hr)) - { - pT->m_bRequiresSave=FALSE; - } - return hr; - - } -}; - -////////////////////////////////////////////////////////////////////////////// -// CSecurityDescriptor -ATL_DEPRECATED("CSecurityDescriptor has been replaced by CSID") class CSecurityDescriptor -{ -public: - CSecurityDescriptor(); - ~CSecurityDescriptor(); - -public: - HRESULT Attach(PSECURITY_DESCRIPTOR pSelfRelativeSD); - HRESULT AttachObject(HANDLE hObject); - HRESULT Initialize(); - HRESULT InitializeFromProcessToken(BOOL bDefaulted = FALSE); - HRESULT InitializeFromThreadToken(BOOL bDefaulted = FALSE, BOOL bRevertToProcessToken = TRUE); - HRESULT SetOwner(PSID pOwnerSid, BOOL bDefaulted = FALSE); - HRESULT SetGroup(PSID pGroupSid, BOOL bDefaulted = FALSE); - HRESULT Allow(LPCTSTR pszPrincipal, DWORD dwAccessMask); - HRESULT Deny(LPCTSTR pszPrincipal, DWORD dwAccessMask); - HRESULT Revoke(LPCTSTR pszPrincipal); - HRESULT Allow(PSID pSid, DWORD dwAccessMask); - HRESULT Deny(PSID pSid, DWORD dwAccessMask); - HRESULT Revoke(PSID pSid); - - // utility functions - // Any PSID you get from these functions should be free()ed - static HRESULT SetPrivilege(LPCTSTR Privilege, BOOL bEnable = TRUE, HANDLE hToken = NULL); - static HRESULT GetTokenSids(HANDLE hToken, PSID* ppUserSid, PSID* ppGroupSid); - static HRESULT GetProcessSids(PSID* ppUserSid, PSID* ppGroupSid = NULL); - static HRESULT GetThreadSids(PSID* ppUserSid, PSID* ppGroupSid = NULL, BOOL bOpenAsSelf = FALSE); - static HRESULT CopyACL(PACL pDest, PACL pSrc); - static HRESULT GetCurrentUserSID(PSID *ppSid); - static HRESULT GetPrincipalSID(LPCTSTR pszPrincipal, PSID *ppSid); - static HRESULT AddAccessAllowedACEToACL(PACL *Acl, PSID pSid, DWORD dwAccessMask); - static HRESULT AddAccessDeniedACEToACL(PACL *Acl, PSID pSid, DWORD dwAccessMask); - static HRESULT RemovePrincipalFromACL(PACL Acl, PSID pSid); - static HRESULT CloneSID(PSID *ppSIDDest, PSID pSIDSrc) - { - HRESULT hr = S_OK; - if (ppSIDDest == NULL) - return E_POINTER; - - if (*ppSIDDest != NULL) - return E_INVALIDARG; - *ppSIDDest = NULL; - - if (!IsValidSid(pSIDSrc)) - return E_INVALIDARG; - - DWORD dwSize = GetLengthSid(pSIDSrc); - - *ppSIDDest = (PSID) malloc(dwSize); - if (*ppSIDDest == NULL) - return E_OUTOFMEMORY; - if (!CopySid(dwSize, *ppSIDDest, pSIDSrc)) - { - hr = AtlHresultFromLastError(); - ATLASSERT(FALSE); - free(*ppSIDDest); - *ppSIDDest = NULL; - } - return hr; - } - operator PSECURITY_DESCRIPTOR() - { - return m_pSD; - } - -public: - PSECURITY_DESCRIPTOR m_pSD; - PSID m_pOwner; - PSID m_pGroup; - PACL m_pDACL; - PACL m_pSACL; -}; - -inline CSecurityDescriptor::CSecurityDescriptor() -{ - m_pSD = NULL; - m_pOwner = NULL; - m_pGroup = NULL; - m_pDACL = NULL; - m_pSACL= NULL; -} - -inline CSecurityDescriptor::~CSecurityDescriptor() -{ - delete m_pSD; - free(m_pOwner); - free(m_pGroup); - free(m_pDACL); - free(m_pSACL); -} - -inline HRESULT CSecurityDescriptor::Initialize() -{ - delete m_pSD; - m_pSD = NULL; - - free(m_pOwner); - m_pOwner = NULL; - - free(m_pGroup); - m_pGroup = NULL; - - free(m_pDACL); - m_pDACL = NULL; - - free(m_pSACL); - m_pSACL = NULL; - - ATLTRY(m_pSD = new SECURITY_DESCRIPTOR); - if (m_pSD != NULL) - { - if (InitializeSecurityDescriptor(m_pSD, SECURITY_DESCRIPTOR_REVISION)) - return S_OK; - - HRESULT hr = AtlHresultFromLastError(); - delete m_pSD; - m_pSD = NULL; - ATLASSERT(FALSE); - return hr; - } - - return E_OUTOFMEMORY; -} - -inline HRESULT CSecurityDescriptor::InitializeFromProcessToken(BOOL bDefaulted) -{ - HRESULT hr = Initialize(); - if (SUCCEEDED(hr)) - { - PSID pUserSid = NULL; - PSID pGroupSid = NULL; - hr = GetProcessSids(&pUserSid, &pGroupSid); - if (SUCCEEDED(hr)) - { - hr = SetOwner(pUserSid, bDefaulted); - if (SUCCEEDED(hr)) - { - hr = SetGroup(pGroupSid, bDefaulted); - } - free(pUserSid); - free(pGroupSid); - // If something failed reinitialize the object - if (FAILED(hr)) - Initialize(); - } - } - return hr; -} - -inline HRESULT CSecurityDescriptor::InitializeFromThreadToken(BOOL bDefaulted, BOOL bRevertToProcessToken) -{ - HRESULT hr = Initialize(); - if (SUCCEEDED(hr)) - { - PSID pUserSid = NULL; - PSID pGroupSid = NULL; - - hr = GetThreadSids(&pUserSid, &pGroupSid); - if (HRESULT_CODE(hr) == ERROR_NO_TOKEN && bRevertToProcessToken) - hr = GetProcessSids(&pUserSid, &pGroupSid); - if (SUCCEEDED(hr)) - { - hr = SetOwner(pUserSid, bDefaulted); - if (SUCCEEDED(hr)) - hr = SetGroup(pGroupSid, bDefaulted); - free(pUserSid); - free(pGroupSid); - // If something failed reinitialize the object - if (FAILED(hr)) - Initialize(); - } - } - return hr; -} - -inline HRESULT CSecurityDescriptor::SetOwner(PSID pOwnerSid, BOOL bDefaulted) -{ - ATLASSUME(m_pSD); - HRESULT hr = S_OK; - - // Mark the SD as having no owner - if (SetSecurityDescriptorOwner(m_pSD, NULL, bDefaulted)) - { - free(m_pOwner); - m_pOwner = NULL; - - // If they asked for no owner don't do the copy - if (pOwnerSid == NULL) - return S_OK; - - // Make a copy of the Sid for the return value - hr = CloneSID(&m_pOwner, pOwnerSid); - if (SUCCEEDED(hr)) - { - ATLASSERT(IsValidSid(m_pOwner)); - - if (!SetSecurityDescriptorOwner(m_pSD, m_pOwner, bDefaulted)) - { - hr = AtlHresultFromLastError(); - ATLASSERT(FALSE); - free(m_pOwner); - m_pOwner = NULL; - } - } - } - else - { - hr = AtlHresultFromLastError(); - ATLASSERT(FALSE); - } - - return hr; -} - -inline HRESULT CSecurityDescriptor::SetGroup(PSID pGroupSid, BOOL bDefaulted) -{ - ATLASSUME(m_pSD); - HRESULT hr = S_OK; - - // Mark the SD as having no Group - if (SetSecurityDescriptorGroup(m_pSD, NULL, bDefaulted)) - { - free(m_pGroup); - m_pGroup = NULL; - - // If they asked for no Group don't do the copy - if (pGroupSid == NULL) - return S_OK; - - // Make a copy of the Sid for the return value - hr = CloneSID(&m_pGroup, pGroupSid); - if (SUCCEEDED(hr)) - { - ATLASSERT(IsValidSid(m_pGroup)); - - if (!SetSecurityDescriptorGroup(m_pSD, m_pGroup, bDefaulted)) - { - hr = AtlHresultFromLastError(); - ATLASSERT(FALSE); - free(m_pGroup); - m_pGroup = NULL; - } - } - } - else - { - hr = AtlHresultFromLastError(); - ATLASSERT(FALSE); - } - - return hr; -} - -inline HRESULT CSecurityDescriptor::Allow(LPCTSTR pszPrincipal, DWORD dwAccessMask) -{ - PSID pSid; - HRESULT hr = GetPrincipalSID(pszPrincipal, &pSid); - if (SUCCEEDED(hr)) - { - hr = Allow(pSid, dwAccessMask); - free(pSid); - } - return hr; -} - -inline HRESULT CSecurityDescriptor::Deny(LPCTSTR pszPrincipal, DWORD dwAccessMask) -{ - PSID pSid; - HRESULT hr = GetPrincipalSID(pszPrincipal, &pSid); - if (SUCCEEDED(hr)) - { - hr = Deny(pSid, dwAccessMask); - free(pSid); - } - return hr; -} - -inline HRESULT CSecurityDescriptor::Revoke(LPCTSTR pszPrincipal) -{ - PSID pSid; - HRESULT hr = GetPrincipalSID(pszPrincipal, &pSid); - if (SUCCEEDED(hr)) - { - hr = Revoke(pSid); - free(pSid); - } - return hr; -} - -inline HRESULT CSecurityDescriptor::Allow(PSID pSid, DWORD dwAccessMask) -{ - HRESULT hr = AddAccessAllowedACEToACL(&m_pDACL, pSid, dwAccessMask); - if (SUCCEEDED(hr)) - { - if (!SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE)) - hr = AtlHresultFromLastError(); - } - return hr; -} - -inline HRESULT CSecurityDescriptor::Deny(PSID pSid, DWORD dwAccessMask) -{ - HRESULT hr = AddAccessDeniedACEToACL(&m_pDACL, pSid, dwAccessMask); - if (SUCCEEDED(hr)) - { - if (!SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE)) - hr = AtlHresultFromLastError(); - } - return hr; -} - -inline HRESULT CSecurityDescriptor::Revoke(PSID pSid) -{ - HRESULT hr = RemovePrincipalFromACL(m_pDACL, pSid); - if (SUCCEEDED(hr)) - { - if (!SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE)) - hr = AtlHresultFromLastError(); - } - return hr; -} - -inline HRESULT CSecurityDescriptor::GetProcessSids(PSID* ppUserSid, PSID* ppGroupSid) -{ - HRESULT hr = S_OK; - HANDLE hToken = NULL; - if (ppUserSid) - *ppUserSid = NULL; - if (ppGroupSid) - *ppGroupSid = NULL; - if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) - { - hr = GetTokenSids(hToken, ppUserSid, ppGroupSid); - CloseHandle(hToken); - } - else - { - // Couldn't open process token - hr = AtlHresultFromLastError(); - ATLASSERT(FALSE); - } - - return hr; -} - -inline HRESULT CSecurityDescriptor::GetThreadSids(PSID* ppUserSid, PSID* ppGroupSid, BOOL bOpenAsSelf) -{ - HRESULT hr = S_OK; - HANDLE hToken = NULL; - if (ppUserSid) - *ppUserSid = NULL; - if (ppGroupSid) - *ppGroupSid = NULL; - if(OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, bOpenAsSelf, &hToken)) - { - hr = GetTokenSids(hToken, ppUserSid, ppGroupSid); - CloseHandle(hToken); - } - else - // Couldn't open thread token - hr = AtlHresultFromLastError(); - - return hr; -} - -inline HRESULT CSecurityDescriptor::GetTokenSids(HANDLE hToken, PSID* ppUserSid, PSID* ppGroupSid) -{ - DWORD dwSize = 0; - HRESULT hr = S_OK; - if (ppUserSid != NULL) - *ppUserSid = NULL; - if (ppGroupSid != NULL) - *ppGroupSid = NULL; - - if (ppUserSid != NULL) - { - PTOKEN_USER ptkUser = NULL; - - // Get length required for TokenUser by specifying buffer length of 0 - GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize); - // Expected ERROR_INSUFFICIENT_BUFFER - DWORD dwError = GetLastError(); - if (dwError == ERROR_INSUFFICIENT_BUFFER) - { - ptkUser = (TOKEN_USER*) malloc(dwSize); - if (ptkUser != NULL) - { - // Get Sid of process token. - if (GetTokenInformation(hToken, TokenUser, ptkUser, dwSize, &dwSize)) - { - // Make a copy of the Sid for the return value - hr = CloneSID(ppUserSid, ptkUser->User.Sid); - -#ifdef _DEBUG - if (SUCCEEDED(hr)) - { - ATLASSERT(IsValidSid(*ppUserSid)); - } -#endif - } - else - // Couldn't get user info - hr = AtlHresultFromLastError(); - - free(ptkUser); - ptkUser = NULL; - } - else - hr = E_OUTOFMEMORY; - } - else - { - ATLASSERT(FALSE); - hr = AtlHresultFromWin32(dwError); - } - } - if (SUCCEEDED(hr) && ppGroupSid != NULL) - { - PTOKEN_PRIMARY_GROUP ptkGroup = NULL; - - // Get length required for TokenPrimaryGroup by specifying buffer length of 0 - GetTokenInformation(hToken, TokenPrimaryGroup, NULL, 0, &dwSize); - DWORD dwError = GetLastError(); - // Expected ERROR_INSUFFICIENT_BUFFER - if (dwError == ERROR_INSUFFICIENT_BUFFER) - { - ptkGroup = (TOKEN_PRIMARY_GROUP*) malloc(dwSize); - if (ptkGroup != NULL) - { - // Get Sid of process token. - if (GetTokenInformation(hToken, TokenPrimaryGroup, ptkGroup, dwSize, &dwSize)) - { - // Make a copy of the Sid for the return value - hr = CloneSID(ppGroupSid, ptkGroup->PrimaryGroup); - -#ifdef _DEBUG - if (SUCCEEDED(hr)) - { - ATLASSERT(IsValidSid(*ppGroupSid)); - } -#endif - } - else - // Couldn't get user info - hr = AtlHresultFromLastError(); - - free(ptkGroup); - ptkGroup = NULL; - } - else - hr = E_OUTOFMEMORY; - } - else - hr = AtlHresultFromWin32(dwError); - } - if (FAILED(hr)) - { - if (ppUserSid != NULL) - { - free (*ppUserSid); - *ppUserSid = NULL; - } - if (ppGroupSid != NULL) - { - free (*ppGroupSid); - *ppGroupSid = NULL; - } - } - - return hr; -} - - -inline HRESULT CSecurityDescriptor::GetCurrentUserSID(PSID *ppSid) -{ - if (ppSid == NULL) - return E_POINTER; - *ppSid = NULL; - - HANDLE tkHandle; - HRESULT hr = S_OK; - - if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &tkHandle)) - { - TOKEN_USER *tkUser = NULL; - DWORD tkSize; - - // Get length required for TokenPrimaryGroup by specifying buffer length of 0 - GetTokenInformation(tkHandle, TokenUser, NULL, 0, &tkSize); - DWORD dwError = GetLastError(); - // Expected ERROR_INSUFFICIENT_BUFFER - if (dwError == ERROR_INSUFFICIENT_BUFFER) - { - tkUser = (TOKEN_USER *) malloc(tkSize); - if (tkUser != NULL) - { - // Now make the real call - if (GetTokenInformation(tkHandle, TokenUser, tkUser, tkSize, &tkSize)) - { - hr = CloneSID(ppSid, tkUser->User.Sid); - -#ifdef _DEBUG - if (SUCCEEDED(hr)) - { - ATLASSERT(IsValidSid(*ppSid)); - } -#endif - } - else - hr = AtlHresultFromLastError(); - - free (tkUser); - tkUser = NULL; - } - else - hr = E_OUTOFMEMORY; - } - else - { - hr = AtlHresultFromWin32(dwError); - ATLASSERT(FALSE); - } - CloseHandle(tkHandle); - } - else - hr = AtlHresultFromLastError(); - - return hr; -} - - -inline HRESULT CSecurityDescriptor::GetPrincipalSID(LPCTSTR pszPrincipal, PSID *ppSid) -{ - if (ppSid == NULL) - return E_POINTER; - if (pszPrincipal == NULL) - return E_INVALIDARG; - *ppSid = NULL; - - HRESULT hr; - LPTSTR pszRefDomain = NULL; - DWORD dwDomainSize = 0; - DWORD dwSidSize = 0; - SID_NAME_USE snu; - DWORD dwError; - - // Call to get size info for alloc - LookupAccountName(NULL, pszPrincipal, NULL, &dwSidSize, NULL, &dwDomainSize, &snu); - - dwError = GetLastError(); - if (dwError == ERROR_INSUFFICIENT_BUFFER) - { - ATLTRY(pszRefDomain = new TCHAR[dwDomainSize]); - if (pszRefDomain != NULL) - { - *ppSid = (PSID) malloc(dwSidSize); - if (*ppSid != NULL) - { - if (LookupAccountName(NULL, pszPrincipal, *ppSid, &dwSidSize, pszRefDomain, &dwDomainSize, &snu)) - { - hr = S_OK; - } - else - { - hr = AtlHresultFromLastError(); - free(*ppSid); - *ppSid = NULL; - } - } - else - hr = E_OUTOFMEMORY; - delete[] pszRefDomain; - } - else - hr = E_OUTOFMEMORY; - } - else - hr = AtlHresultFromWin32(dwError); - - return hr; -} - -inline HRESULT CSecurityDescriptor::Attach(PSECURITY_DESCRIPTOR pSelfRelativeSD) -{ - PACL pDACL = NULL; - PACL pSACL = NULL; - BOOL bDACLPresent, bSACLPresent; - BOOL bDefaulted; - HRESULT hr; - PSID pUserSid; - PSID pGroupSid; - - if (pSelfRelativeSD == NULL || !IsValidSecurityDescriptor(pSelfRelativeSD)) - return E_INVALIDARG; - - hr = Initialize(); - if(FAILED(hr)) - return hr; - - // get the existing DACL. - if (GetSecurityDescriptorDacl(pSelfRelativeSD, &bDACLPresent, &pDACL, &bDefaulted)) - { - if (bDACLPresent) - { - // pDACL should be valid if bDACLPresent is true - ATLENSURE_RETURN(pDACL != NULL); - // allocate new DACL. - m_pDACL = (PACL) malloc(pDACL->AclSize); - if (m_pDACL != NULL) - { - // initialize the DACL - if (InitializeAcl(m_pDACL, pDACL->AclSize, ACL_REVISION)) - { - // copy the ACL - hr = CopyACL(m_pDACL, pDACL); - if (SUCCEEDED(hr) && !IsValidAcl(m_pDACL)) - hr = E_FAIL; - } - else - hr = AtlHresultFromLastError(); - } - else - hr = E_OUTOFMEMORY; - } - // set the DACL - if (SUCCEEDED(hr) && !SetSecurityDescriptorDacl(m_pSD, bDACLPresent, m_pDACL, bDefaulted)) - hr = AtlHresultFromLastError(); - } - else - hr = AtlHresultFromLastError(); - - // get the existing SACL. - if (SUCCEEDED(hr) && GetSecurityDescriptorSacl(pSelfRelativeSD, &bSACLPresent, &pSACL, &bDefaulted)) - { - if (bSACLPresent) - { - // pSACL should be valid if bSACLPresent is true - ATLENSURE_RETURN(pSACL != NULL); - // allocate new SACL. - m_pSACL = (PACL) malloc(pSACL->AclSize); - if (m_pSACL != NULL) - { - // initialize the SACL - if (InitializeAcl(m_pSACL, pSACL->AclSize, ACL_REVISION)) - { - // copy the ACL - hr = CopyACL(m_pSACL, pSACL); - if (SUCCEEDED(hr) && !IsValidAcl(m_pSACL)) - hr = E_FAIL; - } - else - hr = AtlHresultFromLastError(); - } - else - hr = E_OUTOFMEMORY; - } - // set the SACL - if (SUCCEEDED(hr) && !SetSecurityDescriptorSacl(m_pSD, bSACLPresent, m_pSACL, bDefaulted)) - hr = AtlHresultFromLastError(); - } - else if (SUCCEEDED(hr)) - hr = AtlHresultFromLastError(); - - if (SUCCEEDED(hr)) - { - if (GetSecurityDescriptorOwner(pSelfRelativeSD, &pUserSid, &bDefaulted)) - { - if (SUCCEEDED(hr = SetOwner(pUserSid, bDefaulted))) - { - if (GetSecurityDescriptorGroup(pSelfRelativeSD, &pGroupSid, &bDefaulted)) - { - if (SUCCEEDED(hr = SetGroup(pGroupSid, bDefaulted))) - { - if (!IsValidSecurityDescriptor(m_pSD)) - hr = E_FAIL; - } - } - else - hr = AtlHresultFromLastError(); - } - } - else - hr = AtlHresultFromLastError(); - } - - if (FAILED(hr)) - { - free(m_pDACL); - m_pDACL = NULL; - - free(m_pSACL); - m_pSACL = NULL; - - delete m_pSD; - m_pSD = NULL; - } - - return hr; -} - -inline HRESULT CSecurityDescriptor::AttachObject(HANDLE hObject) -{ - HRESULT hr; - DWORD dwError; - DWORD dwSize = 0; - PSECURITY_DESCRIPTOR pSD = NULL; - -#pragma warning(push) -#pragma warning(disable: 6309 6387) - /* prefast noise VSW 497702 */ - GetKernelObjectSecurity(hObject, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, NULL, 0, &dwSize); -#pragma warning(pop) - - dwError = GetLastError(); - if (dwError != ERROR_INSUFFICIENT_BUFFER) - return AtlHresultFromWin32(dwError); - - pSD = (PSECURITY_DESCRIPTOR) malloc(dwSize); - if (pSD != NULL) - { - if (GetKernelObjectSecurity(hObject, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | - DACL_SECURITY_INFORMATION, pSD, dwSize, &dwSize)) - - hr = Attach(pSD); - else - hr = AtlHresultFromLastError(); - free(pSD); - } - else - hr = E_OUTOFMEMORY; - - return hr; -} - - -inline HRESULT CSecurityDescriptor::CopyACL(PACL pDest, PACL pSrc) -{ - ACL_SIZE_INFORMATION aclSizeInfo; - LPVOID pAce; - ACE_HEADER *aceHeader; - - if (pDest == NULL) - return E_POINTER; - - if (pSrc == NULL) - return S_OK; - - if (!GetAclInformation(pSrc, (LPVOID) &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) - return AtlHresultFromLastError(); - - // Copy all of the ACEs to the new ACL - for (UINT i = 0; i < aclSizeInfo.AceCount; i++) - { - if (!GetAce(pSrc, i, &pAce)) - return AtlHresultFromLastError(); - - aceHeader = (ACE_HEADER *) pAce; - - if (!AddAce(pDest, ACL_REVISION, 0xffffffff, pAce, aceHeader->AceSize)) - return AtlHresultFromLastError(); - } - - return S_OK; -} - -inline HRESULT CSecurityDescriptor::AddAccessDeniedACEToACL(PACL *ppAcl, PSID pSid, DWORD dwAccessMask) -{ - ACL_SIZE_INFORMATION aclSizeInfo; - int aclSize; - PACL oldACL, newACL = NULL; - HRESULT hr = S_OK; - - if (ppAcl == NULL) - return E_POINTER; - - oldACL = *ppAcl; - - if (pSid == NULL || !IsValidSid(pSid)) - return E_INVALIDARG; - - aclSizeInfo.AclBytesInUse = 0; - if (*ppAcl != NULL && !GetAclInformation(oldACL, (LPVOID) &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) - hr = AtlHresultFromLastError(); - - if (SUCCEEDED(hr)) - { - aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_DENIED_ACE) + GetLengthSid(pSid) - sizeof(DWORD); - newACL = (PACL) malloc(aclSize); - if (newACL != NULL) - { - if (InitializeAcl(newACL, aclSize, ACL_REVISION)) - { - // access denied ACEs should be before access allowed ACEs - if (AddAccessDeniedAce(newACL, ACL_REVISION2, dwAccessMask, pSid)) - { - // Copy existing ACEs to the new ACL - hr = CopyACL(newACL, oldACL); - if (SUCCEEDED(hr)) - { - *ppAcl = newACL; - free(oldACL); - } - } - else - hr = AtlHresultFromLastError(); - } - else - hr = AtlHresultFromLastError(); - - if (FAILED(hr)) - free(newACL); - } - else - hr = E_OUTOFMEMORY; - } - return hr; -} - - -inline HRESULT CSecurityDescriptor::AddAccessAllowedACEToACL(PACL *ppAcl, PSID pSid, DWORD dwAccessMask) -{ - ACL_SIZE_INFORMATION aclSizeInfo; - int aclSize; - HRESULT hr = S_OK; - PACL oldACL, newACL = NULL; - - if (ppAcl == NULL) - return E_POINTER; - - oldACL = *ppAcl; - - if (pSid == NULL || !IsValidSid(pSid)) - return E_INVALIDARG; - - aclSizeInfo.AclBytesInUse = 0; - if (*ppAcl != NULL && !GetAclInformation(oldACL, (LPVOID) &aclSizeInfo, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) - hr = AtlHresultFromLastError(); - - if (SUCCEEDED(hr)) - { - aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pSid) - sizeof(DWORD); - newACL = (PACL) malloc(aclSize); - if (newACL != NULL) - { - if (InitializeAcl(newACL, aclSize, ACL_REVISION)) - { - // Copy existing ACEs - hr = CopyACL(newACL, oldACL); - if (SUCCEEDED(hr)) - { - // Add access Allowed ACEs after all other existing ACEs (possibly access denied ACEs) - if (AddAccessAllowedAce(newACL, ACL_REVISION2, dwAccessMask, pSid)) - { - *ppAcl = newACL; - free(oldACL); - } - else - hr = AtlHresultFromLastError(); - } - } - else - hr = AtlHresultFromLastError(); - - if (FAILED(hr)) - free(newACL); - } - else - hr = E_OUTOFMEMORY; - } - return hr; -} - -inline HRESULT CSecurityDescriptor::RemovePrincipalFromACL(PACL pAcl, PSID principalSID) -{ - if (pAcl == NULL || principalSID == NULL || !IsValidSid(principalSID)) - return E_INVALIDARG; - - HRESULT hr = S_OK; - ACL_SIZE_INFORMATION aclSizeInfo; - if (!GetAclInformation(pAcl, (LPVOID) &aclSizeInfo, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) - { - hr = AtlHresultFromLastError(); - aclSizeInfo.AceCount = 0; - } - - for (ULONG i = aclSizeInfo.AceCount; i > 0; i--) - { - ULONG uIndex = i - 1; - LPVOID ace; - if (!GetAce(pAcl, uIndex, &ace)) - { - hr = AtlHresultFromLastError(); - break; - } - - ACE_HEADER *aceHeader = (ACE_HEADER *) ace; - - if (aceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE) - { - ACCESS_ALLOWED_ACE *accessAllowedAce = (ACCESS_ALLOWED_ACE *) ace; - if (EqualSid(principalSID, (PSID) &accessAllowedAce->SidStart)) - { - DeleteAce(pAcl, uIndex); - } - } - else if (aceHeader->AceType == ACCESS_DENIED_ACE_TYPE) - { - ACCESS_DENIED_ACE *accessDeniedAce = (ACCESS_DENIED_ACE *) ace; - if (EqualSid(principalSID, (PSID) &accessDeniedAce->SidStart)) - { - DeleteAce(pAcl, uIndex); - } - } - else if (aceHeader->AceType == SYSTEM_AUDIT_ACE_TYPE) - { - SYSTEM_AUDIT_ACE *systemAuditAce = (SYSTEM_AUDIT_ACE *) ace; - if (EqualSid(principalSID, (PSID) &systemAuditAce->SidStart)) - { - DeleteAce(pAcl, uIndex); - } - } - } - return hr; -} - -inline HRESULT CSecurityDescriptor::SetPrivilege(LPCTSTR privilege, BOOL bEnable, HANDLE hToken) -{ - TOKEN_PRIVILEGES tpPrevious; - TOKEN_PRIVILEGES tp; - DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES); - LUID luid; - HANDLE hTokenUsed; - - if (!LookupPrivilegeValue(NULL, privilege, &luid )) - goto _Error; - - // if no token specified open process token - if (hToken != 0) - hTokenUsed = hToken; - else - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hTokenUsed)) - goto _Error; - - tp.PrivilegeCount = 1; - tp.Privileges[0].Luid = luid; - tp.Privileges[0].Attributes = 0; - - memset(&tpPrevious, 0, sizeof(tpPrevious)); - - if (!AdjustTokenPrivileges(hTokenUsed, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &tpPrevious, &cbPrevious)) - goto _Error_CloseHandle; - - tpPrevious.PrivilegeCount = 1; - tpPrevious.Privileges[0].Luid = luid; - - if (bEnable) - tpPrevious.Privileges[0].Attributes |= SE_PRIVILEGE_ENABLED; - else - tpPrevious.Privileges[0].Attributes &= ~SE_PRIVILEGE_ENABLED; - - if (!AdjustTokenPrivileges(hTokenUsed, FALSE, &tpPrevious, cbPrevious, NULL, NULL)) - goto _Error_CloseHandle; - - if(hToken == 0) - CloseHandle(hTokenUsed); - - return S_OK; - - HRESULT hr; - -_Error: - hr = AtlHresultFromLastError(); - return hr; - -_Error_CloseHandle: - hr = AtlHresultFromLastError(); - if (hToken == 0) - CloseHandle(hTokenUsed); - return hr; -} - -///////////////////////////////////////////////////////////////////////////// -// COM Objects - -#define DECLARE_PROTECT_FINAL_CONSTRUCT()\ - void InternalFinalConstructAddRef() {InternalAddRef();}\ - void InternalFinalConstructRelease() {InternalRelease();} - -template -class CComCreator -{ -public: - static HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv) - { - ATLASSERT(ppv != NULL); - if (ppv == NULL) - return E_POINTER; - *ppv = NULL; - - HRESULT hRes = E_OUTOFMEMORY; - T1* p = NULL; -#pragma warning(push) -#pragma warning(disable: 6014) - /* prefast noise VSW 489981 */ - ATLTRY(p = new T1(pv)) -#pragma warning(pop) - if (p != NULL) - { - p->SetVoid(pv); - p->InternalFinalConstructAddRef(); - hRes = p->_AtlInitialConstruct(); - if (SUCCEEDED(hRes)) - hRes = p->FinalConstruct(); - if (SUCCEEDED(hRes)) - hRes = p->_AtlFinalConstruct(); - p->InternalFinalConstructRelease(); - if (hRes == S_OK) - hRes = p->QueryInterface(riid, ppv); - if (hRes != S_OK) - delete p; - } - return hRes; - } -}; - -template -class CComInternalCreator -{ -public: - static HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv) - { - ATLASSERT(ppv != NULL); - if (ppv == NULL) - return E_POINTER; - *ppv = NULL; - - HRESULT hRes = E_OUTOFMEMORY; - T1* p = NULL; -#pragma warning(push) -#pragma warning(disable: 6014) - ATLTRY(p = new T1(pv)) -#pragma warning(pop) - if (p != NULL) - { - p->SetVoid(pv); - p->InternalFinalConstructAddRef(); - hRes = p->_AtlInitialConstruct(); - if (SUCCEEDED(hRes)) - hRes = p->FinalConstruct(); - if (SUCCEEDED(hRes)) - hRes = p->_AtlFinalConstruct(); - p->InternalFinalConstructRelease(); - if (hRes == S_OK) - hRes = p->_InternalQueryInterface(riid, ppv); - if (hRes != S_OK) - delete p; - } - return hRes; - } -}; - -template -class CComFailCreator -{ -public: - static HRESULT WINAPI CreateInstance(void*, REFIID, LPVOID* ppv) - { - if (ppv == NULL) - return E_POINTER; - *ppv = NULL; - - return hr; - } -}; - -template -class CComCreator2 -{ -public: - static HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv) - { - ATLASSERT(ppv != NULL); - - return (pv == NULL) ? - T1::CreateInstance(NULL, riid, ppv) : - T2::CreateInstance(pv, riid, ppv); - } -}; - -#define DECLARE_NOT_AGGREGATABLE(x) public:\ - typedef ATL::CComCreator2< ATL::CComCreator< ATL::CComObject< x > >, ATL::CComFailCreator > _CreatorClass; -#define DECLARE_AGGREGATABLE(x) public:\ - typedef ATL::CComCreator2< ATL::CComCreator< ATL::CComObject< x > >, ATL::CComCreator< ATL::CComAggObject< x > > > _CreatorClass; -#define DECLARE_ONLY_AGGREGATABLE(x) public:\ - typedef ATL::CComCreator2< ATL::CComFailCreator, ATL::CComCreator< ATL::CComAggObject< x > > > _CreatorClass; -#define DECLARE_POLY_AGGREGATABLE(x) public:\ - typedef ATL::CComCreator< ATL::CComPolyObject< x > > _CreatorClass; - -struct _ATL_CREATORDATA -{ - _ATL_CREATORFUNC* pFunc; -}; - -template -class _CComCreatorData -{ -public: - static _ATL_CREATORDATA data; -}; - -template -_ATL_CREATORDATA _CComCreatorData::data = {Creator::CreateInstance}; - -struct _ATL_CACHEDATA -{ - DWORD dwOffsetVar; - _ATL_CREATORFUNC* pFunc; -}; - -template -class _CComCacheData -{ -public: - static _ATL_CACHEDATA data; -}; - -template -_ATL_CACHEDATA _CComCacheData::data = {dwVar, Creator::CreateInstance}; - -struct _ATL_CHAINDATA -{ - DWORD_PTR dwOffset; - const _ATL_INTMAP_ENTRY* (WINAPI *pFunc)(); -}; - -template -class _CComChainData -{ -public: - static _ATL_CHAINDATA data; -}; - -template -_ATL_CHAINDATA _CComChainData::data = - {offsetofclass(base, derived), base::_GetEntries}; - -template -class CComAggregateCreator -{ -public: - static HRESULT WINAPI CreateInstance(void* pv, REFIID/*riid*/, LPVOID* ppv) throw() - { - // Only Assert here. CoCreateInstance will return the correct HRESULT if ppv == NULL - ATLASSERT(ppv != NULL && *ppv == NULL); - - ATLASSERT(pv != NULL); - if (pv == NULL) - return E_INVALIDARG; - - T* p = (T*) pv; - // Add the following line to your object if you get a message about - // GetControllingUnknown() being undefined - // DECLARE_GET_CONTROLLING_UNKNOWN() - return CoCreateInstance(*pclsid, p->GetControllingUnknown(), CLSCTX_INPROC, __uuidof(IUnknown), ppv); - } -}; - -#ifdef _ATL_DEBUG -#define DEBUG_QI_ENTRY(x) \ - {NULL, \ - (DWORD_PTR)_T(#x), \ - (ATL::_ATL_CREATORARGFUNC*)0}, -#else -#define DEBUG_QI_ENTRY(x) -#endif //_ATL_DEBUG - -#ifdef _ATL_DEBUG_INTERFACES -#define _ATL_DECLARE_GET_UNKNOWN(x)\ - IUnknown* GetUnknown() throw() \ - { \ - IUnknown* p; \ - ATL::_AtlDebugInterfacesModule.AddNonAddRefThunk(_GetRawUnknown(), _T(#x), &p); \ - return p; \ - } -#else -#define _ATL_DECLARE_GET_UNKNOWN(x) IUnknown* GetUnknown() throw() {return _GetRawUnknown();} -#endif - -//If you get a message that FinalConstruct is ambiguous then you need to -// override it in your class and call each base class' version of this -#define BEGIN_COM_MAP(x) public: \ - typedef x _ComMapClass; \ - static HRESULT WINAPI _Cache(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw) throw()\ - {\ - _ComMapClass* p = (_ComMapClass*)pv;\ - p->Lock();\ - HRESULT hRes = E_FAIL; \ - __try \ - { \ - hRes = ATL::CComObjectRootBase::_Cache(pv, iid, ppvObject, dw);\ - } \ - __finally \ - { \ - p->Unlock();\ - } \ - return hRes;\ - }\ - IUnknown* _GetRawUnknown() throw() \ - { ATLASSERT(_GetEntries()[0].pFunc == _ATL_SIMPLEMAPENTRY); return (IUnknown*)((INT_PTR)this+_GetEntries()->dw); } \ - _ATL_DECLARE_GET_UNKNOWN(x)\ - HRESULT _InternalQueryInterface(REFIID iid, void** ppvObject) throw() \ - { return InternalQueryInterface(this, _GetEntries(), iid, ppvObject); } \ - const static ATL::_ATL_INTMAP_ENTRY* WINAPI _GetEntries() throw() { \ - static const ATL::_ATL_INTMAP_ENTRY _entries[] = { DEBUG_QI_ENTRY(x) - -// For use by attributes for chaining to existing COM_MAP -#define BEGIN_ATTRCOM_MAP(x) public: \ - typedef x _AttrComMapClass; \ - const static ATL::_ATL_INTMAP_ENTRY* WINAPI _GetAttrEntries() throw() { \ - static const ATL::_ATL_INTMAP_ENTRY _entries[] = { - -#define DECLARE_GET_CONTROLLING_UNKNOWN() public:\ - virtual IUnknown* GetControllingUnknown() throw() {return GetUnknown();} - -#define COM_INTERFACE_ENTRY_BREAK(x)\ - {&_ATL_IIDOF(x), \ - NULL, \ - _Break}, - -#define COM_INTERFACE_ENTRY_NOINTERFACE(x)\ - {&_ATL_IIDOF(x), \ - NULL, \ - _NoInterface}, - -#define COM_INTERFACE_ENTRY(x)\ - {&_ATL_IIDOF(x), \ - offsetofclass(x, _ComMapClass), \ - _ATL_SIMPLEMAPENTRY}, - -#define COM_INTERFACE_ENTRY_IID(iid, x)\ - {&iid,\ - offsetofclass(x, _ComMapClass),\ - _ATL_SIMPLEMAPENTRY}, - -// The impl macros are now obsolete -#define COM_INTERFACE_ENTRY_IMPL(x)\ - COM_INTERFACE_ENTRY_IID(_ATL_IIDOF(x), x##Impl<_ComMapClass>) - -#define COM_INTERFACE_ENTRY_IMPL_IID(iid, x)\ - COM_INTERFACE_ENTRY_IID(iid, x##Impl<_ComMapClass>) -// - -#define COM_INTERFACE_ENTRY2(x, x2)\ - {&_ATL_IIDOF(x),\ - reinterpret_cast(static_cast(static_cast(reinterpret_cast<_ComMapClass*>(8))))-8,\ - _ATL_SIMPLEMAPENTRY}, - -#define COM_INTERFACE_ENTRY2_IID(iid, x, x2)\ - {&iid,\ - reinterpret_cast(static_cast(static_cast(reinterpret_cast<_ComMapClass*>(8))))-8,\ - _ATL_SIMPLEMAPENTRY}, - -#define COM_INTERFACE_ENTRY_FUNC(iid, dw, func)\ - {&iid, \ - dw, \ - func}, - -#define COM_INTERFACE_ENTRY_FUNC_BLIND(dw, func)\ - {NULL, \ - dw, \ - func}, - -#define COM_INTERFACE_ENTRY_TEAR_OFF(iid, x)\ - {&iid,\ - (DWORD_PTR)&ATL::_CComCreatorData<\ - ATL::CComInternalCreator< ATL::CComTearOffObject< x > >\ - >::data,\ - _Creator}, - -#define COM_INTERFACE_ENTRY_CACHED_TEAR_OFF(iid, x, punk)\ - {&iid,\ - (DWORD_PTR)&ATL::_CComCacheData<\ - ATL::CComCreator< ATL::CComCachedTearOffObject< x > >,\ - (DWORD_PTR)offsetof(_ComMapClass, punk)\ - >::data,\ - _Cache}, - -#define COM_INTERFACE_ENTRY_AGGREGATE(iid, punk)\ - {&iid,\ - (DWORD_PTR)offsetof(_ComMapClass, punk),\ - _Delegate}, - -#define COM_INTERFACE_ENTRY_AGGREGATE_BLIND(punk)\ - {NULL,\ - (DWORD_PTR)offsetof(_ComMapClass, punk),\ - _Delegate}, - -#define COM_INTERFACE_ENTRY_AUTOAGGREGATE(iid, punk, clsid)\ - {&iid,\ - (DWORD_PTR)&ATL::_CComCacheData<\ - ATL::CComAggregateCreator<_ComMapClass, &clsid>,\ - (DWORD_PTR)offsetof(_ComMapClass, punk)\ - >::data,\ - _Cache}, - -#define COM_INTERFACE_ENTRY_AUTOAGGREGATE_BLIND(punk, clsid)\ - {NULL,\ - (DWORD_PTR)&ATL::_CComCacheData<\ - ATL::CComAggregateCreator<_ComMapClass, &clsid>,\ - (DWORD_PTR)offsetof(_ComMapClass, punk)\ - >::data,\ - _Cache}, - -#define COM_INTERFACE_ENTRY_CHAIN(classname)\ - {NULL,\ - (DWORD_PTR)&ATL::_CComChainData::data,\ - _Chain}, - -#ifdef _ATL_DEBUG -#define END_COM_MAP() \ - __if_exists(_GetAttrEntries) {{NULL, (DWORD_PTR)_GetAttrEntries, _ChainAttr }, }\ - {NULL, 0, 0}}; return &_entries[1];} \ - virtual ULONG STDMETHODCALLTYPE AddRef( void) throw() = 0; \ - virtual ULONG STDMETHODCALLTYPE Release( void) throw() = 0; \ - STDMETHOD(QueryInterface)(REFIID, void**) throw() = 0; -#else -#define END_COM_MAP() \ - __if_exists(_GetAttrEntries) {{NULL, (DWORD_PTR)_GetAttrEntries, _ChainAttr }, }\ - {NULL, 0, 0}}; return _entries;} \ - virtual ULONG STDMETHODCALLTYPE AddRef( void) throw() = 0; \ - virtual ULONG STDMETHODCALLTYPE Release( void) throw() = 0; \ - STDMETHOD(QueryInterface)(REFIID, void**) throw() = 0; -#endif // _ATL_DEBUG - -#define END_ATTRCOM_MAP() \ - {NULL, 0, 0}}; return _entries;} - - -#define BEGIN_CATEGORY_MAP(x)\ - static const struct ATL::_ATL_CATMAP_ENTRY* GetCategoryMap() throw() {\ - static const struct ATL::_ATL_CATMAP_ENTRY pMap[] = { -#define IMPLEMENTED_CATEGORY( catid ) { _ATL_CATMAP_ENTRY_IMPLEMENTED, &catid }, -#define REQUIRED_CATEGORY( catid ) { _ATL_CATMAP_ENTRY_REQUIRED, &catid }, -#define END_CATEGORY_MAP()\ - { _ATL_CATMAP_ENTRY_END, NULL } };\ - return( pMap ); } - -#define BEGIN_OBJECT_MAP(x) static ATL::_ATL_OBJMAP_ENTRY x[] = { -#define END_OBJECT_MAP() {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}}; -#define OBJECT_ENTRY(clsid, class) {&clsid, class::UpdateRegistry, class::_ClassFactoryCreatorClass::CreateInstance, class::_CreatorClass::CreateInstance, NULL, 0, class::GetObjectDescription, class::GetCategoryMap, class::ObjectMain }, -#define OBJECT_ENTRY_NON_CREATEABLE(class) {&CLSID_NULL, class::UpdateRegistry, NULL, NULL, NULL, 0, NULL, class::GetCategoryMap, class::ObjectMain }, -#define OBJECT_ENTRY_NON_CREATEABLE_EX(clsid, class) {&clsid, class::UpdateRegistry, NULL, NULL, NULL, 0, NULL, class::GetCategoryMap, class::ObjectMain }, - -#ifndef OBJECT_ENTRY_PRAGMA - -#if defined(_M_IX86) -#define OBJECT_ENTRY_PRAGMA(class) __pragma(comment(linker, "/include:___pobjMap_" #class)); -#elif defined(_M_IA64) -#define OBJECT_ENTRY_PRAGMA(class) __pragma(comment(linker, "/include:__pobjMap_" #class)); -#elif defined(_M_AMD64) -#define OBJECT_ENTRY_PRAGMA(class) __pragma(comment(linker, "/include:__pobjMap_" #class)); -#else -#error Unknown Platform. define OBJECT_ENTRY_PRAGMA -#endif - -#endif //OBJECT_ENTRY_PRAGMA - -#define OBJECT_ENTRY_AUTO(clsid, class) \ - __declspec(selectany) ATL::_ATL_OBJMAP_ENTRY __objMap_##class = {&clsid, class::UpdateRegistry, class::_ClassFactoryCreatorClass::CreateInstance, class::_CreatorClass::CreateInstance, NULL, 0, class::GetObjectDescription, class::GetCategoryMap, class::ObjectMain }; \ - extern "C" __declspec(allocate("ATL$__m")) __declspec(selectany) ATL::_ATL_OBJMAP_ENTRY* const __pobjMap_##class = &__objMap_##class; \ - OBJECT_ENTRY_PRAGMA(class) - - -#define OBJECT_ENTRY_NON_CREATEABLE_EX_AUTO(clsid, class) \ - __declspec(selectany) ATL::_ATL_OBJMAP_ENTRY __objMap_##class = {&clsid, class::UpdateRegistry, NULL, NULL, NULL, 0, NULL, class::GetCategoryMap, class::ObjectMain }; \ - extern "C" __declspec(allocate("ATL$__m")) __declspec(selectany) ATL::_ATL_OBJMAP_ENTRY* const __pobjMap_##class = &__objMap_##class; \ - OBJECT_ENTRY_PRAGMA(class) - -// the functions in this class don't need to be virtual because -// they are called from CComObject -class CComObjectRootBase -{ -public: - CComObjectRootBase() - { - m_dwRef = 0L; - } - ~CComObjectRootBase() - { - } - HRESULT FinalConstruct() - { - return S_OK; - } - // For library initialization only - HRESULT _AtlFinalConstruct() - { - return S_OK; - } - void FinalRelease() {} - void _AtlFinalRelease() {} // temp - - void _HRPass(HRESULT hr) // temp - { - (hr); - } - - void _HRFail(HRESULT hr) // temp... - { - (hr); - } - - - //ObjectMain is called during Module::Init and Module::Term - static void WINAPI ObjectMain(bool /* bStarting */); - - static const struct _ATL_CATMAP_ENTRY* GetCategoryMap() {return NULL;}; - static HRESULT WINAPI InternalQueryInterface(void* pThis, - const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject) - { - // Only Assert here. AtlInternalQueryInterface will return the correct HRESULT if ppvObject == NULL -#ifndef _ATL_OLEDB_CONFORMANCE_TESTS - ATLASSERT(ppvObject != NULL); -#endif - ATLASSERT(pThis != NULL); - // First entry in the com map should be a simple map entry - ATLASSERT(pEntries->pFunc == _ATL_SIMPLEMAPENTRY); - #if defined(_ATL_DEBUG_INTERFACES) || defined(_ATL_DEBUG_QI) - LPCTSTR pszClassName = (LPCTSTR) pEntries[-1].dw; - #endif // _ATL_DEBUG_INTERFACES - HRESULT hRes = AtlInternalQueryInterface(pThis, pEntries, iid, ppvObject); - #ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.AddThunk((IUnknown**)ppvObject, pszClassName, iid); - #endif // _ATL_DEBUG_INTERFACES - return _ATLDUMPIID(iid, pszClassName, hRes); - } - -//Outer funcs - ULONG OuterAddRef() - { - return m_pOuterUnknown->AddRef(); - } - ULONG OuterRelease() - { - return m_pOuterUnknown->Release(); - } - HRESULT OuterQueryInterface(REFIID iid, void ** ppvObject) - { - return m_pOuterUnknown->QueryInterface(iid, ppvObject); - } - - void SetVoid(void*) {} - void InternalFinalConstructAddRef() {} - void InternalFinalConstructRelease() - { - ATLASSUME(m_dwRef == 0); - } - // If this assert occurs, your object has probably been deleted - // Try using DECLARE_PROTECT_FINAL_CONSTRUCT() - - - static HRESULT WINAPI _Break(void* /* pv */, REFIID iid, void** /* ppvObject */, DWORD_PTR /* dw */) - { - (iid); - _ATLDUMPIID(iid, _T("Break due to QI for interface "), S_OK); - DebugBreak(); - return S_FALSE; - } - static HRESULT WINAPI _NoInterface(void* /* pv */, REFIID /* iid */, void** /* ppvObject */, DWORD_PTR /* dw */) - { - return E_NOINTERFACE; - } - static HRESULT WINAPI _Creator(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw) - { - _ATL_CREATORDATA* pcd = (_ATL_CREATORDATA*)dw; - return pcd->pFunc(pv, iid, ppvObject); - } - static HRESULT WINAPI _Delegate(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw) - { - HRESULT hRes = E_NOINTERFACE; - IUnknown* p = *(IUnknown**)((DWORD_PTR)pv + dw); - if (p != NULL) - hRes = p->QueryInterface(iid, ppvObject); - return hRes; - } - static HRESULT WINAPI _Chain(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw) - { - _ATL_CHAINDATA* pcd = (_ATL_CHAINDATA*)dw; - void* p = (void*)((DWORD_PTR)pv + pcd->dwOffset); - return InternalQueryInterface(p, pcd->pFunc(), iid, ppvObject); - } - static HRESULT WINAPI _ChainAttr(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw) - { - const _ATL_INTMAP_ENTRY* (WINAPI *pFunc)() = (const _ATL_INTMAP_ENTRY* (WINAPI *)())dw; - const _ATL_INTMAP_ENTRY *pEntries = pFunc(); - if (pEntries == NULL) - return S_OK; - return InternalQueryInterface(pv, pEntries, iid, ppvObject); - } - static HRESULT WINAPI _Cache(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw) - { - HRESULT hRes = E_NOINTERFACE; - _ATL_CACHEDATA* pcd = (_ATL_CACHEDATA*)dw; - IUnknown** pp = (IUnknown**)((DWORD_PTR)pv + pcd->dwOffsetVar); - if (*pp == NULL) - hRes = pcd->pFunc(pv, __uuidof(IUnknown), (void**)pp); - if (*pp != NULL) - hRes = (*pp)->QueryInterface(iid, ppvObject); - return hRes; - } - - union - { - long m_dwRef; - IUnknown* m_pOuterUnknown; - }; -}; - -#pragma managed(push, off) -inline void WINAPI CComObjectRootBase::ObjectMain(bool /* bStarting */) -{ -} -#pragma managed(pop) - - -//foward declaration -template -class CComObjectRootEx; - -template -class CComObjectLockT -{ -public: - CComObjectLockT(CComObjectRootEx* p) - { - if (p) - p->Lock(); - m_p = p; - } - - ~CComObjectLockT() - { - if (m_p) - m_p->Unlock(); - } - CComObjectRootEx* m_p; -}; - -template <> class CComObjectLockT; - -template -class CComObjectRootEx : public CComObjectRootBase -{ -public: - typedef ThreadModel _ThreadModel; - typedef typename _ThreadModel::AutoCriticalSection _CritSec; - typedef typename _ThreadModel::AutoDeleteCriticalSection _AutoDelCritSec; - typedef CComObjectLockT<_ThreadModel> ObjectLock; - - ~CComObjectRootEx() {} - - ULONG InternalAddRef() - { - ATLASSUME(m_dwRef != -1L); - return _ThreadModel::Increment(&m_dwRef); - } - ULONG InternalRelease() - { -#ifdef _DEBUG - LONG nRef = _ThreadModel::Decrement(&m_dwRef); - if (nRef < -(LONG_MAX / 2)) - { - ATLASSERT(0 && _T("Release called on a pointer that has already been released")); - } - return nRef; -#else - return _ThreadModel::Decrement(&m_dwRef); -#endif - } - - HRESULT _AtlInitialConstruct() - { - return m_critsec.Init(); - } - void Lock() {m_critsec.Lock();} - void Unlock() {m_critsec.Unlock();} -private: - _AutoDelCritSec m_critsec; -}; - -template <> -class CComObjectRootEx : public CComObjectRootBase -{ -public: - typedef CComSingleThreadModel _ThreadModel; - typedef _ThreadModel::AutoCriticalSection _CritSec; - typedef _ThreadModel::AutoDeleteCriticalSection _AutoDelCritSec; - typedef CComObjectLockT<_ThreadModel> ObjectLock; - - ~CComObjectRootEx() {} - - ULONG InternalAddRef() - { - ATLASSUME(m_dwRef != -1L); - return _ThreadModel::Increment(&m_dwRef); - } - ULONG InternalRelease() - { -#ifdef _DEBUG - long nRef = _ThreadModel::Decrement(&m_dwRef); - if (nRef < -(LONG_MAX / 2)) - { - ATLASSERT(0 && _T("Release called on a pointer that has already been released")); - } - return nRef; -#else - return _ThreadModel::Decrement(&m_dwRef); -#endif - } - - HRESULT _AtlInitialConstruct() - { - return S_OK; - } - - void Lock() {} - void Unlock() {} -}; - -template <> -class CComObjectLockT -{ -public: - CComObjectLockT(CComObjectRootEx*) {} - ~CComObjectLockT() {} -}; - -typedef CComObjectRootEx CComObjectRoot; - -#if defined(_WINDLL) | defined(_USRDLL) -#define DECLARE_CLASSFACTORY_EX(cf) typedef ATL::CComCreator< ATL::CComObjectCached< cf > > _ClassFactoryCreatorClass; -#else -// don't let class factory refcount influence lock count -#define DECLARE_CLASSFACTORY_EX(cf) typedef ATL::CComCreator< ATL::CComObjectNoLock< cf > > _ClassFactoryCreatorClass; -#endif -#define DECLARE_CLASSFACTORY() DECLARE_CLASSFACTORY_EX(ATL::CComClassFactory) -#define DECLARE_CLASSFACTORY2(lic) DECLARE_CLASSFACTORY_EX(ATL::CComClassFactory2) -#define DECLARE_CLASSFACTORY_AUTO_THREAD() DECLARE_CLASSFACTORY_EX(ATL::CComClassFactoryAutoThread) -#define DECLARE_CLASSFACTORY_SINGLETON(obj) DECLARE_CLASSFACTORY_EX(ATL::CComClassFactorySingleton) - -#define DECLARE_OBJECT_DESCRIPTION(x)\ - static LPCTSTR WINAPI GetObjectDescription() throw()\ - {\ - return _T(x);\ - } - -#define DECLARE_NO_REGISTRY()\ - static HRESULT WINAPI UpdateRegistry(BOOL /*bRegister*/) throw()\ - {return S_OK;} - -#define DECLARE_REGISTRY(class, pid, vpid, nid, flags)\ - static HRESULT WINAPI UpdateRegistry(BOOL bRegister) throw()\ - {\ - return _Module.UpdateRegistryClass(GetObjectCLSID(), pid, vpid, nid,\ - flags, bRegister);\ - } - -#define DECLARE_REGISTRY_RESOURCE(x)\ - static HRESULT WINAPI UpdateRegistry(BOOL bRegister) throw()\ - {\ - __if_exists(_GetMiscStatus) \ - { \ - ATL::_ATL_REGMAP_ENTRY regMapEntries[2]; \ - memset(®MapEntries[1], 0, sizeof(ATL::_ATL_REGMAP_ENTRY)); \ - regMapEntries[0].szKey = L"OLEMISC"; \ - TCHAR szOleMisc[32]; \ - ATL::Checked::itot_s(_GetMiscStatus(), szOleMisc, _countof(szOleMisc), 10); \ - USES_CONVERSION_EX; \ - regMapEntries[0].szData = T2OLE_EX(szOleMisc, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); \ - if (regMapEntries[0].szData == NULL) \ - return E_OUTOFMEMORY; \ - __if_exists(_Module) \ - { \ - return _Module.UpdateRegistryFromResource(_T(#x), bRegister, regMapEntries); \ - } \ - __if_not_exists(_Module) \ - { \ - return ATL::_pAtlModule->UpdateRegistryFromResource(_T(#x), bRegister, regMapEntries); \ - } \ - } \ - __if_not_exists(_GetMiscStatus) \ - { \ - __if_exists(_Module) \ - { \ - return _Module.UpdateRegistryFromResource(_T(#x), bRegister); \ - } \ - __if_not_exists(_Module) \ - { \ - return ATL::_pAtlModule->UpdateRegistryFromResource(_T(#x), bRegister); \ - } \ - } \ - } - -#define DECLARE_REGISTRY_RESOURCEID(x)\ - static HRESULT WINAPI UpdateRegistry(BOOL bRegister) throw()\ - {\ - __if_exists(_GetMiscStatus) \ - { \ - ATL::_ATL_REGMAP_ENTRY regMapEntries[2]; \ - memset(®MapEntries[1], 0, sizeof(ATL::_ATL_REGMAP_ENTRY)); \ - regMapEntries[0].szKey = L"OLEMISC"; \ - TCHAR szOleMisc[32]; \ - ATL::Checked::itot_s(_GetMiscStatus(), szOleMisc, _countof(szOleMisc), 10); \ - USES_CONVERSION_EX; \ - regMapEntries[0].szData = T2OLE_EX(szOleMisc, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); \ - if (regMapEntries[0].szData == NULL) \ - return E_OUTOFMEMORY; \ - __if_exists(_Module) \ - { \ - return _Module.UpdateRegistryFromResource(x, bRegister, regMapEntries); \ - } \ - __if_not_exists(_Module) \ - { \ - return ATL::_pAtlModule->UpdateRegistryFromResource(x, bRegister, regMapEntries); \ - } \ - } \ - __if_not_exists(_GetMiscStatus) \ - { \ - __if_exists(_Module) \ - { \ - return _Module.UpdateRegistryFromResource(x, bRegister); \ - } \ - __if_not_exists(_Module) \ - { \ - return ATL::_pAtlModule->UpdateRegistryFromResource(x, bRegister); \ - } \ - } \ - } - -//DECLARE_STATIC_* provided for backward compatibility -#ifdef _ATL_STATIC_REGISTRY -#define DECLARE_STATIC_REGISTRY_RESOURCE(x) DECLARE_REGISTRY_RESOURCE(x) -#define DECLARE_STATIC_REGISTRY_RESOURCEID(x) DECLARE_REGISTRY_RESOURCEID(x) -#endif //_ATL_STATIC_REGISTRY - -#define DECLARE_OLEMISC_STATUS(x) \ - static DWORD _GetMiscStatus() throw() \ - { \ - static DWORD m_dwOleMisc = x; \ - return m_dwOleMisc; \ - } - -template class CComObject; // fwd decl - -template -class CComTearOffObjectBase : public CComObjectRootEx -{ -public: - typedef Owner _OwnerClass; - Owner* m_pOwner; - CComTearOffObjectBase() {m_pOwner = NULL;} -}; - -//Base is the user's class that derives from CComObjectRoot and whatever -//interfaces the user wants to support on the object -template -class CComObject : public Base -{ -public: - typedef Base _BaseClass; - CComObject(void* = NULL) throw() - { - _pAtlModule->Lock(); - } - // Set refcount to -(LONG_MAX/2) to protect destruction and - // also catch mismatched Release in debug builds - virtual ~CComObject() throw() - { - m_dwRef = -(LONG_MAX/2); - FinalRelease(); -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.DeleteNonAddRefThunk(_GetRawUnknown()); -#endif - _pAtlModule->Unlock(); - } - //If InternalAddRef or InternalRelease is undefined then your class - //doesn't derive from CComObjectRoot - STDMETHOD_(ULONG, AddRef)() {return InternalAddRef();} - STDMETHOD_(ULONG, Release)() - { - ULONG l = InternalRelease(); - if (l == 0) - delete this; - return l; - } - //if _InternalQueryInterface is undefined then you forgot BEGIN_COM_MAP - STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) throw() - {return _InternalQueryInterface(iid, ppvObject);} - template - HRESULT STDMETHODCALLTYPE QueryInterface(Q** pp) throw() - { - return QueryInterface(__uuidof(Q), (void**)pp); - } - - static HRESULT WINAPI CreateInstance(CComObject** pp) throw(); -}; - -template -HRESULT WINAPI CComObject::CreateInstance(CComObject** pp) throw() -{ - ATLASSERT(pp != NULL); - if (pp == NULL) - return E_POINTER; - *pp = NULL; - - HRESULT hRes = E_OUTOFMEMORY; - CComObject* p = NULL; - ATLTRY(p = new CComObject()) - if (p != NULL) - { - p->SetVoid(NULL); - p->InternalFinalConstructAddRef(); - hRes = p->_AtlInitialConstruct(); - if (SUCCEEDED(hRes)) - hRes = p->FinalConstruct(); - if (SUCCEEDED(hRes)) - hRes = p->_AtlFinalConstruct(); - p->InternalFinalConstructRelease(); - if (hRes != S_OK) - { - delete p; - p = NULL; - } - } - *pp = p; - return hRes; -} - -//Base is the user's class that derives from CComObjectRoot and whatever -//interfaces the user wants to support on the object -// CComObjectCached is used primarily for class factories in DLL's -// but it is useful anytime you want to cache an object -template -class CComObjectCached : public Base -{ -public: - typedef Base _BaseClass; - CComObjectCached(void* = NULL){} - // Set refcount to -(LONG_MAX/2) to protect destruction and - // also catch mismatched Release in debug builds - // This will be made virtual again for Beta 2 - /*virtual*/ ~CComObjectCached() - { - m_dwRef = -(LONG_MAX/2); - FinalRelease(); -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.DeleteNonAddRefThunk(_GetRawUnknown()); -#endif - } - //If InternalAddRef or InternalRelease is undefined then your class - //doesn't derive from CComObjectRoot - STDMETHOD_(ULONG, AddRef)() throw() - { - ULONG l = InternalAddRef(); - if (l == 2) - _pAtlModule->Lock(); - return l; - } - STDMETHOD_(ULONG, Release)() throw() - { - ULONG l = InternalRelease(); - if (l == 0) - delete this; - else if (l == 1) - _pAtlModule->Unlock(); - return l; - } - //if _InternalQueryInterface is undefined then you forgot BEGIN_COM_MAP - STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) throw() - {return _InternalQueryInterface(iid, ppvObject);} - static HRESULT WINAPI CreateInstance(CComObjectCached** pp) throw(); -}; - -template -HRESULT WINAPI CComObjectCached::CreateInstance(CComObjectCached** pp) throw() -{ - ATLASSERT(pp != NULL); - if (pp == NULL) - return E_POINTER; - *pp = NULL; - - HRESULT hRes = E_OUTOFMEMORY; - CComObjectCached* p = NULL; - ATLTRY(p = new CComObjectCached()) - if (p != NULL) - { - p->SetVoid(NULL); - p->InternalFinalConstructAddRef(); - hRes = p->_AtlInitialConstruct(); - if (SUCCEEDED(hRes)) - hRes = p->FinalConstruct(); - if (SUCCEEDED(hRes)) - hRes = p->_AtlFinalConstruct(); - p->InternalFinalConstructRelease(); - if (hRes != S_OK) - { - delete p; - p = NULL; - } - } - *pp = p; - return hRes; -} - - -//Base is the user's class that derives from CComObjectRoot and whatever -//interfaces the user wants to support on the object -template -class CComObjectNoLock : public Base -{ -public: - typedef Base _BaseClass; - CComObjectNoLock(void* = NULL){} - // Set refcount to -(LONG_MAX/2) to protect destruction and - // also catch mismatched Release in debug builds - - // This will be made virtual again for Beta 2 - /*virtual*/ ~CComObjectNoLock() - { - m_dwRef = -(LONG_MAX/2); - FinalRelease(); -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.DeleteNonAddRefThunk(_GetRawUnknown()); -#endif - } - - //If InternalAddRef or InternalRelease is undefined then your class - //doesn't derive from CComObjectRoot - STDMETHOD_(ULONG, AddRef)() throw() {return InternalAddRef();} - STDMETHOD_(ULONG, Release)() throw() - { - ULONG l = InternalRelease(); - if (l == 0) - delete this; - return l; - } - //if _InternalQueryInterface is undefined then you forgot BEGIN_COM_MAP - STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) throw() - {return _InternalQueryInterface(iid, ppvObject);} -}; - - -// It is possible for Base not to derive from CComObjectRoot -// However, you will need to provide _InternalQueryInterface -template -class CComObjectGlobal : public Base -{ -public: - typedef Base _BaseClass; - CComObjectGlobal(void* = NULL) - { - m_hResFinalConstruct = S_OK; - __if_exists(FinalConstruct) - { - __if_exists(InternalFinalConstructAddRef) - { - InternalFinalConstructAddRef(); - } - m_hResFinalConstruct = _AtlInitialConstruct(); - if (SUCCEEDED(m_hResFinalConstruct)) - m_hResFinalConstruct = FinalConstruct(); - __if_exists(InternalFinalConstructRelease) - { - InternalFinalConstructRelease(); - } - } - } - virtual ~CComObjectGlobal() - { - __if_exists(FinalRelease) - { - FinalRelease(); - } -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.DeleteNonAddRefThunk(_GetRawUnknown()); -#endif - } - - STDMETHOD_(ULONG, AddRef)() throw() - { - return _pAtlModule->Lock(); - } - STDMETHOD_(ULONG, Release)() throw() - { - return _pAtlModule->Unlock(); - } - STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) throw() - { - return _InternalQueryInterface(iid, ppvObject); - } - HRESULT m_hResFinalConstruct; -}; - -// It is possible for Base not to derive from CComObjectRoot -// However, you will need to provide FinalConstruct and InternalQueryInterface -template -class CComObjectStack : public Base -{ -public: - typedef Base _BaseClass; - CComObjectStack(void* = NULL) - { - m_hResFinalConstruct = _AtlInitialConstruct(); - if (SUCCEEDED(m_hResFinalConstruct)) - m_hResFinalConstruct = FinalConstruct(); - } - virtual ~CComObjectStack() - { - FinalRelease(); -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.DeleteNonAddRefThunk(_GetRawUnknown()); -#endif - } - - - STDMETHOD_(ULONG, AddRef)() throw() {ATLASSERT(FALSE);return 0;} - STDMETHOD_(ULONG, Release)() throw() {ATLASSERT(FALSE);return 0;} - STDMETHOD(QueryInterface)(REFIID, void**) throw() - {ATLASSERT(FALSE);return E_NOINTERFACE;} - HRESULT m_hResFinalConstruct; -}; - -// Base must be derived from CComObjectRoot -template -class CComObjectStackEx : public Base -{ -public: - typedef Base _BaseClass; - - CComObjectStackEx(void* = NULL) - { -#ifdef _DEBUG - m_dwRef = 0; -#endif - m_hResFinalConstruct = _AtlInitialConstruct(); - if (SUCCEEDED(m_hResFinalConstruct)) - m_hResFinalConstruct = FinalConstruct(); - } - - virtual ~CComObjectStackEx() - { - // This assert indicates mismatched ref counts. - // - // The ref count has no control over the - // lifetime of this object, so you must ensure - // by some other means that the object remains - // alive while clients have references to its interfaces. - ATLASSUME(m_dwRef == 0); - FinalRelease(); -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.DeleteNonAddRefThunk(_GetRawUnknown()); -#endif - } - - STDMETHOD_(ULONG, AddRef)() throw() - { -#ifdef _DEBUG - return InternalAddRef(); -#else - return 0; -#endif - } - - STDMETHOD_(ULONG, Release)() throw() - { -#ifdef _DEBUG - return InternalRelease(); -#else - return 0; -#endif - } - - STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) throw() - { - return _InternalQueryInterface(iid, ppvObject); - } - - HRESULT m_hResFinalConstruct; -}; - -template //Base must be derived from CComObjectRoot -class CComContainedObject : public Base -{ -public: - typedef Base _BaseClass; - CComContainedObject(void* pv) {m_pOuterUnknown = (IUnknown*)pv;} -#ifdef _ATL_DEBUG_INTERFACES - virtual ~CComContainedObject() - { - _AtlDebugInterfacesModule.DeleteNonAddRefThunk(_GetRawUnknown()); - _AtlDebugInterfacesModule.DeleteNonAddRefThunk(m_pOuterUnknown); - } -#endif - - STDMETHOD_(ULONG, AddRef)() throw() {return OuterAddRef();} - STDMETHOD_(ULONG, Release)() throw() {return OuterRelease();} - STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) throw() - { - return OuterQueryInterface(iid, ppvObject); - } - template - HRESULT STDMETHODCALLTYPE QueryInterface(Q** pp) - { - return QueryInterface(__uuidof(Q), (void**)pp); - } - //GetControllingUnknown may be virtual if the Base class has declared - //DECLARE_GET_CONTROLLING_UNKNOWN() - IUnknown* GetControllingUnknown() throw() - { -#ifdef _ATL_DEBUG_INTERFACES - IUnknown* p; - _AtlDebugInterfacesModule.AddNonAddRefThunk(m_pOuterUnknown, _T("CComContainedObject"), &p); - return p; -#else - return m_pOuterUnknown; -#endif - } -}; - -//contained is the user's class that derives from CComObjectRoot and whatever -//interfaces the user wants to support on the object -template -class CComAggObject : - public IUnknown, - public CComObjectRootEx< typename contained::_ThreadModel::ThreadModelNoCS > -{ -public: - typedef contained _BaseClass; - CComAggObject(void* pv) : m_contained(pv) - { - _pAtlModule->Lock(); - } - HRESULT _AtlInitialConstruct() - { - HRESULT hr = m_contained._AtlInitialConstruct(); - if (SUCCEEDED(hr)) - { - hr = CComObjectRootEx< typename contained::_ThreadModel::ThreadModelNoCS >::_AtlInitialConstruct(); - } - return hr; - } - //If you get a message that this call is ambiguous then you need to - // override it in your class and call each base class' version of this - HRESULT FinalConstruct() - { - CComObjectRootEx::FinalConstruct(); - return m_contained.FinalConstruct(); - } - void FinalRelease() - { - CComObjectRootEx::FinalRelease(); - m_contained.FinalRelease(); - } - // Set refcount to -(LONG_MAX/2) to protect destruction and - // also catch mismatched Release in debug builds - virtual ~CComAggObject() - { - m_dwRef = -(LONG_MAX/2); - FinalRelease(); -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.DeleteNonAddRefThunk(this); -#endif - _pAtlModule->Unlock(); - } - - STDMETHOD_(ULONG, AddRef)() {return InternalAddRef();} - STDMETHOD_(ULONG, Release)() - { - ULONG l = InternalRelease(); - if (l == 0) - delete this; - return l; - } - STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) - { - ATLASSERT(ppvObject != NULL); - if (ppvObject == NULL) - return E_POINTER; - *ppvObject = NULL; - - HRESULT hRes = S_OK; - if (InlineIsEqualUnknown(iid)) - { - *ppvObject = (void*)(IUnknown*)this; - AddRef(); -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.AddThunk((IUnknown**)ppvObject, (LPCTSTR)contained::_GetEntries()[-1].dw, iid); -#endif // _ATL_DEBUG_INTERFACES - } - else - hRes = m_contained._InternalQueryInterface(iid, ppvObject); - return hRes; - } - template - HRESULT STDMETHODCALLTYPE QueryInterface(Q** pp) - { - return QueryInterface(__uuidof(Q), (void**)pp); - } - static HRESULT WINAPI CreateInstance(LPUNKNOWN pUnkOuter, CComAggObject** pp) - { - ATLASSERT(pp != NULL); - if (pp == NULL) - return E_POINTER; - *pp = NULL; - - HRESULT hRes = E_OUTOFMEMORY; - CComAggObject* p = NULL; - ATLTRY(p = new CComAggObject(pUnkOuter)) - if (p != NULL) - { - p->SetVoid(NULL); - p->InternalFinalConstructAddRef(); - hRes = p->_AtlInitialConstruct(); - if (SUCCEEDED(hRes)) - hRes = p->FinalConstruct(); - if (SUCCEEDED(hRes)) - hRes = p->_AtlFinalConstruct(); - p->InternalFinalConstructRelease(); - if (hRes != S_OK) - { - delete p; - p = NULL; - } - } - *pp = p; - return hRes; - } - - CComContainedObject m_contained; -}; - -/////////////////////////////////////////////////////////////////////////////// -// CComPolyObject can be either aggregated or not aggregated - -template -class CComPolyObject : - public IUnknown, - public CComObjectRootEx< typename contained::_ThreadModel::ThreadModelNoCS > -{ -public: - typedef contained _BaseClass; - CComPolyObject(void* pv) : m_contained(pv ? pv : this) - { - _pAtlModule->Lock(); - } - HRESULT _AtlInitialConstruct() - { - HRESULT hr = m_contained._AtlInitialConstruct(); - if (SUCCEEDED(hr)) - { - hr = CComObjectRootEx< typename contained::_ThreadModel::ThreadModelNoCS >::_AtlInitialConstruct(); - } - return hr; - } - //If you get a message that this call is ambiguous then you need to - // override it in your class and call each base class' version of this - HRESULT FinalConstruct() - { - InternalAddRef(); - CComObjectRootEx::FinalConstruct(); - HRESULT hr = m_contained.FinalConstruct(); - InternalRelease(); - return hr; - } - void FinalRelease() - { - CComObjectRootEx::FinalRelease(); - m_contained.FinalRelease(); - } - // Set refcount to -(LONG_MAX/2) to protect destruction and - // also catch mismatched Release in debug builds - virtual ~CComPolyObject() - { - m_dwRef = -(LONG_MAX/2); - FinalRelease(); -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.DeleteNonAddRefThunk(this); -#endif - _pAtlModule->Unlock(); - } - - STDMETHOD_(ULONG, AddRef)() {return InternalAddRef();} - STDMETHOD_(ULONG, Release)() - { - ULONG l = InternalRelease(); - if (l == 0) - delete this; - return l; - } - STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) - { -#ifndef _ATL_OLEDB_CONFORMANCE_TESTS - ATLASSERT(ppvObject != NULL); -#endif - if (ppvObject == NULL) - return E_POINTER; - *ppvObject = NULL; - - HRESULT hRes = S_OK; - if (InlineIsEqualUnknown(iid)) - { - *ppvObject = (void*)(IUnknown*)this; - AddRef(); -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.AddThunk((IUnknown**)ppvObject, (LPCTSTR)contained::_GetEntries()[-1].dw, iid); -#endif // _ATL_DEBUG_INTERFACES - } - else - hRes = m_contained._InternalQueryInterface(iid, ppvObject); - return hRes; - } - template - HRESULT STDMETHODCALLTYPE QueryInterface(Q** pp) - { - return QueryInterface(__uuidof(Q), (void**)pp); - } - static HRESULT WINAPI CreateInstance(LPUNKNOWN pUnkOuter, CComPolyObject** pp) - { - ATLASSERT(pp != NULL); - if (pp == NULL) - return E_POINTER; - *pp = NULL; - - - HRESULT hRes = E_OUTOFMEMORY; - CComPolyObject* p = NULL; - ATLTRY(p = new CComPolyObject(pUnkOuter)) - if (p != NULL) - { - p->SetVoid(NULL); - p->InternalFinalConstructAddRef(); - hRes = p->_AtlInitialConstruct(); - if (SUCCEEDED(hRes)) - hRes = p->FinalConstruct(); - if (SUCCEEDED(hRes)) - hRes = p->_AtlFinalConstruct(); - p->InternalFinalConstructRelease(); - if (hRes != S_OK) - { - delete p; - p = NULL; - } - } - *pp = p; - return hRes; - } - - CComContainedObject m_contained; -}; - -template -class CComTearOffObject : public Base -{ -public: - CComTearOffObject(void* pv) - { - ATLASSUME(m_pOwner == NULL); - m_pOwner = reinterpret_cast(pv); - m_pOwner->AddRef(); - } - // Set refcount to -(LONG_MAX/2) to protect destruction and - // also catch mismatched Release in debug builds - ~CComTearOffObject() - { - m_dwRef = -(LONG_MAX/2); - FinalRelease(); -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.DeleteNonAddRefThunk(_GetRawUnknown()); -#endif - m_pOwner->Release(); - } - - STDMETHOD_(ULONG, AddRef)() throw() {return InternalAddRef();} - STDMETHOD_(ULONG, Release)() throw() - { - ULONG l = InternalRelease(); - if (l == 0) - delete this; - return l; - } - STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) throw() - { - return m_pOwner->QueryInterface(iid, ppvObject); - } -}; - -template -class CComCachedTearOffObject : - public IUnknown, - public CComObjectRootEx -{ -public: - typedef contained _BaseClass; - CComCachedTearOffObject(void* pv) : - m_contained(((contained::_OwnerClass*)pv)->GetControllingUnknown()) - { - ATLASSUME(m_contained.m_pOwner == NULL); - m_contained.m_pOwner = reinterpret_cast(pv); - } - HRESULT _AtlInitialConstruct() - { - HRESULT hr = m_contained._AtlInitialConstruct(); - if (SUCCEEDED(hr)) - { - hr = CComObjectRootEx< typename contained::_ThreadModel::ThreadModelNoCS >::_AtlInitialConstruct(); - } - return hr; - } - //If you get a message that this call is ambiguous then you need to - // override it in your class and call each base class' version of this - HRESULT FinalConstruct() - { - CComObjectRootEx::FinalConstruct(); - return m_contained.FinalConstruct(); - } - void FinalRelease() - { - CComObjectRootEx::FinalRelease(); - m_contained.FinalRelease(); - } - // Set refcount to -(LONG_MAX/2) to protect destruction and - // also catch mismatched Release in debug builds - ~CComCachedTearOffObject() - { - m_dwRef = -(LONG_MAX/2); - FinalRelease(); -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.DeleteNonAddRefThunk(this); -#endif - } - - - STDMETHOD_(ULONG, AddRef)() {return InternalAddRef();} - STDMETHOD_(ULONG, Release)() - { - ULONG l = InternalRelease(); - if (l == 0) - delete this; - return l; - } - STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) - { - ATLASSERT(ppvObject != NULL); - if (ppvObject == NULL) - return E_POINTER; - *ppvObject = NULL; - - HRESULT hRes = S_OK; - if (InlineIsEqualUnknown(iid)) - { - *ppvObject = (void*)(IUnknown*)this; - AddRef(); -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.AddThunk((IUnknown**)ppvObject, (LPCTSTR)contained::_GetEntries()[-1].dw, iid); -#endif // _ATL_DEBUG_INTERFACES - } - else - hRes = m_contained._InternalQueryInterface(iid, ppvObject); - return hRes; - } - CComContainedObject m_contained; -}; - - -class CComClassFactory : - public IClassFactory, - public CComObjectRootEx -{ -public: - BEGIN_COM_MAP(CComClassFactory) - COM_INTERFACE_ENTRY(IClassFactory) - END_COM_MAP() - - // This will be made virtual again for Beta 2 - /*virtual*/ ~CComClassFactory() - { - } - - // IClassFactory - STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj) - { - ATLASSUME(m_pfnCreateInstance != NULL); - HRESULT hRes = E_POINTER; - if (ppvObj != NULL) - { - *ppvObj = NULL; - // can't ask for anything other than IUnknown when aggregating - - if ((pUnkOuter != NULL) && !InlineIsEqualUnknown(riid)) - { - ATLTRACE(atlTraceCOM, 0, _T("CComClassFactory: asked for non IUnknown interface while creating an aggregated object")); - hRes = CLASS_E_NOAGGREGATION; - } - else - hRes = m_pfnCreateInstance(pUnkOuter, riid, ppvObj); - } - return hRes; - } - - STDMETHOD(LockServer)(BOOL fLock) - { - if (fLock) - _pAtlModule->Lock(); - else - _pAtlModule->Unlock(); - return S_OK; - } - // helper - void SetVoid(void* pv) - { - m_pfnCreateInstance = (_ATL_CREATORFUNC*)pv; - } - _ATL_CREATORFUNC* m_pfnCreateInstance; -}; - -template -class CComClassFactory2 : - public IClassFactory2, - public CComObjectRootEx, - public license -{ -public: - typedef license _LicenseClass; - typedef CComClassFactory2 _ComMapClass; -BEGIN_COM_MAP(CComClassFactory2) - COM_INTERFACE_ENTRY(IClassFactory) - COM_INTERFACE_ENTRY(IClassFactory2) -END_COM_MAP() - // IClassFactory - STDMETHOD(LockServer)(BOOL fLock) - { - if (fLock) - _pAtlModule->Lock(); - else - _pAtlModule->Unlock(); - return S_OK; - } - STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, - REFIID riid, void** ppvObj) - { - ATLASSUME(m_pfnCreateInstance != NULL); - if (ppvObj == NULL) - return E_POINTER; - *ppvObj = NULL; - if (!IsLicenseValid()) - return CLASS_E_NOTLICENSED; - - if ((pUnkOuter != NULL) && !InlineIsEqualUnknown(riid)) - return CLASS_E_NOAGGREGATION; - else - return m_pfnCreateInstance(pUnkOuter, riid, ppvObj); - } - // IClassFactory2 - STDMETHOD(CreateInstanceLic)(IUnknown* pUnkOuter, - IUnknown* /* pUnkReserved */, REFIID riid, BSTR bstrKey, - void** ppvObject) - { - ATLASSUME(m_pfnCreateInstance != NULL); - if (ppvObject == NULL) - return E_POINTER; - *ppvObject = NULL; - if ( ((bstrKey != NULL) && !VerifyLicenseKey(bstrKey)) || - ((bstrKey == NULL) && !IsLicenseValid()) ) - return CLASS_E_NOTLICENSED; - if ((pUnkOuter != NULL) && !InlineIsEqualUnknown(riid)) - return CLASS_E_NOAGGREGATION; - else - return m_pfnCreateInstance(pUnkOuter, riid, ppvObject); - } - STDMETHOD(RequestLicKey)(DWORD dwReserved, BSTR* pbstrKey) - { - if (pbstrKey == NULL) - return E_POINTER; - *pbstrKey = NULL; - - if (!IsLicenseValid()) - return CLASS_E_NOTLICENSED; - return GetLicenseKey(dwReserved,pbstrKey) ? S_OK : E_FAIL; - } - STDMETHOD(GetLicInfo)(LICINFO* pLicInfo) - { - if (pLicInfo == NULL) - return E_POINTER; - pLicInfo->cbLicInfo = sizeof(LICINFO); - pLicInfo->fLicVerified = IsLicenseValid(); - BSTR bstr = NULL; - pLicInfo->fRuntimeKeyAvail = GetLicenseKey(0,&bstr); - ::SysFreeString(bstr); - return S_OK; - } - void SetVoid(void* pv) - { - m_pfnCreateInstance = (_ATL_CREATORFUNC*)pv; - } - _ATL_CREATORFUNC* m_pfnCreateInstance; -}; - -///////////////////////////////////////////////////////////////////////////////////////////// -// Thread Pooling class factory -class CComClassFactoryAutoThread : - public IClassFactory, - public CComObjectRootEx -{ -public: - BEGIN_COM_MAP(CComClassFactoryAutoThread) - COM_INTERFACE_ENTRY(IClassFactory) - END_COM_MAP() - - // This will be made virtual again for Beta 2 - /*virtual*/ ~CComClassFactoryAutoThread() - { - } - - // helper - void SetVoid(void* pv) - { - m_pfnCreateInstance = (_ATL_CREATORFUNC*)pv; - } - STDMETHODIMP CreateInstance(LPUNKNOWN pUnkOuter, - REFIID riid, void** ppvObj) - { - ATLASSUME(m_pfnCreateInstance != NULL); - HRESULT hRes = E_POINTER; - if (ppvObj != NULL) - { - *ppvObj = NULL; - // cannot aggregate across apartments - ATLASSERT(pUnkOuter == NULL); - if (pUnkOuter != NULL) - hRes = CLASS_E_NOAGGREGATION; - else - { - ATLASSERT(_pAtlAutoThreadModule && _T("Global instance of CAtlAutoThreadModule not declared")); - if (_pAtlAutoThreadModule == NULL) - return E_FAIL; - - hRes = _pAtlAutoThreadModule->CreateInstance(m_pfnCreateInstance, riid, ppvObj); - } - } - return hRes; - } - STDMETHODIMP LockServer(BOOL fLock) - { - if (fLock) - _pAtlModule->Lock(); - else - _pAtlModule->Unlock(); - return S_OK; - } - _ATL_CREATORFUNC* m_pfnCreateInstance; -}; - - -///////////////////////////////////////////////////////////////////////////////////////////// -// Singleton Class Factory -template -class CComClassFactorySingleton : public CComClassFactory -{ -public: - CComClassFactorySingleton() : m_hrCreate(S_OK) - { - } - // This will be made virtual again for Beta 2 - /*virtual*/ ~CComClassFactorySingleton() - { - } - // IClassFactory - STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj) - { - HRESULT hRes = E_POINTER; - if (ppvObj != NULL) - { - *ppvObj = NULL; - // aggregation is not supported in Singletons - ATLASSERT(pUnkOuter == NULL); - if (pUnkOuter != NULL) - hRes = CLASS_E_NOAGGREGATION; - else - { - if (m_hrCreate == S_OK && m_spObj == NULL) - { - __try - { - Lock(); - // Did another thread get here first? - if (m_hrCreate == S_OK && m_spObj == NULL) - { - CComObjectCached *p; - m_hrCreate = CComObjectCached::CreateInstance(&p); - if (SUCCEEDED(m_hrCreate)) - { - m_hrCreate = p->QueryInterface(IID_IUnknown, (void**)&m_spObj); - if (FAILED(m_hrCreate)) - { - delete p; - } - } - } - } - __finally - { - Unlock(); - } - } - if (m_hrCreate == S_OK) - { - hRes = m_spObj->QueryInterface(riid, ppvObj); - } - else - { - hRes = m_hrCreate; - } - } - } - return hRes; - } - HRESULT m_hrCreate; - CComPtr m_spObj; -}; - - -template -class CComCoClass -{ -public: - DECLARE_CLASSFACTORY() - DECLARE_AGGREGATABLE(T) - typedef T _CoClass; - static const CLSID& WINAPI GetObjectCLSID() {return *pclsid;} - static LPCTSTR WINAPI GetObjectDescription() {return NULL;} - static HRESULT WINAPI Error(LPCOLESTR lpszDesc, - const IID& iid = GUID_NULL, HRESULT hRes = 0) - { - return AtlReportError(GetObjectCLSID(), lpszDesc, iid, hRes); - } - static HRESULT WINAPI Error(LPCOLESTR lpszDesc, DWORD dwHelpID, - LPCOLESTR lpszHelpFile, const IID& iid = GUID_NULL, HRESULT hRes = 0) - { - return AtlReportError(GetObjectCLSID(), lpszDesc, dwHelpID, lpszHelpFile, - iid, hRes); - } - static HRESULT WINAPI Error(UINT nID, const IID& iid = GUID_NULL, - HRESULT hRes = 0, HINSTANCE hInst = _AtlBaseModule.GetResourceInstance()) - { - return AtlReportError(GetObjectCLSID(), nID, iid, hRes, hInst); - } - static HRESULT WINAPI Error(UINT nID, DWORD dwHelpID, - LPCOLESTR lpszHelpFile, const IID& iid = GUID_NULL, - HRESULT hRes = 0, HINSTANCE hInst = _AtlBaseModule.GetResourceInstance()) - { - return AtlReportError(GetObjectCLSID(), nID, dwHelpID, lpszHelpFile, - iid, hRes, hInst); - } - static HRESULT WINAPI Error(LPCSTR lpszDesc, - const IID& iid = GUID_NULL, HRESULT hRes = 0) - { - return AtlReportError(GetObjectCLSID(), lpszDesc, iid, hRes); - } - static HRESULT WINAPI Error(LPCSTR lpszDesc, DWORD dwHelpID, - LPCSTR lpszHelpFile, const IID& iid = GUID_NULL, HRESULT hRes = 0) - { - return AtlReportError(GetObjectCLSID(), lpszDesc, dwHelpID, - lpszHelpFile, iid, hRes); - } - template - static HRESULT CreateInstance(IUnknown* punkOuter, Q** pp) - { - return T::_CreatorClass::CreateInstance(punkOuter, __uuidof(Q), (void**) pp); - } - template - static HRESULT CreateInstance(Q** pp) - { - return T::_CreatorClass::CreateInstance(NULL, __uuidof(Q), (void**) pp); - } -}; - -// ATL doesn't support multiple LCID's at the same time -// Whatever LCID is queried for first is the one that is used. -class CComTypeInfoHolder -{ -// Should be 'protected' but can cause compiler to generate fat code. -public: - const GUID* m_pguid; - const GUID* m_plibid; - WORD m_wMajor; - WORD m_wMinor; - - ITypeInfo* m_pInfo; - long m_dwRef; - struct stringdispid - { - CComBSTR bstr; - int nLen; - DISPID id; - stringdispid() : nLen(0), id(DISPID_UNKNOWN){} - }; - stringdispid* m_pMap; - int m_nCount; - -public: - -#ifdef _ATL_DLL_IMPL - CComTypeInfoHolder(const GUID* pguid, const GUID* plibid, WORD wMajor, WORD wMinor) : - m_pguid(pguid), m_plibid(plibid), m_wMajor(wMajor), m_wMinor(wMinor), - m_pInfo(NULL), m_dwRef(0), m_pMap(NULL), m_nCount(0) - { - } - - ~CComTypeInfoHolder() - { - if (m_pInfo != NULL) - m_pInfo->Release(); - m_pInfo = NULL; - delete [] m_pMap; - m_pMap = NULL; - } -#endif - - HRESULT GetTI(LCID lcid, ITypeInfo** ppInfo) - { - ATLASSERT(ppInfo != NULL); - if (ppInfo == NULL) - return E_POINTER; - - HRESULT hr = S_OK; - if (m_pInfo == NULL) - hr = GetTI(lcid); - *ppInfo = m_pInfo; - if (m_pInfo != NULL) - { - m_pInfo->AddRef(); - hr = S_OK; - } - return hr; - } - HRESULT GetTI(LCID lcid); - HRESULT EnsureTI(LCID lcid) - { - HRESULT hr = S_OK; - if (m_pInfo == NULL || m_pMap == NULL) - hr = GetTI(lcid); - return hr; - } - - // This function is called by the module on exit - // It is registered through _pAtlModule->AddTermFunc() - static void __stdcall Cleanup(DWORD_PTR dw); - - HRESULT GetTypeInfo(UINT /* itinfo */, LCID lcid, ITypeInfo** pptinfo) - { - return GetTI(lcid, pptinfo); - } - HRESULT GetIDsOfNames(REFIID /* riid */, LPOLESTR* rgszNames, UINT cNames, - LCID lcid, DISPID* rgdispid) - { - HRESULT hRes = EnsureTI(lcid); - if (m_pInfo != NULL) - { - hRes = E_FAIL; - // Look in cache if - // cache is populated - // parameter names are not requested - if (m_pMap != NULL && cNames == 1) - { - int n = int( ocslen(rgszNames[0]) ); - for (int j=m_nCount-1; j>=0; j--) - { - if ((n == m_pMap[j].nLen) && - (memcmp(m_pMap[j].bstr, rgszNames[0], m_pMap[j].nLen * sizeof(OLECHAR)) == 0)) - { - rgdispid[0] = m_pMap[j].id; - hRes = S_OK; - break; - } - } - } - // if cache is empty or name not in cache or parameter names are requested, - // delegate to ITypeInfo::GetIDsOfNames - if (FAILED(hRes)) - { - hRes = m_pInfo->GetIDsOfNames(rgszNames, cNames, rgdispid); - } - } - return hRes; - } - - HRESULT Invoke(IDispatch* p, DISPID dispidMember, REFIID /* riid */, - LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, - EXCEPINFO* pexcepinfo, UINT* puArgErr) - { - HRESULT hRes = EnsureTI(lcid); - if (m_pInfo != NULL) - hRes = m_pInfo->Invoke(p, dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr); - return hRes; - } - __checkReturn HRESULT LoadNameCache(ITypeInfo* pTypeInfo) - { - TYPEATTR* pta; - HRESULT hr = pTypeInfo->GetTypeAttr(&pta); - if (SUCCEEDED(hr)) - { - stringdispid* pMap = NULL; - m_nCount = pta->cFuncs; - m_pMap = NULL; - if (m_nCount != 0) - { - ATLTRY(pMap = new stringdispid[m_nCount]); - if (pMap == NULL) - { - pTypeInfo->ReleaseTypeAttr(pta); - return E_OUTOFMEMORY; - } - } - for (int i=0; iGetFuncDesc(i, &pfd))) - { - CComBSTR bstrName; - if (SUCCEEDED(pTypeInfo->GetDocumentation(pfd->memid, &bstrName, NULL, NULL, NULL))) - { - pMap[i].bstr.Attach(bstrName.Detach()); - pMap[i].nLen = SysStringLen(pMap[i].bstr); - pMap[i].id = pfd->memid; - } - pTypeInfo->ReleaseFuncDesc(pfd); - } - } - m_pMap = pMap; - pTypeInfo->ReleaseTypeAttr(pta); - } - return S_OK; - } -}; - - inline void __stdcall CComTypeInfoHolder::Cleanup(DWORD_PTR dw) - { - ATLASSERT(dw != 0); - if (dw == 0) - return; - - CComTypeInfoHolder* p = (CComTypeInfoHolder*) dw; - if (p->m_pInfo != NULL) - p->m_pInfo->Release(); - p->m_pInfo = NULL; - delete [] p->m_pMap; - p->m_pMap = NULL; - } - -inline HRESULT CComTypeInfoHolder::GetTI(LCID lcid) -{ - //If this assert occurs then most likely didn't initialize properly - ATLASSUME(m_plibid != NULL && m_pguid != NULL); - ATLASSUME(!InlineIsEqualGUID(*m_plibid, GUID_NULL) && "Did you forget to pass the LIBID to CComModule::Init?"); - - if (m_pInfo != NULL && m_pMap != NULL) - return S_OK; - - CComCritSecLock lock(_pAtlModule->m_csStaticDataInitAndTypeInfo, false); - HRESULT hRes = lock.Lock(); - if (FAILED(hRes)) - { - ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to lock critical section in CComTypeInfoHolder::GetTI\n")); - ATLASSERT(0); - return hRes; - } - hRes = E_FAIL; - if (m_pInfo == NULL) - { - ITypeLib* pTypeLib = NULL; - if (InlineIsEqualGUID(CAtlModule::m_libid, *m_plibid) && m_wMajor == 0xFFFF && m_wMinor == 0xFFFF) - { - TCHAR szFilePath[MAX_PATH]; - DWORD dwFLen = ::GetModuleFileName(_AtlBaseModule.GetModuleInstance(), szFilePath, MAX_PATH); - if( dwFLen != 0 && dwFLen != MAX_PATH ) - { - USES_CONVERSION_EX; - LPOLESTR pszFile = T2OLE_EX(szFilePath, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if (pszFile == NULL) - return E_OUTOFMEMORY; -#endif - hRes = LoadTypeLib(pszFile, &pTypeLib); - } - } - else - { - hRes = LoadRegTypeLib(*m_plibid, m_wMajor, m_wMinor, lcid, &pTypeLib); -#ifdef _DEBUG - if (SUCCEEDED(hRes)) - { - // Trace out an warning if the requested TypelibID is the same as the modules TypelibID - // and versions do not match. - // - // In most cases it is due to wrong version template parameters to IDispatchImpl, - // IProvideClassInfoImpl or IProvideClassInfo2Impl. - // Set major and minor versions to 0xFFFF if the modules type lib has to be loaded - // irrespective of its version. - // - // Get the module's file path - TCHAR szFilePath[MAX_PATH]; - DWORD dwFLen = ::GetModuleFileName(_AtlBaseModule.GetModuleInstance(), szFilePath, MAX_PATH); - if( dwFLen != 0 && dwFLen != MAX_PATH ) - { - USES_CONVERSION_EX; - CComPtr spTypeLibModule; - HRESULT hRes2 = S_OK; - LPOLESTR pszFile = T2OLE_EX(szFilePath, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); - if (pszFile == NULL) - hRes2 = E_OUTOFMEMORY; - else - hRes2 = LoadTypeLib(pszFile, &spTypeLibModule); - if (SUCCEEDED(hRes2)) - { - TLIBATTR* pLibAttr; - hRes2 = spTypeLibModule->GetLibAttr(&pLibAttr); - if (SUCCEEDED(hRes2)) - { - if (InlineIsEqualGUID(pLibAttr->guid, *m_plibid) && - (pLibAttr->wMajorVerNum != m_wMajor || - pLibAttr->wMinorVerNum != m_wMinor)) - { - ATLTRACE(atlTraceCOM, 0, _T("Warning : CComTypeInfoHolder::GetTI : Loaded typelib does not match the typelib in the module : %s\n"), szFilePath); - ATLTRACE(atlTraceCOM, 0, _T("\tSee IDispatchImpl overview help topic for more information\n"), szFilePath); - } - spTypeLibModule->ReleaseTLibAttr(pLibAttr); - } - } - } - } - else - { - ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to load Typelibrary. (HRESULT = 0x%x)\n"), hRes); - ATLTRACE(atlTraceCOM, 0, _T("\tVerify TypelibID and major version specified with\n")); - ATLTRACE(atlTraceCOM, 0, _T("\tIDispatchImpl, CStockPropImpl, IProvideClassInfoImpl or IProvideCLassInfo2Impl\n")); - } -#endif - } - if (SUCCEEDED(hRes)) - { - CComPtr spTypeInfo; - hRes = pTypeLib->GetTypeInfoOfGuid(*m_pguid, &spTypeInfo); - if (SUCCEEDED(hRes)) - { - CComPtr spInfo(spTypeInfo); - CComPtr spTypeInfo2; - if (SUCCEEDED(spTypeInfo->QueryInterface(&spTypeInfo2))) - spInfo = spTypeInfo2; - - m_pInfo = spInfo.Detach(); -#ifndef _ATL_DLL_IMPL - _pAtlModule->AddTermFunc(Cleanup, (DWORD_PTR)this); -#endif - } - pTypeLib->Release(); - } - } - else - { - // Another thread has loaded the typeinfo so we're OK. - hRes = S_OK; - } - - if (m_pInfo != NULL && m_pMap == NULL) - { - hRes=LoadNameCache(m_pInfo); - } - - return hRes; -} - - -////////////////////////////////////////////////////////////////////////////// -// IObjectWithSite -// -template -class ATL_NO_VTABLE IObjectWithSiteImpl : public IObjectWithSite -{ -public: - virtual ~IObjectWithSiteImpl() - { - } - - STDMETHOD(SetSite)(IUnknown *pUnkSite) - { - ATLTRACE(atlTraceCOM, 2, _T("IObjectWithSiteImpl::SetSite\n")); - T* pT = static_cast(this); - pT->m_spUnkSite = pUnkSite; - return S_OK; - } - STDMETHOD(GetSite)(REFIID riid, void **ppvSite) - { - ATLTRACE(atlTraceCOM, 2, _T("IObjectWithSiteImpl::GetSite\n")); - T* pT = static_cast(this); - ATLASSERT(ppvSite); - HRESULT hRes = E_POINTER; - if (ppvSite != NULL) - { - if (pT->m_spUnkSite) - hRes = pT->m_spUnkSite->QueryInterface(riid, ppvSite); - else - { - *ppvSite = NULL; - hRes = E_FAIL; - } - } - return hRes; - } - - HRESULT SetChildSite(IUnknown* punkChild) - { - if (punkChild == NULL) - return E_POINTER; - - HRESULT hr; - CComPtr spChildSite; - hr = punkChild->QueryInterface(__uuidof(IObjectWithSite), (void**)&spChildSite); - if (SUCCEEDED(hr)) - hr = spChildSite->SetSite((IUnknown*)this); - - return hr; - } - - static HRESULT SetChildSite(IUnknown* punkChild, IUnknown* punkParent) - { - return AtlSetChildSite(punkChild, punkParent); - } - - CComPtr m_spUnkSite; -}; - -////////////////////////////////////////////////////////////////////////////// -// IServiceProvider -// -template -class ATL_NO_VTABLE IServiceProviderImpl : public IServiceProvider -{ -public: - STDMETHOD(QueryService)(REFGUID guidService, REFIID riid, void** ppvObject) - { - ATLTRACE(atlTraceCOM, 2, _T("IServiceProviderImpl::QueryService\n")); - - T* pT = static_cast(this); - return pT->_InternalQueryService(guidService, riid, ppvObject); - } -}; - -#define BEGIN_SERVICE_MAP(x) public: \ - HRESULT _InternalQueryService(REFGUID guidService, REFIID riid, void** ppvObject) \ - { \ - ATLASSERT(ppvObject != NULL); \ - if (ppvObject == NULL) \ - return E_POINTER; \ - *ppvObject = NULL; - -#define SERVICE_ENTRY(x) \ - if (InlineIsEqualGUID(guidService, x)) \ - return QueryInterface(riid, ppvObject); - -#define SERVICE_ENTRY_CHAIN(x) \ - ATL::CComQIPtr spProvider(x); \ - if (spProvider != NULL) \ - return spProvider->QueryService(guidService, riid, ppvObject); - -#define END_SERVICE_MAP() \ - return E_NOINTERFACE; \ - } - - -///////////////////////////////////////////////////////////////////////////// -// IDispEventImpl - -ATLAPI AtlGetObjectSourceInterface(IUnknown* punkObj, GUID* plibid, IID* piid, unsigned short* pdwMajor, unsigned short* pdwMinor); - -#ifdef _M_IA64 -template -class CComStdCallThunk -{ -public: - typedef void (__stdcall T::*TMFP)(); - void* pVtable; - void* pFunc; - _stdcallthunk thunk; - void Init(TMFP dw, void* pThis) - { - pVtable = &pFunc; - pFunc = &thunk; - union { - DWORD_PTR dwFunc; - TMFP pfn; - } pfn; - pfn.pfn = dw; - thunk.Init(pfn.dwFunc, pThis); - } -}; - -#elif defined ( _M_IX86 ) || defined ( _M_AMD64 ) - -extern "C" -{ -void __stdcall CComStdCallThunkHelper(); -} - -template -class CComStdCallThunk -{ -public: - typedef void (__stdcall T::*TMFP)(); - void *pVTable; // pointer to artificial VTABLE - void *pThis; // pointer to the class - TMFP pfn; // Pointer to member function to call - void (__stdcall *pfnHelper)(); // Artificial VTABLE entry. Points to CComStdCallThunkHelper - // which modifies the stack and jumps to pfn - - void Init(TMFP pf, void *p) - { - pfnHelper = CComStdCallThunkHelper; - pVTable = &pfnHelper; - pThis = p; - pfn = pf; - } -}; -#else -#error X86, AMD64 and IA64 -#endif // _M_IX86 | - -#ifndef _ATL_MAX_VARTYPES -#define _ATL_MAX_VARTYPES 8 -#endif - -struct _ATL_FUNC_INFO -{ - CALLCONV cc; - VARTYPE vtReturn; - SHORT nParams; - VARTYPE pVarTypes[_ATL_MAX_VARTYPES]; -}; - -class ATL_NO_VTABLE _IDispEvent -{ -public: - _IDispEvent() : m_libid(GUID_NULL), m_iid(IID_NULL), m_wMajorVerNum(0), m_wMinorVerNum(0), m_dwEventCookie(0xFEFEFEFE) { } - //this method needs a different name than QueryInterface - STDMETHOD(_LocDEQueryInterface)(REFIID riid, void ** ppvObject) = 0; - virtual ULONG STDMETHODCALLTYPE AddRef(void) = 0; - virtual ULONG STDMETHODCALLTYPE Release(void) = 0; - GUID m_libid; // used for dynamic case - IID m_iid; // used for dynamic case - unsigned short m_wMajorVerNum; // Major version number. used for dynamic case - unsigned short m_wMinorVerNum; // Minor version number. used for dynamic case - DWORD m_dwEventCookie; - HRESULT DispEventAdvise(IUnknown* pUnk, const IID* piid) - { - ATLENSURE(m_dwEventCookie == 0xFEFEFEFE); - return AtlAdvise(pUnk, (IUnknown*)this, *piid, &m_dwEventCookie); - } - HRESULT DispEventUnadvise(IUnknown* pUnk, const IID* piid) - { - HRESULT hr = AtlUnadvise(pUnk, *piid, m_dwEventCookie); - m_dwEventCookie = 0xFEFEFEFE; - return hr; - } - //---- add Advise & Unadvise for ease of calling from attribute code ---- - HRESULT Advise(IUnknown *punk) - { - HRESULT hr = AtlGetObjectSourceInterface(punk, &m_libid, &m_iid, &m_wMajorVerNum, &m_wMinorVerNum); - if (FAILED(hr)) - return hr; - return DispEventAdvise(punk, &m_iid); - } - HRESULT Unadvise(IUnknown *punk) - { - HRESULT hr = AtlGetObjectSourceInterface(punk, &m_libid, &m_iid, &m_wMajorVerNum, &m_wMinorVerNum); - if (FAILED(hr)) - return hr; - return DispEventUnadvise(punk, &m_iid); - } -}; - -template -class ATL_NO_VTABLE _IDispEventLocator : public _IDispEvent -{ -public: -}; - -template -class ATL_NO_VTABLE IDispEventSimpleImpl : public _IDispEventLocator -{ -public: - STDMETHOD(_LocDEQueryInterface)(REFIID riid, void ** ppvObject) - { - ATLASSERT(ppvObject != NULL); - if (ppvObject == NULL) - return E_POINTER; - *ppvObject = NULL; - - if (InlineIsEqualGUID(riid, IID_NULL)) - return E_NOINTERFACE; - - if (InlineIsEqualGUID(riid, *pdiid) || - InlineIsEqualUnknown(riid) || - InlineIsEqualGUID(riid, __uuidof(IDispatch)) || - InlineIsEqualGUID(riid, m_iid)) - { - *ppvObject = this; - AddRef(); -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.AddThunk((IUnknown**)ppvObject, _T("IDispEventImpl"), riid); -#endif // _ATL_DEBUG_INTERFACES - return S_OK; - } - else - return E_NOINTERFACE; - } - - // These are here only to support use in non-COM objects - virtual ULONG STDMETHODCALLTYPE AddRef() - { - return 1; - } - virtual ULONG STDMETHODCALLTYPE Release() - { - return 1; - } - - STDMETHOD(GetTypeInfoCount)(UINT* /*pctinfo*/) - {ATLTRACENOTIMPL(_T("IDispEventSimpleImpl::GetTypeInfoCount"));} - - STDMETHOD(GetTypeInfo)(UINT /*itinfo*/, LCID /*lcid*/, ITypeInfo** /*pptinfo*/) - {ATLTRACENOTIMPL(_T("IDispEventSimpleImpl::GetTypeInfo"));} - - STDMETHOD(GetIDsOfNames)(REFIID /*riid*/, LPOLESTR* /*rgszNames*/, UINT /*cNames*/, - LCID /*lcid*/, DISPID* /*rgdispid*/) - {ATLTRACENOTIMPL(_T("IDispEventSimpleImpl::GetIDsOfNames"));} - - STDMETHOD(Invoke)(DISPID dispidMember, REFIID /*riid*/, - LCID lcid, WORD /*wFlags*/, DISPPARAMS* pdispparams, VARIANT* pvarResult, - EXCEPINFO* /*pexcepinfo*/, UINT* /*puArgErr*/) - { - const _ATL_EVENT_ENTRY* pMap = T::_GetSinkMap(); - const _ATL_EVENT_ENTRY* pFound = NULL; - while (pMap->piid != NULL) - { - if ((pMap->nControlID == nID) && (pMap->dispid == dispidMember) && - (IsEqualIID(*(pMap->piid), *pdiid))) - { - pFound = pMap; - break; - } - pMap++; - } - if (pFound == NULL) - return S_OK; - - - _ATL_FUNC_INFO info; - _ATL_FUNC_INFO* pInfo; - if (pFound->pInfo != NULL) - pInfo = pFound->pInfo; - else - { - pInfo = &info; - HRESULT hr = GetFuncInfoFromId(*pdiid, dispidMember, lcid, info); - if (FAILED(hr)) - return S_OK; - } - return InvokeFromFuncInfo(pFound->pfn, *pInfo, pdispparams, pvarResult); - } - - //Helper for invoking the event - HRESULT InvokeFromFuncInfo(void (__stdcall T::*pEvent)(), _ATL_FUNC_INFO& info, DISPPARAMS* pdispparams, VARIANT* pvarResult) - { - ATLASSERT(pdispparams->cArgs == (UINT)info.nParams); - - T* pT = static_cast(this); - - // If this assert occurs, then add - // #define _ATL_MAX_VARTYPES nnnn - // before including atlcom.h - ATLASSERT(info.nParams <= _ATL_MAX_VARTYPES); - if (info.nParams > _ATL_MAX_VARTYPES) - { - return E_FAIL; - } - VARIANTARG* rgVarArgs[_ATL_MAX_VARTYPES]; - VARIANTARG** pVarArgs = info.nParams ? rgVarArgs : 0; - - UINT nIndex = 0; - -#ifndef _ATL_IGNORE_NAMED_ARGS - for (nIndex; nIndex < pdispparams->cNamedArgs; nIndex++) - pVarArgs[pdispparams->rgdispidNamedArgs[nIndex]] = &pdispparams->rgvarg[nIndex]; -#endif - - for (; nIndex < pdispparams->cArgs; nIndex++) - pVarArgs[info.nParams-nIndex-1] = &pdispparams->rgvarg[nIndex]; - - CComStdCallThunk thunk; - thunk.Init(pEvent, pT); - - CComVariant tmpResult; - if (pvarResult == NULL) - pvarResult = &tmpResult; - - HRESULT hr = DispCallFunc( - &thunk, - 0, - info.cc, - info.vtReturn, - info.nParams, - info.pVarTypes, - pVarArgs, - pvarResult); - ATLASSERT(SUCCEEDED(hr)); - return hr; - } - - //Helper for finding the function index for a DISPID - virtual HRESULT GetFuncInfoFromId(const IID& /*iid*/, DISPID /*dispidMember*/, LCID /*lcid*/, _ATL_FUNC_INFO& /*info*/) - { - ATLTRACE(_T("TODO: Classes using IDispEventSimpleImpl should override this method\n")); - ATLASSERT(0); - ATLTRACENOTIMPL(_T("IDispEventSimpleImpl::GetFuncInfoFromId")); - } - //Helpers for sinking events on random IUnknown* - HRESULT DispEventAdvise(IUnknown* pUnk, const IID* piid) - { - ATLENSURE(m_dwEventCookie == 0xFEFEFEFE); - return AtlAdvise(pUnk, (IUnknown*)this, *piid, &m_dwEventCookie); - } - HRESULT DispEventUnadvise(IUnknown* pUnk, const IID* piid) - { - HRESULT hr = AtlUnadvise(pUnk, *piid, m_dwEventCookie); - m_dwEventCookie = 0xFEFEFEFE; - return hr; - } - HRESULT DispEventAdvise(IUnknown* pUnk) - { - return _IDispEvent::DispEventAdvise(pUnk, pdiid); - } - HRESULT DispEventUnadvise(IUnknown* pUnk) - { - return _IDispEvent::DispEventUnadvise(pUnk, pdiid); - } -}; - -//Helper for advising connections points from a sink map -template -inline HRESULT AtlAdviseSinkMap(T* pT, bool bAdvise) -{ - ATLASSERT(::IsWindow(pT->m_hWnd)); - const _ATL_EVENT_ENTRY* pEntries = T::_GetSinkMap(); - if (pEntries == NULL) - return S_OK; - HRESULT hr = S_OK; - while (pEntries->piid != NULL) - { - _IDispEvent* pDE = (_IDispEvent*)((DWORD_PTR)pT+pEntries->nOffset); - bool bNotAdvised = pDE->m_dwEventCookie == 0xFEFEFEFE; - if (bAdvise ^ bNotAdvised) - { - pEntries++; - continue; - } - hr = E_FAIL; - HWND h = pT->GetDlgItem(pEntries->nControlID); - ATLASSERT(h != NULL); - if (h != NULL) - { - CComPtr spUnk; - AtlAxGetControl(h, &spUnk); - ATLASSERT(spUnk != NULL); - if (spUnk != NULL) - { - if (bAdvise) - { - if (!InlineIsEqualGUID(IID_NULL, *pEntries->piid)) - hr = pDE->DispEventAdvise(spUnk, pEntries->piid); - else - { - hr = AtlGetObjectSourceInterface(spUnk, &pDE->m_libid, &pDE->m_iid, &pDE->m_wMajorVerNum, &pDE->m_wMinorVerNum); - if (FAILED(hr)) - return hr; - hr = pDE->DispEventAdvise(spUnk, &pDE->m_iid); - } - } - else - { - if (!InlineIsEqualGUID(IID_NULL, *pEntries->piid)) - hr = pDE->DispEventUnadvise(spUnk, pEntries->piid); - else - hr = pDE->DispEventUnadvise(spUnk, &pDE->m_iid); - } - ATLASSERT(hr == S_OK); - } - } - if (FAILED(hr)) - break; - pEntries++; - } - return hr; -} - -#pragma warning(push) -#pragma warning(disable: 4061) // enumerate XXX not explicitly handled by a case label -inline VARTYPE AtlGetUserDefinedType(ITypeInfo *pTI, HREFTYPE hrt) -{ - ATLENSURE_THROW(pTI != NULL, E_INVALIDARG); - - CComPtr spTypeInfo; - VARTYPE vt = VT_USERDEFINED; - HRESULT hr = E_FAIL; - hr = pTI->GetRefTypeInfo(hrt, &spTypeInfo); - if(FAILED(hr)) - return vt; - TYPEATTR *pta = NULL; - - hr = spTypeInfo->GetTypeAttr(&pta); - if(SUCCEEDED(hr) && pta && (pta->typekind == TKIND_ALIAS || pta->typekind == TKIND_ENUM)) - { - if (pta->tdescAlias.vt == VT_USERDEFINED) - vt = AtlGetUserDefinedType(spTypeInfo, pta->tdescAlias.hreftype); - else - { - switch (pta->typekind) - { - case TKIND_ENUM : - vt = VT_I4; - break; - case TKIND_INTERFACE : - vt = VT_UNKNOWN; - break; - case TKIND_DISPATCH : - vt = VT_DISPATCH; - break; - default: - vt = pta->tdescAlias.vt; - } - } - } - - if(pta) - spTypeInfo->ReleaseTypeAttr(pta); - return vt; - -} -#pragma warning(pop) - -inline HRESULT AtlGetFuncInfoFromId(ITypeInfo* pTypeInfo, const IID& /*iid*/, DISPID dispidMember, LCID /*lcid*/, _ATL_FUNC_INFO& info) -{ - if (pTypeInfo == NULL) - return E_INVALIDARG; - - HRESULT hr = S_OK; - FUNCDESC* pFuncDesc = NULL; - TYPEATTR* pAttr; - hr = pTypeInfo->GetTypeAttr(&pAttr); - if (FAILED(hr)) - return hr; - int i; - for (i=0;icFuncs;i++) - { - hr = pTypeInfo->GetFuncDesc(i, &pFuncDesc); - if (FAILED(hr)) - return hr; - if (pFuncDesc->memid == dispidMember) - break; - pTypeInfo->ReleaseFuncDesc(pFuncDesc); - pFuncDesc = NULL; - } - pTypeInfo->ReleaseTypeAttr(pAttr); - if (pFuncDesc == NULL) - return E_FAIL; - - // If this assert occurs, then add a #define _ATL_MAX_VARTYPES nnnn - // before including atlcom.h - ATLASSERT(pFuncDesc->cParams <= _ATL_MAX_VARTYPES); - if (pFuncDesc->cParams > _ATL_MAX_VARTYPES) - return E_FAIL; - - for (i = 0; i < pFuncDesc->cParams; i++) - { - info.pVarTypes[i] = pFuncDesc->lprgelemdescParam[i].tdesc.vt; - if (info.pVarTypes[i] == VT_PTR) - info.pVarTypes[i] = (VARTYPE)(pFuncDesc->lprgelemdescParam[i].tdesc.lptdesc->vt | VT_BYREF); - if (info.pVarTypes[i] == VT_USERDEFINED) - info.pVarTypes[i] = AtlGetUserDefinedType(pTypeInfo, pFuncDesc->lprgelemdescParam[i].tdesc.hreftype); - } - - VARTYPE vtReturn = pFuncDesc->elemdescFunc.tdesc.vt; - switch(vtReturn) - { - case VT_INT: - vtReturn = VT_I4; - break; - case VT_UINT: - vtReturn = VT_UI4; - break; - case VT_VOID: - vtReturn = VT_EMPTY; // this is how DispCallFunc() represents void - break; - case VT_HRESULT: - vtReturn = VT_ERROR; - break; - } - info.vtReturn = vtReturn; - info.cc = pFuncDesc->callconv; - info.nParams = pFuncDesc->cParams; - pTypeInfo->ReleaseFuncDesc(pFuncDesc); - return S_OK; -} - -template -class ATL_NO_VTABLE IDispEventImpl : public IDispEventSimpleImpl -{ -public: - typedef tihclass _tihclass; - - IDispEventImpl() - { - m_libid = *plibid; - m_iid = *pdiid; - m_wMajorVerNum = wMajor; - m_wMinorVerNum = wMinor; - } - - STDMETHOD(GetTypeInfoCount)(UINT* pctinfo) - { - if (pctinfo == NULL) - return E_POINTER; - *pctinfo = 1; - return S_OK; - } - - STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo** pptinfo) - {return _tih.GetTypeInfo(itinfo, lcid, pptinfo);} - - STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames, - LCID lcid, DISPID* rgdispid) - {return _tih.GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);} - - //Helper for finding the function index for a DISPID - HRESULT GetFuncInfoFromId(const IID& iid, DISPID dispidMember, LCID lcid, _ATL_FUNC_INFO& info) - { - CComPtr spTypeInfo; - - if (InlineIsEqualGUID(*_tih.m_plibid, GUID_NULL)) - { - m_InnerLibid = m_libid; - m_InnerIid = m_iid; - _tih.m_plibid = &m_InnerLibid; - _tih.m_pguid = &m_InnerIid; - _tih.m_wMajor = m_wMajorVerNum; - _tih.m_wMinor = m_wMinorVerNum; - - } - HRESULT hr = _tih.GetTI(lcid, &spTypeInfo); - if (FAILED(hr)) - return hr; - return AtlGetFuncInfoFromId(spTypeInfo, iid, dispidMember, lcid, info); - } - VARTYPE GetUserDefinedType(ITypeInfo *pTI, HREFTYPE hrt) - { - return AtlGetUserDefinedType(pTI, hrt); - } -protected: - static _tihclass _tih; - static GUID m_InnerLibid; // used for dynamic case - static IID m_InnerIid; // used for dynamic case - static HRESULT GetTI(LCID lcid, ITypeInfo** ppInfo) - {return _tih.GetTI(lcid, ppInfo);} -}; - -template -typename IDispEventImpl::_tihclass -IDispEventImpl::_tih = - {piid, plibid, wMajor, wMinor, NULL, 0, NULL, 0}; - -template -GUID IDispEventImpl::m_InnerLibid=GUID_NULL; - -template -IID IDispEventImpl::m_InnerIid=IID_NULL; - -template -struct _ATL_EVENT_ENTRY -{ - UINT nControlID; //ID identifying object instance - const IID* piid; //dispinterface IID - int nOffset; //offset of dispinterface from this pointer - DISPID dispid; //DISPID of method/property - void (__stdcall T::*pfn)(); //method to invoke - _ATL_FUNC_INFO* pInfo; -}; - - - -//Sink map is used to set up event handling -#define BEGIN_SINK_MAP(_class)\ - typedef _class _GetSinkMapFinder;\ - static const ATL::_ATL_EVENT_ENTRY<_class>* _GetSinkMap()\ - {\ - PTM_WARNING_DISABLE \ - typedef _class _atl_event_classtype;\ - static const ATL::_ATL_EVENT_ENTRY<_class> map[] = { - - - - -#define SINK_ENTRY_INFO(id, iid, dispid, fn, info) {id, &iid, (int)(INT_PTR)(static_cast*>((_atl_event_classtype*)8))-8, dispid, (void (__stdcall _atl_event_classtype::*)())fn, info}, -#define SINK_ENTRY_EX(id, iid, dispid, fn) SINK_ENTRY_INFO(id, iid, dispid, fn, NULL) -#define SINK_ENTRY(id, dispid, fn) SINK_ENTRY_EX(id, IID_NULL, dispid, fn) -#define END_SINK_MAP() \ - {0, NULL, 0, 0, NULL, NULL} }; return map;\ - PTM_WARNING_RESTORE \ - } - -///////////////////////////////////////////////////////////////////////////// -// IDispatchImpl - -template -class ATL_NO_VTABLE IDispatchImpl : public T -{ -public: - typedef tihclass _tihclass; -// IDispatch - STDMETHOD(GetTypeInfoCount)(UINT* pctinfo) - { - if (pctinfo == NULL) - return E_POINTER; - *pctinfo = 1; - return S_OK; - } - STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo** pptinfo) - { - return _tih.GetTypeInfo(itinfo, lcid, pptinfo); - } - STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames, - LCID lcid, DISPID* rgdispid) - { - return _tih.GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid); - } - STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid, - LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, - EXCEPINFO* pexcepinfo, UINT* puArgErr) - { - return _tih.Invoke((IDispatch*)this, dispidMember, riid, lcid, - wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr); - } - -#ifdef _ATL_DLL_IMPL - // Do not cache type info if it is used in atl71.dll - IDispatchImpl() : _tih(piid, plibid, wMajor, wMinor) - { - } - virtual ~IDispatchImpl() - { - } - -protected: - _tihclass _tih; - HRESULT GetTI(LCID lcid, ITypeInfo** ppInfo) - { - return _tih.GetTI(lcid, ppInfo); - } - -#else - -protected: - static _tihclass _tih; - static HRESULT GetTI(LCID lcid, ITypeInfo** ppInfo) - { - return _tih.GetTI(lcid, ppInfo); - } - -#endif - -}; - -#ifndef _ATL_DLL_IMPL - -template -typename IDispatchImpl::_tihclass -IDispatchImpl::_tih = -{piid, plibid, wMajor, wMinor, NULL, 0, NULL, 0}; - -#endif - -///////////////////////////////////////////////////////////////////////////// -// IProvideClassInfoImpl -template -class ATL_NO_VTABLE IProvideClassInfoImpl : public IProvideClassInfo -{ -public: - typedef tihclass _tihclass; - - STDMETHOD(GetClassInfo)(ITypeInfo** pptinfo) - { - return _tih.GetTypeInfo(0, LANG_NEUTRAL, pptinfo); - } - -protected: - static _tihclass _tih; -}; - -template -typename IProvideClassInfoImpl::_tihclass -IProvideClassInfoImpl::_tih = -{pcoclsid,plibid, wMajor, wMinor, NULL, 0, NULL, 0}; - -///////////////////////////////////////////////////////////////////////////// -// IProvideClassInfo2Impl -template -class ATL_NO_VTABLE IProvideClassInfo2Impl : public IProvideClassInfo2 -{ -public: - typedef tihclass _tihclass; - - STDMETHOD(GetClassInfo)(ITypeInfo** pptinfo) - { - return _tih.GetTypeInfo(0, LANG_NEUTRAL, pptinfo); - } - STDMETHOD(GetGUID)(DWORD dwGuidKind, GUID* pGUID) - { - if (pGUID == NULL) - return E_POINTER; - - if (dwGuidKind == GUIDKIND_DEFAULT_SOURCE_DISP_IID && psrcid != NULL) - { - *pGUID = *psrcid; - return S_OK; - } - *pGUID = GUID_NULL; - return E_FAIL; - } - -protected: - static _tihclass _tih; -}; - - -template -typename IProvideClassInfo2Impl::_tihclass -IProvideClassInfo2Impl::_tih = -{pcoclsid,plibid, wMajor, wMinor, NULL, 0, NULL, 0}; - - -///////////////////////////////////////////////////////////////////////////// -// ISupportErrorInfoImpl - -template -class ATL_NO_VTABLE ISupportErrorInfoImpl : public ISupportErrorInfo -{ -public: - STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid) - { - return (InlineIsEqualGUID(riid,*piid)) ? S_OK : S_FALSE; - } -}; - - -///////////////////////////////////////////////////////////////////////////// -// CComEnumImpl - -// These _CopyXXX classes are used with enumerators in order to control -// how enumerated items are initialized, copied, and deleted - -// Default is shallow copy with no special init or cleanup -template -class _Copy -{ -public: - static HRESULT copy(T* p1, const T* p2) { Checked::memcpy_s(p1, sizeof(T), p2, sizeof(T)); return S_OK;} - static void init(T*) {} - static void destroy(T*) {} -}; - -template<> -class _Copy -{ -public: - static HRESULT copy(VARIANT* p1, const VARIANT* p2) {p1->vt = VT_EMPTY; return VariantCopy(p1, const_cast(p2));} - static void init(VARIANT* p) {p->vt = VT_EMPTY;} - static void destroy(VARIANT* p) {VariantClear(p);} -}; - -template<> -class _Copy -{ -public: - static HRESULT copy(LPOLESTR* p1, const LPOLESTR* p2) - { - ATLENSURE(p1 != NULL && p2 != NULL); - HRESULT hr = S_OK; - ULONG len = ocslen(*p2)+1; - (*p1) = (LPOLESTR)::ATL::AtlCoTaskMemCAlloc(len, static_cast(sizeof(OLECHAR))); - if (*p1 == NULL) - { - hr = E_OUTOFMEMORY; - } - else - { - if(!ocscpy_s(*p1, len, *p2)) - { - hr = E_FAIL; - } - } - return hr; - } - static void init(LPOLESTR* p) {*p = NULL;} - static void destroy(LPOLESTR* p) { CoTaskMemFree(*p);} -}; - -template<> -class _Copy -{ -public: - static HRESULT copy(OLEVERB* p1, const OLEVERB* p2) - { - ATLENSURE(p1 != NULL && p2 != NULL); - HRESULT hr = S_OK; - *p1 = *p2; - if (p2->lpszVerbName == NULL) - { - return S_OK; - } - - ULONG len = ocslen(p2->lpszVerbName)+1; - p1->lpszVerbName = (LPOLESTR)::ATL::AtlCoTaskMemCAlloc(len, static_cast(sizeof(OLECHAR))); - if (p1->lpszVerbName == NULL) - { - hr = E_OUTOFMEMORY; - } - else - { - if(!ocscpy_s(p1->lpszVerbName, len, p2->lpszVerbName)) - { - hr = E_FAIL; - } - } - return hr; - } - static void init(OLEVERB* p) { p->lpszVerbName = NULL;} - static void destroy(OLEVERB* p) { if (p->lpszVerbName) CoTaskMemFree(p->lpszVerbName);} -}; - -template<> -class _Copy -{ -public: - static HRESULT copy(CONNECTDATA* p1, const CONNECTDATA* p2) - { - ATLENSURE(p1 != NULL && p2 != NULL); - *p1 = *p2; - if (p1->pUnk) - p1->pUnk->AddRef(); - return S_OK; - } - static void init(CONNECTDATA* ) {} - static void destroy(CONNECTDATA* p) {if (p->pUnk) p->pUnk->Release();} -}; - -template -class _CopyInterface -{ -public: - static HRESULT copy(T** p1, T** p2) - { - ATLENSURE(p1 != NULL && p2 != NULL); - *p1 = *p2; - if (*p1) - (*p1)->AddRef(); - return S_OK; - } - static void init(T** ) {} - static void destroy(T** p) {if (*p) (*p)->Release();} -}; - -template -class ATL_NO_VTABLE CComIEnum : public IUnknown -{ -public: - STDMETHOD(Next)(ULONG celt, T* rgelt, ULONG* pceltFetched) = 0; - STDMETHOD(Skip)(ULONG celt) = 0; - STDMETHOD(Reset)(void) = 0; - STDMETHOD(Clone)(CComIEnum** ppEnum) = 0; -}; - - -enum CComEnumFlags -{ - //see FlagBits in CComEnumImpl - AtlFlagNoCopy = 0, - AtlFlagTakeOwnership = 2, - AtlFlagCopy = 3 // copy implies ownership -}; - -template -class ATL_NO_VTABLE CComEnumImpl : public Base -{ -public: - CComEnumImpl() {m_begin = m_end = m_iter = NULL; m_dwFlags = 0;} - virtual ~CComEnumImpl(); - STDMETHOD(Next)(ULONG celt, T* rgelt, ULONG* pceltFetched); - STDMETHOD(Skip)(ULONG celt); - STDMETHOD(Reset)(void){m_iter = m_begin;return S_OK;} - STDMETHOD(Clone)(Base** ppEnum); - HRESULT Init(T* begin, T* end, IUnknown* pUnk, - CComEnumFlags flags = AtlFlagNoCopy); - CComPtr m_spUnk; - T* m_begin; - T* m_end; - T* m_iter; - DWORD m_dwFlags; -protected: - enum FlagBits - { - BitCopy=1, - BitOwn=2 - }; -}; - -template -CComEnumImpl::~CComEnumImpl() -{ - if (m_dwFlags & BitOwn) - { - for (T* p = m_begin; p != m_end; p++) - Copy::destroy(p); - delete [] m_begin; - } -} - -template -STDMETHODIMP CComEnumImpl::Next(ULONG celt, T* rgelt, - ULONG* pceltFetched) -{ - if (pceltFetched != NULL) - *pceltFetched = 0; - if (celt == 0) - return E_INVALIDARG; - if (rgelt == NULL || (celt != 1 && pceltFetched == NULL)) - return E_POINTER; - if (m_begin == NULL || m_end == NULL || m_iter == NULL) - return E_FAIL; - ULONG nRem = (ULONG)(m_end - m_iter); - HRESULT hRes = S_OK; - if (nRem < celt) - hRes = S_FALSE; - ULONG nMin = celt < nRem ? celt : nRem ; - if (pceltFetched != NULL) - *pceltFetched = nMin; - T* pelt = rgelt; - while(nMin--) - { - HRESULT hr = Copy::copy(pelt, m_iter); - if (FAILED(hr)) - { - while (rgelt < pelt) - Copy::destroy(rgelt++); - if (pceltFetched != NULL) - *pceltFetched = 0; - return hr; - } - pelt++; - m_iter++; - } - return hRes; -} - -template -STDMETHODIMP CComEnumImpl::Skip(ULONG celt) -{ - if (celt == 0) - return E_INVALIDARG; - - ULONG nRem = ULONG(m_end - m_iter); - ULONG nSkip = (celt > nRem) ? nRem : celt; - m_iter += nSkip; - return (celt == nSkip) ? S_OK : S_FALSE; -} - -template -STDMETHODIMP CComEnumImpl::Clone(Base** ppEnum) -{ - typedef CComObject > _class; - HRESULT hRes = E_POINTER; - if (ppEnum != NULL) - { - *ppEnum = NULL; - _class* p; - hRes = _class::CreateInstance(&p); - if (SUCCEEDED(hRes)) - { - // If this object has ownership of the data then we need to keep it around - hRes = p->Init(m_begin, m_end, (m_dwFlags & BitOwn) ? this : m_spUnk); - if (SUCCEEDED(hRes)) - { - p->m_iter = m_iter; - hRes = p->_InternalQueryInterface(*piid, (void**)ppEnum); - } - if (FAILED(hRes)) - delete p; - } - } - return hRes; -} - -template -HRESULT CComEnumImpl::Init(T* begin, T* end, IUnknown* pUnk, - CComEnumFlags flags) -{ - if (flags == AtlFlagCopy) - { - ATLASSUME(m_begin == NULL); //Init called twice? - ATLTRY(m_begin = new T[end-begin]) - m_iter = m_begin; - if (m_begin == NULL) - return E_OUTOFMEMORY; - for (T* i=begin; i != end; i++) - { - Copy::init(m_iter); - HRESULT hr = Copy::copy(m_iter, i); - if (FAILED(hr)) - { - T* p = m_begin; - while (p < m_iter) - Copy::destroy(p++); - delete [] m_begin; - m_begin = m_end = m_iter = NULL; - return hr; - } - m_iter++; - } - m_end = m_begin + (end-begin); - } - else - { - m_begin = begin; - m_end = end; - } - m_spUnk = pUnk; - m_iter = m_begin; - m_dwFlags = flags; - return S_OK; -} - -template -class ATL_NO_VTABLE CComEnum : - public CComEnumImpl, - public CComObjectRootEx< ThreadModel > -{ -public: - typedef CComEnum _CComEnum; - typedef CComEnumImpl _CComEnumBase; - BEGIN_COM_MAP(_CComEnum) - COM_INTERFACE_ENTRY_IID(*piid, _CComEnumBase) - END_COM_MAP() -}; - -template -class ATL_NO_VTABLE IEnumOnSTLImpl : public Base -{ -public: - HRESULT Init(IUnknown *pUnkForRelease, CollType& collection) - { - m_spUnk = pUnkForRelease; - m_pcollection = &collection; - m_iter = m_pcollection->begin(); - return S_OK; - } - STDMETHOD(Next)(ULONG celt, T* rgelt, ULONG* pceltFetched); - STDMETHOD(Skip)(ULONG celt); - STDMETHOD(Reset)(void) - { - if (m_pcollection == NULL) - return E_FAIL; - m_iter = m_pcollection->begin(); - return S_OK; - } - STDMETHOD(Clone)(Base** ppEnum); -//Data - CComPtr m_spUnk; - CollType* m_pcollection; - typename CollType::const_iterator m_iter; -}; - -template -STDMETHODIMP IEnumOnSTLImpl::Next(ULONG celt, T* rgelt, - ULONG* pceltFetched) -{ - if (rgelt == NULL || (celt != 1 && pceltFetched == NULL)) - return E_POINTER; - if (pceltFetched != NULL) - *pceltFetched = 0; - if (m_pcollection == NULL) - return E_FAIL; - - ULONG nActual = 0; - HRESULT hr = S_OK; - T* pelt = rgelt; - while (SUCCEEDED(hr) && m_iter != m_pcollection->end() && nActual < celt) - { - hr = Copy::copy(pelt, &*m_iter); - if (FAILED(hr)) - { - while (rgelt < pelt) - Copy::destroy(rgelt++); - nActual = 0; - } - else - { - pelt++; - m_iter++; - nActual++; - } - } - if (SUCCEEDED(hr)) - { - if (pceltFetched) - *pceltFetched = nActual; - if (nActual < celt) - hr = S_FALSE; - } - return hr; -} - -template -STDMETHODIMP IEnumOnSTLImpl::Skip(ULONG celt) -{ - HRESULT hr = S_OK; - while (celt--) - { - if (m_iter != m_pcollection->end()) - m_iter++; - else - { - hr = S_FALSE; - break; - } - } - return hr; -} - -template -STDMETHODIMP IEnumOnSTLImpl::Clone(Base** ppEnum) -{ - typedef CComObject > _class; - HRESULT hRes = E_POINTER; - if (ppEnum != NULL) - { - *ppEnum = NULL; - _class* p; - hRes = _class::CreateInstance(&p); - if (SUCCEEDED(hRes)) - { - hRes = p->Init(m_spUnk, *m_pcollection); - if (SUCCEEDED(hRes)) - { - p->m_iter = m_iter; - hRes = p->_InternalQueryInterface(*piid, (void**)ppEnum); - } - if (FAILED(hRes)) - delete p; - } - } - return hRes; -} - -template -class ATL_NO_VTABLE CComEnumOnSTL : - public IEnumOnSTLImpl, - public CComObjectRootEx< ThreadModel > -{ -public: - typedef CComEnumOnSTL _CComEnum; - typedef IEnumOnSTLImpl _CComEnumBase; - BEGIN_COM_MAP(_CComEnum) - COM_INTERFACE_ENTRY_IID(*piid, _CComEnumBase) - END_COM_MAP() -}; - -template -class ICollectionOnSTLImpl : public T -{ -public: - STDMETHOD(get_Count)(long* pcount) - { - if (pcount == NULL) - return E_POINTER; - ATLASSUME(m_coll.size()<=LONG_MAX); - - *pcount = (long)m_coll.size(); - - return S_OK; - } - STDMETHOD(get_Item)(long Index, ItemType* pvar) - { - //Index is 1-based - if (pvar == NULL) - return E_POINTER; - if (Index < 1) - return E_INVALIDARG; - HRESULT hr = E_FAIL; - Index--; - CollType::const_iterator iter = m_coll.begin(); - while (iter != m_coll.end() && Index > 0) - { - iter++; - Index--; - } - if (iter != m_coll.end()) - hr = CopyItem::copy(pvar, &*iter); - return hr; - } - STDMETHOD(get__NewEnum)(IUnknown** ppUnk) - { - if (ppUnk == NULL) - return E_POINTER; - *ppUnk = NULL; - HRESULT hRes = S_OK; - CComObject* p; - hRes = CComObject::CreateInstance(&p); - if (SUCCEEDED(hRes)) - { - hRes = p->Init(this, m_coll); - if (hRes == S_OK) - hRes = p->QueryInterface(__uuidof(IUnknown), (void**)ppUnk); - } - if (hRes != S_OK) - delete p; - return hRes; - } - CollType m_coll; -}; - -////////////////////////////////////////////////////////////////////////////// -// ISpecifyPropertyPagesImpl -template -class ATL_NO_VTABLE ISpecifyPropertyPagesImpl : public ISpecifyPropertyPages -{ -public: - // ISpecifyPropertyPages - // - STDMETHOD(GetPages)(CAUUID* pPages) - { - ATLTRACE(atlTraceCOM, 2, _T("ISpecifyPropertyPagesImpl::GetPages\n")); - ATL_PROPMAP_ENTRY* pMap = T::GetPropertyMap(); - return GetPagesHelper(pPages, pMap); - } -protected: - HRESULT GetPagesHelper(CAUUID* pPages, ATL_PROPMAP_ENTRY* pMap) - { - if (pPages == NULL) - return E_POINTER; - ATLASSERT(pMap != NULL); - if (pMap == NULL) - return E_POINTER; - - int nCnt = 0; - int i; - // Get count of unique pages to alloc the array - for (i = 0; pMap[i].pclsidPropPage != NULL; i++) - { - // only allow non data entry types - if (pMap[i].vt == 0) - { - // Does this property have a page? CLSID_NULL means it does not - if (!InlineIsEqualGUID(*pMap[i].pclsidPropPage, CLSID_NULL)) - nCnt++; - } - } - pPages->pElems = (GUID*) ::ATL::AtlCoTaskMemCAlloc(nCnt, static_cast(sizeof(CLSID))); - if (pPages->pElems == NULL) - return E_OUTOFMEMORY; - // reset count of items we have added to the array - nCnt = 0; - for (i = 0; pMap[i].pclsidPropPage != NULL; i++) - { - // only allow non data entry types - if (pMap[i].vt == 0) - { - // Does this property have a page? CLSID_NULL means it does not - if (!InlineIsEqualGUID(*pMap[i].pclsidPropPage, CLSID_NULL)) - { - BOOL bFound = FALSE; - // Search through array we are building up to see - // if it is already in there - for (int j=0; jpElems[j])) - { - // It's already there, so no need to add it again - bFound = TRUE; - break; - } - } - // If we didn't find it in there then add it - if (!bFound) - pPages->pElems[nCnt++] = *pMap[i].pclsidPropPage; - } - } - } - pPages->cElems = nCnt; - return S_OK; - } - -}; - -#ifndef _ATL_NO_CONNECTION_POINTS -///////////////////////////////////////////////////////////////////////////// -// Connection Points - -struct _ATL_CONNMAP_ENTRY -{ - DWORD_PTR dwOffset; -}; - - -// We want the offset of the connection point relative to the connection -// point container base class -#define BEGIN_CONNECTION_POINT_MAP(x)\ - __if_not_exists(_atl_conn_classtype) \ - { \ - typedef x _atl_conn_classtype;\ - } \ - static const ATL::_ATL_CONNMAP_ENTRY* GetConnMap(int* pnEntries) {\ - static const ATL::_ATL_CONNMAP_ENTRY _entries[] = { -#define BEGIN_ATTRCONNECTION_POINT_MAP(x)\ - __if_not_exists(_atl_conn_classtype) \ - { \ - typedef x _atl_conn_classtype;\ - } \ - static const ATL::_ATL_CONNMAP_ENTRY* GetAttrConnMap(int* pnEntries) {\ - static const ATL::_ATL_CONNMAP_ENTRY _entries[] = { - -// CONNECTION_POINT_ENTRY computes the offset of the connection point to the -// IConnectionPointContainer interface -#define CONNECTION_POINT_ENTRY(iid){offsetofclass(ATL::_ICPLocator<&iid>, _atl_conn_classtype)-\ - offsetofclass(ATL::IConnectionPointContainerImpl<_atl_conn_classtype>, _atl_conn_classtype)}, -#define END_CONNECTION_POINT_MAP() \ - __if_exists(GetAttrConnMap) \ - { \ - {(DWORD_PTR) -2}, \ - {(DWORD_PTR) GetAttrConnMap }, \ - } \ - {(DWORD_PTR)-1} }; \ - if (pnEntries) \ - { \ - __if_exists(GetAttrConnMap) \ - { \ - GetAttrConnMap(pnEntries); \ - *pnEntries += sizeof(_entries)/sizeof(ATL::_ATL_CONNMAP_ENTRY) - 3; \ - } \ - __if_not_exists(GetAttrConnMap) \ - { \ - *pnEntries = sizeof(_entries)/sizeof(ATL::_ATL_CONNMAP_ENTRY) - 1; \ - } \ - } \ - return _entries;} -#define END_ATTRCONNECTION_POINT_MAP() \ - {(DWORD_PTR)-1} }; \ - if (pnEntries) \ - { \ - *pnEntries = sizeof(_entries)/sizeof(ATL::_ATL_CONNMAP_ENTRY) - 1; \ - } \ - return _entries;} - - -#ifndef _DEFAULT_VECTORLENGTH -#define _DEFAULT_VECTORLENGTH 4 -#endif - -template -class CComUnkArray -{ -public: - CComUnkArray() - { - memset(m_arr, 0, sizeof(IUnknown*)*nMaxSize); - } - DWORD Add(IUnknown* pUnk); - BOOL Remove(DWORD dwCookie); - // If there is more than one instance of the same IUnknown*, - // this function returns the cookie for the first one. - DWORD WINAPI GetCookie(IUnknown** ppFind) - { - ATLASSERT(ppFind && *ppFind); - if (ppFind && *ppFind) - { - // find IUnknown* in array - for (DWORD dwCookie = 0; dwCookie < nMaxSize; dwCookie++) - { - if (m_arr[dwCookie] == *ppFind) - return dwCookie+1; // cookie minus one is an index into the array - } - } - return 0; - } - IUnknown* WINAPI GetUnknown(DWORD dwCookie) - { - ATLASSERT(dwCookie != 0 && dwCookie <= nMaxSize); - if (dwCookie != 0 && dwCookie <= nMaxSize) - return m_arr[dwCookie-1]; // cookie minus one is an index into the array - else - return NULL; - } - IUnknown** begin() - { - return &m_arr[0]; - } - IUnknown** end() - { - return &m_arr[nMaxSize]; - } -protected: - IUnknown* m_arr[nMaxSize]; -}; - -template -inline DWORD CComUnkArray::Add(IUnknown* pUnk) -{ - DWORD dwCookie = 1; - for (IUnknown** pp = begin(); pp < end(); pp++) - { - if (*pp == NULL) - { - *pp = pUnk; - return dwCookie; - } - aiwdwCookie++; - } - // If this fires then you need a larger array - ATLASSERT(0); - return 0; -} - -template -inline BOOL CComUnkArray::Remove(DWORD dwCookie) -{ - ATLASSERT(dwCookie != 0 && dwCookie <= nMaxSize); - if (dwCookie != 0 && dwCookie <= nMaxSize && m_arr[dwCookie-1] != NULL) - { - m_arr[dwCookie-1] = NULL; - return TRUE; - } - else - return FALSE; -} - -template<> -class CComUnkArray<1> -{ -public: - CComUnkArray() - { - m_arr[0] = NULL; - } - DWORD Add(IUnknown* pUnk) - { - if (m_arr[0] != NULL) - { - // If this fires then you need a larger array - ATLASSERT(0); - return 0; - } - m_arr[0] = pUnk; - return 1; - } - BOOL Remove(DWORD dwCookie) - { - ATLASSERT(dwCookie == 1); - if (dwCookie == 1 && m_arr[0] != NULL) - { - m_arr[0] = NULL; - return TRUE; - } - else - return FALSE; - } - DWORD WINAPI GetCookie(IUnknown** /* pp */) - { - return 1; - } - IUnknown* WINAPI GetUnknown(DWORD dwCookie) - { - ATLASSERT(dwCookie == 1); - if (dwCookie == 1) - return m_arr[0]; - else - return NULL; - } - IUnknown** begin() - { - return &m_arr[0]; - } - IUnknown** end() - { - return (&m_arr[0])+1; - } -protected: - IUnknown* m_arr[1]; -}; - -class CComDynamicUnkArray -{ -public: - CComDynamicUnkArray() - { - m_nSize = 0; - m_ppUnk = NULL; - } - - ~CComDynamicUnkArray() - { - if (m_nSize > 0) - free(m_ppUnk); - } - DWORD Add(IUnknown* pUnk); - BOOL Remove(DWORD dwCookie); - // If there is more than one instance of the same IUnknown*, - // this function returns the cookie for the first one. - DWORD WINAPI GetCookie(IUnknown** ppFind) - { - ATLASSERT(ppFind && *ppFind); - if (ppFind && *ppFind) - { - IUnknown** ppUnk = NULL; - DWORD dwCookie = 1; - // find IUnknown* in array - for (ppUnk = begin(); ppUnk < end(); ppUnk++) - { - if (*ppUnk == *ppFind) - return dwCookie; // cookie minus one is an index into the array - dwCookie++; - } - } - return 0; - } - IUnknown* WINAPI GetUnknown(DWORD dwCookie) - { -#ifndef _ATL_OLEDB_CONFORMANCE_TESTS - ATLASSERT(dwCookie != 0 && dwCookie <= (DWORD)m_nSize); -#endif - if (dwCookie != 0 && dwCookie <= (DWORD)m_nSize) - return GetAt(dwCookie-1); // cookie minus one is an index into the array - else - return NULL; - } - IUnknown** begin() - { - return m_ppUnk; - } - IUnknown** end() - { - return &m_ppUnk[m_nSize]; - } - - IUnknown* GetAt(int nIndex) - { - ATLASSERT(nIndex >= 0 && nIndex < m_nSize); - if (nIndex >= 0 && nIndex < m_nSize) - return m_ppUnk[nIndex]; - else - return NULL; - - } - int GetSize() const - { - return m_nSize; - } - void clear() - { - if (m_nSize > 0) - { - free(m_ppUnk); - m_ppUnk = 0; - } - m_nSize = 0; - } -protected: - IUnknown** m_ppUnk; - int m_nSize; -}; - -inline DWORD CComDynamicUnkArray::Add(IUnknown* pUnk) -{ - IUnknown** pp = NULL; - if (m_nSize == 0) - { - // Create array with _DEFAULT_VECTORLENGTH number of items. - ATLTRY(pp = (IUnknown**)calloc(sizeof(IUnknown*),_DEFAULT_VECTORLENGTH)); - if (pp == NULL) - return 0; - memset(pp, 0, sizeof(IUnknown*)*_DEFAULT_VECTORLENGTH); - m_ppUnk = pp; - m_nSize = _DEFAULT_VECTORLENGTH; - } - // Walk array and use empty slots if any. - DWORD dwCookie = 1; - for (pp = begin(); pp < end(); pp++) - { - if (*pp == NULL) - { - *pp = pUnk; - return dwCookie; // cookie mi nus one is index into array - } - dwCookie++; - } - // No empty slots so resize array. - // # of new slots is double of current size. - int nAlloc = m_nSize*2; - pp = (IUnknown**)_recalloc(m_ppUnk, sizeof(IUnknown*),nAlloc); - if (pp == NULL) - return 0; - m_ppUnk = pp; - memset(&m_ppUnk[m_nSize], 0, sizeof(IUnknown*)*m_nSize); - m_ppUnk[m_nSize] = pUnk; - dwCookie = m_nSize+1; - m_nSize = nAlloc; - return dwCookie; // cookie minus one is index into array -} - -inline BOOL CComDynamicUnkArray::Remove(DWORD dwCookie) -{ - DWORD idx = dwCookie -1; -#ifndef _ATL_OLEDB_CONFORMANCE_TESTS - ATLASSERT(idx < dwCookie && idx < (DWORD)m_nSize); -#endif - if (idx < dwCookie && idx < (DWORD)m_nSize) - { - // cookie minus one is index into array - if (m_ppUnk[idx] == NULL) - return FALSE; - m_ppUnk[idx] = NULL; - return TRUE; - } - else - return FALSE; -} - -template -class ATL_NO_VTABLE _ICPLocator -{ -public: - //this method needs a different name than QueryInterface - STDMETHOD(_LocCPQueryInterface)(REFIID riid, void ** ppvObject) = 0; - virtual ULONG STDMETHODCALLTYPE AddRef(void) = 0; - virtual ULONG STDMETHODCALLTYPE Release(void) = 0; -}; - -template -class ATL_NO_VTABLE IConnectionPointImpl : public _ICPLocator -{ - typedef CComEnum > CComEnumConnections; - typedef CDV _CDV; -public: - ~IConnectionPointImpl(); - STDMETHOD(_LocCPQueryInterface)(REFIID riid, void ** ppvObject) - { -#ifndef _ATL_OLEDB_CONFORMANCE_TESTS - ATLASSERT(ppvObject != NULL); -#endif - if (ppvObject == NULL) - return E_POINTER; - *ppvObject = NULL; - - if (InlineIsEqualGUID(riid, __uuidof(IConnectionPoint)) || InlineIsEqualUnknown(riid)) - { - *ppvObject = this; - AddRef(); -#ifdef _ATL_DEBUG_INTERFACES - _AtlDebugInterfacesModule.AddThunk((IUnknown**)ppvObject, _T("IConnectionPointImpl"), riid); -#endif // _ATL_DEBUG_INTERFACES - return S_OK; - } - else - return E_NOINTERFACE; - } - - STDMETHOD(GetConnectionInterface)(IID* piid2) - { - if (piid2 == NULL) - return E_POINTER; - *piid2 = *piid; - return S_OK; - } - STDMETHOD(GetConnectionPointContainer)(IConnectionPointContainer** ppCPC) - { - T* pT = static_cast(this); - // No need to check ppCPC for NULL since QI will do that for us - return pT->QueryInterface(__uuidof(IConnectionPointContainer), (void**)ppCPC); - } - STDMETHOD(Advise)(IUnknown* pUnkSink, DWORD* pdwCookie); - STDMETHOD(Unadvise)(DWORD dwCookie); - STDMETHOD(EnumConnections)(IEnumConnections** ppEnum); - CDV m_vec; -}; - -template -IConnectionPointImpl::~IConnectionPointImpl() -{ - IUnknown** pp = m_vec.begin(); - while (pp < m_vec.end()) - { - if (*pp != NULL) - (*pp)->Release(); - pp++; - } -} - -template -STDMETHODIMP IConnectionPointImpl::Advise(IUnknown* pUnkSink, - DWORD* pdwCookie) -{ - T* pT = static_cast(this); - IUnknown* p; - HRESULT hRes = S_OK; - if (pdwCookie != NULL) - *pdwCookie = 0; - if (pUnkSink == NULL || pdwCookie == NULL) - return E_POINTER; - IID iid; - GetConnectionInterface(&iid); - hRes = pUnkSink->QueryInterface(iid, (void**)&p); - if (SUCCEEDED(hRes)) - { - pT->Lock(); - *pdwCookie = m_vec.Add(p); - hRes = (*pdwCookie != NULL) ? S_OK : CONNECT_E_ADVISELIMIT; - pT->Unlock(); - if (hRes != S_OK) - p->Release(); - } - else if (hRes == E_NOINTERFACE) - hRes = CONNECT_E_CANNOTCONNECT; - if (FAILED(hRes)) - *pdwCookie = 0; - return hRes; -} - -template -STDMETHODIMP IConnectionPointImpl::Unadvise(DWORD dwCookie) -{ - T* pT = static_cast(this); - pT->Lock(); - IUnknown* p = m_vec.GetUnknown(dwCookie); - HRESULT hRes = m_vec.Remove(dwCookie) ? S_OK : CONNECT_E_NOCONNECTION; - pT->Unlock(); - if (hRes == S_OK && p != NULL) - p->Release(); - return hRes; -} - -#pragma warning(push) -#pragma warning(disable: 6014 6211) -template -STDMETHODIMP IConnectionPointImpl::EnumConnections( - IEnumConnections** ppEnum) -{ - if (ppEnum == NULL) - return E_POINTER; - *ppEnum = NULL; - CComObject* pEnum = NULL; - ATLTRY(pEnum = new CComObject) - if (pEnum == NULL) - return E_OUTOFMEMORY; - T* pT = static_cast(this); - pT->Lock(); - CONNECTDATA* pcd = NULL; - ATLTRY(pcd = new CONNECTDATA[m_vec.end()-m_vec.begin()]) - if (pcd == NULL) - { - delete pEnum; - pT->Unlock(); - return E_OUTOFMEMORY; - } - CONNECTDATA* pend = pcd; - // Copy the valid CONNECTDATA's - for (IUnknown** pp = m_vec.begin();ppAddRef(); - pend->pUnk = *pp; - pend->dwCookie = m_vec.GetCookie(pp); - pend++; - } - } - // don't copy the data, but transfer ownership to it - pEnum->Init(pcd, pend, NULL, AtlFlagTakeOwnership); - pT->Unlock(); - HRESULT hRes = pEnum->_InternalQueryInterface(__uuidof(IEnumConnections), (void**)ppEnum); - if (FAILED(hRes)) - delete pEnum; - return hRes; -} -#pragma warning(pop) - -///////////////////////////////////////////////////////////////////////////// -// IConnectionPointContainerImpl - -template -class ATL_NO_VTABLE IConnectionPointContainerImpl : public IConnectionPointContainer -{ - typedef CComEnum > - CComEnumConnectionPoints; -public: -#pragma warning(push) -#pragma warning(disable: 6014 6211) - STDMETHOD(EnumConnectionPoints)(IEnumConnectionPoints** ppEnum) - { - if (ppEnum == NULL) - return E_POINTER; - *ppEnum = NULL; - CComEnumConnectionPoints* pEnum = NULL; - ATLTRY(pEnum = new CComObject) - if (pEnum == NULL) - return E_OUTOFMEMORY; - - int nCPCount; - const _ATL_CONNMAP_ENTRY* pEntry = T::GetConnMap(&nCPCount); - - // allocate an initialize a vector of connection point object pointers - USES_ATL_SAFE_ALLOCA; - if ((nCPCount < 0) || (nCPCount > (INT_MAX / sizeof(IConnectionPoint*)))) - return E_OUTOFMEMORY; - size_t nBytes=0; - HRESULT hr=S_OK; - if( FAILED(hr=::ATL::AtlMultiply(&nBytes, sizeof(IConnectionPoint*), static_cast(nCPCount)))) - { - return hr; - } - IConnectionPoint** ppCP = (IConnectionPoint**)_ATL_SAFE_ALLOCA(nBytes, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); - if (ppCP == NULL) - { - delete pEnum; - return E_OUTOFMEMORY; - } - - int i = 0; - while (pEntry->dwOffset != (DWORD_PTR)-1) - { - if (pEntry->dwOffset == (DWORD_PTR)-2) - { - pEntry++; - const _ATL_CONNMAP_ENTRY* (*pFunc)(int*) = (const _ATL_CONNMAP_ENTRY* (*)(int*))(pEntry->dwOffset); - pEntry = pFunc(NULL); - continue; - } - ppCP[i++] = (IConnectionPoint*)((INT_PTR)this+pEntry->dwOffset); - pEntry++; - } - - // copy the pointers: they will AddRef this object - HRESULT hRes = pEnum->Init((IConnectionPoint**)&ppCP[0], - (IConnectionPoint**)&ppCP[nCPCount], - reinterpret_cast(this), AtlFlagCopy); - if (FAILED(hRes)) - { - delete pEnum; - return hRes; - } - hRes = pEnum->QueryInterface(__uuidof(IEnumConnectionPoints), (void**)ppEnum); - if (FAILED(hRes)) - delete pEnum; - return hRes; - } -#pragma warning(pop) - - STDMETHOD(FindConnectionPoint)(REFIID riid, IConnectionPoint** ppCP) - { - if (ppCP == NULL) - return E_POINTER; - *ppCP = NULL; - HRESULT hRes = CONNECT_E_NOCONNECTION; - const _ATL_CONNMAP_ENTRY* pEntry = T::GetConnMap(NULL); - IID iid; - while (pEntry->dwOffset != (DWORD_PTR)-1) - { - if (pEntry->dwOffset == (DWORD_PTR)-2) - { - pEntry++; - const _ATL_CONNMAP_ENTRY* (*pFunc)(int*) = (const _ATL_CONNMAP_ENTRY* (*)(int*))(pEntry->dwOffset); - pEntry = pFunc(NULL); - continue; - } - IConnectionPoint* pCP = - (IConnectionPoint*)((INT_PTR)this+pEntry->dwOffset); - if (SUCCEEDED(pCP->GetConnectionInterface(&iid)) && - InlineIsEqualGUID(riid, iid)) - { - *ppCP = pCP; - pCP->AddRef(); - hRes = S_OK; - break; - } - pEntry++; - } - return hRes; - } -}; - -#endif //!_ATL_NO_CONNECTION_POINTS - -///////////////////////////////////////////////////////////////////////////// -// IExternalConnectionImpl - -// An object that implements IExternalConnection should explicitly call -// CoDisconnectObject on itself when its external reference count drops to 0. -// This call will cause the stub manager to call Release on the object so the -// object can destroy itself. - -template -class IExternalConnectionImpl : public IExternalConnection -{ -public: - IExternalConnectionImpl(void) : m_nStrongLocks(0) {} - STDMETHODIMP_(DWORD) AddConnection(DWORD extconn, DWORD /*dwReserved*/) - { - DWORD dw = 0; - if (extconn & EXTCONN_STRONG) - { - dw = T::_ThreadModel::Increment(&m_nStrongLocks); - static_cast(this)->OnAddConnection(dw == 1); - } - return dw; - } - STDMETHODIMP_(DWORD) ReleaseConnection(DWORD extconn, DWORD /*dwReserved*/, BOOL bLastUnlockReleases) - { - DWORD dw = 0; - if (extconn & EXTCONN_STRONG) - { - dw = T::_ThreadModel::Decrement(&m_nStrongLocks); - static_cast(this)->OnReleaseConnection(dw == 0, !!bLastUnlockReleases); - } - return dw; - } - - // Services provided by this class - bool DoIHaveAStub() { return m_nStrongLocks != 0; } - LONG GetStrongConnectionCount() { return m_nStrongLocks; } - // Extensibility points provided by this class - void OnAddConnection(bool bThisIsFirstLock) {} - void OnReleaseConnection(bool bThisIsLastUnlock, bool bLastUnlockReleases) - { - if (bThisIsLastUnlock && bLastUnlockReleases) - CoDisconnectObject(static_cast(this)->GetUnknown(), 0); - } - // Implementation - LONG m_nStrongLocks; -}; - -#pragma pack(pop) - -// All exports go here -#ifndef _ATL_DLL - -///////////////////////////////////////////////////////////////////////////// -// IDispatch Error handling - -ATLINLINE ATLAPI AtlSetErrorInfo(const CLSID& clsid, LPCOLESTR lpszDesc, DWORD dwHelpID, - LPCOLESTR lpszHelpFile, const IID& iid, HRESULT hRes, HINSTANCE hInst) -{ - USES_CONVERSION_EX; - TCHAR szDesc[1024]; - szDesc[0] = NULL; - // For a valid HRESULT the id should be in the range [0x0200, 0xffff] - if (IS_INTRESOURCE(lpszDesc)) //id - { - UINT nID = LOWORD((DWORD_PTR)lpszDesc); - ATLASSERT((nID >= 0x0200 && nID <= 0xffff) || hRes != 0); - if (LoadString(hInst, nID, szDesc, 1024) == 0) - { - ATLASSERT(FALSE); - Checked::tcscpy_s(szDesc, _countof(szDesc), _T("Unknown Error")); - } - lpszDesc = T2OLE_EX(szDesc, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if(lpszDesc == NULL) - return E_OUTOFMEMORY; -#endif - if (hRes == 0) - hRes = MAKE_HRESULT(3, FACILITY_ITF, nID); - } - - CComPtr pICEI; - if (SUCCEEDED(CreateErrorInfo(&pICEI))) - { - CComPtr pErrorInfo; - pICEI->SetGUID(iid); - LPOLESTR lpsz; - ProgIDFromCLSID(clsid, &lpsz); - if (lpsz != NULL) - pICEI->SetSource(lpsz); - if (dwHelpID != 0 && lpszHelpFile != NULL) - { - pICEI->SetHelpContext(dwHelpID); - pICEI->SetHelpFile(const_cast(lpszHelpFile)); - } - CoTaskMemFree(lpsz); - pICEI->SetDescription((LPOLESTR)lpszDesc); - if (SUCCEEDED(pICEI->QueryInterface(__uuidof(IErrorInfo), (void**)&pErrorInfo))) - SetErrorInfo(0, pErrorInfo); - } - return (hRes == 0) ? DISP_E_EXCEPTION : hRes; -} - -///////////////////////////////////////////////////////////////////////////// -// IPersist* helpers. - -ATLINLINE ATLAPI AtlIPersistStreamInit_Load(LPSTREAM pStm, ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk) -{ - ATLASSERT(pMap != NULL); - if (pStm == NULL || pMap == NULL || pThis == NULL || pUnk == NULL) - return E_INVALIDARG; - - HRESULT hr = S_OK; - DWORD dwVer; - hr = pStm->Read(&dwVer, sizeof(DWORD), NULL); - if (FAILED(hr)) - return hr; - if (dwVer > _ATL_VER) - return E_FAIL; - - CComPtr pDispatch; - const IID* piidOld = NULL; - for (int i = 0; pMap[i].pclsidPropPage != NULL; i++) - { - if (pMap[i].szDesc == NULL) - continue; - - // check if raw data entry - if (pMap[i].dwSizeData != 0) - { - void* pData = (void*) (pMap[i].dwOffsetData + (DWORD_PTR)pThis); - // call CComBSTR::ReadFromStream for BSTRs - if (pMap[i].vt == VT_BSTR) - { - CComBSTR bstrRead; - hr = bstrRead.ReadFromStream(pStm); - (*(BSTR*)pData) = bstrRead.Detach(); - } - else - hr = pStm->Read(pData, pMap[i].dwSizeData, NULL); - if (FAILED(hr)) - return hr; - continue; - } - - CComVariant var; - - hr = var.ReadFromStream(pStm); - if (FAILED(hr)) - break; - - if (pMap[i].piidDispatch != piidOld) - { - pDispatch.Release(); - if (FAILED(pUnk->QueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch))) - { - ATLTRACE(atlTraceCOM, 0, _T("Failed to get a dispatch pointer for property #%i\n"), i); - hr = E_FAIL; - break; - } - piidOld = pMap[i].piidDispatch; - } - - if (FAILED(pDispatch.PutProperty(pMap[i].dispid, &var))) - { - ATLTRACE(atlTraceCOM, 0, _T("Invoked failed on DISPID %x\n"), pMap[i].dispid); - hr = E_FAIL; - break; - } - } - return hr; -} - -ATLINLINE ATLAPI AtlIPersistStreamInit_Save(LPSTREAM pStm, - BOOL /* fClearDirty */, ATL_PROPMAP_ENTRY* pMap, - void* pThis, IUnknown* pUnk) -{ - ATLASSERT(pMap != NULL); - if (pStm == NULL || pMap == NULL || pThis == NULL || pUnk == NULL) - return E_INVALIDARG; - - DWORD dw = _ATL_VER; - HRESULT hr = pStm->Write(&dw, sizeof(DWORD), NULL); - if (FAILED(hr)) - return hr; - - CComPtr pDispatch; - const IID* piidOld = NULL; - for (int i = 0; pMap[i].pclsidPropPage != NULL; i++) - { - if (pMap[i].szDesc == NULL) - continue; - - // check if raw data entry - if (pMap[i].dwSizeData != 0) - { - void* pData = (void*) (pMap[i].dwOffsetData + (DWORD_PTR)pThis); - // call CComBSTR::WriteToStream for BSTRs - if (pMap[i].vt == VT_BSTR) - { - CComBSTR bstrWrite; - bstrWrite.Attach(*(BSTR*)pData); - hr = bstrWrite.WriteToStream(pStm); - bstrWrite.Detach(); - } - else - hr = pStm->Write(pData, pMap[i].dwSizeData, NULL); - if (FAILED(hr)) - return hr; - continue; - } - - CComVariant var; - if (pMap[i].piidDispatch != piidOld) - { - pDispatch.Release(); - if (FAILED(pUnk->QueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch))) - { - ATLTRACE(atlTraceCOM, 0, _T("Failed to get a dispatch pointer for property #%i\n"), i); - hr = E_FAIL; - break; - } - piidOld = pMap[i].piidDispatch; - } - - if (FAILED(pDispatch.GetProperty(pMap[i].dispid, &var))) - { - ATLTRACE(atlTraceCOM, 0, _T("Invoked failed on DISPID %x\n"), pMap[i].dispid); - hr = E_FAIL; - break; - } - - hr = var.WriteToStream(pStm); - if (FAILED(hr)) - break; - } - return hr; -} -ATLINLINE ATLAPI AtlIPersistPropertyBag_Load(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog, ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk) -{ - if (pPropBag == NULL || pMap == NULL || pThis == NULL || pUnk == NULL) - return E_INVALIDARG; - - CComPtr pDispatch; - const IID* piidOld = NULL; - for (int i = 0; pMap[i].pclsidPropPage != NULL; i++) - { - if (pMap[i].szDesc == NULL) - continue; - - CComVariant var; - - // If raw entry skip it - we don't handle it for property bags just yet - if (pMap[i].dwSizeData != 0) - { - var.Clear(); - var.vt = pMap[i].vt; - void* pData = (void*) (pMap[i].dwOffsetData + (DWORD_PTR)pThis); - HRESULT hr = pPropBag->Read(pMap[i].szDesc, &var, pErrorLog); - if (SUCCEEDED(hr)) - { - // check the type - we only deal with limited set - switch (pMap[i].vt) - { - case VT_UI1: - case VT_I1: - *((BYTE*)pData) = var.bVal; - break; - case VT_BOOL: - *((VARIANT_BOOL*)pData) = var.boolVal; - break; - case VT_I2: - case VT_UI2: - *((short*)pData) = var.iVal; - break; - case VT_I4: - case VT_UI4: - case VT_INT: - case VT_UINT: - *((long*)pData) = var.lVal; - break; - case VT_BSTR: - *((BSTR*)pData) = ::SysAllocString(var.bstrVal); - if (*((BSTR*)pData) == NULL && var.bstrVal != NULL) - return E_OUTOFMEMORY; - break; - } - } - continue; - } - - if (pMap[i].piidDispatch != piidOld) - { - pDispatch.Release(); - if (FAILED(pUnk->QueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch))) - { - ATLTRACE(atlTraceCOM, 0, _T("Failed to get a dispatch pointer for property #%i\n"), i); - return E_FAIL; - } - piidOld = pMap[i].piidDispatch; - } - - if (FAILED(pDispatch.GetProperty(pMap[i].dispid, &var))) - { - ATLTRACE(atlTraceCOM, 0, _T("Invoked failed on DISPID %x\n"), pMap[i].dispid); - return E_FAIL; - } - - - VARTYPE vt = var.vt; - var.Clear(); - var.vt = vt; - - HRESULT hr = pPropBag->Read(pMap[i].szDesc, &var, pErrorLog); - if (FAILED(hr)) - { -#ifdef _DEBUG - COLE2CT strDesc(pMap[i].szDesc); - LPCTSTR lp = static_cast(strDesc); - - if (hr == E_INVALIDARG) - { - if (lp == NULL) - ATLTRACE(atlTraceCOM, 0, _T("Property not in Bag\n")); - else - ATLTRACE(atlTraceCOM, 0, _T("Property %s not in Bag\n"), lp); - } - else - { - // Many containers return different ERROR values for Member not found - if (lp == NULL) - ATLTRACE(atlTraceCOM, 0, _T("Error attempting to read Property from PropertyBag \n")); - else - ATLTRACE(atlTraceCOM, 0, _T("Error attempting to read Property %s from PropertyBag \n"), lp); - } -#endif - continue; - } - - if (FAILED(pDispatch.PutProperty(pMap[i].dispid, &var))) - { - ATLTRACE(atlTraceCOM, 0, _T("Invoked failed on DISPID %x\n"), pMap[i].dispid); - return E_FAIL; - } - } - return S_OK; -} -ATLINLINE ATLAPI AtlIPersistPropertyBag_Save(LPPROPERTYBAG pPropBag, - BOOL /* fClearDirty */, BOOL /* fSaveAllProperties */, - ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk) -{ - if (pPropBag == NULL) - { - ATLTRACE(atlTraceCOM, 0, _T("PropBag pointer passed in was invalid\n")); - return E_INVALIDARG; - } - if (pMap == NULL || pThis == NULL || pUnk == NULL) - return E_INVALIDARG; - - CComPtr pDispatch; - const IID* piidOld = NULL; - for (int i = 0; pMap[i].pclsidPropPage != NULL; i++) - { - if (pMap[i].szDesc == NULL) - continue; - - CComVariant var; - - // If raw entry skip it - we don't handle it for property bags just yet - if (pMap[i].dwSizeData != 0) - { - void* pData = (void*) (pMap[i].dwOffsetData + (DWORD_PTR)pThis); - // check the type - we only deal with limited set - bool bTypeOK = false; - switch (pMap[i].vt) - { - case VT_UI1: - case VT_I1: - var.bVal = *((BYTE*)pData); - bTypeOK = true; - break; - case VT_BOOL: - var.boolVal = *((VARIANT_BOOL*)pData); - bTypeOK = true; - break; - case VT_UI2: - var.iVal = *((short*)pData); - bTypeOK = true; - break; - case VT_UI4: - case VT_INT: - case VT_UINT: - var.lVal = *((long*)pData); - bTypeOK = true; - break; - case VT_BSTR: - var.bstrVal = ::SysAllocString(*((BSTR*)pData)); - if (var.bstrVal == NULL && *((BSTR*)pData) != NULL) - return E_OUTOFMEMORY; - bTypeOK = true; - break; - } - if (bTypeOK) - { - var.vt = pMap[i].vt; - HRESULT hr = pPropBag->Write(pMap[i].szDesc, &var); - if (FAILED(hr)) - return hr; - } - continue; - } - - if (pMap[i].piidDispatch != piidOld) - { - pDispatch.Release(); - if (FAILED(pUnk->QueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch))) - { - ATLTRACE(atlTraceCOM, 0, _T("Failed to get a dispatch pointer for property #%i\n"), i); - return E_FAIL; - } - piidOld = pMap[i].piidDispatch; - } - - if (FAILED(pDispatch.GetProperty(pMap[i].dispid, &var))) - { - ATLTRACE(atlTraceCOM, 0, _T("Invoked failed on DISPID %x\n"), pMap[i].dispid); - return E_FAIL; - } - - if (var.vt == VT_UNKNOWN || var.vt == VT_DISPATCH) - { - if (var.punkVal == NULL) - { - ATLTRACE(atlTraceCOM, 2, _T("Warning skipping empty IUnknown in Save\n")); - continue; - } - } - - HRESULT hr = pPropBag->Write(pMap[i].szDesc, &var); - if (FAILED(hr)) - return hr; - } - return S_OK; -} - -///////////////////////////////////////////////////////////////////////////// -// Connection Point Sink Helper - -ATLINLINE ATLAPI AtlGetObjectSourceInterface(IUnknown* punkObj, GUID* plibid, IID* piid, unsigned short* pdwMajor, unsigned short* pdwMinor) -{ - if (plibid == NULL || piid == NULL || pdwMajor == NULL || pdwMinor == NULL) - return E_POINTER; - - *plibid = GUID_NULL; - *piid = IID_NULL; - *pdwMajor = 0; - *pdwMinor = 0; - - - HRESULT hr = E_FAIL; - if (punkObj != NULL) - { - CComPtr spDispatch; - hr = punkObj->QueryInterface(__uuidof(IDispatch), (void**)&spDispatch); - if (SUCCEEDED(hr)) - { - CComPtr spTypeInfo; - hr = spDispatch->GetTypeInfo(0, 0, &spTypeInfo); - if (SUCCEEDED(hr)) - { - CComPtr spTypeLib; - hr = spTypeInfo->GetContainingTypeLib(&spTypeLib, 0); - if (SUCCEEDED(hr)) - { - TLIBATTR* plibAttr; - hr = spTypeLib->GetLibAttr(&plibAttr); - if (SUCCEEDED(hr)) - { - Checked::memcpy_s(plibid, sizeof(GUID), &plibAttr->guid, sizeof(GUID)); - *pdwMajor = plibAttr->wMajorVerNum; - *pdwMinor = plibAttr->wMinorVerNum; - spTypeLib->ReleaseTLibAttr(plibAttr); - // First see if the object is willing to tell us about the - // default source interface via IProvideClassInfo2 - CComPtr spProvideClassInfo; - hr = punkObj->QueryInterface(__uuidof(IProvideClassInfo2), (void**)&spProvideClassInfo); - if (SUCCEEDED(hr) && spProvideClassInfo != NULL) - hr = spProvideClassInfo->GetGUID(GUIDKIND_DEFAULT_SOURCE_DISP_IID, piid); - else - { - // No, we have to go hunt for it - CComPtr spInfoCoClass; - // If we have a clsid, use that - // Otherwise, try to locate the clsid from IPersist - CComPtr spPersist; - CLSID clsid; - hr = punkObj->QueryInterface(__uuidof(IPersist), (void**)&spPersist); - if (SUCCEEDED(hr)) - { - hr = spPersist->GetClassID(&clsid); - if (SUCCEEDED(hr)) - { - hr = spTypeLib->GetTypeInfoOfGuid(clsid, &spInfoCoClass); - if (SUCCEEDED(hr)) - { - TYPEATTR* pAttr=NULL; - spInfoCoClass->GetTypeAttr(&pAttr); - if (pAttr != NULL) - { - HREFTYPE hRef; - for (int i = 0; i < pAttr->cImplTypes; i++) - { - int nType; - hr = spInfoCoClass->GetImplTypeFlags(i, &nType); - if (SUCCEEDED(hr)) - { - if (nType == (IMPLTYPEFLAG_FDEFAULT | IMPLTYPEFLAG_FSOURCE)) - { - // we found it - hr = spInfoCoClass->GetRefTypeOfImplType(i, &hRef); - if (SUCCEEDED(hr)) - { - CComPtr spInfo; - hr = spInfoCoClass->GetRefTypeInfo(hRef, &spInfo); - if (SUCCEEDED(hr)) - { - TYPEATTR* pAttrIF; - spInfo->GetTypeAttr(&pAttrIF); - if (pAttrIF != NULL) - { - Checked::memcpy_s(piid, sizeof(GUID), &pAttrIF->guid, sizeof(GUID)); - spInfo->ReleaseTypeAttr(pAttrIF); - } - } - } - break; - } - } - } - spInfoCoClass->ReleaseTypeAttr(pAttr); - } - } - } - } - } - } - } - } - } - } - return hr; -} - -#endif // !_ATL_DLL - -} // namespace ATL -#pragma pack(pop) - -#ifdef _ATL_ALL_WARNINGS -#pragma warning( pop ) -#endif - -#ifndef _ATL_NO_PRAGMA_WARNINGS -#pragma warning (pop) -#endif - -#endif // __ATLCOM_H__ - -///////////////////////////////////////////////////////////////////////////// diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlcomcli.h b/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlcomcli.h deleted file mode 100644 index ca6bfe1f2..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlcomcli.h +++ /dev/null @@ -1,2769 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLCOMCLI_H__ -#define __ATLCOMCLI_H__ - -#pragma once - -#include -#include -#include - -#pragma warning (push) -#pragma warning (disable: 4127) // conditional expression constant -#pragma warning (disable: 4571) //catch(...) blocks compiled with /EHs do NOT catch or re-throw Structured Exceptions - - -#pragma pack(push,_ATL_PACKING) -namespace ATL -{ -///////////////////////////////////////////////////////////////////////////// -// Error to HRESULT helpers - -ATL_NOINLINE inline HRESULT AtlHresultFromLastError() throw() -{ - DWORD dwErr = ::GetLastError(); - return HRESULT_FROM_WIN32(dwErr); -} - -ATL_NOINLINE inline HRESULT AtlHresultFromWin32(__in DWORD nError) throw() -{ - return( HRESULT_FROM_WIN32( nError ) ); -} - -///////////////////////////////////////////////////////////////////////////// -// Smart Pointer helpers - -ATLAPI_(IUnknown*) AtlComPtrAssign(IUnknown** pp, IUnknown* lp); -ATLAPI_(IUnknown*) AtlComQIPtrAssign(IUnknown** pp, IUnknown* lp, REFIID riid); - -#ifndef _ATL_DLL - -ATLINLINE ATLAPI_(IUnknown*) AtlComPtrAssign(__deref_out_opt IUnknown** pp, __in_opt IUnknown* lp) -{ - if (pp == NULL) - return NULL; - - if (lp != NULL) - lp->AddRef(); - if (*pp) - (*pp)->Release(); - *pp = lp; - return lp; -} - -ATLINLINE ATLAPI_(IUnknown*) AtlComQIPtrAssign(__deref_out_opt IUnknown** pp, __in_opt IUnknown* lp, REFIID riid) -{ - if (pp == NULL) - return NULL; - - IUnknown* pTemp = *pp; - *pp = NULL; - if (lp != NULL) - lp->QueryInterface(riid, (void**)pp); - if (pTemp) - pTemp->Release(); - return *pp; -} - -#endif // _ATL_DLL - -///////////////////////////////////////////////////////////////////////////// -// COM Smart pointers - -template -class _NoAddRefReleaseOnCComPtr : public T -{ - private: - STDMETHOD_(ULONG, AddRef)()=0; - STDMETHOD_(ULONG, Release)()=0; -}; - -inline __checkReturn HRESULT AtlSetChildSite(__inout IUnknown* punkChild, __in_opt IUnknown* punkParent) -{ - if (punkChild == NULL) - return E_POINTER; - - HRESULT hr; - IObjectWithSite* pChildSite = NULL; - hr = punkChild->QueryInterface(__uuidof(IObjectWithSite), (void**)&pChildSite); - if (SUCCEEDED(hr) && pChildSite != NULL) - { - hr = pChildSite->SetSite(punkParent); - pChildSite->Release(); - } - return hr; -} - - -//CComPtrBase provides the basis for all other smart pointers -//The other smartpointers add their own constructors and operators -template -class CComPtrBase -{ -protected: - CComPtrBase() throw() - { - p = NULL; - } - CComPtrBase(__in int nNull) throw() - { - ATLASSERT(nNull == 0); - (void)nNull; - p = NULL; - } - CComPtrBase(__in T* lp) throw() - { - p = lp; - if (p != NULL) - p->AddRef(); - } -public: - typedef T _PtrClass; - ~CComPtrBase() throw() - { - if (p) - p->Release(); - } - operator T*() const throw() - { - return p; - } - T& operator*() const - { - ATLENSURE(p!=NULL); - return *p; - } - //The assert on operator& usually indicates a bug. If this is really - //what is needed, however, take the address of the p member explicitly. - T** operator&() throw() - { - ATLASSERT(p==NULL); - return &p; - } - _NoAddRefReleaseOnCComPtr* operator->() const throw() - { - ATLASSERT(p!=NULL); - return (_NoAddRefReleaseOnCComPtr*)p; - } - bool operator!() const throw() - { - return (p == NULL); - } - bool operator<(__in_opt T* pT) const throw() - { - return p < pT; - } - bool operator!=(__in_opt T* pT) const - { - return !operator==(pT); - } - bool operator==(__in_opt T* pT) const throw() - { - return p == pT; - } - - // Release the interface and set to NULL - void Release() throw() - { - T* pTemp = p; - if (pTemp) - { - p = NULL; - pTemp->Release(); - } - } - // Compare two objects for equivalence - bool IsEqualObject(__in_opt IUnknown* pOther) throw() - { - if (p == NULL && pOther == NULL) - return true; // They are both NULL objects - - if (p == NULL || pOther == NULL) - return false; // One is NULL the other is not - - CComPtr punk1; - CComPtr punk2; - p->QueryInterface(__uuidof(IUnknown), (void**)&punk1); - pOther->QueryInterface(__uuidof(IUnknown), (void**)&punk2); - return punk1 == punk2; - } - // Attach to an existing interface (does not AddRef) - void Attach(__in T* p2) throw() - { - if (p) - p->Release(); - p = p2; - } - // Detach the interface (does not Release) - T* Detach() throw() - { - T* pt = p; - p = NULL; - return pt; - } - __checkReturn HRESULT CopyTo(__deref_out_opt T** ppT) throw() - { - ATLASSERT(ppT != NULL); - if (ppT == NULL) - return E_POINTER; - *ppT = p; - if (p) - p->AddRef(); - return S_OK; - } - __checkReturn HRESULT SetSite(__in_opt IUnknown* punkParent) throw() - { - return AtlSetChildSite(p, punkParent); - } - __checkReturn HRESULT Advise(__in IUnknown* pUnk, __in const IID& iid, __out LPDWORD pdw) throw() - { - return AtlAdvise(p, pUnk, iid, pdw); - } - __checkReturn HRESULT CoCreateInstance(__in REFCLSID rclsid, __in_opt LPUNKNOWN pUnkOuter = NULL, __in DWORD dwClsContext = CLSCTX_ALL) throw() - { - ATLASSERT(p == NULL); - return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&p); - } - __checkReturn HRESULT CoCreateInstance(__in LPCOLESTR szProgID, __in_opt LPUNKNOWN pUnkOuter = NULL, __in DWORD dwClsContext = CLSCTX_ALL) throw() - { - CLSID clsid; - HRESULT hr = CLSIDFromProgID(szProgID, &clsid); - ATLASSERT(p == NULL); - if (SUCCEEDED(hr)) - hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&p); - return hr; - } - template - __checkReturn HRESULT QueryInterface(__deref_out_opt Q** pp) const throw() - { - ATLASSERT(pp != NULL); - return p->QueryInterface(__uuidof(Q), (void**)pp); - } - T* p; -}; - -template -class CComPtr : public CComPtrBase -{ -public: - CComPtr() throw() - { - } - CComPtr(int nNull) throw() : - CComPtrBase(nNull) - { - } - CComPtr(T* lp) throw() : - CComPtrBase(lp) - - { - } - CComPtr(__in const CComPtr& lp) throw() : - CComPtrBase(lp.p) - { - } - T* operator=(__in_opt T* lp) throw() - { - if(*this!=lp) - { - return static_cast(AtlComPtrAssign((IUnknown**)&p, lp)); - } - return *this; - } - template - T* operator=(__in const CComPtr& lp) throw() - { - if( !IsEqualObject(lp) ) - { - return static_cast(AtlComQIPtrAssign((IUnknown**)&p, lp, __uuidof(T))); - } - return *this; - } - T* operator=(__in const CComPtr& lp) throw() - { - if(*this!=lp) - { - return static_cast(AtlComPtrAssign((IUnknown**)&p, lp)); - } - return *this; - } -}; - -//specialization for IDispatch -template <> -class CComPtr : public CComPtrBase -{ -public: - CComPtr() throw() - { - } - CComPtr(IDispatch* lp) throw() : - CComPtrBase(lp) - { - } - CComPtr(const CComPtr& lp) throw() : - CComPtrBase(lp.p) - { - } - IDispatch* operator=(IDispatch* lp) throw() - { - if(*this!=lp) - { - return static_cast(AtlComPtrAssign((IUnknown**)&p, lp)); - } - return *this; - } - IDispatch* operator=(const CComPtr& lp) throw() - { - if(*this!=lp) - { - return static_cast(AtlComPtrAssign((IUnknown**)&p, lp.p)); - } - return *this; - } - -// IDispatch specific stuff - __checkReturn HRESULT GetPropertyByName(__in LPCOLESTR lpsz, __out VARIANT* pVar) throw() - { - ATLASSERT(p); - ATLASSERT(pVar); - DISPID dwDispID; - HRESULT hr = GetIDOfName(lpsz, &dwDispID); - if (SUCCEEDED(hr)) - hr = GetProperty(dwDispID, pVar); - return hr; - } - __checkReturn HRESULT GetProperty(__in DISPID dwDispID, __out VARIANT* pVar) throw() - { - return GetProperty(p, dwDispID, pVar); - } - __checkReturn HRESULT PutPropertyByName(__in LPCOLESTR lpsz, __in VARIANT* pVar) throw() - { - ATLASSERT(p); - ATLASSERT(pVar); - DISPID dwDispID; - HRESULT hr = GetIDOfName(lpsz, &dwDispID); - if (SUCCEEDED(hr)) - hr = PutProperty(dwDispID, pVar); - return hr; - } - __checkReturn HRESULT PutProperty(__in DISPID dwDispID, __in VARIANT* pVar) throw() - { - return PutProperty(p, dwDispID, pVar); - } - __checkReturn HRESULT GetIDOfName(__in LPCOLESTR lpsz, __out DISPID* pdispid) throw() - { - return p->GetIDsOfNames(IID_NULL, const_cast(&lpsz), 1, LOCALE_USER_DEFAULT, pdispid); - } - // Invoke a method by DISPID with no parameters - __checkReturn HRESULT Invoke0(__in DISPID dispid, __out_opt VARIANT* pvarRet = NULL) throw() - { - DISPPARAMS dispparams = { NULL, NULL, 0, 0}; - return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL); - } - // Invoke a method by name with no parameters - __checkReturn HRESULT Invoke0(__in LPCOLESTR lpszName, __out_opt VARIANT* pvarRet = NULL) throw() - { - HRESULT hr; - DISPID dispid; - hr = GetIDOfName(lpszName, &dispid); - if (SUCCEEDED(hr)) - hr = Invoke0(dispid, pvarRet); - return hr; - } - // Invoke a method by DISPID with a single parameter - __checkReturn HRESULT Invoke1(__in DISPID dispid, VARIANT* pvarParam1, __out_opt VARIANT* pvarRet = NULL) throw() - { - DISPPARAMS dispparams = { pvarParam1, NULL, 1, 0}; - return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL); - } - // Invoke a method by name with a single parameter - __checkReturn HRESULT Invoke1(__in LPCOLESTR lpszName, VARIANT* pvarParam1, __out_opt VARIANT* pvarRet = NULL) throw() - { - HRESULT hr; - DISPID dispid; - hr = GetIDOfName(lpszName, &dispid); - if (SUCCEEDED(hr)) - hr = Invoke1(dispid, pvarParam1, pvarRet); - return hr; - } - // Invoke a method by DISPID with two parameters - __checkReturn HRESULT Invoke2(__in DISPID dispid, __in VARIANT* pvarParam1, __in VARIANT* pvarParam2, __out_opt VARIANT* pvarRet = NULL) throw(); - // Invoke a method by name with two parameters - __checkReturn HRESULT Invoke2(__in LPCOLESTR lpszName, __in VARIANT* pvarParam1, __in VARIANT* pvarParam2, __out_opt VARIANT* pvarRet = NULL) throw() - { - HRESULT hr; - DISPID dispid; - hr = GetIDOfName(lpszName, &dispid); - if (SUCCEEDED(hr)) - hr = Invoke2(dispid, pvarParam1, pvarParam2, pvarRet); - return hr; - } - // Invoke a method by DISPID with N parameters - __checkReturn HRESULT InvokeN(DISPID dispid, VARIANT* pvarParams, int nParams, VARIANT* pvarRet = NULL) throw() - { - DISPPARAMS dispparams = { pvarParams, NULL, nParams, 0}; - return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL); - } - // Invoke a method by name with Nparameters - __checkReturn HRESULT InvokeN(LPCOLESTR lpszName, VARIANT* pvarParams, int nParams, VARIANT* pvarRet = NULL) throw() - { - HRESULT hr; - DISPID dispid; - hr = GetIDOfName(lpszName, &dispid); - if (SUCCEEDED(hr)) - hr = InvokeN(dispid, pvarParams, nParams, pvarRet); - return hr; - } - static __checkReturn HRESULT PutProperty(__inout IDispatch* p, __in DISPID dwDispID, __in VARIANT* pVar) throw() - { - ATLASSERT(p); - ATLASSERT(pVar != NULL); - if (pVar == NULL) - return E_POINTER; - - if(p == NULL) - return E_INVALIDARG; - - ATLTRACE(atlTraceCOM, 2, _T("CPropertyHelper::PutProperty\n")); - DISPPARAMS dispparams = {NULL, NULL, 1, 1}; - dispparams.rgvarg = pVar; - DISPID dispidPut = DISPID_PROPERTYPUT; - dispparams.rgdispidNamedArgs = &dispidPut; - - if (pVar->vt == VT_UNKNOWN || pVar->vt == VT_DISPATCH || - (pVar->vt & VT_ARRAY) || (pVar->vt & VT_BYREF)) - { - HRESULT hr = p->Invoke(dwDispID, IID_NULL, - LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF, - &dispparams, NULL, NULL, NULL); - if (SUCCEEDED(hr)) - return hr; - } - return p->Invoke(dwDispID, IID_NULL, - LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, - &dispparams, NULL, NULL, NULL); - } - static __checkReturn HRESULT GetProperty(__in IDispatch* p, __in DISPID dwDispID, __out VARIANT* pVar) throw() - { - ATLASSERT(p); - ATLASSERT(pVar != NULL); - if (pVar == NULL) - return E_POINTER; - - if(p == NULL) - return E_INVALIDARG; - - ATLTRACE(atlTraceCOM, 2, _T("CPropertyHelper::GetProperty\n")); - DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0}; - return p->Invoke(dwDispID, IID_NULL, - LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, - &dispparamsNoArgs, pVar, NULL, NULL); - } -}; - -template -class CComQIPtr : public CComPtr -{ -public: - CComQIPtr() throw() - { - } - CComQIPtr(__in T* lp) throw() : - CComPtr(lp) - { - } - CComQIPtr(__in const CComQIPtr& lp) throw() : - CComPtr(lp.p) - { - } - CComQIPtr(__in_opt IUnknown* lp) throw() - { - if (lp != NULL) - lp->QueryInterface(*piid, (void **)&p); - } - T* operator=(__in T* lp) throw() - { - if(*this!=lp) - { - return static_cast(AtlComPtrAssign((IUnknown**)&p, lp)); - } - return *this; - } - T* operator=(__in const CComQIPtr& lp) throw() - { - if(*this!=lp) - { - return static_cast(AtlComPtrAssign((IUnknown**)&p, lp.p)); - } - return *this; - } - T* operator=(__in IUnknown* lp) throw() - { - if(*this!=lp) - { - return static_cast(AtlComQIPtrAssign((IUnknown**)&p, lp, *piid)); - } - return *this; - } -}; - -//Specialization to make it work -template<> -class CComQIPtr : public CComPtr -{ -public: - CComQIPtr() throw() - { - } - CComQIPtr(__in IUnknown* lp) throw() - { - //Actually do a QI to get identity - if (lp != NULL) - lp->QueryInterface(__uuidof(IUnknown), (void **)&p); - } - CComQIPtr(__in const CComQIPtr& lp) throw() : - CComPtr(lp.p) - { - } - IUnknown* operator=(__in IUnknown* lp) throw() - { - if(*this!=lp) - { - //Actually do a QI to get identity - return AtlComQIPtrAssign((IUnknown**)&p, lp, __uuidof(IUnknown)); - } - return *this; - } - - IUnknown* operator=(__in const CComQIPtr& lp) throw() - { - if(*this!=lp) - { - return AtlComPtrAssign((IUnknown**)&p, lp.p); - } - return *this; - } -}; - -typedef CComQIPtr CComDispatchDriver; - -#define com_cast ATL::CComQIPtr - -///////////////////////////////////////////////////////////////////////////// -// CComBSTR - -class CComBSTR -{ -public: - BSTR m_str; - - CComBSTR() throw() - { - m_str = NULL; - } - - CComBSTR(__in int nSize) - { - if (nSize == 0) - m_str = NULL; - else - { - m_str = ::SysAllocStringLen(NULL, nSize); - if (!*this) - { - AtlThrow(E_OUTOFMEMORY); - } - } - } - - CComBSTR(__in int nSize, __in_ecount_opt(nSize) LPCOLESTR sz) - { - if (nSize == 0) - { - m_str = NULL; - } - else - { - m_str = ::SysAllocStringLen(sz, nSize); - if (!*this) - { - AtlThrow(E_OUTOFMEMORY); - } - } - } - - CComBSTR(__in_opt LPCOLESTR pSrc) - { - if (pSrc == NULL) - { - m_str = NULL; - } - else - { - m_str = ::SysAllocString(pSrc); - if (!*this) - { - AtlThrow(E_OUTOFMEMORY); - } - } - } - - CComBSTR(__in const CComBSTR& src) - { - m_str = src.Copy(); - if (!!src && !*this) - { - AtlThrow(E_OUTOFMEMORY); - } - } - - CComBSTR(__in REFGUID guid) - { - OLECHAR szGUID[64]; - ::StringFromGUID2(guid, szGUID, 64); - m_str = ::SysAllocString(szGUID); - if (!*this) - { - AtlThrow(E_OUTOFMEMORY); - } - } - - CComBSTR& operator=(__in const CComBSTR& src) - { - if (m_str != src.m_str) - { - ::SysFreeString(m_str); - m_str = src.Copy(); - if (!!src && !*this) - { - AtlThrow(E_OUTOFMEMORY); - } - } - return *this; - } - - CComBSTR& operator=(__in_opt LPCOLESTR pSrc) - { - if (pSrc != m_str) - { - ::SysFreeString(m_str); - if (pSrc != NULL) - { - m_str = ::SysAllocString(pSrc); - if (!*this) - { - AtlThrow(E_OUTOFMEMORY); - } - } - else - { - m_str = NULL; - } - } - return *this; - } - - ~CComBSTR() throw(); - - unsigned int Length() const throw() - { - return ::SysStringLen(m_str); - } - - unsigned int ByteLength() const throw() - { - return ::SysStringByteLen(m_str); - } - - operator BSTR() const throw() - { - return m_str; - } - - -#ifndef ATL_CCOMBSTR_ADDRESS_OF_ASSERT -// Temp disable CComBSTR::operator& Assert -#define ATL_NO_CCOMBSTR_ADDRESS_OF_ASSERT -#endif - - - BSTR* operator&() throw() - { -#ifndef ATL_NO_CCOMBSTR_ADDRESS_OF_ASSERT -#pragma warning(push) -#pragma warning(disable:4068) -#pragma prefast(push) -#pragma prefast(disable:325, "We are deliberately checking if this has already been allocated") - ATLASSERT(!*this); -#pragma prefast(pop) -#pragma warning(pop) -#endif - return &m_str; - } - - BSTR Copy() const throw() - { - if (!*this) - { - return NULL; - } - return ::SysAllocStringByteLen((char*)m_str, ::SysStringByteLen(m_str)); - } - - __checkReturn HRESULT CopyTo(__inout_opt BSTR* pbstr) throw() - { - ATLASSERT(pbstr != NULL); - if (pbstr == NULL) - { - return E_POINTER; - } - *pbstr = Copy(); -#pragma warning(push) -#pragma warning(disable:4068) -#pragma prefast(push) -#pragma prefast(disable:325, "We are checking allocation semantics here") - if ((*pbstr == NULL) && (m_str != NULL)) - { - return E_OUTOFMEMORY; - } -#pragma prefast(pop) -#pragma warning(pop) - return S_OK; - } - - // copy BSTR to VARIANT - __checkReturn HRESULT CopyTo(__out_opt VARIANT *pvarDest) throw() - { - ATLASSERT(pvarDest != NULL); - HRESULT hRes = E_POINTER; - if (pvarDest != NULL) - { - pvarDest->vt = VT_BSTR; - pvarDest->bstrVal = Copy(); -#pragma warning(push) -#pragma warning(disable:4068) -#pragma prefast(push) -#pragma prefast(disable:325, "We are checking allocation semantics here") - if (pvarDest->bstrVal == NULL && m_str != NULL) - { - hRes = E_OUTOFMEMORY; - } -#pragma prefast(pop) -#pragma warning(pop) - else - { - hRes = S_OK; - } - } - return hRes; - } - - void Attach(__in BSTR src) throw() - { - if (m_str != src) - { - ::SysFreeString(m_str); - m_str = src; - } - } - - BSTR Detach() throw() - { - BSTR s = m_str; - m_str = NULL; - return s; - } - - void Empty() throw() - { - ::SysFreeString(m_str); - m_str = NULL; - } - - bool operator!() const throw() - { -#pragma warning(push) -#pragma warning(disable:4068) -#pragma prefast(push) -#pragma prefast(disable:325, "The semantics of this function are about allocation, not content") - return (m_str == NULL); -#pragma prefast(pop) -#pragma warning(pop) - } - - __checkReturn HRESULT Append(__in const CComBSTR& bstrSrc) throw() - { - return AppendBSTR(bstrSrc.m_str); - } - - __checkReturn HRESULT Append(__in_opt LPCOLESTR lpsz) throw() - { - return Append(lpsz, UINT(ocslen(lpsz))); - } - - // a BSTR is just a LPCOLESTR so we need a special version to signify - // that we are appending a BSTR - __checkReturn HRESULT AppendBSTR(__in BSTR p) throw() - { - if (::SysStringLen(p) == 0) - { - return S_OK; - } - BSTR bstrNew = NULL; - HRESULT hr; - hr = VarBstrCat(m_str, p, &bstrNew); - if (SUCCEEDED(hr)) - { - ::SysFreeString(m_str); - m_str = bstrNew; - } - return hr; - } - - __checkReturn HRESULT Append(__in_ecount_opt(nLen) LPCOLESTR lpsz, __in int nLen) throw() - { -#pragma warning(push) -#pragma warning(disable:4068) -#pragma prefast(push) -#pragma prefast(disable:325, "The semantics of this function are about allocation, not content") - if (lpsz == NULL || (m_str != NULL && nLen == 0)) -#pragma prefast(pop) -#pragma warning(pop) - return S_OK; - int n1 = Length(); - if (n1+nLen < n1) - return E_OUTOFMEMORY; - BSTR b; - b = ::SysAllocStringLen(NULL, n1+nLen); -#pragma warning(push) -#pragma warning(disable:4068) -#pragma prefast(push) -#pragma prefast(disable:325, "The semantics of this function are about allocation, not content") - if (b == NULL) -#pragma prefast(pop) -#pragma warning(pop) - return E_OUTOFMEMORY; - if(::SysStringLen(m_str) > 0) - { - Checked::memcpy_s(b, (n1+nLen)*sizeof(OLECHAR), m_str, n1*sizeof(OLECHAR)); - } - Checked::memcpy_s(b+n1, nLen*sizeof(OLECHAR), lpsz, nLen*sizeof(OLECHAR)); - b[n1+nLen] = NULL; - SysFreeString(m_str); - m_str = b; - return S_OK; - } - - __checkReturn HRESULT Append(__in char ch) throw() - { - OLECHAR chO = ch; - - return( Append( &chO, 1 ) ); - } - - __checkReturn HRESULT Append(__in wchar_t ch) throw() - { - return( Append( &ch, 1 ) ); - } - - __checkReturn HRESULT AppendBytes(__in_ecount_opt(nLen) const char* lpsz, __in int nLen) throw() - { - if (lpsz == NULL || nLen == 0) - return S_OK; - int n1 = ByteLength(); - if (n1+nLen < n1) - return E_OUTOFMEMORY; - BSTR b; - b = ::SysAllocStringByteLen(NULL, n1+nLen); - if (b == NULL) - { - return E_OUTOFMEMORY; - } - Checked::memcpy_s(b, n1+nLen, m_str, n1); - Checked::memcpy_s(((char*)b)+n1, nLen, lpsz, nLen); - *((OLECHAR*)(((char*)b)+n1+nLen)) = NULL; - SysFreeString(m_str); - m_str = b; - return S_OK; - } - - __checkReturn HRESULT AssignBSTR(const BSTR bstrSrc) throw() - { - HRESULT hr = S_OK; - if (m_str != bstrSrc) - { - ::SysFreeString(m_str); -#pragma warning(push) -#pragma warning(disable:4068) -#pragma prefast(push) -#pragma prefast(disable:325, "The semantics of this function are about allocation, not content") - if (bstrSrc != NULL) -#pragma prefast(pop) -#pragma warning(pop) - { - m_str = ::SysAllocStringByteLen((char*)bstrSrc, ::SysStringByteLen(bstrSrc)); - if (!*this) - { - hr = E_OUTOFMEMORY; - } - } - else - { - m_str = NULL; - } - } - - return hr; - } - - __checkReturn HRESULT ToLower() throw() - { - if (::SysStringLen(m_str) > 0) - { -#ifdef _UNICODE - // Convert in place - CharLowerBuff(m_str, Length()); -#else - // Cannot use conversion macros due to possible embedded NULLs - UINT _acp = _AtlGetConversionACP(); - int _convert = WideCharToMultiByte(_acp, 0, m_str, Length(), NULL, 0, NULL, NULL); - CTempBuffer pszA; - ATLTRY(pszA.Allocate(_convert)); - if (pszA == NULL) - return E_OUTOFMEMORY; - - int nRet = WideCharToMultiByte(_acp, 0, m_str, Length(), pszA, _convert, NULL, NULL); - if (nRet == 0) - { - ATLASSERT(0); - return AtlHresultFromLastError(); - } - - CharLowerBuff(pszA, nRet); - - _convert = MultiByteToWideChar(_acp, 0, pszA, nRet, NULL, 0); - - CTempBuffer pszW; - ATLTRY(pszW.Allocate(_convert)); - if (pszW == NULL) - return E_OUTOFMEMORY; - - nRet = MultiByteToWideChar(_acp, 0, pszA, nRet, pszW, _convert); - if (nRet <= 0) - { - ATLASSERT(0); - return AtlHresultFromLastError(); - } - - UINT nBytes=0; - HRESULT hr=S_OK; - if( FAILED(hr=::ATL::AtlMultiply(&nBytes, static_cast(nRet), static_cast(sizeof(OLECHAR))))) - { - return hr; - } - BSTR b = ::SysAllocStringByteLen((LPCSTR) (LPWSTR) pszW, nBytes); - if (b == NULL) - return E_OUTOFMEMORY; - SysFreeString(m_str); - m_str = b; -#endif - } - return S_OK; - } - __checkReturn HRESULT ToUpper() throw() - { - if (::SysStringLen(m_str) > 0) - { -#ifdef _UNICODE - // Convert in place - CharUpperBuff(m_str, Length()); -#else - // Cannot use conversion macros due to possible embedded NULLs - UINT _acp = _AtlGetConversionACP(); - int _convert = WideCharToMultiByte(_acp, 0, m_str, Length(), NULL, 0, NULL, NULL); - CTempBuffer pszA; - ATLTRY(pszA.Allocate(_convert)); - if (pszA == NULL) - return E_OUTOFMEMORY; - - int nRet = WideCharToMultiByte(_acp, 0, m_str, Length(), pszA, _convert, NULL, NULL); - if (nRet == 0) - { - ATLASSERT(0); - return AtlHresultFromLastError(); - } - - CharUpperBuff(pszA, nRet); - - _convert = MultiByteToWideChar(_acp, 0, pszA, nRet, NULL, 0); - - CTempBuffer pszW; - ATLTRY(pszW.Allocate(_convert)); - if (pszW == NULL) - return E_OUTOFMEMORY; - - nRet = MultiByteToWideChar(_acp, 0, pszA, nRet, pszW, _convert); - if (nRet <= 0) - { - ATLASSERT(0); - return AtlHresultFromLastError(); - } - - UINT nBytes=0; - HRESULT hr=S_OK; - if( FAILED(hr=::ATL::AtlMultiply(&nBytes, static_cast(nRet), static_cast(sizeof(OLECHAR))))) - { - return hr; - } - BSTR b = ::SysAllocStringByteLen((LPCSTR) (LPWSTR) pszW, nBytes); - if (b == NULL) - return E_OUTOFMEMORY; - SysFreeString(m_str); - m_str = b; -#endif - } - return S_OK; - } - - bool LoadString(__in HINSTANCE hInst, __in UINT nID) throw() - { - ::SysFreeString(m_str); - m_str = NULL; - return LoadStringResource(hInst, nID, m_str); - } - - bool LoadString(__in UINT nID) throw() - { - ::SysFreeString(m_str); - m_str = NULL; - return LoadStringResource(nID, m_str); - } - - CComBSTR& operator+=(__in const CComBSTR& bstrSrc) - { - HRESULT hr; - hr = AppendBSTR(bstrSrc.m_str); - if (FAILED(hr)) - AtlThrow(hr); - return *this; - } - - CComBSTR& operator+=(__in_opt LPCOLESTR pszSrc) - { - HRESULT hr; - hr = Append(pszSrc); - if (FAILED(hr)) - AtlThrow(hr); - return *this; - } - - bool operator<(const CComBSTR& bstrSrc) const throw() - { - return VarBstrCmp(m_str, bstrSrc.m_str, LOCALE_USER_DEFAULT, 0) == static_cast(VARCMP_LT); - } - bool operator<(LPCOLESTR pszSrc) const - { - CComBSTR bstr2(pszSrc); - return operator<(bstr2); - } - bool operator<(LPOLESTR pszSrc) const - { - return operator<((LPCOLESTR)pszSrc); - } - - bool operator>(const CComBSTR& bstrSrc) const throw() - { - return VarBstrCmp(m_str, bstrSrc.m_str, LOCALE_USER_DEFAULT, 0) == static_cast(VARCMP_GT); - } - bool operator>(LPCOLESTR pszSrc) const - { - CComBSTR bstr2(pszSrc); - return operator>(bstr2); - } - bool operator>(LPOLESTR pszSrc) const - { - return operator>((LPCOLESTR)pszSrc); - } - - bool operator!=(const CComBSTR& bstrSrc) const throw() - { - return !operator==(bstrSrc); - } - bool operator!=(LPCOLESTR pszSrc) const - { - return !operator==(pszSrc); - } - bool operator!=(int nNull) const throw() - { - return !operator==(nNull); - } - bool operator!=(LPOLESTR pszSrc) const - { - return operator!=((LPCOLESTR)pszSrc); - } - - bool operator==(const CComBSTR& bstrSrc) const throw() - { - return VarBstrCmp(m_str, bstrSrc.m_str, LOCALE_USER_DEFAULT, 0) == static_cast(VARCMP_EQ); - } - bool operator==(LPCOLESTR pszSrc) const - { - CComBSTR bstr2(pszSrc); - return operator==(bstr2); - } - bool operator==(LPOLESTR pszSrc) const - { - return operator==((LPCOLESTR)pszSrc); - } - - bool operator==(int nNull) const throw() - { - ATLASSERT(nNull == NULL); - (void)nNull; - return (!*this); - } - - CComBSTR(__in LPCSTR pSrc) - { - if (pSrc != NULL) - { - m_str = A2WBSTR(pSrc); - if (!*this) - { - AtlThrow(E_OUTOFMEMORY); - } - } - else - { - m_str = NULL; - } - } - - CComBSTR(__in int nSize, __in_ecount_opt(nSize) LPCSTR sz) - { - if (nSize != 0 && sz == NULL) - { - m_str = ::SysAllocStringLen(NULL, nSize); - if (!*this) - { - AtlThrow(E_OUTOFMEMORY); - } - return; - } - - m_str = A2WBSTR(sz, nSize); - if (!*this && nSize != 0) - { - AtlThrow(E_OUTOFMEMORY); - } - } - - __checkReturn HRESULT Append(__in LPCSTR lpsz) throw() - { - if (lpsz == NULL) - return S_OK; - - CComBSTR bstrTemp; - ATLTRY(bstrTemp = lpsz); - if (!bstrTemp) - { - return E_OUTOFMEMORY; - } - return Append(bstrTemp); - } - - CComBSTR& operator=(__in LPCSTR pSrc) - { - ::SysFreeString(m_str); - m_str = A2WBSTR(pSrc); - if (!*this && pSrc != NULL) - { - AtlThrow(E_OUTOFMEMORY); - } - return *this; - } - - bool operator<(__in LPCSTR pszSrc) const - { - CComBSTR bstr2(pszSrc); - return operator<(bstr2); - } - bool operator>(__in LPCSTR pszSrc) const - { - CComBSTR bstr2(pszSrc); - return operator>(bstr2); - } - bool operator!=(__in LPCSTR pszSrc) const - { - return !operator==(pszSrc); - } - bool operator==(__in LPCSTR pszSrc) const - { - CComBSTR bstr2(pszSrc); - return operator==(bstr2); - } - - __checkReturn HRESULT WriteToStream(__inout IStream* pStream) throw() - { - ATLASSERT(pStream != NULL); - if(pStream == NULL) - return E_INVALIDARG; - - ULONG cb; - ULONG cbStrLen = CComBSTR::GetStreamSize(m_str) - sizeof(ULONG); - HRESULT hr = pStream->Write((void*) &cbStrLen, sizeof(cbStrLen), &cb); - if (FAILED(hr)) - return hr; - return cbStrLen ? pStream->Write((void*) m_str, cbStrLen, &cb) : S_OK; - } - - __checkReturn HRESULT ReadFromStream(__inout IStream* pStream) throw() - { - ATLASSERT(pStream != NULL); - if(pStream == NULL) - return E_INVALIDARG; - - ATLASSERT(!*this); // should be empty - Empty(); - - ULONG cbStrLen = 0; - HRESULT hr = pStream->Read((void*) &cbStrLen, sizeof(cbStrLen), NULL); - if ((hr == S_OK) && (cbStrLen != 0)) - { - //subtract size for terminating NULL which we wrote out - //since SysAllocStringByteLen overallocates for the NULL - m_str = SysAllocStringByteLen(NULL, cbStrLen-sizeof(OLECHAR)); - if (!*this) - { - hr = E_OUTOFMEMORY; - } - else - { - hr = pStream->Read((void*) m_str, cbStrLen, NULL); - } - // If SysAllocStringByteLen or IStream::Read failed, reset seek - // pointer to start of BSTR size. - if (hr != S_OK) - { - LARGE_INTEGER nOffset; - nOffset.QuadPart = -(static_cast(sizeof(cbStrLen))); - pStream->Seek(nOffset, STREAM_SEEK_CUR, NULL); - } - } - if (hr == S_FALSE) - hr = E_FAIL; - return hr; - } - - static bool LoadStringResource(__in HINSTANCE hInstance, __in UINT uID, __deref_out_opt BSTR& bstrText) throw() - { - const ATLSTRINGRESOURCEIMAGE* pImage; - -#pragma warning(push) -#pragma warning(disable:4068) -#pragma prefast(push) -#pragma prefast(disable:325, "The semantics of this function are about allocation, not content") - ATLASSERT(bstrText == NULL); -#pragma prefast(pop) -#pragma warning(pop) - - pImage = AtlGetStringResourceImage(hInstance, uID); - if (pImage != NULL) - { - bstrText = ::SysAllocStringLen(pImage->achString, pImage->nLength); - } -#pragma warning(push) -#pragma warning(disable:4068) -#pragma prefast(push) -#pragma prefast(disable:325, "The semantics of this function are about allocation, not content") - return (bstrText != NULL) ? true : false; -#pragma prefast(pop) -#pragma warning(pop) - } - - static bool LoadStringResource(__in UINT uID, __deref_out_opt BSTR& bstrText) throw() - { - const ATLSTRINGRESOURCEIMAGE* pImage; - -#pragma warning(push) -#pragma warning(disable:4068) -#pragma prefast(push) -#pragma prefast(disable:325, "The semantics of this function are about allocation, not content") - ATLASSERT(bstrText == NULL); -#pragma prefast(pop) -#pragma warning(pop) - - pImage = AtlGetStringResourceImage(uID); - if (pImage != NULL) - { - bstrText = ::SysAllocStringLen(pImage->achString, pImage->nLength); - } - -#pragma warning(push) -#pragma warning(disable:4068) -#pragma prefast(push) -#pragma prefast(disable:325, "The semantics of this function are about allocation, not content") - return (bstrText != NULL) ? true : false; -#pragma prefast(pop) -#pragma warning(pop) - } - - // each character in BSTR is copied to each element in SAFEARRAY - __success(SUCCEEDED(return)) HRESULT BSTRToArray(__deref_out LPSAFEARRAY *ppArray) throw() - { - return VectorFromBstr(m_str, ppArray); - } - - // first character of each element in SAFEARRAY is copied to BSTR - __checkReturn HRESULT ArrayToBSTR(__in const SAFEARRAY *pSrc) throw() - { - ::SysFreeString(m_str); - return BstrFromVector((LPSAFEARRAY)pSrc, &m_str); - } - static ULONG GetStreamSize(BSTR bstr) - { - ULONG ulSize=sizeof(ULONG); -#pragma warning(push) -#pragma warning(disable:4068) -#pragma prefast(push) -#pragma prefast(disable:325, "The semantics of this function are about allocation, not content") - if (bstr != NULL) -#pragma prefast(pop) -#pragma warning(pop) - { - ulSize += SysStringByteLen(bstr) + sizeof(OLECHAR); - } - return ulSize; - } -}; - -inline CComBSTR::~CComBSTR() throw() - { - ::SysFreeString(m_str); - } - -inline void SysFreeStringHelper(__in CComBSTR& bstr) -{ - bstr.Empty(); -} - -inline void SysFreeStringHelper(BSTR bstr) -{ - ::SysFreeString(bstr); -} - -inline __checkReturn HRESULT SysAllocStringHelper(__out_opt CComBSTR& bstrDest,BSTR bstrSrc) -{ - bstrDest=bstrSrc; - return !bstrDest ? E_OUTOFMEMORY : S_OK; -} - -inline __checkReturn HRESULT SysAllocStringHelper(__out_opt BSTR& bstrDest,BSTR bstrSrc) -{ - bstrDest=::SysAllocString(bstrSrc); -#pragma warning(push) -#pragma warning(disable:4068) -#pragma prefast(push) -#pragma prefast(disable:325, "The semantics of this function are about allocation, not content") - return bstrDest==NULL ? E_OUTOFMEMORY : S_OK; -#pragma prefast(pop) -#pragma warning(pop) -} - -///////////////////////////////////////////////////////////// -// Class to Adapt CComBSTR and CComPtr for use with STL containers -// the syntax to use it is -// std::vector< CAdapt > vect; - -template -class CAdapt -{ -public: - CAdapt() - { - } - CAdapt(__in const T& rSrc) : - m_T( rSrc ) - { - } - - CAdapt(__in const CAdapt& rSrCA) : - m_T( rSrCA.m_T ) - { - } - - CAdapt& operator=(__in const T& rSrc) - { - m_T = rSrc; - return *this; - } - bool operator<(__in const T& rSrc) const - { - return m_T < rSrc; - } - bool operator==(__in const T& rSrc) const - { - return m_T == rSrc; - } - operator T&() - { - return m_T; - } - - operator const T&() const - { - return m_T; - } - - T m_T; -}; - -///////////////////////////////////////////////////////////////////////////// -// CComVariant - - -#define ATL_VARIANT_TRUE VARIANT_BOOL( -1 ) -#define ATL_VARIANT_FALSE VARIANT_BOOL( 0 ) - -template< typename T > -class CVarTypeInfo -{ -// static const VARTYPE VT; // VARTYPE corresponding to type T -// static T VARIANT::* const pmField; // Pointer-to-member of corresponding field in VARIANT struct -}; - -template<> -class CVarTypeInfo< char > -{ -public: - static const VARTYPE VT = VT_I1; - static char VARIANT::* const pmField; -}; - -__declspec( selectany ) char VARIANT::* const CVarTypeInfo< char >::pmField = &VARIANT::cVal; - -template<> -class CVarTypeInfo< unsigned char > -{ -public: - static const VARTYPE VT = VT_UI1; - static unsigned char VARIANT::* const pmField; -}; - -__declspec( selectany ) unsigned char VARIANT::* const CVarTypeInfo< unsigned char >::pmField = &VARIANT::bVal; - -template<> -class CVarTypeInfo< char* > -{ -public: - static const VARTYPE VT = VT_I1|VT_BYREF; - static char* VARIANT::* const pmField; -}; - -__declspec( selectany ) char* VARIANT::* const CVarTypeInfo< char* >::pmField = &VARIANT::pcVal; - -template<> -class CVarTypeInfo< unsigned char* > -{ -public: - static const VARTYPE VT = VT_UI1|VT_BYREF; - static unsigned char* VARIANT::* const pmField; -}; - -__declspec( selectany ) unsigned char* VARIANT::* const CVarTypeInfo< unsigned char* >::pmField = &VARIANT::pbVal; - -template<> -class CVarTypeInfo< short > -{ -public: - static const VARTYPE VT = VT_I2; - static short VARIANT::* const pmField; -}; - -__declspec( selectany ) short VARIANT::* const CVarTypeInfo< short >::pmField = &VARIANT::iVal; - -template<> -class CVarTypeInfo< short* > -{ -public: - static const VARTYPE VT = VT_I2|VT_BYREF; - static short* VARIANT::* const pmField; -}; - -__declspec( selectany ) short* VARIANT::* const CVarTypeInfo< short* >::pmField = &VARIANT::piVal; - -template<> -class CVarTypeInfo< unsigned short > -{ -public: - static const VARTYPE VT = VT_UI2; - static unsigned short VARIANT::* const pmField; -}; - -__declspec( selectany ) unsigned short VARIANT::* const CVarTypeInfo< unsigned short >::pmField = &VARIANT::uiVal; - -#ifdef _NATIVE_WCHAR_T_DEFINED // Only treat unsigned short* as VT_UI2|VT_BYREF if BSTR isn't the same as unsigned short* -template<> -class CVarTypeInfo< unsigned short* > -{ -public: - static const VARTYPE VT = VT_UI2|VT_BYREF; - static unsigned short* VARIANT::* const pmField; -}; - -__declspec( selectany ) unsigned short* VARIANT::* const CVarTypeInfo< unsigned short* >::pmField = &VARIANT::puiVal; -#endif // _NATIVE_WCHAR_T_DEFINED - -template<> -class CVarTypeInfo< int > -{ -public: - static const VARTYPE VT = VT_I4; - static int VARIANT::* const pmField; -}; - -__declspec( selectany ) int VARIANT::* const CVarTypeInfo< int >::pmField = &VARIANT::intVal; - -template<> -class CVarTypeInfo< int* > -{ -public: - static const VARTYPE VT = VT_I4|VT_BYREF; - static int* VARIANT::* const pmField; -}; - -__declspec( selectany ) int* VARIANT::* const CVarTypeInfo< int* >::pmField = &VARIANT::pintVal; - -template<> -class CVarTypeInfo< unsigned int > -{ -public: - static const VARTYPE VT = VT_UI4; - static unsigned int VARIANT::* const pmField; -}; - -__declspec( selectany ) unsigned int VARIANT::* const CVarTypeInfo< unsigned int >::pmField = &VARIANT::uintVal; - -template<> -class CVarTypeInfo< unsigned int* > -{ -public: - static const VARTYPE VT = VT_UI4|VT_BYREF; - static unsigned int* VARIANT::* const pmField; -}; - -__declspec( selectany ) unsigned int* VARIANT::* const CVarTypeInfo< unsigned int* >::pmField = &VARIANT::puintVal; - -template<> -class CVarTypeInfo< long > -{ -public: - static const VARTYPE VT = VT_I4; - static long VARIANT::* const pmField; -}; - -__declspec( selectany ) long VARIANT::* const CVarTypeInfo< long >::pmField = &VARIANT::lVal; - -template<> -class CVarTypeInfo< long* > -{ -public: - static const VARTYPE VT = VT_I4|VT_BYREF; - static long* VARIANT::* const pmField; -}; - -__declspec( selectany ) long* VARIANT::* const CVarTypeInfo< long* >::pmField = &VARIANT::plVal; - -template<> -class CVarTypeInfo< unsigned long > -{ -public: - static const VARTYPE VT = VT_UI4; - static unsigned long VARIANT::* const pmField; -}; - -__declspec( selectany ) unsigned long VARIANT::* const CVarTypeInfo< unsigned long >::pmField = &VARIANT::ulVal; - -template<> -class CVarTypeInfo< unsigned long* > -{ -public: - static const VARTYPE VT = VT_UI4|VT_BYREF; - static unsigned long* VARIANT::* const pmField; -}; - -__declspec( selectany ) unsigned long* VARIANT::* const CVarTypeInfo< unsigned long* >::pmField = &VARIANT::pulVal; - -template<> -class CVarTypeInfo< __int64 > -{ -public: - static const VARTYPE VT = VT_I8; - static __int64 VARIANT::* const pmField; -}; - -__declspec( selectany ) __int64 VARIANT::* const CVarTypeInfo< __int64 >::pmField = &VARIANT::llVal; - -template<> -class CVarTypeInfo< __int64* > -{ -public: - static const VARTYPE VT = VT_I8|VT_BYREF; - static __int64* VARIANT::* const pmField; -}; - -__declspec( selectany ) __int64* VARIANT::* const CVarTypeInfo< __int64* >::pmField = &VARIANT::pllVal; - -template<> -class CVarTypeInfo< unsigned __int64 > -{ -public: - static const VARTYPE VT = VT_UI8; - static unsigned __int64 VARIANT::* const pmField; -}; - -__declspec( selectany ) unsigned __int64 VARIANT::* const CVarTypeInfo< unsigned __int64 >::pmField = &VARIANT::ullVal; - -template<> -class CVarTypeInfo< unsigned __int64* > -{ -public: - static const VARTYPE VT = VT_UI8|VT_BYREF; - static unsigned __int64* VARIANT::* const pmField; -}; - -__declspec( selectany ) unsigned __int64* VARIANT::* const CVarTypeInfo< unsigned __int64* >::pmField = &VARIANT::pullVal; - -template<> -class CVarTypeInfo< float > -{ -public: - static const VARTYPE VT = VT_R4; - static float VARIANT::* const pmField; -}; - -__declspec( selectany ) float VARIANT::* const CVarTypeInfo< float >::pmField = &VARIANT::fltVal; - -template<> -class CVarTypeInfo< float* > -{ -public: - static const VARTYPE VT = VT_R4|VT_BYREF; - static float* VARIANT::* const pmField; -}; - -__declspec( selectany ) float* VARIANT::* const CVarTypeInfo< float* >::pmField = &VARIANT::pfltVal; - -template<> -class CVarTypeInfo< double > -{ -public: - static const VARTYPE VT = VT_R8; - static double VARIANT::* const pmField; -}; - -__declspec( selectany ) double VARIANT::* const CVarTypeInfo< double >::pmField = &VARIANT::dblVal; - -template<> -class CVarTypeInfo< double* > -{ -public: - static const VARTYPE VT = VT_R8|VT_BYREF; - static double* VARIANT::* const pmField; -}; - -__declspec( selectany ) double* VARIANT::* const CVarTypeInfo< double* >::pmField = &VARIANT::pdblVal; - -template<> -class CVarTypeInfo< VARIANT > -{ -public: - static const VARTYPE VT = VT_VARIANT; -}; - -template<> -class CVarTypeInfo< BSTR > -{ -public: - static const VARTYPE VT = VT_BSTR; - static BSTR VARIANT::* const pmField; -}; - -__declspec( selectany ) BSTR VARIANT::* const CVarTypeInfo< BSTR >::pmField = &VARIANT::bstrVal; - -template<> -class CVarTypeInfo< BSTR* > -{ -public: - static const VARTYPE VT = VT_BSTR|VT_BYREF; - static BSTR* VARIANT::* const pmField; -}; - -__declspec( selectany ) BSTR* VARIANT::* const CVarTypeInfo< BSTR* >::pmField = &VARIANT::pbstrVal; - -template<> -class CVarTypeInfo< IUnknown* > -{ -public: - static const VARTYPE VT = VT_UNKNOWN; - static IUnknown* VARIANT::* const pmField; -}; - -__declspec( selectany ) IUnknown* VARIANT::* const CVarTypeInfo< IUnknown* >::pmField = &VARIANT::punkVal; - -template<> -class CVarTypeInfo< IUnknown** > -{ -public: - static const VARTYPE VT = VT_UNKNOWN|VT_BYREF; - static IUnknown** VARIANT::* const pmField; -}; - -__declspec( selectany ) IUnknown** VARIANT::* const CVarTypeInfo< IUnknown** >::pmField = &VARIANT::ppunkVal; - -template<> -class CVarTypeInfo< IDispatch* > -{ -public: - static const VARTYPE VT = VT_DISPATCH; - static IDispatch* VARIANT::* const pmField; -}; - -__declspec( selectany ) IDispatch* VARIANT::* const CVarTypeInfo< IDispatch* >::pmField = &VARIANT::pdispVal; - -template<> -class CVarTypeInfo< IDispatch** > -{ -public: - static const VARTYPE VT = VT_DISPATCH|VT_BYREF; - static IDispatch** VARIANT::* const pmField; -}; - -__declspec( selectany ) IDispatch** VARIANT::* const CVarTypeInfo< IDispatch** >::pmField = &VARIANT::ppdispVal; - -template<> -class CVarTypeInfo< CY > -{ -public: - static const VARTYPE VT = VT_CY; - static CY VARIANT::* const pmField; -}; - -__declspec( selectany ) CY VARIANT::* const CVarTypeInfo< CY >::pmField = &VARIANT::cyVal; - -template<> -class CVarTypeInfo< CY* > -{ -public: - static const VARTYPE VT = VT_CY|VT_BYREF; - static CY* VARIANT::* const pmField; -}; - -__declspec( selectany ) CY* VARIANT::* const CVarTypeInfo< CY* >::pmField = &VARIANT::pcyVal; - -class CComVariant : public tagVARIANT -{ -// Constructors -public: - CComVariant() throw() - { - ::VariantInit(this); - } - ~CComVariant() throw() - { - Clear(); - } - - CComVariant(__in const VARIANT& varSrc) - { - vt = VT_EMPTY; - InternalCopy(&varSrc); - } - - CComVariant(__in const CComVariant& varSrc) - { - vt = VT_EMPTY; - InternalCopy(&varSrc); - } - CComVariant(__in LPCOLESTR lpszSrc) - { - vt = VT_EMPTY; - *this = lpszSrc; - } - - CComVariant(__in LPCSTR lpszSrc) - { - vt = VT_EMPTY; - *this = lpszSrc; - } - - CComVariant(__in bool bSrc) - { - vt = VT_BOOL; - boolVal = bSrc ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE; - } - - CComVariant(__in int nSrc, __in VARTYPE vtSrc = VT_I4) throw() - { - ATLASSERT(vtSrc == VT_I4 || vtSrc == VT_INT); - vt = vtSrc; - intVal = nSrc; - } - CComVariant(__in BYTE nSrc) throw() - { - vt = VT_UI1; - bVal = nSrc; - } - CComVariant(__in short nSrc) throw() - { - vt = VT_I2; - iVal = nSrc; - } - CComVariant(__in long nSrc, __in VARTYPE vtSrc = VT_I4) throw() - { - ATLASSERT(vtSrc == VT_I4 || vtSrc == VT_ERROR); - vt = vtSrc; - lVal = nSrc; - } - CComVariant(__in float fltSrc) throw() - { - vt = VT_R4; - fltVal = fltSrc; - } - CComVariant(__in double dblSrc, __in VARTYPE vtSrc = VT_R8) throw() - { - ATLASSERT(vtSrc == VT_R8 || vtSrc == VT_DATE); - vt = vtSrc; - dblVal = dblSrc; - } -#if (_WIN32_WINNT >= 0x0501) || defined(_ATL_SUPPORT_VT_I8) - CComVariant(__in LONGLONG nSrc) throw() - { - vt = VT_I8; - llVal = nSrc; - } - CComVariant(__in ULONGLONG nSrc) throw() - { - vt = VT_UI8; - ullVal = nSrc; - } -#endif - CComVariant(CY __in cySrc) throw() - { - vt = VT_CY; - cyVal.Hi = cySrc.Hi; - cyVal.Lo = cySrc.Lo; - } - CComVariant(__in_opt IDispatch* pSrc) throw() - { - vt = VT_DISPATCH; - pdispVal = pSrc; - // Need to AddRef as VariantClear will Release - if (pdispVal != NULL) - pdispVal->AddRef(); - } - CComVariant(__in_opt IUnknown* pSrc) throw() - { - vt = VT_UNKNOWN; - punkVal = pSrc; - // Need to AddRef as VariantClear will Release - if (punkVal != NULL) - punkVal->AddRef(); - } - CComVariant(__in char cSrc) throw() - { - vt = VT_I1; - cVal = cSrc; - } - CComVariant(__in unsigned short nSrc) throw() - { - vt = VT_UI2; - uiVal = nSrc; - } - CComVariant(__in unsigned long nSrc) throw() - { - vt = VT_UI4; - ulVal = nSrc; - } - CComVariant(__in unsigned int nSrc, __in VARTYPE vtSrc = VT_UI4) throw() - { - ATLASSERT(vtSrc == VT_UI4 || vtSrc == VT_UINT); - vt = vtSrc; - uintVal= nSrc; - } - CComVariant(__in const CComBSTR& bstrSrc) - { - vt = VT_EMPTY; - *this = bstrSrc; - } - CComVariant(__in_opt const SAFEARRAY *pSrc) - { - LPSAFEARRAY pCopy; - if (pSrc != NULL) - { - HRESULT hRes = ::SafeArrayCopy((LPSAFEARRAY)pSrc, &pCopy); - if (SUCCEEDED(hRes) && pCopy != NULL) - { - ::ATL::AtlSafeArrayGetActualVartype((LPSAFEARRAY)pSrc, &vt); - vt |= VT_ARRAY; - parray = pCopy; - } - else - { - vt = VT_ERROR; - scode = hRes; -#ifndef _ATL_NO_VARIANT_THROW - ATLENSURE_THROW(FALSE, E_OUTOFMEMORY); -#endif - } - } - else - { - vt = VT_EMPTY; - } - } -// Assignment Operators -public: - CComVariant& operator=(__in const CComVariant& varSrc) - { - if(this!=&varSrc) - { - InternalCopy(&varSrc); - } - return *this; - } - CComVariant& operator=(__in const VARIANT& varSrc) - { - if(static_cast(this)!=&varSrc) - { - InternalCopy(&varSrc); - } - return *this; - } - - CComVariant& operator=(__in const CComBSTR& bstrSrc) - { - Clear(); - vt = VT_BSTR; - bstrVal = bstrSrc.Copy(); -#pragma warning(push) -#pragma warning(disable:4068) -#pragma prefast(push) -#pragma prefast(disable:325, "We are checking allocation semantics here") - if (bstrVal == NULL && bstrSrc.m_str != NULL) - { - vt = VT_ERROR; - scode = E_OUTOFMEMORY; -#ifndef _ATL_NO_VARIANT_THROW - ATLENSURE_THROW(FALSE, E_OUTOFMEMORY); -#endif - } -#pragma prefast(pop) -#pragma warning(pop) - return *this; - } - - CComVariant& operator=(__in LPCOLESTR lpszSrc) - { - Clear(); - vt = VT_BSTR; - bstrVal = ::SysAllocString(lpszSrc); - - if (bstrVal == NULL && lpszSrc != NULL) - { - vt = VT_ERROR; - scode = E_OUTOFMEMORY; -#ifndef _ATL_NO_VARIANT_THROW - ATLENSURE_THROW(FALSE, E_OUTOFMEMORY); -#endif - - } - return *this; - } - - CComVariant& operator=(__in LPCSTR lpszSrc) - { - USES_CONVERSION_EX; - Clear(); - vt = VT_BSTR; - bstrVal = ::SysAllocString(A2COLE_EX(lpszSrc, _ATL_SAFE_ALLOCA_DEF_THRESHOLD)); - - if (bstrVal == NULL && lpszSrc != NULL) - { - vt = VT_ERROR; - scode = E_OUTOFMEMORY; -#ifndef _ATL_NO_VARIANT_THROW - ATLENSURE_THROW(FALSE, E_OUTOFMEMORY); -#endif - } - return *this; - } - - CComVariant& operator=(__in bool bSrc) - { - if (vt != VT_BOOL) - { - Clear(); - vt = VT_BOOL; - } - boolVal = bSrc ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE; - return *this; - } - - CComVariant& operator=(__in int nSrc) throw() - { - if (vt != VT_I4) - { - Clear(); - vt = VT_I4; - } - intVal = nSrc; - - return *this; - } - - CComVariant& operator=(__in BYTE nSrc) throw() - { - if (vt != VT_UI1) - { - Clear(); - vt = VT_UI1; - } - bVal = nSrc; - return *this; - } - - CComVariant& operator=(__in short nSrc) throw() - { - if (vt != VT_I2) - { - Clear(); - vt = VT_I2; - } - iVal = nSrc; - return *this; - } - - CComVariant& operator=(__in long nSrc) throw() - { - if (vt != VT_I4) - { - Clear(); - vt = VT_I4; - } - lVal = nSrc; - return *this; - } - - CComVariant& operator=(__in float fltSrc) throw() - { - if (vt != VT_R4) - { - Clear(); - vt = VT_R4; - } - fltVal = fltSrc; - return *this; - } - - CComVariant& operator=(__in double dblSrc) throw() - { - if (vt != VT_R8) - { - Clear(); - vt = VT_R8; - } - dblVal = dblSrc; - return *this; - } - - CComVariant& operator=(__in CY cySrc) throw() - { - if (vt != VT_CY) - { - Clear(); - vt = VT_CY; - } - cyVal.Hi = cySrc.Hi; - cyVal.Lo = cySrc.Lo; - return *this; - } - - CComVariant& operator=(__in_opt IDispatch* pSrc) throw() - { - Clear(); - vt = VT_DISPATCH; - pdispVal = pSrc; - // Need to AddRef as VariantClear will Release - if (pdispVal != NULL) - pdispVal->AddRef(); - return *this; - } - - CComVariant& operator=(__in_opt IUnknown* pSrc) throw() - { - Clear(); - vt = VT_UNKNOWN; - punkVal = pSrc; - - // Need to AddRef as VariantClear will Release - if (punkVal != NULL) - punkVal->AddRef(); - return *this; - } - - CComVariant& operator=(__in char cSrc) throw() - { - if (vt != VT_I1) - { - Clear(); - vt = VT_I1; - } - cVal = cSrc; - return *this; - } - - CComVariant& operator=(__in unsigned short nSrc) throw() - { - if (vt != VT_UI2) - { - Clear(); - vt = VT_UI2; - } - uiVal = nSrc; - return *this; - } - - CComVariant& operator=(__in unsigned long nSrc) throw() - { - if (vt != VT_UI4) - { - Clear(); - vt = VT_UI4; - } - ulVal = nSrc; - return *this; - } - - CComVariant& operator=(__in unsigned int nSrc) throw() - { - if (vt != VT_UI4) - { - Clear(); - vt = VT_UI4; - } - uintVal= nSrc; - return *this; - } - - CComVariant& operator=(__in_opt BYTE* pbSrc) throw() - { - if (vt != (VT_UI1|VT_BYREF)) - { - Clear(); - vt = VT_UI1|VT_BYREF; - } - pbVal = pbSrc; - return *this; - } - - CComVariant& operator=(__in_opt short* pnSrc) throw() - { - if (vt != (VT_I2|VT_BYREF)) - { - Clear(); - vt = VT_I2|VT_BYREF; - } - piVal = pnSrc; - return *this; - } - -#ifdef _NATIVE_WCHAR_T_DEFINED - CComVariant& operator=(__in_opt USHORT* pnSrc) throw() - { - if (vt != (VT_UI2|VT_BYREF)) - { - Clear(); - vt = VT_UI2|VT_BYREF; - } - puiVal = pnSrc; - return *this; - } -#endif - - CComVariant& operator=(__in_opt int* pnSrc) throw() - { - if (vt != (VT_I4|VT_BYREF)) - { - Clear(); - vt = VT_I4|VT_BYREF; - } - pintVal = pnSrc; - return *this; - } - - CComVariant& operator=(__in_opt UINT* pnSrc) throw() - { - if (vt != (VT_UI4|VT_BYREF)) - { - Clear(); - vt = VT_UI4|VT_BYREF; - } - puintVal = pnSrc; - return *this; - } - - CComVariant& operator=(__in_opt long* pnSrc) throw() - { - if (vt != (VT_I4|VT_BYREF)) - { - Clear(); - vt = VT_I4|VT_BYREF; - } - plVal = pnSrc; - return *this; - } - - CComVariant& operator=(__in_opt ULONG* pnSrc) throw() - { - if (vt != (VT_UI4|VT_BYREF)) - { - Clear(); - vt = VT_UI4|VT_BYREF; - } - pulVal = pnSrc; - return *this; - } - -#if (_WIN32_WINNT >= 0x0501) || defined(_ATL_SUPPORT_VT_I8) - CComVariant& operator=(__in LONGLONG nSrc) throw() - { - if (vt != VT_I8) - { - Clear(); - vt = VT_I8; - } - llVal = nSrc; - - return *this; - } - - CComVariant& operator=(__in_opt LONGLONG* pnSrc) throw() - { - if (vt != (VT_I8|VT_BYREF)) - { - Clear(); - vt = VT_I8|VT_BYREF; - } - pllVal = pnSrc; - return *this; - } - - CComVariant& operator=(__in ULONGLONG nSrc) throw() - { - if (vt != VT_UI8) - { - Clear(); - vt = VT_UI8; - } - ullVal = nSrc; - - return *this; - } - - CComVariant& operator=(__in_opt ULONGLONG* pnSrc) throw() - { - if (vt != (VT_UI8|VT_BYREF)) - { - Clear(); - vt = VT_UI8|VT_BYREF; - } - pullVal = pnSrc; - return *this; - } -#endif - - CComVariant& operator=(__in_opt float* pfSrc) throw() - { - if (vt != (VT_R4|VT_BYREF)) - { - Clear(); - vt = VT_R4|VT_BYREF; - } - pfltVal = pfSrc; - return *this; - } - - CComVariant& operator=(__in_opt double* pfSrc) throw() - { - if (vt != (VT_R8|VT_BYREF)) - { - Clear(); - vt = VT_R8|VT_BYREF; - } - pdblVal = pfSrc; - return *this; - } - - CComVariant& operator=(__in_opt const SAFEARRAY *pSrc) - { - Clear(); - LPSAFEARRAY pCopy; - if (pSrc != NULL) - { - HRESULT hRes = ::SafeArrayCopy((LPSAFEARRAY)pSrc, &pCopy); - if (SUCCEEDED(hRes) && pCopy != NULL) - { - ::ATL::AtlSafeArrayGetActualVartype((LPSAFEARRAY)pSrc, &vt); - vt |= VT_ARRAY; - parray = pCopy; - } - else - { - vt = VT_ERROR; - scode = hRes; -#ifndef _ATL_NO_VARIANT_THROW - ATLENSURE_THROW(FALSE, E_OUTOFMEMORY); -#endif - } - } - return *this; - } - -// Comparison Operators -public: - bool operator==(__in const VARIANT& varSrc) const throw() - { - // For backwards compatibility - if (vt == VT_NULL && varSrc.vt == VT_NULL) - { - return true; - } - // Variants not equal if types don't match - if (vt != varSrc.vt) - { - return false; - } - return VarCmp((VARIANT*)this, (VARIANT*)&varSrc, LOCALE_USER_DEFAULT, 0) == static_cast(VARCMP_EQ); - } - - bool operator!=(__in const VARIANT& varSrc) const throw() - { - return !operator==(varSrc); - } - - bool operator<(__in const VARIANT& varSrc) const throw() - { - if (vt == VT_NULL && varSrc.vt == VT_NULL) - return false; - return VarCmp((VARIANT*)this, (VARIANT*)&varSrc, LOCALE_USER_DEFAULT, 0)== static_cast(VARCMP_LT); - } - - bool operator>(__in const VARIANT& varSrc) const throw() - { - if (vt == VT_NULL && varSrc.vt == VT_NULL) - return false; - return VarCmp((VARIANT*)this, (VARIANT*)&varSrc, LOCALE_USER_DEFAULT, 0)== static_cast(VARCMP_GT); - } - -// Operations -public: - HRESULT Clear() { return ::VariantClear(this); } - HRESULT Copy(__in const VARIANT* pSrc) { return ::VariantCopy(this, const_cast(pSrc)); } - // copy VARIANT to BSTR - HRESULT CopyTo(__out BSTR *pstrDest) - { - ATLASSERT(pstrDest != NULL && vt == VT_BSTR); - HRESULT hRes = E_POINTER; - if (pstrDest != NULL && vt == VT_BSTR) - { - *pstrDest = ::SysAllocStringByteLen((char*)bstrVal, ::SysStringByteLen(bstrVal)); - if (*pstrDest == NULL) - hRes = E_OUTOFMEMORY; - else - hRes = S_OK; - } - else if (vt != VT_BSTR) - hRes = DISP_E_TYPEMISMATCH; - return hRes; - } - HRESULT Attach(__in VARIANT* pSrc) - { - if(pSrc == NULL) - return E_INVALIDARG; - - // Clear out the variant - HRESULT hr = Clear(); - if (!FAILED(hr)) - { - // Copy the contents and give control to CComVariant - Checked::memcpy_s(this, sizeof(CComVariant), pSrc, sizeof(VARIANT)); - pSrc->vt = VT_EMPTY; - hr = S_OK; - } - return hr; - } - - HRESULT Detach(__out VARIANT* pDest) - { - ATLASSERT(pDest != NULL); - if(pDest == NULL) - return E_POINTER; - - // Clear out the variant - HRESULT hr = ::VariantClear(pDest); - if (!FAILED(hr)) - { - // Copy the contents and remove control from CComVariant - Checked::memcpy_s(pDest, sizeof(VARIANT), this, sizeof(VARIANT)); - vt = VT_EMPTY; - hr = S_OK; - } - return hr; - } - - HRESULT ChangeType(__in VARTYPE vtNew, __in_opt const VARIANT* pSrc = NULL) - { - VARIANT* pVar = const_cast(pSrc); - // Convert in place if pSrc is NULL - if (pVar == NULL) - pVar = this; - // Do nothing if doing in place convert and vts not different - return ::VariantChangeType(this, pVar, 0, vtNew); - } - - template< typename T > - void SetByRef( __in T* pT ) throw() - { - Clear(); - vt = CVarTypeInfo< T >::VT|VT_BYREF; - byref = pT; - } - - HRESULT WriteToStream(__inout IStream* pStream); - HRESULT ReadFromStream(__inout IStream* pStream); - - // Return the size in bytes of the current contents - ULONG GetSize() const; - -// Implementation -public: - HRESULT InternalClear() - { - HRESULT hr = Clear(); - ATLASSERT(SUCCEEDED(hr)); - if (FAILED(hr)) - { - vt = VT_ERROR; - scode = hr; -#ifndef _ATL_NO_VARIANT_THROW - AtlThrow(hr); -#endif - } - return hr; - } - - void InternalCopy(__in const VARIANT* pSrc) - { - HRESULT hr = Copy(pSrc); - if (FAILED(hr)) - { - vt = VT_ERROR; - scode = hr; -#ifndef _ATL_NO_VARIANT_THROW - AtlThrow(hr); -#endif - } - } -}; - -#pragma warning(push) -#pragma warning(disable: 4702) -inline HRESULT CComVariant::WriteToStream(__inout IStream* pStream) -{ - if(pStream == NULL) - return E_INVALIDARG; - - HRESULT hr = pStream->Write(&vt, sizeof(VARTYPE), NULL); - if (FAILED(hr)) - return hr; - - int cbWrite = 0; - switch (vt) - { - case VT_UNKNOWN: - case VT_DISPATCH: - { - CComPtr spStream; - if (punkVal != NULL) - { - hr = punkVal->QueryInterface(__uuidof(IPersistStream), (void**)&spStream); - if (FAILED(hr)) - { - hr = punkVal->QueryInterface(__uuidof(IPersistStreamInit), (void**)&spStream); - if (FAILED(hr)) - return hr; - } - } - if (spStream != NULL) - return OleSaveToStream(spStream, pStream); - return WriteClassStm(pStream, CLSID_NULL); - } - case VT_UI1: - case VT_I1: - cbWrite = sizeof(BYTE); - break; - case VT_I2: - case VT_UI2: - case VT_BOOL: - cbWrite = sizeof(short); - break; - case VT_I4: - case VT_UI4: - case VT_R4: - case VT_INT: - case VT_UINT: - case VT_ERROR: - cbWrite = sizeof(long); - break; - case VT_I8: - case VT_UI8: - cbWrite = sizeof(LONGLONG); - break; - case VT_R8: - case VT_CY: - case VT_DATE: - cbWrite = sizeof(double); - break; - default: - break; - } - if (cbWrite != 0) - return pStream->Write((void*) &bVal, cbWrite, NULL); - - CComBSTR bstrWrite; - CComVariant varBSTR; - if (vt != VT_BSTR) - { - hr = VariantChangeType(&varBSTR, this, VARIANT_NOVALUEPROP, VT_BSTR); - if (FAILED(hr)) - return hr; - bstrWrite.Attach(varBSTR.bstrVal); - } - else - bstrWrite.Attach(bstrVal); - - hr = bstrWrite.WriteToStream(pStream); - bstrWrite.Detach(); - return hr; -} -#pragma warning(pop) // C4702 - -inline HRESULT CComVariant::ReadFromStream(__inout IStream* pStream) -{ - ATLASSERT(pStream != NULL); - if(pStream == NULL) - return E_INVALIDARG; - - HRESULT hr; - hr = VariantClear(this); - if (FAILED(hr)) - return hr; - VARTYPE vtRead = VT_EMPTY; - ULONG cbRead = 0; - hr = pStream->Read(&vtRead, sizeof(VARTYPE), &cbRead); - if (hr == S_FALSE || (cbRead != sizeof(VARTYPE) && hr == S_OK)) - hr = E_FAIL; - if (FAILED(hr)) - return hr; - - vt = vtRead; - cbRead = 0; - switch (vtRead) - { - case VT_UNKNOWN: - case VT_DISPATCH: - { - punkVal = NULL; - hr = OleLoadFromStream(pStream, - (vtRead == VT_UNKNOWN) ? __uuidof(IUnknown) : __uuidof(IDispatch), - (void**)&punkVal); - // If IPictureDisp or IFontDisp property is not set, - // OleLoadFromStream() will return REGDB_E_CLASSNOTREG. - if (hr == REGDB_E_CLASSNOTREG) - hr = S_OK; - return hr; - } - case VT_UI1: - case VT_I1: - cbRead = sizeof(BYTE); - break; - case VT_I2: - case VT_UI2: - case VT_BOOL: - cbRead = sizeof(short); - break; - case VT_I4: - case VT_UI4: - case VT_R4: - case VT_INT: - case VT_UINT: - case VT_ERROR: - cbRead = sizeof(long); - break; - case VT_I8: - case VT_UI8: - cbRead = sizeof(LONGLONG); - break; - case VT_R8: - case VT_CY: - case VT_DATE: - cbRead = sizeof(double); - break; - default: - break; - } - if (cbRead != 0) - { - hr = pStream->Read((void*) &bVal, cbRead, NULL); - if (hr == S_FALSE) - hr = E_FAIL; - return hr; - } - CComBSTR bstrRead; - - hr = bstrRead.ReadFromStream(pStream); - if (FAILED(hr)) - { - // If CComBSTR::ReadFromStream failed, reset seek pointer to start of - // variant type. - LARGE_INTEGER nOffset; - nOffset.QuadPart = -(static_cast(sizeof(VARTYPE))); - pStream->Seek(nOffset, STREAM_SEEK_CUR, NULL); - return hr; - } - vt = VT_BSTR; - bstrVal = bstrRead.Detach(); - if (vtRead != VT_BSTR) - hr = ChangeType(vtRead); - return hr; -} - -inline ULONG CComVariant::GetSize() const -{ - ULONG nSize = sizeof(VARTYPE); - HRESULT hr; - - switch (vt) - { - case VT_UNKNOWN: - case VT_DISPATCH: - { - CComPtr spStream; - if (punkVal != NULL) - { - hr = punkVal->QueryInterface(__uuidof(IPersistStream), (void**)&spStream); - if (FAILED(hr)) - { - hr = punkVal->QueryInterface(__uuidof(IPersistStreamInit), (void**)&spStream); - if (FAILED(hr)) - break; - } - } - if (spStream != NULL) - { - ULARGE_INTEGER nPersistSize; - nPersistSize.QuadPart = 0; - spStream->GetSizeMax(&nPersistSize); - nSize += nPersistSize.LowPart + sizeof(CLSID); - } - else - nSize += sizeof(CLSID); - } - break; - case VT_UI1: - case VT_I1: - nSize += sizeof(BYTE); - break; - case VT_I2: - case VT_UI2: - case VT_BOOL: - nSize += sizeof(short); - break; - case VT_I4: - case VT_UI4: - case VT_R4: - case VT_INT: - case VT_UINT: - case VT_ERROR: - nSize += sizeof(long); - break; - case VT_I8: - case VT_UI8: - nSize += sizeof(LONGLONG); - break; - case VT_R8: - case VT_CY: - case VT_DATE: - nSize += sizeof(double); - break; - default: - break; - } - if (nSize == sizeof(VARTYPE)) - { - VARTYPE vtTmp = vt; - BSTR bstr = NULL; - CComVariant varBSTR; - if (vtTmp != VT_BSTR) - { - hr = VariantChangeType(&varBSTR, const_cast((const VARIANT*)this), VARIANT_NOVALUEPROP, VT_BSTR); - if (SUCCEEDED(hr)) - { - bstr = varBSTR.bstrVal; - vtTmp = VT_BSTR; - } - } else - { - bstr = bstrVal; - } - - if (vtTmp == VT_BSTR) - { - // Add the size of the length + string (in bytes) + NULL terminator. - nSize += CComBSTR::GetStreamSize(bstr); - } - } - return nSize; -} - -inline HRESULT CComPtr::Invoke2(__in DISPID dispid, __in VARIANT* pvarParam1, __in VARIANT* pvarParam2, __out_opt VARIANT* pvarRet) throw() -{ - if(pvarParam1 == NULL || pvarParam2 == NULL) - return E_INVALIDARG; - - CComVariant varArgs[2] = { *pvarParam2, *pvarParam1 }; - DISPPARAMS dispparams = { &varArgs[0], NULL, 2, 0}; - return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL); -} - -} // namespace ATL -#pragma pack(pop) - -#pragma warning (pop) - -#ifndef _ATL_NO_AUTOMATIC_NAMESPACE -using namespace ATL; -#endif //!_ATL_NO_AUTOMATIC_NAMESPACE - -#endif // __ATLCOMCLI_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlconv.h b/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlconv.h deleted file mode 100644 index 957a549fb..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlconv.h +++ /dev/null @@ -1,1313 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLCONV_H__ -#define __ATLCONV_H__ - -#pragma once - -#ifndef _ATL_NO_PRAGMA_WARNINGS -#pragma warning (push) -#pragma warning(disable: 4127) // unreachable code -#endif //!_ATL_NO_PRAGMA_WARNINGS - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#include -#include -#include - -#ifndef __wtypes_h__ - -#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_IX86) -#define _X86_ -#endif - -#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_AMD64) -#define _AMD64_ -#endif - -#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_M68K) -#define _68K_ -#endif - -#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_MPPC) -#define _MPPC_ -#endif - -#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_M_IX86) && !defined(_AMD64_) && defined(_M_IA64) -#if !defined(_IA64_) -#define _IA64_ -#endif // !_IA64_ -#endif - -#include -#include -#include -#include - -#if defined(_WIN32) && !defined(OLE2ANSI) - -typedef WCHAR OLECHAR; -typedef OLECHAR *LPOLESTR; -typedef const OLECHAR *LPCOLESTR; -#define OLESTR(str) L##str - -#else - -typedef char OLECHAR; -typedef LPSTR LPOLESTR; -typedef LPCSTR LPCOLESTR; -#define OLESTR(str) str - -#endif // _WIN32 && !OLE2ANSI -#endif // __wtypes_h__ - -#ifndef _OLEAUTO_H_ -typedef LPWSTR BSTR;// must (semantically) match typedef in oleauto.h - -extern "C" -{ -__declspec(dllimport) BSTR __stdcall SysAllocString(const OLECHAR *); -__declspec(dllimport) BSTR __stdcall SysAllocStringLen(const OLECHAR *, UINT); -__declspec(dllimport) INT __stdcall SysReAllocStringLen(BSTR *, const OLECHAR *, UINT); -__declspec(dllimport) void __stdcall SysFreeString(BSTR); -} -#endif - -// we use our own implementation of InterlockedExchangePointer because of problems with the one in system headers -#ifdef _M_IX86 -#undef InterlockedExchangePointer -inline void* WINAPI InterlockedExchangePointer(void** pp, void* pNew) throw() -{ - return( reinterpret_cast(static_cast(::InterlockedExchange(reinterpret_cast(pp), static_cast(reinterpret_cast(pNew))))) ); -} -#endif - -#define ATLCONV_DEADLAND_FILL _SECURECRT_FILL_BUFFER_PATTERN - -#pragma pack(push,_ATL_PACKING) -namespace ATL -{ -#ifndef _CONVERSION_DONT_USE_THREAD_LOCALE -typedef UINT (WINAPI *ATLGETTHREADACP)(); - -inline UINT WINAPI _AtlGetThreadACPFake() throw() -{ - UINT nACP = 0; - - LCID lcidThread = ::GetThreadLocale(); - - char szACP[7]; - // GetLocaleInfoA will fail for a Unicode-only LCID, but those are only supported on - // Windows 2000. Since Windows 2000 supports CP_THREAD_ACP, this code path is never - // executed on Windows 2000. - if (::GetLocaleInfoA(lcidThread, LOCALE_IDEFAULTANSICODEPAGE, szACP, 7) != 0) - { - char* pch = szACP; - while (*pch != '\0') - { - nACP *= 10; - nACP += *pch++ - '0'; - } - } - // Use the Default ANSI Code Page if we were unable to get the thread ACP or if one does not exist. - if (nACP == 0) - nACP = ::GetACP(); - - return nACP; -} - -inline UINT WINAPI _AtlGetThreadACPReal() throw() -{ - return( CP_THREAD_ACP ); -} - -extern ATLGETTHREADACP g_pfnGetThreadACP; - -inline UINT WINAPI _AtlGetThreadACPThunk() throw() -{ - OSVERSIONINFO ver; - ATLGETTHREADACP pfnGetThreadACP; - - ver.dwOSVersionInfoSize = sizeof( ver ); - ::GetVersionEx( &ver ); - if( (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) && (ver.dwMajorVersion >= 5) ) - { - // On Win2K, CP_THREAD_ACP is supported - pfnGetThreadACP = _AtlGetThreadACPReal; - } - else - { - pfnGetThreadACP = _AtlGetThreadACPFake; - } - InterlockedExchangePointer( reinterpret_cast< void** >(&g_pfnGetThreadACP), reinterpret_cast< void** >(pfnGetThreadACP) ); - - return( g_pfnGetThreadACP() ); -} - -inline UINT WINAPI _AtlGetConversionACP() throw() -{ - return( g_pfnGetThreadACP() ); -} - -#else - -inline UINT WINAPI _AtlGetConversionACP() throw() -{ - return( CP_ACP ); -} - -#endif // _CONVERSION_DONT_USE_THREAD_LOCALE -template -inline void AtlConvAllocMemory(__deref_ecount_opt(nLength) _CharType** ppBuff,__in int nLength,__inout_ecount(nFixedBufferLength) _CharType* pszFixedBuffer,__in int nFixedBufferLength) -{ - ATLENSURE_THROW(ppBuff != NULL, E_INVALIDARG); - ATLENSURE_THROW(nLength >= 0, E_INVALIDARG); - ATLENSURE_THROW(pszFixedBuffer != NULL, E_INVALIDARG); - - //if buffer malloced, try to realloc. - if (*ppBuff != pszFixedBuffer) - { - if( nLength > nFixedBufferLength ) - { - _CharType* ppReallocBuf = static_cast< _CharType* >( _recalloc(*ppBuff, nLength,sizeof( _CharType ) ) ); - if (ppReallocBuf == NULL) - { - AtlThrow( E_OUTOFMEMORY ); - } - *ppBuff = ppReallocBuf; - } else - { - free(*ppBuff); - *ppBuff=pszFixedBuffer; - } - - } else //Buffer is not currently malloced. - { - if( nLength > nFixedBufferLength ) - { - *ppBuff = static_cast< _CharType* >( calloc(nLength,sizeof( _CharType ) ) ); - } else - { - *ppBuff=pszFixedBuffer; - } - } - - if (*ppBuff == NULL) - { - AtlThrow( E_OUTOFMEMORY ); - } - -} - -template -inline void AtlConvFreeMemory(_CharType* pBuff,_CharType* pszFixedBuffer,int nFixedBufferLength) -{ - (nFixedBufferLength); - if( pBuff != pszFixedBuffer ) - { - free( pBuff ); - } -#ifdef _DEBUG - else - { - memset(pszFixedBuffer,ATLCONV_DEADLAND_FILL,nFixedBufferLength*sizeof(_CharType)); - } -#endif - -} - -template< int t_nBufferLength = 128 > -class CW2WEX -{ -public: - CW2WEX( __in_opt LPCWSTR psz ) throw(...) : - m_psz( m_szBuffer ) - { - Init( psz ); - } - CW2WEX( __in_opt LPCWSTR psz, UINT nCodePage ) throw(...) : - m_psz( m_szBuffer ) - { - (void)nCodePage; // Code page doesn't matter - - Init( psz ); - } - ~CW2WEX() throw() - { - AtlConvFreeMemory(m_psz,m_szBuffer,t_nBufferLength); - } - - operator LPWSTR() const throw() - { - return( m_psz ); - } - -private: - void Init( __in_opt LPCWSTR psz ) throw(...) - { - if (psz == NULL) - { - m_psz = NULL; - return; - } - int nLength = lstrlenW( psz )+1; - AtlConvAllocMemory(&m_psz,nLength,m_szBuffer,t_nBufferLength); - Checked::memcpy_s( m_psz, nLength*sizeof( wchar_t ), psz, nLength*sizeof( wchar_t )); - } - -public: - LPWSTR m_psz; - wchar_t m_szBuffer[t_nBufferLength]; - -private: - CW2WEX( const CW2WEX& ) throw(); - CW2WEX& operator=( const CW2WEX& ) throw(); -}; -typedef CW2WEX<> CW2W; - -template< int t_nBufferLength = 128 > -class CA2AEX -{ -public: - CA2AEX( __in_opt LPCSTR psz ) throw(...) : - m_psz( m_szBuffer ) - { - Init( psz ); - } - CA2AEX( __in_opt LPCSTR psz, UINT nCodePage ) throw(...) : - m_psz( m_szBuffer ) - { - (void)nCodePage; // Code page doesn't matter - - Init( psz ); - } - ~CA2AEX() throw() - { - AtlConvFreeMemory(m_psz,m_szBuffer,t_nBufferLength); - } - - operator LPSTR() const throw() - { - return( m_psz ); - } - -private: - void Init( __in_opt LPCSTR psz ) throw(...) - { - if (psz == NULL) - { - m_psz = NULL; - return; - } - int nLength = lstrlenA( psz )+1; - AtlConvAllocMemory(&m_psz,nLength,m_szBuffer,t_nBufferLength); - Checked::memcpy_s( m_psz, nLength*sizeof( char ), psz, nLength*sizeof( char )); - } - -public: - LPSTR m_psz; - char m_szBuffer[t_nBufferLength]; - -private: - CA2AEX( const CA2AEX& ) throw(); - CA2AEX& operator=( const CA2AEX& ) throw(); -}; -typedef CA2AEX<> CA2A; - -template< int t_nBufferLength = 128 > -class CA2CAEX -{ -public: - CA2CAEX( __in LPCSTR psz ) throw(...) : - m_psz( psz ) - { - } - CA2CAEX( __in LPCSTR psz, UINT nCodePage ) throw(...) : - m_psz( psz ) - { - (void)nCodePage; - } - ~CA2CAEX() throw() - { - } - - operator LPCSTR() const throw() - { - return( m_psz ); - } - -public: - LPCSTR m_psz; - -private: - CA2CAEX( const CA2CAEX& ) throw(); - CA2CAEX& operator=( const CA2CAEX& ) throw(); -}; -typedef CA2CAEX<> CA2CA; - -template< int t_nBufferLength = 128 > -class CW2CWEX -{ -public: - CW2CWEX( __in LPCWSTR psz ) throw(...) : - m_psz( psz ) - { - } - CW2CWEX( __in LPCWSTR psz, UINT nCodePage ) throw(...) : - m_psz( psz ) - { - (void)nCodePage; - } - ~CW2CWEX() throw() - { - } - - operator LPCWSTR() const throw() - { - return( m_psz ); - } - -public: - LPCWSTR m_psz; - -private: - CW2CWEX( const CW2CWEX& ) throw(); - CW2CWEX& operator=( const CW2CWEX& ) throw(); -}; -typedef CW2CWEX<> CW2CW; - -template< int t_nBufferLength = 128 > -class CA2WEX -{ -public: - CA2WEX( __in_opt LPCSTR psz ) throw(...) : - m_psz( m_szBuffer ) - { - Init( psz, _AtlGetConversionACP() ); - } - CA2WEX( __in_opt LPCSTR psz, UINT nCodePage ) throw(...) : - m_psz( m_szBuffer ) - { - Init( psz, nCodePage ); - } - ~CA2WEX() throw() - { - AtlConvFreeMemory(m_psz,m_szBuffer,t_nBufferLength); - } - - operator LPWSTR() const throw() - { - return( m_psz ); - } - -private: - void Init( __in_opt LPCSTR psz, UINT nCodePage ) throw(...) - { - if (psz == NULL) - { - m_psz = NULL; - return; - } - int nLengthA = lstrlenA( psz )+1; - int nLengthW = nLengthA; - - AtlConvAllocMemory(&m_psz,nLengthW,m_szBuffer,t_nBufferLength); - - BOOL bFailed=(0 == ::MultiByteToWideChar( nCodePage, 0, psz, nLengthA, m_psz, nLengthW ) ); - if (bFailed) - { - if (GetLastError()==ERROR_INSUFFICIENT_BUFFER) - { - nLengthW = ::MultiByteToWideChar( nCodePage, 0, psz, nLengthA, NULL, 0); - AtlConvAllocMemory(&m_psz,nLengthW,m_szBuffer,t_nBufferLength); - bFailed=(0 == ::MultiByteToWideChar( nCodePage, 0, psz, nLengthA, m_psz, nLengthW ) ); - } - } - if (bFailed) - { - AtlThrowLastWin32(); - } - } - -public: - LPWSTR m_psz; - wchar_t m_szBuffer[t_nBufferLength]; - -private: - CA2WEX( const CA2WEX& ) throw(); - CA2WEX& operator=( const CA2WEX& ) throw(); -}; -typedef CA2WEX<> CA2W; - -template< int t_nBufferLength = 128 > -class CW2AEX -{ -public: - CW2AEX( __in_opt LPCWSTR psz ) throw(...) : - m_psz( m_szBuffer ) - { - Init( psz, _AtlGetConversionACP() ); - } - CW2AEX( __in_opt LPCWSTR psz, UINT nCodePage ) throw(...) : - m_psz( m_szBuffer ) - { - Init( psz, nCodePage ); - } - ~CW2AEX() throw() - { - AtlConvFreeMemory(m_psz,m_szBuffer,t_nBufferLength); - } - - operator LPSTR() const throw() - { - return( m_psz ); - } - -private: - void Init( __in_opt LPCWSTR psz, __in UINT nConvertCodePage ) throw(...) - { - if (psz == NULL) - { - m_psz = NULL; - return; - } - int nLengthW = lstrlenW( psz )+1; - int nLengthA = nLengthW*4; - - AtlConvAllocMemory(&m_psz,nLengthA,m_szBuffer,t_nBufferLength); - - BOOL bFailed=(0 == ::WideCharToMultiByte( nConvertCodePage, 0, psz, nLengthW, m_psz, nLengthA, NULL, NULL )); - if (bFailed) - { - if (GetLastError()==ERROR_INSUFFICIENT_BUFFER) - { - nLengthA = ::WideCharToMultiByte( nConvertCodePage, 0, psz, nLengthW, NULL, 0, NULL, NULL ); - AtlConvAllocMemory(&m_psz,nLengthA,m_szBuffer,t_nBufferLength); - bFailed=(0 == ::WideCharToMultiByte( nConvertCodePage, 0, psz, nLengthW, m_psz, nLengthA, NULL, NULL )); - } - } - if (bFailed) - { - AtlThrowLastWin32(); - } - } - -public: - LPSTR m_psz; - char m_szBuffer[t_nBufferLength]; - -private: - CW2AEX( const CW2AEX& ) throw(); - CW2AEX& operator=( const CW2AEX& ) throw(); -}; -typedef CW2AEX<> CW2A; - -#ifdef _UNICODE - - #define CW2T CW2W - #define CW2TEX CW2WEX - #define CW2CT CW2CW - #define CW2CTEX CW2CWEX - #define CT2W CW2W - #define CT2WEX CW2WEX - #define CT2CW CW2CW - #define CT2CWEX CW2CWEX - - #define CA2T CA2W - #define CA2TEX CA2WEX - #define CA2CT CA2W - #define CA2CTEX CA2WEX - #define CT2A CW2A - #define CT2AEX CW2AEX - #define CT2CA CW2A - #define CT2CAEX CW2AEX - -#else // !_UNICODE - - #define CW2T CW2A - #define CW2TEX CW2AEX - #define CW2CT CW2A - #define CW2CTEX CW2AEX - #define CT2W CA2W - #define CT2WEX CA2WEX - #define CT2CW CA2W - #define CT2CWEX CA2WEX - - #define CA2T CA2A - #define CA2TEX CA2AEX - #define CA2CT CA2CA - #define CA2CTEX CA2CAEX - #define CT2A CA2A - #define CT2AEX CA2AEX - #define CT2CA CA2CA - #define CT2CAEX CA2CAEX - -#endif // !_UNICODE - -#define COLE2T CW2T -#define COLE2TEX CW2TEX -#define COLE2CT CW2CT -#define COLE2CTEX CW2CTEX -#define CT2OLE CT2W -#define CT2OLEEX CT2WEX -#define CT2COLE CT2CW -#define CT2COLEEX CT2CWEX - -}; // namespace ATL -#pragma pack(pop) - -#pragma pack(push,8) - -#ifndef _ATL_EX_CONVERSION_MACROS_ONLY - -#ifndef _DEBUG - #define USES_CONVERSION int _convert; (_convert); UINT _acp = ATL::_AtlGetConversionACP() /*CP_THREAD_ACP*/; (_acp); LPCWSTR _lpw; (_lpw); LPCSTR _lpa; (_lpa) -#else - #define USES_CONVERSION int _convert = 0; (_convert); UINT _acp = ATL::_AtlGetConversionACP() /*CP_THREAD_ACP*/; (_acp); LPCWSTR _lpw = NULL; (_lpw); LPCSTR _lpa = NULL; (_lpa) -#endif - -#endif // _ATL_EX_CONVERSION_MACROS_ONLY - -#ifndef _DEBUG - #define USES_CONVERSION_EX int _convert_ex; (_convert_ex); UINT _acp_ex = ATL::_AtlGetConversionACP(); (_acp_ex); LPCWSTR _lpw_ex; (_lpw_ex); LPCSTR _lpa_ex; (_lpa_ex); USES_ATL_SAFE_ALLOCA -#else - #define USES_CONVERSION_EX int _convert_ex = 0; (_convert_ex); UINT _acp_ex = ATL::_AtlGetConversionACP(); (_acp_ex); LPCWSTR _lpw_ex = NULL; (_lpw_ex); LPCSTR _lpa_ex = NULL; (_lpa_ex); USES_ATL_SAFE_ALLOCA -#endif - -#ifdef _WINGDI_ - ATLAPI_(LPDEVMODEA) AtlDevModeW2A(LPDEVMODEA lpDevModeA, const DEVMODEW* lpDevModeW); -#endif - -///////////////////////////////////////////////////////////////////////////// -// Global UNICODE<>ANSI translation helpers -inline LPWSTR WINAPI AtlA2WHelper(__out_ecount(nChars) LPWSTR lpw, __in LPCSTR lpa, __in int nChars, __in UINT acp) throw() -{ - ATLASSERT(lpa != NULL); - ATLASSERT(lpw != NULL); - if (lpw == NULL || lpa == NULL) - return NULL; - // verify that no illegal character present - // since lpw was allocated based on the size of lpa - // don't worry about the number of chars - lpw[0] = '\0'; - int ret = MultiByteToWideChar(acp, 0, lpa, -1, lpw, nChars); - if(ret == 0) - { - ATLASSERT(FALSE); - return NULL; - } - return lpw; -} - -inline LPSTR WINAPI AtlW2AHelper(__out_ecount(nChars) LPSTR lpa, __in LPCWSTR lpw, __in int nChars, __in UINT acp) throw() -{ - ATLASSERT(lpw != NULL); - ATLASSERT(lpa != NULL); - if (lpa == NULL || lpw == NULL) - return NULL; - // verify that no illegal character present - // since lpa was allocated based on the size of lpw - // don't worry about the number of chars - lpa[0] = '\0'; - int ret = WideCharToMultiByte(acp, 0, lpw, -1, lpa, nChars, NULL, NULL); - if(ret == 0) - { - ATLASSERT(FALSE); - return NULL; - } - return lpa; -} -inline LPWSTR WINAPI AtlA2WHelper(__out_ecount(nChars) LPWSTR lpw, __in LPCSTR lpa, __in int nChars) throw() -{ - return AtlA2WHelper(lpw, lpa, nChars, CP_ACP); -} - -inline LPSTR WINAPI AtlW2AHelper(__out_ecount(nChars) LPSTR lpa, __in LPCWSTR lpw, __in int nChars) throw() -{ - return AtlW2AHelper(lpa, lpw, nChars, CP_ACP); -} - -#ifndef _CONVERSION_DONT_USE_THREAD_LOCALE - #ifdef ATLA2WHELPER - #undef ATLA2WHELPER - #undef ATLW2AHELPER - #endif - #define ATLA2WHELPER AtlA2WHelper - #define ATLW2AHELPER AtlW2AHelper -#else - #ifndef ATLA2WHELPER - #define ATLA2WHELPER AtlA2WHelper - #define ATLW2AHELPER AtlW2AHelper - #endif -#endif - -#ifndef _ATL_EX_CONVERSION_MACROS_ONLY - -#define A2W(lpa) (\ - ((_lpa = lpa) == NULL) ? NULL : (\ - _convert = (lstrlenA(_lpa)+1),\ - (INT_MAX/2<_convert)? NULL : \ - ATLA2WHELPER((LPWSTR) alloca(_convert*sizeof(WCHAR)), _lpa, _convert, _acp))) - -#define W2A(lpw) (\ - ((_lpw = lpw) == NULL) ? NULL : (\ - (_convert = (lstrlenW(_lpw)+1), \ - (_convert>INT_MAX/2) ? NULL : \ - ATLW2AHELPER((LPSTR) alloca(_convert*sizeof(WCHAR)), _lpw, _convert*sizeof(WCHAR), _acp)))) - -#define A2W_CP(lpa, cp) (\ - ((_lpa = lpa) == NULL) ? NULL : (\ - _convert = (lstrlenA(_lpa)+1),\ - (INT_MAX/2<_convert)? NULL : \ - ATLA2WHELPER((LPWSTR) alloca(_convert*sizeof(WCHAR)), _lpa, _convert, (cp))) - -#define W2A_CP(lpw, cp) (\ - ((_lpw = lpw) == NULL) ? NULL : (\ - (_convert = (lstrlenW(_lpw)+1), \ - (_convert>INT_MAX/2) ? NULL : \ - ATLW2AHELPER((LPSTR) alloca(_convert*sizeof(WCHAR)), _lpw, _convert*sizeof(WCHAR), (cp)))) - -#endif - -// The call to _alloca will not cause stack overflow if _AtlVerifyStackAvailable returns TRUE. -#define A2W_EX(lpa, nChars) (\ - ((_lpa_ex = lpa) == NULL) ? NULL : (\ - _convert_ex = (lstrlenA(_lpa_ex)+1),\ - FAILED(::ATL::AtlMultiply(&_convert_ex, _convert_ex, static_cast(sizeof(WCHAR)))) ? NULL : \ - ATLA2WHELPER( \ - (LPWSTR)_ATL_SAFE_ALLOCA(_convert_ex, _ATL_SAFE_ALLOCA_DEF_THRESHOLD), \ - _lpa_ex, \ - _convert_ex, \ - _acp_ex))) - -#define A2W_EX_DEF(lpa) A2W_EX(lpa, _ATL_SAFE_ALLOCA_DEF_THRESHOLD) - -#define W2A_EX(lpw, nChars) (\ - ((_lpw_ex = lpw) == NULL) ? NULL : (\ - _convert_ex = (lstrlenW(_lpw_ex)+1),\ - FAILED(::ATL::AtlMultiply(&_convert_ex, _convert_ex, static_cast(sizeof(WCHAR)))) ? NULL : \ - ATLW2AHELPER( \ - (LPSTR)_ATL_SAFE_ALLOCA(_convert_ex, _ATL_SAFE_ALLOCA_DEF_THRESHOLD), \ - _lpw_ex, \ - _convert_ex, \ - _acp_ex))) - -#define W2A_EX_DEF(lpa) W2A_EX(lpa, _ATL_SAFE_ALLOCA_DEF_THRESHOLD) - -#define A2W_CP_EX(lpa, nChars, cp) (\ - ((_lpa_ex = lpa) == NULL) ? NULL : (\ - _convert_ex = (lstrlenA(_lpa_ex)+1),\ - FAILED(::ATL::AtlMultiply(&_convert_ex, _convert_ex, static_cast(sizeof(WCHAR)))) ? NULL : \ - ATLA2WHELPER( \ - (LPWSTR)_ATL_SAFE_ALLOCA(_convert_ex, _ATL_SAFE_ALLOCA_DEF_THRESHOLD), \ - _lpa_ex, \ - _convert_ex, \ - (cp)))) - -#define W2A_CP_EX(lpw, nChars, cp) (\ - ((_lpw_ex = lpw) == NULL) ? NULL : (\ - _convert_ex = (lstrlenW(_lpw_ex)+1),\ - FAILED(::ATL::AtlMultiply(&_convert_ex, _convert_ex, static_cast(sizeof(WCHAR)))) ? NULL : \ - ATLW2AHELPER( \ - (LPSTR)_ATL_SAFE_ALLOCA(_convert_ex, _ATL_SAFE_ALLOCA_DEF_THRESHOLD), \ - _lpw_ex, \ - _convert_ex, \ - (cp)))) - -#ifndef _ATL_EX_CONVERSION_MACROS_ONLY - -#define A2CW(lpa) ((LPCWSTR)A2W(lpa)) -#define W2CA(lpw) ((LPCSTR)W2A(lpw)) - -#define A2CW_CP(lpa, cp) ((LPCWSTR)A2W_CP(lpa, (cp))) -#define W2CA_CP(lpw, cp) ((LPCSTR)W2A_CP(lpw, (cp))) - -#endif // _ATL_EX_CONVERSION_MACROS_ONLY - -#define A2CW_EX(lpa, nChar) ((LPCWSTR)A2W_EX(lpa, nChar)) -#define A2CW_EX_DEF(lpa) ((LPCWSTR)A2W_EX_DEF(lpa)) -#define W2CA_EX(lpw, nChar) ((LPCSTR)W2A_EX(lpw, nChar)) -#define W2CA_EX_DEF(lpw) ((LPCSTR)W2A_EX_DEF(lpw)) - -#define A2CW_CP_EX(lpa, nChar, cp) ((LPCWSTR)A2W_CP_EX(lpa, nChar, (cp))) -#define W2CA_CP_EX(lpw, nChar, cp) ((LPCSTR)W2A_CP_EX(lpw, nChar, (cp))) - - inline int ocslen(__in_z LPCOLESTR x) throw() { return lstrlenW(x); } - -#if _SECURE_ATL - inline bool ocscpy_s(__out_ecount_z(maxSize) LPOLESTR dest, __in size_t maxSize, __in_z LPCOLESTR src) throw() - { return 0 == memcpy_s(dest, maxSize*sizeof(WCHAR), src, (ocslen(src)+1)*sizeof(WCHAR)); } - inline bool ocscat_s(__out_ecount_z(maxSize) LPOLESTR dest, __in size_t maxSize, __in_z LPCOLESTR src) throw() - { return 0 == wcscat_s(dest, maxSize,src); } -#else - inline bool ocscpy_s(__out_ecount_z(maxSize) LPOLESTR dest, __in size_t maxSize, __in_z LPCOLESTR src) throw() - { (void)maxSize; memcpy(dest, src, (ocslen(src)+1)*sizeof(WCHAR)); return true; } - inline bool ocscat_s(__out_ecount_z(maxSize) LPOLESTR dest, __in size_t maxSize, __in_z LPCOLESTR src) throw() - { (void)maxSize; wcscat(dest, src); } -#endif - -#if defined(_UNICODE) - -// in these cases the default (TCHAR) is the same as OLECHAR - -#if _SECURE_ATL - _ATL_INSECURE_DEPRECATE("ocscpy is not safe. Intead, use ocscpy_s") - inline OLECHAR* ocscpy(__out_z LPOLESTR dest, __in_z LPCOLESTR src) throw() - { -#pragma warning(push) -#pragma warning(disable:4996) - return wcscpy(dest, src); -#pragma warning(pop) - } - _ATL_INSECURE_DEPRECATE("ocscat is not safe. Intead, use ocscat_s") - inline OLECHAR* ocscat(__out_z LPOLESTR dest, __in_z LPCOLESTR src) throw() - { -#pragma warning(push) -#pragma warning(disable:4996) - return wcscat(dest, src); -#pragma warning(pop) - } -#else - inline OLECHAR* ocscpy(__out_z LPOLESTR dest, __in_z LPCOLESTR src) throw() { return lstrcpyW(dest, src); } - inline OLECHAR* ocscat(__out_z LPOLESTR dest, __in_z LPCOLESTR src) throw() { return lstrcatW(dest, src); } -#endif - - inline LPCOLESTR T2COLE_EX(__in_opt LPCTSTR lp, UINT) { return lp; } - inline LPCOLESTR T2COLE_EX_DEF(__in_opt LPCTSTR lp) { return lp; } - inline LPCTSTR OLE2CT_EX(__in_opt LPCOLESTR lp, UINT) { return lp; } - inline LPCTSTR OLE2CT_EX_DEF(__in_opt LPCOLESTR lp) { return lp; } - inline LPOLESTR T2OLE_EX(__in_opt LPTSTR lp, UINT) { return lp; } - inline LPOLESTR T2OLE_EX_DEF(__in_opt LPTSTR lp) { return lp; } - inline LPTSTR OLE2T_EX(__in_opt LPOLESTR lp, UINT) { return lp; } - inline LPTSTR OLE2T_EX_DEF(__in_opt LPOLESTR lp) { return lp; } - -#ifndef _ATL_EX_CONVERSION_MACROS_ONLY - - inline LPCOLESTR T2COLE(__in_opt LPCTSTR lp) { return lp; } - inline LPCTSTR OLE2CT(__in_opt LPCOLESTR lp) { return lp; } - inline LPOLESTR T2OLE(__in_opt LPTSTR lp) { return lp; } - inline LPTSTR OLE2T(__in_opt LPOLESTR lp) { return lp; } - inline LPOLESTR CharNextO(__in LPCOLESTR lp) throw() {return CharNextW(lp);} - -#endif // _ATL_EX_CONVERSION_MACROS_ONLY - -#else // !defined(_UNICODE) - -#if _SECURE_ATL - - _ATL_INSECURE_DEPRECATE("ocscpy is not safe. Intead, use ocscpy_s") - inline OLECHAR* ocscpy(__out_z LPOLESTR dest, __in_z LPCOLESTR src) throw() - { -#pragma warning(push) -#pragma warning(disable:4996) - return (LPOLESTR) memcpy(dest, src, (lstrlenW(src)+1)*sizeof(WCHAR)); -#pragma warning(pop) - } - _ATL_INSECURE_DEPRECATE("ocscat is not safe. Intead, use ocscat_s") - inline OLECHAR* ocscat(__inout_z LPOLESTR dest, __in_z LPCOLESTR src) throw() - { -#pragma warning(push) -#pragma warning(disable:4996) - return ocscpy(dest+ocslen(dest), src); -#pragma warning(pop) - } - -#else - - //lstrcpyW doesn't work on Win95, so we do this - inline OLECHAR* ocscpy(__out_z LPOLESTR dest, __in_z LPCOLESTR src) throw() - { - return (LPOLESTR) memcpy(dest, src, (lstrlenW(src)+1)*sizeof(WCHAR)); - } - inline OLECHAR* ocscat(__out_z LPOLESTR dest, __in_z LPCOLESTR src) throw() - { - return ocscpy(dest+ocslen(dest), src); - } - -#endif - - //CharNextW doesn't work on Win95 so we use this - #define T2COLE_EX(lpa, nChar) A2CW_EX(lpa, nChar) - #define T2COLE_EX_DEF(lpa) A2CW_EX_DEF(lpa) - #define T2OLE_EX(lpa, nChar) A2W_EX(lpa, nChar) - #define T2OLE_EX_DEF(lpa) A2W_EX_DEF(lpa) - #define OLE2CT_EX(lpo, nChar) W2CA_EX(lpo, nChar) - #define OLE2CT_EX_DEF(lpo) W2CA_EX_DEF(lpo) - #define OLE2T_EX(lpo, nChar) W2A_EX(lpo, nChar) - #define OLE2T_EX_DEF(lpo) W2A_EX_DEF(lpo) - -#ifndef _ATL_EX_CONVERSION_MACROS_ONLY - - #define T2COLE(lpa) A2CW(lpa) - #define T2OLE(lpa) A2W(lpa) - #define OLE2CT(lpo) W2CA(lpo) - #define OLE2T(lpo) W2A(lpo) - -#endif // _ATL_EX_CONVERSION_MACROS_ONLY - - inline LPOLESTR CharNextO(LPCOLESTR lp) throw() {return (LPOLESTR) ((*lp) ? (lp+1) : lp);} - -#endif // defined(_UNICODE) - - inline LPOLESTR W2OLE_EX(__in_opt LPWSTR lp, UINT) { return lp; } - inline LPOLESTR W2OLE_EX_DEF(__in_opt LPWSTR lp) { return lp; } - inline LPWSTR OLE2W_EX(__in_opt LPOLESTR lp, UINT) { return lp; } - inline LPWSTR OLE2W_EX_DEF(__in_opt LPOLESTR lp) { return lp; } - #define A2OLE_EX A2W_EX - #define A2OLE_EX_DEF A2W_EX_DEF - #define OLE2A_EX W2A_EX - #define OLE2A_EX_DEF W2A_EX_DEF - inline LPCOLESTR W2COLE_EX(__in_opt LPCWSTR lp, UINT) { return lp; } - inline LPCOLESTR W2COLE_EX_DEF(__in_opt LPCWSTR lp) { return lp; } - inline LPCWSTR OLE2CW_EX(__in_opt LPCOLESTR lp, UINT) { return lp; } - inline LPCWSTR OLE2CW_EX_DEF(__in_opt LPCOLESTR lp) { return lp; } - #define A2COLE_EX A2CW_EX - #define A2COLE_EX_DEF A2CW_EX_DEF - #define OLE2CA_EX W2CA_EX - #define OLE2CA_EX_DEF W2CA_EX_DEF - -#ifndef _ATL_EX_CONVERSION_MACROS_ONLY - - inline LPOLESTR W2OLE(__in_opt LPWSTR lp) { return lp; } - inline LPWSTR OLE2W(__in_opt LPOLESTR lp) { return lp; } - #define A2OLE A2W - #define OLE2A W2A - inline LPCOLESTR W2COLE(__in_opt LPCWSTR lp) { return lp; } - inline LPCWSTR OLE2CW(__in_opt LPCOLESTR lp) { return lp; } - #define A2COLE A2CW - #define OLE2CA W2CA - -#endif // _ATL_EX_CONVERSION_MACROS_ONLY - -#if defined(_UNICODE) - - #define T2A_EX W2A_EX - #define T2A_EX_DEF W2A_EX_DEF - #define A2T_EX A2W_EX - #define A2T_EX_DEF A2W_EX_DEF - inline LPWSTR T2W_EX(__in_opt LPTSTR lp, UINT) { return lp; } - inline LPWSTR T2W_EX_DEF(__in_opt LPTSTR lp) { return lp; } - inline LPTSTR W2T_EX(__in_opt LPWSTR lp, UINT) { return lp; } - inline LPTSTR W2T_DEF(__in_opt LPWSTR lp) { return lp; } - #define T2CA_EX W2CA_EX - #define T2CA_EX_DEF W2CA_EX_DEF - #define A2CT_EX A2CW_EX - #define A2CT_EX_DEF A2CW_EX_DEF - inline LPCWSTR T2CW_EX(__in_opt LPCTSTR lp, UINT) { return lp; } - inline LPCWSTR T2CW_EX_DEF(__in_opt LPCTSTR lp) { return lp; } - inline LPCTSTR W2CT_EX(__in_opt LPCWSTR lp, UINT) { return lp; } - inline LPCTSTR W2CT_EX_DEF(__in_opt LPCWSTR lp) { return lp; } - -#ifndef _ATL_EX_CONVERSION_MACROS_ONLY - - #define T2A W2A - #define A2T A2W - inline LPWSTR T2W(__in_opt LPTSTR lp) { return lp; } - inline LPTSTR W2T(__in_opt LPWSTR lp) { return lp; } - #define T2CA W2CA - #define A2CT A2CW - inline LPCWSTR T2CW(__in_opt LPCTSTR lp) { return lp; } - inline LPCTSTR W2CT(__in_opt LPCWSTR lp) { return lp; } - -#endif // _ATL_EX_CONVERSION_MACROS_ONLY - -#else // !defined(_UNICODE) - - #define T2W_EX A2W_EX - #define T2W_EX_DEF A2W_EX_DEF - #define W2T_EX W2A_EX - #define W2T_EX_DEF W2A_EX_DEF - inline LPSTR T2A_EX(__in_opt LPTSTR lp, UINT) { return lp; } - inline LPSTR T2A_EX_DEF(__in_opt LPTSTR lp) { return lp; } - inline LPTSTR A2T_EX(__in_opt LPSTR lp, UINT) { return lp; } - inline LPTSTR A2T_EX_DEF(__in_opt LPSTR lp) { return lp; } - #define T2CW_EX A2CW_EX - #define T2CW_EX_DEF A2CW_EX_DEF - #define W2CT_EX W2CA_EX - #define W2CT_EX_DEF W2CA_EX_DEF - inline LPCSTR T2CA_EX(__in_opt LPCTSTR lp, UINT) { return lp; } - inline LPCSTR T2CA_EX_DEF(__in_opt LPCTSTR lp) { return lp; } - inline LPCTSTR A2CT_EX(__in_opt LPCSTR lp, UINT) { return lp; } - inline LPCTSTR A2CT_EX_DEF(__in_opt LPCSTR lp) { return lp; } - -#ifndef _ATL_EX_CONVERSION_MACROS_ONLY - - #define T2W A2W - #define W2T W2A - inline LPSTR T2A(__in_opt LPTSTR lp) { return lp; } - inline LPTSTR A2T(__in_opt LPSTR lp) { return lp; } - #define T2CW A2CW - #define W2CT W2CA - inline LPCSTR T2CA(__in_opt LPCTSTR lp) { return lp; } - inline LPCTSTR A2CT(__in_opt LPCSTR lp) { return lp; } - -#endif // _ATL_EX_CONVERSION_MACROS_ONLY - -#endif // defined(_UNICODE) - -inline __checkReturn BSTR A2WBSTR(__in_opt LPCSTR lp, int nLen = -1) -{ - if (lp == NULL || nLen == 0) - return NULL; - USES_CONVERSION_EX; - BSTR str = NULL; - int nConvertedLen = MultiByteToWideChar(_acp_ex, 0, lp, - nLen, NULL, NULL); - int nAllocLen = nConvertedLen; - if (nLen == -1) - nAllocLen -= 1; // Don't allocate terminating '\0' - str = ::SysAllocStringLen(NULL, nAllocLen); - - if (str != NULL) - { - int nResult; - nResult = MultiByteToWideChar(_acp_ex, 0, lp, nLen, str, nConvertedLen); - ATLASSERT(nResult == nConvertedLen); - if(nResult != nConvertedLen) - { - SysFreeString(str); - return NULL; - } - - } - return str; -} - -inline BSTR OLE2BSTR(__in_opt LPCOLESTR lp) {return ::SysAllocString(lp);} -#if defined(_UNICODE) -// in these cases the default (TCHAR) is the same as OLECHAR - inline BSTR T2BSTR_EX(__in_opt LPCTSTR lp) {return ::SysAllocString(lp);} - inline BSTR A2BSTR_EX(__in_opt LPCSTR lp) {return A2WBSTR(lp);} - inline BSTR W2BSTR_EX(__in_opt LPCWSTR lp) {return ::SysAllocString(lp);} - -#ifndef _ATL_EX_CONVERSION_MACROS_ONLY - - inline BSTR T2BSTR(__in_opt LPCTSTR lp) {return ::SysAllocString(lp);} - inline BSTR A2BSTR(__in_opt LPCSTR lp) {return A2WBSTR(lp);} - inline BSTR W2BSTR(__in_opt LPCWSTR lp) {return ::SysAllocString(lp);} - -#endif // _ATL_EX_CONVERSION_MACROS_ONLY - -#else // !defined(_UNICODE) - inline BSTR T2BSTR_EX(__in_opt LPCTSTR lp) {return A2WBSTR(lp);} - inline BSTR A2BSTR_EX(__in_opt LPCSTR lp) {return A2WBSTR(lp);} - inline BSTR W2BSTR_EX(__in_opt LPCWSTR lp) {return ::SysAllocString(lp);} - -#ifndef _ATL_EX_CONVERSION_MACROS_ONLY - - inline BSTR T2BSTR(__in_opt LPCTSTR lp) {return A2WBSTR(lp);} - inline BSTR A2BSTR(__in_opt LPCSTR lp) {return A2WBSTR(lp);} - inline BSTR W2BSTR(__in_opt LPCWSTR lp) {return ::SysAllocString(lp);} - -#endif // _ATL_EX_CONVERSION_MACROS_ONLY - -#endif // defined(_UNICODE) - -#ifdef _WINGDI_ -///////////////////////////////////////////////////////////////////////////// -// Global UNICODE<>ANSI translation helpers -inline LPDEVMODEW AtlDevModeA2W(__out LPDEVMODEW lpDevModeW, __in const DEVMODEA* lpDevModeA) -{ - USES_CONVERSION_EX; - ATLASSERT(lpDevModeW != NULL); - if (lpDevModeA == NULL || lpDevModeW == NULL) - { - return NULL; - } - - AtlA2WHelper(lpDevModeW->dmDeviceName, (LPCSTR)lpDevModeA->dmDeviceName, 32, _acp_ex); - -#if _SECURE_ATL - if(0 != memcpy_s(&lpDevModeW->dmSpecVersion, offsetof(DEVMODEW, dmFormName) - offsetof(DEVMODEW, dmSpecVersion), - &lpDevModeA->dmSpecVersion, offsetof(DEVMODEW, dmFormName) - offsetof(DEVMODEW, dmSpecVersion))) - { - return NULL; - } -#else - memcpy(&lpDevModeW->dmSpecVersion, &lpDevModeA->dmSpecVersion, - offsetof(DEVMODEW, dmFormName) - offsetof(DEVMODEW, dmSpecVersion)); -#endif - - AtlA2WHelper(lpDevModeW->dmFormName, (LPCSTR)lpDevModeA->dmFormName, 32, _acp_ex); - -#if _SECURE_ATL - if(0 != memcpy_s(&lpDevModeW->dmLogPixels, sizeof(DEVMODEW) - offsetof(DEVMODEW, dmLogPixels), - &lpDevModeA->dmLogPixels, sizeof(DEVMODEW) - offsetof(DEVMODEW, dmLogPixels))) - { - return NULL; - } -#else - memcpy(&lpDevModeW->dmLogPixels, &lpDevModeA->dmLogPixels, - sizeof(DEVMODEW) - offsetof(DEVMODEW, dmLogPixels)); -#endif - - if (lpDevModeA->dmDriverExtra != 0) - { - // lpDevModeW holds more info -#pragma warning(push) -#pragma warning(disable:26000) -#if _SECURE_ATL - if(0 != memcpy_s(lpDevModeW+1, lpDevModeA->dmDriverExtra, lpDevModeA+1, lpDevModeA->dmDriverExtra)) - { - return NULL; - } -#else - memcpy(lpDevModeW+1, lpDevModeA+1, lpDevModeA->dmDriverExtra); -#endif -#pragma warning(pop) - } - lpDevModeW->dmSize = sizeof(DEVMODEW); - return lpDevModeW; -} - -inline LPTEXTMETRICW AtlTextMetricA2W(__out LPTEXTMETRICW lptmW, __in LPTEXTMETRICA lptmA) -{ - USES_CONVERSION_EX; - ATLASSERT(lptmW != NULL); - if (lptmA == NULL || lptmW == NULL) - return NULL; - -#if _SECURE_ATL - if(0 != memcpy_s(lptmW, sizeof(LONG) * 11, lptmA, sizeof(LONG) * 11)) - { - return NULL; - } -#else - memcpy(lptmW, lptmA, sizeof(LONG) * 11); -#endif - -#if _SECURE_ATL - if(0 != memcpy_s(&lptmW->tmItalic, sizeof(BYTE) * 5, &lptmA->tmItalic, sizeof(BYTE) * 5)) - { - return NULL; - } -#else - memcpy(&lptmW->tmItalic, &lptmA->tmItalic, sizeof(BYTE) * 5); -#endif - - if(MultiByteToWideChar(_acp_ex, 0, (LPCSTR)&lptmA->tmFirstChar, 1, &lptmW->tmFirstChar, 1) == 0) - { - ATLASSERT(FALSE); - return NULL; - } - - if(MultiByteToWideChar(_acp_ex, 0, (LPCSTR)&lptmA->tmLastChar, 1, &lptmW->tmLastChar, 1) == 0) - { - ATLASSERT(FALSE); - return NULL; - } - - if(MultiByteToWideChar(_acp_ex, 0, (LPCSTR)&lptmA->tmDefaultChar, 1, &lptmW->tmDefaultChar, 1)== 0) - { - ATLASSERT(FALSE); - return NULL; - } - - if(MultiByteToWideChar(_acp_ex, 0, (LPCSTR)&lptmA->tmBreakChar, 1, &lptmW->tmBreakChar, 1) == 0) - { - ATLASSERT(FALSE); - return NULL; - } - - return lptmW; -} - -inline LPTEXTMETRICA AtlTextMetricW2A(__out LPTEXTMETRICA lptmA, __in LPTEXTMETRICW lptmW) -{ - USES_CONVERSION_EX; - ATLASSERT(lptmA != NULL); - if (lptmW == NULL || lptmA == NULL) - { - return NULL; - } - -#if _SECURE_ATL - if(0 != memcpy_s(lptmA, sizeof(LONG) * 11, lptmW, sizeof(LONG) * 11)) - { - return NULL; - } -#else - memcpy(lptmA, lptmW, sizeof(LONG) * 11); -#endif - -#if _SECURE_ATL - if(0 != memcpy_s(&lptmA->tmItalic, sizeof(BYTE) * 5, &lptmW->tmItalic, sizeof(BYTE) * 5)) - { - return NULL; - } -#else - memcpy(&lptmA->tmItalic, &lptmW->tmItalic, sizeof(BYTE) * 5); -#endif - - if(WideCharToMultiByte(_acp_ex, 0, &lptmW->tmFirstChar, 1, (LPSTR)&lptmA->tmFirstChar, 1, NULL, NULL) == 0) - { - ATLASSERT(FALSE); - return NULL; - } - - if(WideCharToMultiByte(_acp_ex, 0, &lptmW->tmLastChar, 1, (LPSTR)&lptmA->tmLastChar, 1, NULL, NULL) == 0) - { - ATLASSERT(FALSE); - return NULL; - } - - if(WideCharToMultiByte(_acp_ex, 0, &lptmW->tmDefaultChar, 1, (LPSTR)&lptmA->tmDefaultChar, 1, NULL, NULL) == 0) - { - ATLASSERT(FALSE); - return NULL; - } - - if(WideCharToMultiByte(_acp_ex, 0, &lptmW->tmBreakChar, 1, (LPSTR)&lptmA->tmBreakChar, 1, NULL, NULL) == 0) - { - ATLASSERT(FALSE); - return NULL; - } - - return lptmA; -} - -#ifndef ATLDEVMODEA2W -#define ATLDEVMODEA2W AtlDevModeA2W -#define ATLDEVMODEW2A AtlDevModeW2A -#define ATLTEXTMETRICA2W AtlTextMetricA2W -#define ATLTEXTMETRICW2A AtlTextMetricW2A -#endif - -// Requires USES_CONVERSION_EX or USES_ATL_SAFE_ALLOCA macro before using the _EX versions of the macros -#define DEVMODEW2A_EX(lpw)\ - (((lpw) == NULL) ? NULL : ATLDEVMODEW2A((LPDEVMODEA)_ATL_SAFE_ALLOCA(sizeof(DEVMODEA)+(lpw)->dmDriverExtra, _ATL_SAFE_ALLOCA_DEF_THRESHOLD), (lpw))) -#define DEVMODEA2W_EX(lpa)\ - (((lpa) == NULL) ? NULL : ATLDEVMODEA2W((LPDEVMODEW)_ATL_SAFE_ALLOCA(sizeof(DEVMODEW)+(lpa)->dmDriverExtra, _ATL_SAFE_ALLOCA_DEF_THRESHOLD), (lpa))) -#define TEXTMETRICW2A_EX(lptmw)\ - (((lptmw) == NULL) ? NULL : ATLTEXTMETRICW2A((LPTEXTMETRICA)_ATL_SAFE_ALLOCA(sizeof(TEXTMETRICA), _ATL_SAFE_ALLOCA_DEF_THRESHOLD), (lptmw))) -#define TEXTMETRICA2W_EX(lptma)\ - (((lptma) == NULL) ? NULL : ATLTEXTMETRICA2W((LPTEXTMETRICW)_ATL_SAFE_ALLOCA(sizeof(TEXTMETRICW), _ATL_SAFE_ALLOCA_DEF_THRESHOLD), (lptma))) - -#ifndef _ATL_EX_CONVERSION_MACROS_ONLY - -#define DEVMODEW2A(lpw)\ - ((lpw == NULL) ? NULL : ATLDEVMODEW2A((LPDEVMODEA)alloca(sizeof(DEVMODEA)+lpw->dmDriverExtra), lpw)) -#define DEVMODEA2W(lpa)\ - ((lpa == NULL) ? NULL : ATLDEVMODEA2W((LPDEVMODEW)alloca(sizeof(DEVMODEW)+lpa->dmDriverExtra), lpa)) -#define TEXTMETRICW2A(lptmw)\ - ((lptmw == NULL) ? NULL : ATLTEXTMETRICW2A((LPTEXTMETRICA)alloca(sizeof(TEXTMETRICA)), lptmw)) -#define TEXTMETRICA2W(lptma)\ - ((lptma == NULL) ? NULL : ATLTEXTMETRICA2W((LPTEXTMETRICW)alloca(sizeof(TEXTMETRICW)), lptma)) - -#endif // _ATL_EX_CONVERSION_MACROS_ONLY - -#define DEVMODEOLE DEVMODEW -#define LPDEVMODEOLE LPDEVMODEW -#define TEXTMETRICOLE TEXTMETRICW -#define LPTEXTMETRICOLE LPTEXTMETRICW - -#if defined(_UNICODE) -// in these cases the default (TCHAR) is the same as OLECHAR - inline LPDEVMODEW DEVMODEOLE2T_EX(LPDEVMODEOLE lp) { return lp; } - inline LPDEVMODEOLE DEVMODET2OLE_EX(LPDEVMODEW lp) { return lp; } - inline LPTEXTMETRICW TEXTMETRICOLE2T_EX(LPTEXTMETRICOLE lp) { return lp; } - inline LPTEXTMETRICOLE TEXTMETRICT2OLE_EX(LPTEXTMETRICW lp) { return lp; } -#ifndef _ATL_EX_CONVERSION_MACROS_ONLY - inline LPDEVMODEW DEVMODEOLE2T(LPDEVMODEOLE lp) { return lp; } - inline LPDEVMODEOLE DEVMODET2OLE(LPDEVMODEW lp) { return lp; } - inline LPTEXTMETRICW TEXTMETRICOLE2T(LPTEXTMETRICOLE lp) { return lp; } - inline LPTEXTMETRICOLE TEXTMETRICT2OLE(LPTEXTMETRICW lp) { return lp; } -#endif // _ATL_EX_CONVERSION_MACROS_ONLY - -#else // !defined(_UNICODE) - #define DEVMODEOLE2T_EX(lpo) DEVMODEW2A_EX(lpo) - #define DEVMODET2OLE_EX(lpa) DEVMODEA2W_EX(lpa) - #define TEXTMETRICOLE2T_EX(lptmw) TEXTMETRICW2A_EX(lptmw) - #define TEXTMETRICT2OLE_EX(lptma) TEXTMETRICA2W_EX(lptma) -#ifndef _ATL_EX_CONVERSION_MACROS_ONLY - #define DEVMODEOLE2T(lpo) DEVMODEW2A(lpo) - #define DEVMODET2OLE(lpa) DEVMODEA2W(lpa) - #define TEXTMETRICOLE2T(lptmw) TEXTMETRICW2A(lptmw) - #define TEXTMETRICT2OLE(lptma) TEXTMETRICA2W(lptma) -#endif // _ATL_EX_CONVERSION_MACROS_ONLY - -#endif // defined(_UNICODE) - -#endif //_WINGDI_ - -#pragma pack(pop) - -///////////////////////////////////////////////////////////////////////////// - -#ifndef _ATL_DLL - -#ifdef _WINGDI_ - -ATLINLINE ATLAPI_(LPDEVMODEA) AtlDevModeW2A(__out LPDEVMODEA lpDevModeA, __in const DEVMODEW* lpDevModeW) -{ - USES_CONVERSION_EX; - ATLASSERT(lpDevModeA != NULL); - if (lpDevModeW == NULL || lpDevModeA == NULL) - return NULL; - - AtlW2AHelper((LPSTR)lpDevModeA->dmDeviceName, lpDevModeW->dmDeviceName, 32, _acp_ex); - -#if _SECURE_ATL - if(0 != memcpy_s(&lpDevModeA->dmSpecVersion, offsetof(DEVMODEA, dmFormName) - offsetof(DEVMODEA, dmSpecVersion), - &lpDevModeW->dmSpecVersion, offsetof(DEVMODEA, dmFormName) - offsetof(DEVMODEA, dmSpecVersion))) - { - return NULL; - } -#else - memcpy(&lpDevModeA->dmSpecVersion, &lpDevModeW->dmSpecVersion, - offsetof(DEVMODEA, dmFormName) - offsetof(DEVMODEA, dmSpecVersion)); -#endif - - AtlW2AHelper((LPSTR)lpDevModeA->dmFormName, lpDevModeW->dmFormName, 32, _acp_ex); - -#if _SECURE_ATL - if(0 != memcpy_s(&lpDevModeA->dmLogPixels, sizeof(DEVMODEA) - offsetof(DEVMODEA, dmLogPixels), - &lpDevModeW->dmLogPixels, sizeof(DEVMODEA) - offsetof(DEVMODEA, dmLogPixels))) - { - return NULL; - } -#else - memcpy(&lpDevModeA->dmLogPixels, &lpDevModeW->dmLogPixels, - sizeof(DEVMODEA) - offsetof(DEVMODEA, dmLogPixels)); -#endif - - if (lpDevModeW->dmDriverExtra != 0) - { - // lpDevModeW holds more info -#pragma warning(push) -#pragma warning(disable:26000) -#if _SECURE_ATL - if(0 != memcpy_s(lpDevModeA+1, lpDevModeW->dmDriverExtra, lpDevModeW+1, lpDevModeW->dmDriverExtra)) - { - return NULL; - } -#else - memcpy(lpDevModeA+1, lpDevModeW+1, lpDevModeW->dmDriverExtra); -#endif -#pragma warning(pop) - } - - lpDevModeA->dmSize = sizeof(DEVMODEA); - return lpDevModeA; -} - -#endif //_WINGDI - -#endif // !_ATL_DLL - -#ifndef _ATL_NO_PRAGMA_WARNINGS -#pragma warning (pop) -#endif //!_ATL_NO_PRAGMA_WARNINGS - -#endif // __ATLCONV_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlcore.h b/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlcore.h deleted file mode 100644 index 010ce61ee..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlcore.h +++ /dev/null @@ -1,545 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLCORE_H__ -#define __ATLCORE_H__ - -#pragma once - -#ifdef _ATL_ALL_WARNINGS -#pragma warning( push ) -#endif - -#pragma warning(disable: 4786) // identifier was truncated in the debug information - -#include -#include -#include - -#include -#include -#include - -#include -#include - -#pragma pack(push,_ATL_PACKING) -namespace ATL -{ -///////////////////////////////////////////////////////////////////////////// -// Verify that a null-terminated string points to valid memory -inline BOOL AtlIsValidString(LPCWSTR psz, size_t nMaxLength = INT_MAX) -{ - (nMaxLength); - return (psz != NULL); -} - -// Verify that a null-terminated string points to valid memory -inline BOOL AtlIsValidString(LPCSTR psz, size_t nMaxLength = UINT_MAX) -{ - (nMaxLength); - return (psz != NULL); -} - -// Verify that a pointer points to valid memory -inline BOOL AtlIsValidAddress(const void* p, size_t nBytes, - BOOL bReadWrite = TRUE) -{ - (bReadWrite); - (nBytes); - return (p != NULL); -} - -template -inline void AtlAssertValidObject(const T *pOb) -{ - ATLASSERT(pOb); - ATLASSERT(AtlIsValidAddress(pOb, sizeof(T))); - if(pOb) - pOb->AssertValid(); -} -#ifdef _DEBUG -#define ATLASSERT_VALID(x) ATL::AtlAssertValidObject(x) -#else -#define ATLASSERT_VALID(x) __noop; -#endif - -// COM Sync Classes -class CComCriticalSection -{ -public: - CComCriticalSection() throw() - { - memset(&m_sec, 0, sizeof(CRITICAL_SECTION)); - } - ~CComCriticalSection() - { - } - HRESULT Lock() throw() - { - EnterCriticalSection(&m_sec); - return S_OK; - } - HRESULT Unlock() throw() - { - LeaveCriticalSection(&m_sec); - return S_OK; - } - HRESULT Init() throw() - { - HRESULT hRes = E_FAIL; - __try - { - InitializeCriticalSection(&m_sec); - hRes = S_OK; - } - // structured exception may be raised in low memory situations - __except(STATUS_NO_MEMORY == GetExceptionCode()) - { - hRes = E_OUTOFMEMORY; - } - return hRes; - } - - HRESULT Term() throw() - { - DeleteCriticalSection(&m_sec); - return S_OK; - } - CRITICAL_SECTION m_sec; -}; - -class CComAutoCriticalSection : public CComCriticalSection -{ -public: - CComAutoCriticalSection() - { - HRESULT hr = CComCriticalSection::Init(); - if (FAILED(hr)) - AtlThrow(hr); - } - ~CComAutoCriticalSection() throw() - { - CComCriticalSection::Term(); - } -private : - HRESULT Init(); // Not implemented. CComAutoCriticalSection::Init should never be called - HRESULT Term(); // Not implemented. CComAutoCriticalSection::Term should never be called -}; - -class CComSafeDeleteCriticalSection : public CComCriticalSection -{ -public: - CComSafeDeleteCriticalSection(): m_bInitialized(false) - { - } - - ~CComSafeDeleteCriticalSection() throw() - { - if (!m_bInitialized) - { - return; - } - m_bInitialized = false; - CComCriticalSection::Term(); - } - - HRESULT Init() throw() - { - ATLASSERT( !m_bInitialized ); - HRESULT hr = CComCriticalSection::Init(); - if (SUCCEEDED(hr)) - { - m_bInitialized = true; - } - return hr; - } - - HRESULT Term() throw() - { - if (!m_bInitialized) - { - return S_OK; - } - m_bInitialized = false; - return CComCriticalSection::Term(); - } - - HRESULT Lock() - { - // CComSafeDeleteCriticalSection::Init or CComAutoDeleteCriticalSection::Init - // not called or failed. - // m_critsec member of CComObjectRootEx is now of type - // CComAutoDeleteCriticalSection. It has to be initialized - // by calling CComObjectRootEx::_AtlInitialConstruct - ATLASSUME(m_bInitialized); - return CComCriticalSection::Lock(); - } - -private: - bool m_bInitialized; -}; - -class CComAutoDeleteCriticalSection : public CComSafeDeleteCriticalSection -{ -private: - // CComAutoDeleteCriticalSection::Term should never be called - HRESULT Term() throw(); -}; - -class CComFakeCriticalSection -{ -public: - HRESULT Lock() throw() { return S_OK; } - HRESULT Unlock() throw() { return S_OK; } - HRESULT Init() throw() { return S_OK; } - HRESULT Term() throw() { return S_OK; } -}; - -///////////////////////////////////////////////////////////////////////////// -// Module - -// Used by any project that uses ATL -struct _ATL_BASE_MODULE70 -{ - UINT cbSize; - HINSTANCE m_hInst; - HINSTANCE m_hInstResource; - bool m_bNT5orWin98; - DWORD dwAtlBuildVer; - const GUID* pguidVer; - CComCriticalSection m_csResource; - CSimpleArray m_rgResourceInstance; -}; -typedef _ATL_BASE_MODULE70 _ATL_BASE_MODULE; - -class CAtlBaseModule : public _ATL_BASE_MODULE -{ -public : - static bool m_bInitFailed; - CAtlBaseModule() throw(); - ~CAtlBaseModule() throw (); - - HINSTANCE GetModuleInstance() throw() - { - return m_hInst; - } - HINSTANCE GetResourceInstance() throw() - { - return m_hInstResource; - } - HINSTANCE SetResourceInstance(HINSTANCE hInst) throw() - { - return static_cast< HINSTANCE >(InterlockedExchangePointer((void**)&m_hInstResource, hInst)); - } - - bool AddResourceInstance(HINSTANCE hInst) throw(); - bool RemoveResourceInstance(HINSTANCE hInst) throw(); - HINSTANCE GetHInstanceAt(int i) throw(); -}; - -__declspec(selectany) bool CAtlBaseModule::m_bInitFailed = false; -extern CAtlBaseModule _AtlBaseModule; - -///////////////////////////////////////////////////////////////////////////// -// String resource helpers - -#pragma warning(push) -#pragma warning(disable: 4200) - struct ATLSTRINGRESOURCEIMAGE - { - WORD nLength; - WCHAR achString[]; - }; -#pragma warning(pop) // C4200 - -inline const ATLSTRINGRESOURCEIMAGE* _AtlGetStringResourceImage( HINSTANCE hInstance, HRSRC hResource, UINT id ) throw() -{ - const ATLSTRINGRESOURCEIMAGE* pImage; - const ATLSTRINGRESOURCEIMAGE* pImageEnd; - ULONG nResourceSize; - HGLOBAL hGlobal; - UINT iIndex; - - hGlobal = ::LoadResource( hInstance, hResource ); - if( hGlobal == NULL ) - { - return( NULL ); - } - - pImage = (const ATLSTRINGRESOURCEIMAGE*)::LockResource( hGlobal ); - if( pImage == NULL ) - { - return( NULL ); - } - - nResourceSize = ::SizeofResource( hInstance, hResource ); - pImageEnd = (const ATLSTRINGRESOURCEIMAGE*)(LPBYTE( pImage )+nResourceSize); - iIndex = id&0x000f; - - while( (iIndex > 0) && (pImage < pImageEnd) ) - { - pImage = (const ATLSTRINGRESOURCEIMAGE*)(LPBYTE( pImage )+(sizeof( ATLSTRINGRESOURCEIMAGE )+(pImage->nLength*sizeof( WCHAR )))); - iIndex--; - } - if( pImage >= pImageEnd ) - { - return( NULL ); - } - if( pImage->nLength == 0 ) - { - return( NULL ); - } - - return( pImage ); -} - -inline const ATLSTRINGRESOURCEIMAGE* AtlGetStringResourceImage( HINSTANCE hInstance, UINT id ) throw() -{ - HRSRC hResource; - - hResource = ::FindResource( hInstance, MAKEINTRESOURCE( ((id>>4)+1) ), RT_STRING ); - if( hResource == NULL ) - { - return( NULL ); - } - - return _AtlGetStringResourceImage( hInstance, hResource, id ); -} - -inline const ATLSTRINGRESOURCEIMAGE* AtlGetStringResourceImage( HINSTANCE hInstance, UINT id, WORD wLanguage ) throw() -{ - HRSRC hResource; - - hResource = ::FindResourceEx( hInstance, RT_STRING, MAKEINTRESOURCE( ((id>>4)+1) ), wLanguage ); - if( hResource == NULL ) - { - return( NULL ); - } - - return _AtlGetStringResourceImage( hInstance, hResource, id ); -} - -inline const ATLSTRINGRESOURCEIMAGE* AtlGetStringResourceImage( UINT id ) throw() -{ - const ATLSTRINGRESOURCEIMAGE* p = NULL; - HINSTANCE hInst = _AtlBaseModule.GetHInstanceAt(0); - - for (int i = 1; hInst != NULL && p == NULL; hInst = _AtlBaseModule.GetHInstanceAt(i++)) - { - p = AtlGetStringResourceImage(hInst, id); - } - return p; -} - -inline const ATLSTRINGRESOURCEIMAGE* AtlGetStringResourceImage( UINT id, WORD wLanguage ) throw() -{ - const ATLSTRINGRESOURCEIMAGE* p = NULL; - HINSTANCE hInst = _AtlBaseModule.GetHInstanceAt(0); - - for (int i = 1; hInst != NULL && p == NULL; hInst = _AtlBaseModule.GetHInstanceAt(i++)) - { - p = AtlGetStringResourceImage(hInst, id, wLanguage); - } - return p; -} - -inline int AtlLoadString(__in UINT nID, __out_ecount_part_z(nBufferMax, return + 1) LPTSTR lpBuffer, __in int nBufferMax) throw() -{ - HINSTANCE hInst = _AtlBaseModule.GetHInstanceAt(0); - int nRet = 0; - - for (int i = 1; hInst != NULL && nRet == 0; hInst = _AtlBaseModule.GetHInstanceAt(i++)) - { - nRet = LoadString(hInst, nID, lpBuffer, nBufferMax); - } - return nRet; -} - -inline HINSTANCE AtlFindResourceInstance(LPCTSTR lpName, LPCTSTR lpType, WORD wLanguage = 0) throw() -{ - ATLASSERT(lpType != RT_STRING); // Call AtlFindStringResourceInstance to find the string - if (lpType == RT_STRING) - return NULL; - - if (ATL_IS_INTRESOURCE(lpType)) - { - /* Prefast false warnings caused by bad-shaped definition of MAKEINTRESOURCE macro from PSDK */ - if (lpType == ATL_RT_ICON) - { - lpType = ATL_RT_GROUP_ICON; - } - else if (lpType == ATL_RT_CURSOR) - { - lpType = ATL_RT_GROUP_CURSOR; - } - } - - HINSTANCE hInst = _AtlBaseModule.GetHInstanceAt(0); - HRSRC hResource = NULL; - - for (int i = 1; hInst != NULL; hInst = _AtlBaseModule.GetHInstanceAt(i++)) - { - hResource = ::FindResourceEx(hInst, lpType, lpName, wLanguage); - if (hResource != NULL) - { - return hInst; - } - } - - return NULL; -} - -inline HINSTANCE AtlFindResourceInstance(UINT nID, LPCTSTR lpType, WORD wLanguage = 0) throw() -{ - return AtlFindResourceInstance(MAKEINTRESOURCE(nID), lpType, wLanguage); -} - -inline HINSTANCE AtlFindStringResourceInstance(UINT nID, WORD wLanguage = 0) throw() -{ - const ATLSTRINGRESOURCEIMAGE* p = NULL; - HINSTANCE hInst = _AtlBaseModule.GetHInstanceAt(0); - - for (int i = 1; hInst != NULL && p == NULL; hInst = _AtlBaseModule.GetHInstanceAt(i++)) - { - p = AtlGetStringResourceImage(hInst, nID, wLanguage); - if (p != NULL) - return hInst; - } - - return NULL; -} - -/* -Needed by both atlcomcli and atlsafe, so needs to be in here -*/ -inline HRESULT AtlSafeArrayGetActualVartype -( - SAFEARRAY *psaArray, - VARTYPE *pvtType -) -{ - HRESULT hrSystem=::SafeArrayGetVartype(psaArray, pvtType); - - if(FAILED(hrSystem)) - { - return hrSystem; - } - - /* - When Windows has a SAFEARRAY of type VT_DISPATCH with FADF_HAVEIID, - it returns VT_UNKNOWN instead of VT_DISPATCH. We patch the value to be correct - */ - if(pvtType && *pvtType==VT_UNKNOWN) - { - if(psaArray && ((psaArray->fFeatures & FADF_HAVEIID)!=0)) - { - if(psaArray->fFeatures & FADF_DISPATCH) - { - *pvtType=VT_DISPATCH; - } - } - } - - return hrSystem; -} -template -inline _CharType* AtlCharNext(const _CharType* p) throw() -{ - ATLASSUME(p != NULL); // Too expensive to check separately here - if (*p == '\0') // ::CharNextA won't increment if we're at a \0 already - return const_cast<_CharType*>(p+1); - else - return ::CharNextA(p); -} - -template <> -inline wchar_t* AtlCharNext(const wchar_t* p) throw() -{ - return const_cast< wchar_t* >( p+1 ); -} -template -inline const CharType* AtlstrchrT(const CharType* p, CharType ch) throw() -{ - ATLASSERT(p != NULL); - if(p==NULL) - { - return NULL; - } - while( *p != 0 ) - { - if (*p == ch) - { - return p; - } - p = AtlCharNext(p); - } - //strchr for '\0' should succeed - the while loop terminates - //*p == 0, but ch also == 0, so NULL terminator address is returned - return (*p == ch) ? p : NULL; -} -//Ansi and Unicode versions of printf, used with templated CharType trait classes. -#pragma warning(push) -#pragma warning(disable : 4793) -template -inline int AtlprintfT(const CharType* pszFormat,... ) throw() -{ - int retval=0; - va_list argList; - va_start( argList, pszFormat ); - retval=vprintf(pszFormat,argList); - va_end( argList ); - return retval; -} -#pragma warning(pop) - -#pragma warning(push) -#pragma warning(disable : 4793) -template<> -inline int AtlprintfT(const wchar_t* pszFormat,... ) throw() -{ - int retval=0; - va_list argList; - va_start( argList, pszFormat ); - retval=vwprintf(pszFormat, argList); - va_end( argList ); - return retval; -} -#pragma warning(pop) - -inline BOOL AtlConvertSystemTimeToVariantTime(const SYSTEMTIME& systimeSrc,double* pVarDtTm) -{ - ATLENSURE(pVarDtTm!=NULL); - //Convert using ::SystemTimeToVariantTime and store the result in pVarDtTm then - //convert variant time back to system time and compare to original system time. - BOOL ok = ::SystemTimeToVariantTime(const_cast(&systimeSrc), pVarDtTm); - SYSTEMTIME sysTime; - ::ZeroMemory(&sysTime, sizeof(SYSTEMTIME)); - - ok = ok && ::VariantTimeToSystemTime(*pVarDtTm, &sysTime); - ok = ok && (systimeSrc.wYear == sysTime.wYear && - systimeSrc.wMonth == sysTime.wMonth && - systimeSrc.wDay == sysTime.wDay && - systimeSrc.wHour == sysTime.wHour && - systimeSrc.wMinute == sysTime.wMinute && - systimeSrc.wSecond == sysTime.wSecond); - - return ok; -} -///////////////////////////////////////////////////////////////////////////// - -} // namespace ATL -#pragma pack(pop) - -#ifdef _ATL_ALL_WARNINGS -#pragma warning( pop ) -#endif - -#endif // __ATLCORE_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atldef.h b/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atldef.h deleted file mode 100644 index 9c291bc27..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atldef.h +++ /dev/null @@ -1,660 +0,0 @@ - -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLDEF_H__ -#define __ATLDEF_H__ - -#pragma once - -#pragma warning(disable : 4619) // there is no warning number - -#include -#include -#include - -#ifndef RC_INVOKED - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#ifdef UNDER_CE - #error This version of ATL is not currently supported for CE. Look for the CE specific version. -#endif - -// If you are mixing compilation units that are built as -// native code with those that are built /clr, you must define -// the symbol '_ATL_MIXED'. _ATL_MIXED must be defined for all -// compilation units in an executable or it must be defined for none of them. -#if !defined(_ATL_MIXED) -namespace Inconsistent_definition_of_symbol__ATL_MIXED -{ - struct _Please_define_it_the_same_throughout_your_project { }; -} -#else -namespace Inconsistent_definition_of_symbol__ATL_MIXED -{ -#ifdef _M_IX86 -#pragma comment(linker, "/include:??3@YAXPAX@Z") -#else -#pragma comment(linker, "/include:??3@YAXPEAX@Z") -#endif - struct _Please_define_it_the_same_throughout_your_project { virtual void one(){} }; -} -#endif -namespace Inconsistent_definition_of_symbol__ATL_MIXED -{ - __declspec(selectany) _Please_define_it_the_same_throughout_your_project clash = _Please_define_it_the_same_throughout_your_project (); -} - -#if !defined(_ATL_MIXED) -namespace Define_the_symbol__ATL_MIXED -{ -#if defined(_M_CEE) - struct Thank_you { }; -#else -#ifdef _M_IX86 -#pragma comment(linker, "/include:??3@YAXPAX@Z") -#else -#pragma comment(linker, "/include:??3@YAXPEAX@Z") -#endif - struct Thank_you { virtual void one(){} }; -#endif - __declspec(selectany) Thank_you clash = Thank_you(); -} -#endif - -#if defined(_ATL_MIXED) -#define _ATL_NATIVE_INITIALIZATION -#endif - -#if !defined(_M_CEE) -#define _ATL_NATIVE_INITIALIZATION -#endif - -#ifdef _UNICODE -#ifndef UNICODE -#define UNICODE // UNICODE is used by Windows headers -#endif -#endif - -#ifdef UNICODE -#ifndef _UNICODE -#define _UNICODE // _UNICODE is used by C-runtime/MFC headers -#endif -#endif - -#ifdef _DEBUG -#ifndef DEBUG -#define DEBUG -#endif -#endif - -#ifdef _WIN64 -#define _ATL_SUPPORT_VT_I8 // Always support VT_I8 on Win64. -#endif - -#if !defined(UNALIGNED) -#if defined(_M_IA64) || defined(_M_AMD64) -#define UNALIGNED __unaligned -#else -#define UNALIGNED -#endif -#endif - -#if !defined(_countof) -#if !defined(__cplusplus) -#define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0])) -#else -extern "C++" -{ -template -char (*__countof_helper(UNALIGNED _CountofType (&_Array)[_SizeOfArray]))[_SizeOfArray]; -#define _countof(_Array) sizeof(*__countof_helper(_Array)) -} -#endif -#endif - -#ifndef AtlThrow -#ifndef _ATL_CUSTOM_THROW -#define AtlThrow ATL::AtlThrowImpl -#endif -#endif // AtlThrow - -#ifndef ATLASSERT -#define ATLASSERT(expr) _ASSERTE(expr) -#endif // ATLASSERT - -/* -Why does ATLASSUME exist? - -ATL 8 has two existing validation models - -ATLASSERT/ATLVERIFY - These are used to make sure a debug build reports a problem with the expression/invariant -ATLENSURE - Debug is the same as ATLVERIFY, retail throws a C++ exception - -We added ATLENSURE because there were too many unreported error paths in ATL and we wanted to bail out of more -error conditions rather than just trying to continue in retail. - -There might be a case for changing 'lots' of ATLASSERT to ATLENSURE, but we chose an incremental approach and only -changed over where we saw a problem with code reported from a customer or test case. This reduces code churn in our -code for this version. - -In general, our approach is to try to make sure that when something goes wrong -- the client does not continue to run, because we report an error condition -- debug builds see an assertion about the problem - -Sometimes we have code like - -HRESULT ComMethod(void) -{ - ATLASSUME(m_pFoo); - return m_pFoo->Method(); -} - -We could add - if(!m_pFoo) return E_POINTER; - -But this is very unlikely to help, since it removes the ability of the developer to debug this problem if it's seen in a retail -build of the application. - -We could try something more severe - - if(!m_pFoo) terminate(); // or your favourite shutdown function - -This would ensure good reporting (because VC8 terminate generates a Windows Error Report and crash dump), but hardly seems a big win -over the previous crash. - -ATLENSURE might seem slightly better. It is debuggable and consistent with ATL in general. In fact, many parts of ATL do just this. -But in this specific context, it doesn't look like a great choice. COM methods should not in general be emitting native C++ exceptions -as an error reporting strategy. - -So we find ourselves in a quandry. For these kinds of methods, the traditional code (ATLASSERT followed by a crash), seems be the most -debuggable thing to do in this situation. At least for VS8, we have decided to stick with this shape. - ---- - -Now consider the impact of cl /analyze. We want cl /analyze to not warn about our potential dereferences when they refer to member variables -whose state was previously validated by another method. But we do want to see the impact of function contracts on the parameters of the -function. - -So we've done a broad replace of all the member-related ATLASSERT to ATLASSUME. - -*/ - -#ifndef ATLASSUME -#define ATLASSUME(expr) do { ATLASSERT(expr); __analysis_assume(!!(expr)); } while(0) -#endif // ATLASSERT - -#ifndef ATLVERIFY -#ifdef _DEBUG -#define ATLVERIFY(expr) ATLASSERT(expr) -#else -#define ATLVERIFY(expr) (expr) -#endif // DEBUG -#endif // ATLVERIFY - -#ifndef ATLENSURE_THROW -#define ATLENSURE_THROW(expr, hr) \ -do { \ - int __atl_condVal=!!(expr); \ - ATLASSERT(__atl_condVal); \ - if(!(__atl_condVal)) AtlThrow(hr); \ -} while (0) -#endif // ATLENSURE - -#ifndef ATLENSURE -#define ATLENSURE(expr) ATLENSURE_THROW(expr, E_FAIL) -#endif // ATLENSURE - -#ifndef ATLENSURE_SUCCEEDED -#define ATLENSURE_SUCCEEDED(hr) ATLENSURE_THROW(SUCCEEDED(hr), hr) -#endif // ATLENSURE - -/* Used inside COM methods that do not want to throw */ -#ifndef ATLENSURE_RETURN_HR -#define ATLENSURE_RETURN_HR(expr, hr) \ -do { \ - int __atl_condVal=!!(expr); \ - ATLASSERT(__atl_condVal); \ - if(!(__atl_condVal)) return hr; \ -} while (0) -#endif - -/* Used inside COM methods that do not want to throw */ -#ifndef ATLENSURE_RETURN -#define ATLENSURE_RETURN(expr) ATLENSURE_RETURN_HR(expr, E_FAIL) -#endif - -#ifndef _SECURE_ATL -#define _SECURE_ATL 1 -#endif // _SECURE_ATL - -#if _SECURE_ATL - -#ifndef ATL_CRT_ERRORCHECK -#define ATL_CRT_ERRORCHECK(expr) AtlCrtErrorCheck(expr) -#endif // ATL_CRT_ERRORCHECK - -#ifndef ATL_CRT_ERRORCHECK_SPRINTF -#define ATL_CRT_ERRORCHECK_SPRINTF(expr) \ -do { \ - errno_t _saveErrno = errno; \ - errno = 0; \ - (expr); \ - if(0 != errno) \ - { \ - AtlCrtErrorCheck(errno); \ - } \ - else \ - { \ - errno = _saveErrno; \ - } \ -} while (0) -#endif // ATL_CRT_ERRORCHECK_SPRINTF - -#else // !_SECURE_ATL - -#define ATL_CRT_ERRORCHECK(expr) do { expr; } while (0) -#define ATL_CRT_ERRORCHECK_SPRINTF(expr) do { expr; } while (0) - -#endif // _SECURE_ATL - -/////////////////////////////////////////////////////////////////////////////// -// __declspec(novtable) is used on a class declaration to prevent the vtable -// pointer from being initialized in the constructor and destructor for the -// class. This has many benefits because the linker can now eliminate the -// vtable and all the functions pointed to by the vtable. Also, the actual -// constructor and destructor code are now smaller. -/////////////////////////////////////////////////////////////////////////////// -// This should only be used on a class that is not directly createable but is -// rather only used as a base class. Additionally, the constructor and -// destructor (if provided by the user) should not call anything that may cause -// a virtual function call to occur back on the object. -/////////////////////////////////////////////////////////////////////////////// -// By default, the wizards will generate new ATL object classes with this -// attribute (through the ATL_NO_VTABLE macro). This is normally safe as long -// the restriction mentioned above is followed. It is always safe to remove -// this macro from your class, so if in doubt, remove it. -/////////////////////////////////////////////////////////////////////////////// - -#ifdef _ATL_DISABLE_NO_VTABLE -#define ATL_NO_VTABLE -#else -#define ATL_NO_VTABLE __declspec(novtable) -#endif - -#ifdef _ATL_DISABLE_NOTHROW -#define ATL_NOTHROW -#else -#define ATL_NOTHROW __declspec(nothrow) -#endif - -#ifdef _ATL_DISABLE_FORCEINLINE -#define ATL_FORCEINLINE -#else -#define ATL_FORCEINLINE __forceinline -#endif - -#ifdef _ATL_DISABLE_NOINLINE -#define ATL_NOINLINE -#else -#define ATL_NOINLINE __declspec( noinline ) -#endif - -#ifdef _ATL_DISABLE_DEPRECATED -#define ATL_DEPRECATED(_Message) -#else -#define ATL_DEPRECATED(_Message) __declspec( deprecated(_Message) ) -#endif - -// If ATL80.DLL is being used then _ATL_STATIC_REGISTRY doesn't really make sense -#ifdef _ATL_DLL -#undef _ATL_STATIC_REGISTRY -#else -// If not linking to ATL80.DLL, use the static registrar and not building atl.dll -#ifndef _ATL_DLL_IMPL -#ifndef _ATL_STATIC_REGISTRY -#define _ATL_STATIC_REGISTRY -#endif -#endif -#endif - -#ifdef _ATL_DEBUG_REFCOUNT -#ifndef _ATL_DEBUG_INTERFACES -#define _ATL_DEBUG_INTERFACES -#endif -#endif - -#ifdef _DEBUG -#ifndef _ATL_DEBUG -#define _ATL_DEBUG -#endif // _ATL_DEBUG -#endif // _DEBUG - -#ifdef _ATL_DEBUG_INTERFACES -#ifndef _ATL_DEBUG -#define _ATL_DEBUG -#endif // _ATL_DEBUG -#endif // _ATL_DEBUG_INTERFACES - -#ifndef _ATL_HEAPFLAGS -#ifdef _MALLOC_ZEROINIT -#define _ATL_HEAPFLAGS HEAP_ZERO_MEMORY -#else -#define _ATL_HEAPFLAGS 0 -#endif -#endif - -#ifndef _ATL_PACKING -#define _ATL_PACKING 8 -#endif - -#if defined(_ATL_DLL) - #define ATLAPI extern "C" HRESULT __declspec(dllimport) __stdcall - #define ATLAPI_(x) extern "C" __declspec(dllimport) x __stdcall - #define ATLINLINE - #define ATLAPIINL extern "C" inline HRESULT __stdcall - #define ATLAPIINL_(x) extern "C" inline x __stdcall -#elif defined(_ATL_DLL_IMPL) - #define ATLAPI extern "C" inline HRESULT __stdcall - #define ATLAPI_(x) extern "C" inline x __stdcall - #define ATLAPIINL ATLAPI - #define ATLAPIINL_(x) ATLAPI_(x) - #define ATLINLINE -#else - #define ATLAPI __declspec(nothrow) HRESULT __stdcall - #define ATLAPI_(x) __declspec(nothrow) x __stdcall - #define ATLAPIINL ATLAPI - #define ATLAPIINL_(x) ATLAPI_(x) - #define ATLINLINE inline -#endif - -#ifdef _ATL_NO_EXCEPTIONS - #ifdef _AFX - #error MFC projects cannot define _ATL_NO_EXCEPTIONS - #endif -#else - #ifndef _CPPUNWIND - #define _ATL_NO_EXCEPTIONS - #endif -#endif - -#ifdef _CPPUNWIND - -#ifndef ATLTRYALLOC - -#ifdef _AFX -#define ATLTRYALLOC(x) try{x;} catch(CException* e){e->Delete();} -#else -/* prefast noise VSW 489981 */ -#define ATLTRYALLOC(x) __pragma(warning(push)) __pragma(warning(disable: 4571)) try{x;} catch(...) {} __pragma(warning(pop)) -#endif //__AFX - -#endif //ATLTRYALLOC - -// If you define _ATLTRY before including this file, then -// you should define _ATLCATCH and _ATLRETHROW as well. -#ifndef _ATLTRY -#define _ATLTRY try -#ifdef _AFX -#define _ATLCATCH( e ) catch( CException* e ) -#else -#define _ATLCATCH( e ) catch( CAtlException e ) -#endif - -#define _ATLCATCHALL() __pragma(warning(push)) __pragma(warning(disable: 4571)) catch( ... ) __pragma(warning(pop)) - -#ifdef _AFX -#define _ATLDELETEEXCEPTION(e) e->Delete(); -#else -#define _ATLDELETEEXCEPTION(e) e; -#endif - -#define _ATLRETHROW throw -#endif // _ATLTRY - -/* -COM functions should not throw. Which means we should protect their callers from C++ exceptions leaking out. These macros -can help with that, though they have not yet been applied to the whole of ATL, which uses a variety of patterns to achieve -this end -*/ - -#ifndef _ATL_COM_BEGIN -#define _ATL_COM_BEGIN \ - HRESULT __hrAtlComMethod=S_OK; \ - try \ - { -#endif - -#ifdef _AFX -/* Nice to do something more complex here in future to translate an MFC exception to a better HR */ -#define _AFX_COM_END_PART \ - catch(CException *e) \ - { \ - if(e) \ - { \ - e->Delete(); \ - } \ - __hrAtlComMethod=E_FAIL; \ - } -#else -#define _AFX_COM_END_PART \ - catch(CAtlException e) \ - { \ - __hrAtlComMethod=e.m_hr; \ - } -#endif - -#ifndef _ATL_COM_END -#define _ATL_COM_END \ - _AFX_COM_END_PART \ - catch(...) \ - { \ - __hrAtlComMethod=E_FAIL; \ - } \ - return hr; -#endif - - - -#else //_CPPUNWIND - -#ifndef ATLTRYALLOC -#define ATLTRYALLOC(x) x; -#endif //ATLTRYALLOC - -// if _ATLTRY is defined before including this file then -// _ATLCATCH and _ATLRETHROW should be defined as well. -#ifndef _ATLTRY -#define _ATLTRY -#define _ATLCATCH( e ) __pragma(warning(push)) __pragma(warning(disable: 4127)) if( false ) __pragma(warning(pop)) -#define _ATLCATCHALL() __pragma(warning(push)) __pragma(warning(disable: 4127)) if( false ) __pragma(warning(pop)) -#define _ATLDELETEEXCEPTION(e) -#define _ATLRETHROW -#endif // _ATLTRY - -#endif //_CPPUNWIND - -#ifndef ATLTRY -#define ATLTRY(x) ATLTRYALLOC(x) -#endif //ATLTRY - -#define offsetofclass(base, derived) ((DWORD_PTR)(static_cast((derived*)_ATL_PACKING))-_ATL_PACKING) - -///////////////////////////////////////////////////////////////////////////// -// Master version numbers - -#define _ATL 1 // Active Template Library -#define _ATL_VER 0x0800 // Active Template Library version 8.00 - -///////////////////////////////////////////////////////////////////////////// -// Threading - -#ifndef _ATL_SINGLE_THREADED -#ifndef _ATL_APARTMENT_THREADED -#ifndef _ATL_FREE_THREADED -#define _ATL_FREE_THREADED -#endif -#endif -#endif - -// UUIDOF -#ifndef _ATL_NO_UUIDOF -#define _ATL_IIDOF(x) __uuidof(x) -#else -#define _ATL_IIDOF(x) IID_##x -#endif - -// Lean and mean -#ifndef ATL_NO_LEAN_AND_MEAN -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#ifndef NOMCX -#define NOMCX -#endif -#endif // ATL_NO_LEAN_AND_MEAN - -#ifdef NOSERVICE -#ifndef _ATL_NO_SERVICE -#define _ATL_NO_SERVICE -#endif // _ATL_NO_SERVICE -#else -#ifdef _ATL_NO_SERVICE -#ifndef NOSERVICE -#define NOSERVICE -#endif // NOSERVICE -#endif // _ATL_NO_SERVICE -#endif // NOSERVICE - -#include -#ifdef _DEBUG -#include -#endif -#ifndef _ATL_NO_DEBUG_CRT -// Warning: if you define the above symbol, you will have -// to provide your own definition of the ATLASSERT(x) macro -// in order to compile ATL - #include -#endif - -#endif // RC_INVOKED - -#define ATLAXWIN_CLASS "AtlAxWin80" -#define ATLAXWINLIC_CLASS "AtlAxWinLic80" - -// _ATL_INSECURE_DEPRECATE define -#ifndef _ATL_INSECURE_DEPRECATE -#ifdef _ATL_SECURE_NO_DEPRECATE -#define _ATL_INSECURE_DEPRECATE(_Message) -#else -#define _ATL_INSECURE_DEPRECATE(_Message) __declspec(deprecated(_Message)) -#endif // _ATL_SECURE_NO_DEPRECATE -#endif // _ATL_INSECURE_DEPRECATE - -/* -This is called when something really bad happens -- so bad -that we consider it dangerous to even throw an exception -*/ -#ifndef _ATL_FATAL_SHUTDOWN -#define _ATL_FATAL_SHUTDOWN do { ::TerminateProcess(::GetCurrentProcess(), 0); } while(0); -#endif - -//ATL/MFC code should use standard pointer to member standard syntax &MyClass::MyMethod, instead -//of the legacy non-standard syntax - MyMethod. -#ifdef _ATL_ENABLE_PTM_WARNING -#define PTM_WARNING_DISABLE -#define PTM_WARNING_RESTORE -#else -#define PTM_WARNING_DISABLE \ - __pragma(warning( push )) \ - __pragma(warning( disable : 4867 )) -#define PTM_WARNING_RESTORE \ - __pragma(warning( pop )) -#endif //_ATL_ENABLE_PTM_WARNING - -/* we have to define our own versions of MAKEINTRESOURCE and IS_INTRESOURCE to - * fix warning 6268. At least until those macros are not cleanend in PSDK. - Same comes true for those definitions of constants which use the above macros -*/ -#define ATL_MAKEINTRESOURCEA(i) ((LPSTR)((ULONG_PTR)((WORD)(i)))) -#define ATL_MAKEINTRESOURCEW(i) ((LPWSTR)((ULONG_PTR)((WORD)(i)))) -#ifdef UNICODE -#define ATL_MAKEINTRESOURCE ATL_MAKEINTRESOURCEW -#else -#define ATL_MAKEINTRESOURCE ATL_MAKEINTRESOURCEA -#endif // !UNICODE -#define ATL_IS_INTRESOURCE(_r) ((((ULONG_PTR)(_r)) >> 16) == 0) - -/* - * Predefined Resource Types - */ -#define ATL_RT_CURSOR ATL_MAKEINTRESOURCE(1) -#define ATL_RT_BITMAP ATL_MAKEINTRESOURCE(2) -#define ATL_RT_ICON ATL_MAKEINTRESOURCE(3) -#define ATL_RT_MENU ATL_MAKEINTRESOURCE(4) -#define ATL_RT_DIALOG ATL_MAKEINTRESOURCE(5) -#define ATL_RT_STRING ATL_MAKEINTRESOURCE(6) -#define ATL_RT_FONTDIR ATL_MAKEINTRESOURCE(7) -#define ATL_RT_FONT ATL_MAKEINTRESOURCE(8) -#define ATL_RT_ACCELERATOR ATL_MAKEINTRESOURCE(9) -#define ATL_RT_RCDATA ATL_MAKEINTRESOURCE(10) -#define ATL_RT_MESSAGETABLE ATL_MAKEINTRESOURCE(11) - -#define ATL_DIFFERENCE 11 -#define ATL_RT_GROUP_CURSOR ATL_MAKEINTRESOURCE((ULONG_PTR)ATL_RT_CURSOR + ATL_DIFFERENCE) -#define ATL_RT_GROUP_ICON ATL_MAKEINTRESOURCE((ULONG_PTR)ATL_RT_ICON + ATL_DIFFERENCE) -#define ATL_RT_VERSION ATL_MAKEINTRESOURCE(16) -#define ATL_RT_DLGINCLUDE ATL_MAKEINTRESOURCE(17) -#if(WINVER >= 0x0400) -#define ATL_RT_PLUGPLAY ATL_MAKEINTRESOURCE(19) -#define ATL_RT_VXD ATL_MAKEINTRESOURCE(20) -#define ATL_RT_ANICURSOR ATL_MAKEINTRESOURCE(21) -#define ATL_RT_ANIICON ATL_MAKEINTRESOURCE(22) -#endif /* WINVER >= 0x0400 */ -#define ATL_RT_HTML ATL_MAKEINTRESOURCE(23) -#ifdef RC_INVOKED -#define ATL_RT_MANIFEST 24 -#define ATL_CREATEPROCESS_MANIFEST_RESOURCE_ID 1 -#define ATL_ISOLATIONAWARE_MANIFEST_RESOURCE_ID 2 -#define ATL_ISOLATIONAWARE_NOSTATICIMPORT_MANIFEST_RESOURCE_ID 3 -#define ATL_MINIMUM_RESERVED_MANIFEST_RESOURCE_ID 1 /* inclusive */ -#define ATL_MAXIMUM_RESERVED_MANIFEST_RESOURCE_ID 16 /* inclusive */ -#else /* RC_INVOKED */ -#define ATL_RT_MANIFEST ATL_MAKEINTRESOURCE(24) -#define ATL_CREATEPROCESS_MANIFEST_RESOURCE_ID ATL_MAKEINTRESOURCE( 1) -#define ATL_ISOLATIONAWARE_MANIFEST_RESOURCE_ID ATL_MAKEINTRESOURCE(2) -#define ATL_ISOLATIONAWARE_NOSTATICIMPORT_MANIFEST_RESOURCE_ID ATL_MAKEINTRESOURCE(3) -#define ATL_MINIMUM_RESERVED_MANIFEST_RESOURCE_ID ATL_MAKEINTRESOURCE( 1 /*inclusive*/) -#define ATL_MAXIMUM_RESERVED_MANIFEST_RESOURCE_ID ATL_MAKEINTRESOURCE(16 /*inclusive*/) -#endif /* RC_INVOKED */ - -/* sal.h stuff that is not in the current LKG */ -#ifndef __out_ecount_part_z -#define __out_ecount_part_z(size,length) __out_ecount_part(size,length) __post __nullterminated -#endif - -#ifndef __out_ecount_part_z_opt -#define __out_ecount_part_z_opt(size,length) __out_ecount_part_opt(size,length) __post __nullterminated -#endif - -#ifndef __deref_opt_out_z -#define __deref_opt_out_z __deref_opt_out __post __deref __nullterminated -#endif - -#ifndef __out_bcount_part_z -#define __out_bcount_part_z(size,length) __out_bcount_part(size,length) __post __nullterminated -#endif - -#endif // __ATLDEF_H__ - -///////////////////////////////////////////////////////////////////////////// diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlexcept.h b/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlexcept.h deleted file mode 100644 index fa24d937a..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlexcept.h +++ /dev/null @@ -1,121 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLEXCEPT_H__ -#define __ATLEXCEPT_H__ - -#pragma once - -#include -#include - - -#pragma pack(push,_ATL_PACKING) -namespace ATL -{ - -///////////////////////////////////////////////////////////////////////////// -// Exception raise (for functions that cannot return an error code) - -inline void __declspec(noreturn) _AtlRaiseException( DWORD dwExceptionCode, DWORD dwExceptionFlags = EXCEPTION_NONCONTINUABLE ) -{ - RaiseException( dwExceptionCode, dwExceptionFlags, 0, NULL ); -} - -class CAtlException -{ -public: - CAtlException() throw() : - m_hr( E_FAIL ) - { - } - - CAtlException( HRESULT hr ) throw() : - m_hr( hr ) - { - } - - operator HRESULT() const throw() - { - return( m_hr ); - } - -public: - HRESULT m_hr; -}; - -#ifndef _ATL_NO_EXCEPTIONS - -// Throw a CAtlException with the given HRESULT -#if defined( _ATL_CUSTOM_THROW ) // You can define your own AtlThrow to throw a custom exception. -#ifdef _AFX -#error MFC projects must use default implementation of AtlThrow() -#endif -#else -ATL_NOINLINE __declspec(noreturn) inline void WINAPI AtlThrowImpl( HRESULT hr ) -{ - ATLTRACE(atlTraceException, 0, _T("AtlThrow: hr = 0x%x\n"), hr ); -#ifdef _AFX - if( hr == E_OUTOFMEMORY ) - { - AfxThrowMemoryException(); - } - else - { - AfxThrowOleException( hr ); - } -#else - throw CAtlException( hr ); -#endif -}; -#endif - -// Throw a CAtlException corresponding to the result of ::GetLastError -ATL_NOINLINE __declspec(noreturn) inline void WINAPI AtlThrowLastWin32() -{ - DWORD dwError = ::GetLastError(); - AtlThrow( HRESULT_FROM_WIN32( dwError ) ); -} - -#else // no exception handling - -// Throw a CAtlException with th given HRESULT -#if !defined( _ATL_CUSTOM_THROW ) // You can define your own AtlThrow - -ATL_NOINLINE inline void WINAPI AtlThrowImpl( HRESULT hr ) -{ - ATLTRACE(atlTraceException, 0, _T("AtlThrow: hr = 0x%x\n"), hr ); - ATLASSERT( false ); - DWORD dwExceptionCode; - switch(hr) - { - case E_OUTOFMEMORY: - dwExceptionCode = STATUS_NO_MEMORY; - break; - default: - dwExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; - } - _AtlRaiseException((DWORD)dwExceptionCode); -} -#endif - -// Throw a CAtlException corresponding to the result of ::GetLastError -ATL_NOINLINE inline void WINAPI AtlThrowLastWin32() -{ - DWORD dwError = ::GetLastError(); - AtlThrow( HRESULT_FROM_WIN32( dwError ) ); -} - -#endif // no exception handling - -}; // namespace ATL -#pragma pack(pop) - -#endif // __ATLEXCEPT_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlhost.h b/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlhost.h deleted file mode 100644 index e2889646d..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlhost.h +++ /dev/null @@ -1,2718 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLHOST_H__ -#define __ATLHOST_H__ - -#pragma once - -#ifndef _ATL_NO_PRAGMA_WARNINGS -#pragma warning (push) -#pragma warning(disable: 4702) // unreachable code -#pragma warning(disable: 4127) // conditional expression constant -#pragma warning(disable: 4571) //catch(...) blocks compiled with /EHs do NOT catch or re-throw Structured Exceptions -#endif //!_ATL_NO_PRAGMA_WARNINGS - -#include -#include -#include -#include - -#ifndef _ATL_AXHOST -#define _ATL_AXHOST -#endif //_ATL_AXHOST - -#include -#include - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#ifdef _ATL_NO_HOSTING - #error atlhost.h requires Hosting support (_ATL_NO_HOSTING is defined) -#endif //_ATL_NO_HOSTING - - -#pragma pack(push,_ATL_PACKING) -namespace ATL -{ -//AtlAxWinTerm is not exported -inline BOOL AtlAxWinTerm() -{ -#ifndef _ATL_DLL //don't unregister DLL's version - UnregisterClass(CAxWindow::GetWndClassName(), _AtlBaseModule.GetModuleInstance()); - UnregisterClass(CAxWindow2::GetWndClassName(), _AtlBaseModule.GetModuleInstance()); -#endif - return TRUE; -} - - -// Define this to host SHDOCVW rather than MSHTML -#define SHDOCVW - -UINT __declspec(selectany) WM_ATLGETHOST = 0; -UINT __declspec(selectany) WM_ATLGETCONTROL = 0; - -typedef HRESULT (__stdcall *typeMkParseDisplayName)(IBindCtx*, LPCWSTR , ULONG*, LPMONIKER*); - -static HRESULT CreateNormalizedObject(LPCOLESTR lpszTricsData, REFIID riid, void** ppvObj, bool& bWasHTML, BSTR bstrLicKey) -{ - ATLASSERT(ppvObj); - if (ppvObj == NULL) - { - return E_POINTER; - } - *ppvObj = NULL; - - CLSID clsid; - HRESULT hr = E_FAIL; - - bWasHTML = false; - - if (lpszTricsData == NULL || lpszTricsData[0] == 0) - { - return S_OK; - } - - // Is it HTML ? - if ((lpszTricsData[0] == OLECHAR('M') || lpszTricsData[0] == OLECHAR('m')) && - (lpszTricsData[1] == OLECHAR('S') || lpszTricsData[1] == OLECHAR('s')) && - (lpszTricsData[2] == OLECHAR('H') || lpszTricsData[2] == OLECHAR('h')) && - (lpszTricsData[3] == OLECHAR('T') || lpszTricsData[3] == OLECHAR('t')) && - (lpszTricsData[4] == OLECHAR('M') || lpszTricsData[4] == OLECHAR('m')) && - (lpszTricsData[5] == OLECHAR('L') || lpszTricsData[5] == OLECHAR('l')) && - (lpszTricsData[6] == OLECHAR(':'))) - { - // It's HTML, so let's create mshtml - hr = CoCreateInstance(__uuidof(HTMLDocument), NULL, CLSCTX_INPROC_SERVER, riid, ppvObj); - bWasHTML = true; - } - // Is it a URL? - else if (CAtlModule::FindOneOf(COLE2CT(lpszTricsData), _T(":"))) - { - // URL so let's create shdocvw - hr = CoCreateInstance(__uuidof(WebBrowser), NULL, CLSCTX_INPROC_SERVER, riid, ppvObj); - bWasHTML = true; - } - // assume ProgID or CLSID - else - { - // Can't be clsid, or progid if length is greater than 255 - if (ocslen(lpszTricsData) < 255) - { - if (lpszTricsData[0] == '{') // Is it a CLSID? - { - hr = CLSIDFromString((LPOLESTR)lpszTricsData, &clsid); - } - else - { - hr = CLSIDFromProgID((LPOLESTR)lpszTricsData, &clsid); // How about a ProgID? - } - } - if (SUCCEEDED(hr)) - { - // If the license key is present - // Create using IClassFactory2. - if (::SysStringLen(bstrLicKey) != 0) - { - CComPtr spClassFactory; - hr = CoGetClassObject(clsid, CLSCTX_INPROC_SERVER, NULL, __uuidof(IClassFactory2), (void**)&spClassFactory); - if (SUCCEEDED(hr)) - { - hr = spClassFactory->CreateInstanceLic(NULL, NULL, riid, bstrLicKey, ppvObj); - } - } - else - { - hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, riid, ppvObj); - } - } - } - return hr; -} - - -class ATL_NO_VTABLE CAxFrameWindow : - public CComObjectRootEx, - public CWindowImpl, - public IOleInPlaceFrame -{ -public: - CAxFrameWindow() - { - } - void FinalRelease() - { - m_spActiveObject.Release(); - if (m_hWnd) - DestroyWindow(); - } - - DECLARE_POLY_AGGREGATABLE(CAxFrameWindow) - - BEGIN_COM_MAP(CAxFrameWindow) - COM_INTERFACE_ENTRY(IOleInPlaceFrame) - COM_INTERFACE_ENTRY(IOleInPlaceUIWindow) - COM_INTERFACE_ENTRY(IOleWindow) - END_COM_MAP() - - DECLARE_EMPTY_MSG_MAP() - -// IOleWindow - STDMETHOD(GetWindow)(HWND* phwnd) - { - ATLASSERT(phwnd != NULL); - if (phwnd == NULL) - return E_POINTER; - - if (m_hWnd == NULL) - Create(NULL, NULL, _T("AXWIN Frame Window"), WS_OVERLAPPEDWINDOW, 0, (UINT)NULL); - *phwnd = m_hWnd; - return S_OK; - } - STDMETHOD(ContextSensitiveHelp)(BOOL /*fEnterMode*/) - { - return S_OK; - } - -// IOleInPlaceUIWindow - STDMETHOD(GetBorder)(LPRECT /*lprectBorder*/) - { - return S_OK; - } - - STDMETHOD(RequestBorderSpace)(LPCBORDERWIDTHS /*pborderwidths*/) - { - return INPLACE_E_NOTOOLSPACE; - } - - STDMETHOD(SetBorderSpace)(LPCBORDERWIDTHS /*pborderwidths*/) - { - return S_OK; - } - - STDMETHOD(SetActiveObject)(IOleInPlaceActiveObject* pActiveObject, LPCOLESTR /*pszObjName*/) - { - m_spActiveObject = pActiveObject; - return S_OK; - } - -// IOleInPlaceFrameWindow - STDMETHOD(InsertMenus)(HMENU /*hmenuShared*/, LPOLEMENUGROUPWIDTHS /*lpMenuWidths*/) - { - return S_OK; - } - - STDMETHOD(SetMenu)(HMENU /*hmenuShared*/, HOLEMENU /*holemenu*/, HWND /*hwndActiveObject*/) - { - return S_OK; - } - - STDMETHOD(RemoveMenus)(HMENU /*hmenuShared*/) - { - return S_OK; - } - - STDMETHOD(SetStatusText)(LPCOLESTR /*pszStatusText*/) - { - return S_OK; - } - - STDMETHOD(EnableModeless)(BOOL /*fEnable*/) - { - return S_OK; - } - - STDMETHOD(TranslateAccelerator)(LPMSG /*lpMsg*/, WORD /*wID*/) - { - return S_FALSE; - } - - CComPtr m_spActiveObject; -}; - - -class ATL_NO_VTABLE CAxUIWindow : - public CComObjectRootEx, - public CWindowImpl, - public IOleInPlaceUIWindow -{ -public: - CAxUIWindow() - { - } - - void FinalRelease() - { - m_spActiveObject.Release(); - if (m_hWnd) - DestroyWindow(); - } - - DECLARE_POLY_AGGREGATABLE(CAxUIWindow) - - BEGIN_COM_MAP(CAxUIWindow) - COM_INTERFACE_ENTRY(IOleInPlaceUIWindow) - COM_INTERFACE_ENTRY(IOleWindow) - END_COM_MAP() - - DECLARE_EMPTY_MSG_MAP() - -// IOleWindow - STDMETHOD(GetWindow)(HWND* phwnd) - { - if (m_hWnd == NULL) - Create(NULL, NULL, _T("AXWIN UI Window"), WS_OVERLAPPEDWINDOW, 0, (UINT)NULL); - *phwnd = m_hWnd; - return S_OK; - } - - STDMETHOD(ContextSensitiveHelp)(BOOL /*fEnterMode*/) - { - return S_OK; - } - -// IOleInPlaceUIWindow - STDMETHOD(GetBorder)(LPRECT /*lprectBorder*/) - { - return S_OK; - } - - STDMETHOD(RequestBorderSpace)(LPCBORDERWIDTHS /*pborderwidths*/) - { - return INPLACE_E_NOTOOLSPACE; - } - - STDMETHOD(SetBorderSpace)(LPCBORDERWIDTHS /*pborderwidths*/) - { - return S_OK; - } - - STDMETHOD(SetActiveObject)(IOleInPlaceActiveObject* pActiveObject, LPCOLESTR /*pszObjName*/) - { - m_spActiveObject = pActiveObject; - return S_OK; - } - - CComPtr m_spActiveObject; -}; - - -///////////////////////////////////////////////////////////////////////////// -// CAxHostWindow -// This class is not cocreateable - -class ATL_NO_VTABLE CAxHostWindow : - public CComCoClass, - public CComObjectRootEx, - public CWindowImpl, - public IAxWinHostWindowLic, - public IOleClientSite, - public IOleInPlaceSiteWindowless, - public IOleControlSite, - public IOleContainer, - public IObjectWithSiteImpl, - public IServiceProvider, - public IAdviseSink, -#ifndef _ATL_NO_DOCHOSTUIHANDLER - public IDocHostUIHandler, -#endif - public IDispatchImpl -{ -public: -// ctor/dtor - CAxHostWindow() - { - m_bInPlaceActive = FALSE; - m_bUIActive = FALSE; - m_bMDIApp = FALSE; - m_bWindowless = FALSE; - m_bCapture = FALSE; - m_bHaveFocus = FALSE; - - // Initialize ambient properties - m_bCanWindowlessActivate = TRUE; - m_bUserMode = TRUE; - m_bDisplayAsDefault = FALSE; - m_clrBackground = NULL; - m_clrForeground = GetSysColor(COLOR_WINDOWTEXT); - m_lcidLocaleID = LOCALE_USER_DEFAULT; - m_bMessageReflect = true; - - m_bReleaseAll = FALSE; - - m_bSubclassed = FALSE; - - m_dwAdviseSink = 0xCDCDCDCD; - m_dwDocHostFlags = DOCHOSTUIFLAG_NO3DBORDER; - m_dwDocHostDoubleClickFlags = DOCHOSTUIDBLCLK_DEFAULT; - m_bAllowContextMenu = true; - m_bAllowShowUI = false; - m_hDCScreen = NULL; - m_bDCReleased = true; - - m_hAccel = NULL; - } - - ~CAxHostWindow() - { - } - void FinalRelease() - { - ReleaseAll(); - } - - virtual void OnFinalMessage(HWND /*hWnd*/) - { - GetControllingUnknown()->Release(); - } - - DECLARE_NO_REGISTRY() - DECLARE_POLY_AGGREGATABLE(CAxHostWindow) - DECLARE_GET_CONTROLLING_UNKNOWN() - - BEGIN_COM_MAP(CAxHostWindow) - COM_INTERFACE_ENTRY2(IDispatch, IAxWinAmbientDispatchEx) - COM_INTERFACE_ENTRY(IAxWinHostWindow) - COM_INTERFACE_ENTRY(IAxWinHostWindowLic) - COM_INTERFACE_ENTRY(IOleClientSite) - COM_INTERFACE_ENTRY(IOleInPlaceSiteWindowless) - COM_INTERFACE_ENTRY(IOleInPlaceSiteEx) - COM_INTERFACE_ENTRY(IOleInPlaceSite) - COM_INTERFACE_ENTRY(IOleWindow) - COM_INTERFACE_ENTRY(IOleControlSite) - COM_INTERFACE_ENTRY(IOleContainer) - COM_INTERFACE_ENTRY(IObjectWithSite) - COM_INTERFACE_ENTRY(IServiceProvider) - COM_INTERFACE_ENTRY(IAxWinAmbientDispatchEx) - COM_INTERFACE_ENTRY(IAxWinAmbientDispatch) -#ifndef _ATL_NO_DOCHOSTUIHANDLER - COM_INTERFACE_ENTRY(IDocHostUIHandler) -#endif - COM_INTERFACE_ENTRY(IAdviseSink) - END_COM_MAP() - - static CWndClassInfo& GetWndClassInfo() - { - static CWndClassInfo wc = - { - { sizeof(WNDCLASSEX), 0, StartWindowProc, - 0, 0, 0, 0, 0, (HBRUSH)(COLOR_WINDOW + 1), 0, _T(ATLAXWIN_CLASS), 0 }, - NULL, NULL, IDC_ARROW, TRUE, 0, _T("") - }; - return wc; - } - - BEGIN_MSG_MAP(CAxHostWindow) - MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) - MESSAGE_HANDLER(WM_PAINT, OnPaint) - MESSAGE_HANDLER(WM_SIZE, OnSize) - MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActivate) - MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) - MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus) - if (m_bWindowless && uMsg >= WM_MOUSEFIRST && uMsg <= WM_MOUSELAST) - { - // Mouse messages handled when a windowless control has captured the cursor - // or if the cursor is over the control - DWORD dwHitResult = m_bCapture ? HITRESULT_HIT : HITRESULT_OUTSIDE; - if (dwHitResult == HITRESULT_OUTSIDE && m_spViewObject != NULL) - { - POINT ptMouse = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; - m_spViewObject->QueryHitPoint(DVASPECT_CONTENT, &m_rcPos, ptMouse, 0, &dwHitResult); - } - if (dwHitResult == HITRESULT_HIT) - { - MESSAGE_HANDLER(WM_MOUSEMOVE, OnWindowlessMouseMessage) - MESSAGE_HANDLER(WM_LBUTTONUP, OnWindowlessMouseMessage) - MESSAGE_HANDLER(WM_RBUTTONUP, OnWindowlessMouseMessage) - MESSAGE_HANDLER(WM_MBUTTONUP, OnWindowlessMouseMessage) - MESSAGE_HANDLER(WM_LBUTTONDOWN, OnWindowlessMouseMessage) - MESSAGE_HANDLER(WM_RBUTTONDOWN, OnWindowlessMouseMessage) - MESSAGE_HANDLER(WM_MBUTTONDOWN, OnWindowlessMouseMessage) - MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnWindowlessMouseMessage) - MESSAGE_HANDLER(WM_RBUTTONDBLCLK, OnWindowlessMouseMessage) - MESSAGE_HANDLER(WM_MBUTTONDBLCLK, OnWindowlessMouseMessage) - } - } - if (m_bWindowless & m_bHaveFocus) - { - // Keyboard messages handled only when a windowless control has the focus - MESSAGE_HANDLER(WM_KEYDOWN, OnWindowMessage) - MESSAGE_HANDLER(WM_KEYUP, OnWindowMessage) - MESSAGE_HANDLER(WM_CHAR, OnWindowMessage) - MESSAGE_HANDLER(WM_DEADCHAR, OnWindowMessage) - MESSAGE_HANDLER(WM_SYSKEYDOWN, OnWindowMessage) - MESSAGE_HANDLER(WM_SYSKEYUP, OnWindowMessage) - MESSAGE_HANDLER(WM_SYSDEADCHAR, OnWindowMessage) - MESSAGE_HANDLER(WM_HELP, OnWindowMessage) - MESSAGE_HANDLER(WM_CANCELMODE, OnWindowMessage) - MESSAGE_HANDLER(WM_IME_CHAR, OnWindowMessage) - MESSAGE_HANDLER(WM_MBUTTONDBLCLK, OnWindowMessage) - MESSAGE_RANGE_HANDLER(WM_IME_SETCONTEXT, WM_IME_KEYUP, OnWindowMessage) - } - MESSAGE_HANDLER(WM_DESTROY, OnDestroy) - if (m_bMessageReflect) - { - bHandled = TRUE; - lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); - if(bHandled) - return TRUE; - } - MESSAGE_HANDLER(WM_ATLGETHOST, OnGetUnknown) - MESSAGE_HANDLER(WM_ATLGETCONTROL, OnGetControl) - MESSAGE_HANDLER(WM_FORWARDMSG, OnForwardMsg) - END_MSG_MAP() - - LRESULT OnForwardMsg(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) - { - ATLASSERT(lParam != 0); - LPMSG lpMsg = (LPMSG)lParam; - CComQIPtr spInPlaceActiveObject(m_spUnknown); - if(spInPlaceActiveObject) - { - if(spInPlaceActiveObject->TranslateAccelerator(lpMsg) == S_OK) - return 1; - } - return 0; - } - - LRESULT OnGetUnknown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - IUnknown* pUnk = GetControllingUnknown(); - pUnk->AddRef(); - return (LRESULT)pUnk; - } - LRESULT OnGetControl(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - IUnknown* pUnk = m_spUnknown; - if (pUnk) - pUnk->AddRef(); - return (LRESULT)pUnk; - } - - void ReleaseAll() - { - if (m_bReleaseAll) - return; - m_bReleaseAll = TRUE; - - if (m_spViewObject != NULL) - m_spViewObject->SetAdvise(DVASPECT_CONTENT, 0, NULL); - - if(m_dwAdviseSink != 0xCDCDCDCD) - { - AtlUnadvise(m_spUnknown, m_iidSink, m_dwAdviseSink); - m_dwAdviseSink = 0xCDCDCDCD; - } - - if (m_spOleObject) - { - m_spOleObject->Unadvise(m_dwOleObject); - m_spOleObject->Close(OLECLOSE_NOSAVE); - m_spOleObject->SetClientSite(NULL); - } - - if (m_spUnknown != NULL) - { - CComPtr spSite; - m_spUnknown->QueryInterface(__uuidof(IObjectWithSite), (void**)&spSite); - if (spSite != NULL) - spSite->SetSite(NULL); - } - - m_spViewObject.Release(); - m_dwViewObjectType = 0; - - m_spInPlaceObjectWindowless.Release(); - m_spOleObject.Release(); - m_spUnknown.Release(); - - m_spInPlaceUIWindow.Release(); - m_spInPlaceFrame.Release(); - - m_bInPlaceActive = FALSE; - m_bWindowless = FALSE; - m_bInPlaceActive = FALSE; - m_bUIActive = FALSE; - m_bCapture = FALSE; - m_bReleaseAll = FALSE; - - if (m_hAccel != NULL) - { - DestroyAcceleratorTable(m_hAccel); - m_hAccel = NULL; - } - } - - -// window message handlers - LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - if (m_spViewObject == NULL) - bHandled = false; - - return 1; - } - - LRESULT OnMouseActivate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - bHandled = FALSE; - if (m_dwMiscStatus & OLEMISC_NOUIACTIVATE) - { - if (m_spOleObject != NULL && !m_bInPlaceActive) - { - CComPtr spClientSite; - GetControllingUnknown()->QueryInterface(__uuidof(IOleClientSite), (void**)&spClientSite); - if (spClientSite != NULL) - m_spOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, spClientSite, 0, m_hWnd, &m_rcPos); - } - } - else - { - BOOL b; - OnSetFocus(0, 0, 0, b); - } - return 0; - } - LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - m_bHaveFocus = TRUE; - if (!m_bReleaseAll) - { - if (m_spOleObject != NULL && !m_bUIActive) - { - CComPtr spClientSite; - GetControllingUnknown()->QueryInterface(__uuidof(IOleClientSite), (void**)&spClientSite); - if (spClientSite != NULL) - m_spOleObject->DoVerb(OLEIVERB_UIACTIVATE, NULL, spClientSite, 0, m_hWnd, &m_rcPos); - } - if (m_bWindowless) - ::SetFocus(m_hWnd); - else if(!IsChild(::GetFocus())) - ::SetFocus(::GetWindow(m_hWnd, GW_CHILD)); - } - bHandled = FALSE; - return 0; - } - LRESULT OnKillFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - m_bHaveFocus = FALSE; - bHandled = FALSE; - return 0; - } - LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) - { - int nWidth = GET_X_LPARAM(lParam); // width of client area - int nHeight = GET_Y_LPARAM(lParam); // height of client area - - m_rcPos.right = m_rcPos.left + nWidth; - m_rcPos.bottom = m_rcPos.top + nHeight; - m_pxSize.cx = m_rcPos.right - m_rcPos.left; - m_pxSize.cy = m_rcPos.bottom - m_rcPos.top; - AtlPixelToHiMetric(&m_pxSize, &m_hmSize); - - if (m_spOleObject) - m_spOleObject->SetExtent(DVASPECT_CONTENT, &m_hmSize); - if (m_spInPlaceObjectWindowless) - m_spInPlaceObjectWindowless->SetObjectRects(&m_rcPos, &m_rcPos); - if (m_bWindowless) - InvalidateRect(NULL, TRUE); - bHandled = FALSE; - return 0; - } - LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - GetControllingUnknown()->AddRef(); - DefWindowProc(uMsg, wParam, lParam); - ReleaseAll(); - bHandled = FALSE; - return 0; - } - LRESULT OnWindowMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - LRESULT lRes = 0; - HRESULT hr = S_FALSE; - if (m_bInPlaceActive && m_bWindowless && m_spInPlaceObjectWindowless) - hr = m_spInPlaceObjectWindowless->OnWindowMessage(uMsg, wParam, lParam, &lRes); - if (hr == S_FALSE) - bHandled = FALSE; - return lRes; - } - LRESULT OnWindowlessMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - LRESULT lRes = 0; - if (m_bInPlaceActive && m_bWindowless && m_spInPlaceObjectWindowless) - m_spInPlaceObjectWindowless->OnWindowMessage(uMsg, wParam, lParam, &lRes); - bHandled = FALSE; - return lRes; - } - LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - if (m_spViewObject == NULL) - { - PAINTSTRUCT ps; - HDC hdc = ::BeginPaint(m_hWnd, &ps); - if (hdc == NULL) - return 0; - RECT rcClient; - GetClientRect(&rcClient); - HBRUSH hbrBack = CreateSolidBrush(m_clrBackground); - if (hbrBack != NULL) - { - FillRect(hdc, &rcClient, hbrBack); - DeleteObject(hbrBack); - } - ::EndPaint(m_hWnd, &ps); - return 1; - } - if (m_spViewObject && m_bWindowless) - { - PAINTSTRUCT ps; - HDC hdc = ::BeginPaint(m_hWnd, &ps); - - if (hdc == NULL) - return 0; - - RECT rcClient; - GetClientRect(&rcClient); - - HBITMAP hBitmap = CreateCompatibleBitmap(hdc, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top); - if (hBitmap != NULL) - { - HDC hdcCompatible = ::CreateCompatibleDC(hdc); - if (hdcCompatible != NULL) - { - HBITMAP hBitmapOld = (HBITMAP)SelectObject(hdcCompatible, hBitmap); - if (hBitmapOld != NULL) - { - HBRUSH hbrBack = CreateSolidBrush(m_clrBackground); - if (hbrBack != NULL) - { - FillRect(hdcCompatible, &rcClient, hbrBack); - DeleteObject(hbrBack); - - m_spViewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL, hdcCompatible, (RECTL*)&m_rcPos, (RECTL*)&m_rcPos, NULL, NULL); - - ::BitBlt(hdc, 0, 0, rcClient.right, rcClient.bottom, hdcCompatible, 0, 0, SRCCOPY); - } - ::SelectObject(hdcCompatible, hBitmapOld); - } - ::DeleteDC(hdcCompatible); - } - ::DeleteObject(hBitmap); - } - ::EndPaint(m_hWnd, &ps); - } - else - { - bHandled = FALSE; - return 0; - } - return 1; - } - -// IAxWinHostWindow - STDMETHOD(CreateControl)(LPCOLESTR lpTricsData, HWND hWnd, IStream* pStream) - { - CComPtr p; - return CreateControlLicEx(lpTricsData, hWnd, pStream, &p, IID_NULL, NULL, NULL); - } - STDMETHOD(CreateControlEx)(LPCOLESTR lpszTricsData, HWND hWnd, IStream* pStream, IUnknown** ppUnk, REFIID iidAdvise, IUnknown* punkSink) - { - return CreateControlLicEx(lpszTricsData, hWnd, pStream, ppUnk, iidAdvise, punkSink, NULL); - } - STDMETHOD(AttachControl)(IUnknown* pUnkControl, HWND hWnd) - { - HRESULT hr = S_FALSE; - - ReleaseAll(); - - bool bReleaseWindowOnFailure = false; // Used to keep track of whether we subclass the window - - if ((m_hWnd != NULL) && (m_hWnd != hWnd)) // Don't release the window if it's the same as the one we already subclass/own - { - RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_INTERNALPAINT | RDW_FRAME); - ReleaseWindow(); - } - - if (::IsWindow(hWnd)) - { - if (m_hWnd != hWnd) // Don't need to subclass the window if we already own it - { - SubclassWindow(hWnd); - bReleaseWindowOnFailure = true; - } - - hr = ActivateAx(pUnkControl, true, NULL); - - if (FAILED(hr)) - { - ReleaseAll(); - - if (m_hWnd != NULL) - { - RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_INTERNALPAINT | RDW_FRAME); - if (bReleaseWindowOnFailure) // We subclassed the window in an attempt to create this control, so we unsubclass on failure - ReleaseWindow(); - } - } - } - return hr; - } - STDMETHOD(QueryControl)(REFIID riid, void** ppvObject) - { - HRESULT hr = E_POINTER; - if (ppvObject) - { - if (m_spUnknown) - { - hr = m_spUnknown->QueryInterface(riid, ppvObject); - } - else - { - *ppvObject = NULL; - hr = OLE_E_NOCONNECTION; - } - } - return hr; - } - STDMETHOD(SetExternalDispatch)(IDispatch* pDisp) - { - m_spExternalDispatch = pDisp; - return S_OK; - } - STDMETHOD(SetExternalUIHandler)(IDocHostUIHandlerDispatch* pUIHandler) - { -#ifndef _ATL_NO_DOCHOSTUIHANDLER - m_spIDocHostUIHandlerDispatch = pUIHandler; -#endif - return S_OK; - } - - STDMETHOD(CreateControlLic)(LPCOLESTR lpTricsData, HWND hWnd, IStream* pStream, BSTR bstrLic) - { - CComPtr p; - return CreateControlLicEx(lpTricsData, hWnd, pStream, &p, IID_NULL, NULL, bstrLic); - } - STDMETHOD(CreateControlLicEx)(LPCOLESTR lpszTricsData, HWND hWnd, IStream* pStream, IUnknown** ppUnk, REFIID iidAdvise, IUnknown* punkSink, BSTR bstrLic) - { - ATLASSERT(ppUnk != NULL); - if (ppUnk == NULL) - return E_POINTER; - *ppUnk = NULL; - HRESULT hr = S_FALSE; - bool bReleaseWindowOnFailure = false; // Used to keep track of whether we subclass the window - - ReleaseAll(); - - if ((m_hWnd != NULL) && (m_hWnd != hWnd)) // Don't release the window if it's the same as the one we already subclass/own - { - RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_INTERNALPAINT | RDW_FRAME); - ReleaseWindow(); - } - - if (::IsWindow(hWnd)) - { - if (m_hWnd != hWnd) // Don't need to subclass the window if we already own it - { - SubclassWindow(hWnd); - bReleaseWindowOnFailure = true; - } - if (m_clrBackground == NULL) - { - if (IsParentDialog()) - { - m_clrBackground = GetSysColor(COLOR_BTNFACE); - } - else - { - m_clrBackground = GetSysColor(COLOR_WINDOW); - } - } - - bool bWasHTML = false; - - hr = CreateNormalizedObject(lpszTricsData, __uuidof(IUnknown), (void**)ppUnk, bWasHTML, bstrLic); - - if (SUCCEEDED(hr)) - { - hr = ActivateAx(*ppUnk, false, pStream); - } - - // Try to hook up any sink the user might have given us. - m_iidSink = iidAdvise; - if(SUCCEEDED(hr) && *ppUnk && punkSink) - { - AtlAdvise(*ppUnk, punkSink, m_iidSink, &m_dwAdviseSink); - } - - if (SUCCEEDED(hr) && bWasHTML && *ppUnk != NULL) - { - if ((GetStyle() & (WS_VSCROLL | WS_HSCROLL)) == 0) - { - m_dwDocHostFlags |= DOCHOSTUIFLAG_SCROLL_NO; - } - else - { - DWORD dwStyle = GetStyle(); - SetWindowLong(GWL_STYLE, dwStyle & ~(WS_VSCROLL | WS_HSCROLL)); - SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOSIZE | SWP_FRAMECHANGED | SWP_DRAWFRAME); - } - - CComPtr spUnk(*ppUnk); - // Is it just plain HTML? - if ((lpszTricsData[0] == OLECHAR('M') || lpszTricsData[0] == OLECHAR('m')) && - (lpszTricsData[1] == OLECHAR('S') || lpszTricsData[1] == OLECHAR('s')) && - (lpszTricsData[2] == OLECHAR('H') || lpszTricsData[2] == OLECHAR('h')) && - (lpszTricsData[3] == OLECHAR('T') || lpszTricsData[3] == OLECHAR('t')) && - (lpszTricsData[4] == OLECHAR('M') || lpszTricsData[4] == OLECHAR('m')) && - (lpszTricsData[5] == OLECHAR('L') || lpszTricsData[5] == OLECHAR('l')) && - (lpszTricsData[6] == OLECHAR(':'))) - { - // Just HTML: load the HTML data into the document - UINT nCreateSize = (static_cast(ocslen(lpszTricsData)) - 7) * sizeof(OLECHAR); - HGLOBAL hGlobal = GlobalAlloc(GHND, nCreateSize); - if (hGlobal) - { - CComPtr spStream; - BYTE* pBytes = (BYTE*) GlobalLock(hGlobal); - Checked::memcpy_s(pBytes, nCreateSize, lpszTricsData + 7, nCreateSize); - GlobalUnlock(hGlobal); - hr = CreateStreamOnHGlobal(hGlobal, TRUE, &spStream); - if (SUCCEEDED(hr)) - { - CComPtr spPSI; - hr = spUnk->QueryInterface(__uuidof(IPersistStreamInit), (void**)&spPSI); - if (SUCCEEDED(hr)) - { - hr = spPSI->Load(spStream); - } - } - } - else - { - hr = E_OUTOFMEMORY; - } - } - else - { - CComPtr spBrowser; - spUnk->QueryInterface(__uuidof(IWebBrowser2), (void**)&spBrowser); - if (spBrowser) - { - CComVariant ve; - CComVariant vurl(lpszTricsData); - spBrowser->put_Visible(ATL_VARIANT_TRUE); - spBrowser->Navigate2(&vurl, &ve, &ve, &ve, &ve); - } - } - - } - if (FAILED(hr) || m_spUnknown == NULL) - { - // We don't have a control or something failed so release - ReleaseAll(); - - if (m_hWnd != NULL) - { - RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_INTERNALPAINT | RDW_FRAME); - if (FAILED(hr) && bReleaseWindowOnFailure) // We subclassed the window in an attempt to create this control, so we unsubclass on failure - { - ReleaseWindow(); - } - } - } - } - return hr; - } - - - -#ifndef _ATL_NO_DOCHOSTUIHANDLER -// IDocHostUIHandler - // MSHTML requests to display its context menu - STDMETHOD(ShowContextMenu)(DWORD dwID, POINT* pptPosition, IUnknown* pCommandTarget, IDispatch* pDispatchObjectHit) - { - HRESULT hr = m_bAllowContextMenu ? S_FALSE : S_OK; - if (m_spIDocHostUIHandlerDispatch != NULL) - m_spIDocHostUIHandlerDispatch->ShowContextMenu( - dwID, - pptPosition->x, - pptPosition->y, - pCommandTarget, - pDispatchObjectHit, - &hr); - return hr; - } - // Called at initialisation to find UI styles from container - STDMETHOD(GetHostInfo)(DOCHOSTUIINFO* pInfo) - { - if (pInfo == NULL) - return E_POINTER; - - if (m_spIDocHostUIHandlerDispatch != NULL) - return m_spIDocHostUIHandlerDispatch->GetHostInfo(&pInfo->dwFlags, &pInfo->dwDoubleClick); - - pInfo->dwFlags = m_dwDocHostFlags; - pInfo->dwDoubleClick = m_dwDocHostDoubleClickFlags; - - return S_OK; - } - // Allows the host to replace the IE4/MSHTML menus and toolbars. - STDMETHOD(ShowUI)(DWORD dwID, IOleInPlaceActiveObject* pActiveObject, IOleCommandTarget* pCommandTarget, IOleInPlaceFrame* pFrame, IOleInPlaceUIWindow* pDoc) - { - HRESULT hr = m_bAllowShowUI ? S_FALSE : S_OK; - if (m_spIDocHostUIHandlerDispatch != NULL) - m_spIDocHostUIHandlerDispatch->ShowUI( - dwID, - pActiveObject, - pCommandTarget, - pFrame, - pDoc, - &hr); - return hr; - } - // Called when IE4/MSHTML removes its menus and toolbars. - STDMETHOD(HideUI)() - { - HRESULT hr = S_OK; - if (m_spIDocHostUIHandlerDispatch != NULL) - hr = m_spIDocHostUIHandlerDispatch->HideUI(); - return hr; - } - // Notifies the host that the command state has changed. - STDMETHOD(UpdateUI)() - { - HRESULT hr = S_OK; - if (m_spIDocHostUIHandlerDispatch != NULL) - hr = m_spIDocHostUIHandlerDispatch->UpdateUI(); - return hr; - } - // Called from the IE4/MSHTML implementation of IOleInPlaceActiveObject::EnableModeless - STDMETHOD(EnableModeless)(BOOL fEnable) - { - HRESULT hr = S_OK; - if (m_spIDocHostUIHandlerDispatch != NULL) - hr = m_spIDocHostUIHandlerDispatch->EnableModeless(fEnable ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE); - return hr; - } - // Called from the IE4/MSHTML implementation of IOleInPlaceActiveObject::OnDocWindowActivate - STDMETHOD(OnDocWindowActivate)(BOOL fActivate) - { - HRESULT hr = S_OK; - if (m_spIDocHostUIHandlerDispatch != NULL) - hr = m_spIDocHostUIHandlerDispatch->OnDocWindowActivate(fActivate ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE); - return hr; - } - // Called from the IE4/MSHTML implementation of IOleInPlaceActiveObject::OnFrameWindowActivate. - STDMETHOD(OnFrameWindowActivate)(BOOL fActivate) - { - HRESULT hr = S_OK; - if (m_spIDocHostUIHandlerDispatch != NULL) - hr = m_spIDocHostUIHandlerDispatch->OnFrameWindowActivate(fActivate ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE); - return hr; - } - // Called from the IE4/MSHTML implementation of IOleInPlaceActiveObject::ResizeBorder. - STDMETHOD(ResizeBorder)(LPCRECT prcBorder, IOleInPlaceUIWindow* pUIWindow, BOOL fFrameWindow) - { - HRESULT hr = S_OK; - if (m_spIDocHostUIHandlerDispatch != NULL) - hr = m_spIDocHostUIHandlerDispatch->ResizeBorder( - prcBorder->left, - prcBorder->top, - prcBorder->right, - prcBorder->bottom, - pUIWindow, - fFrameWindow ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE); - return hr; - } - // Called by IE4/MSHTML when IOleInPlaceActiveObject::TranslateAccelerator or IOleControlSite::TranslateAccelerator is called. - STDMETHOD(TranslateAccelerator)(LPMSG lpMsg, const GUID* pguidCmdGroup, DWORD nCmdID) - { - HRESULT hr = S_FALSE; - if (m_spIDocHostUIHandlerDispatch != NULL) - m_spIDocHostUIHandlerDispatch->TranslateAccelerator( - (DWORD_PTR) lpMsg->hwnd, - lpMsg->message, - lpMsg->wParam, - lpMsg->lParam, - CComBSTR(*pguidCmdGroup), - nCmdID, - &hr); - return hr; - } - // Returns the registry key under which IE4/MSHTML stores user preferences. - // Returns S_OK if successful, or S_FALSE otherwise. If S_FALSE, IE4/MSHTML will default to its own user options. - STDMETHOD(GetOptionKeyPath)(LPOLESTR* pchKey, DWORD dwReserved) - { - HRESULT hr = S_FALSE; - if (pchKey == NULL) - { - return E_POINTER; - } - *pchKey = NULL; - if (m_spIDocHostUIHandlerDispatch != NULL) - { - hr = m_spIDocHostUIHandlerDispatch->GetOptionKeyPath(pchKey, dwReserved); - if (FAILED(hr) || *pchKey == NULL) - hr = S_FALSE; - } - else - { - if (m_bstrOptionKeyPath.Length() != 0) - { - UINT nByteLength = m_bstrOptionKeyPath.ByteLength(); - LPOLESTR pStr = (LPOLESTR)CoTaskMemAlloc(nByteLength + sizeof(OLECHAR)); - if (pStr == NULL) - { - return E_OUTOFMEMORY; - } - if(!ocscpy_s(pStr, nByteLength + sizeof(OLECHAR), m_bstrOptionKeyPath.m_str)) - { - return E_FAIL; - } - *pchKey = pStr; - hr = S_OK; - } - } - return hr; - } - // Called by IE4/MSHTML when it is being used as a drop target to allow the host to supply an alternative IDropTarget - STDMETHOD(GetDropTarget)(IDropTarget* pDropTarget, IDropTarget** ppDropTarget) - { - ATLASSERT(ppDropTarget != NULL); - if (ppDropTarget == NULL) - return E_POINTER; - *ppDropTarget = NULL; - - HRESULT hr = E_NOTIMPL; - if (m_spIDocHostUIHandlerDispatch != NULL) - { - CComPtr spUnk; - hr = m_spIDocHostUIHandlerDispatch->GetDropTarget(pDropTarget, &spUnk); - if (spUnk) - hr = spUnk->QueryInterface(__uuidof(IDropTarget), (void**)ppDropTarget); - if (FAILED(hr) || *ppDropTarget == NULL) - hr = S_FALSE; - } - return hr; - } - // Called by IE4/MSHTML to obtain the host's IDispatch interface - STDMETHOD(GetExternal)(IDispatch** ppDispatch) - { - ATLASSERT(ppDispatch != NULL); - if (ppDispatch == NULL) - return E_POINTER; - *ppDispatch = NULL; - - HRESULT hr = E_NOINTERFACE; - if (m_spIDocHostUIHandlerDispatch != NULL) - { - hr = m_spIDocHostUIHandlerDispatch->GetExternal(ppDispatch); - if (FAILED(hr) || *ppDispatch == NULL) - hr = E_NOINTERFACE; - } - else - { - // return the IDispatch we have for extending the object Model - if (ppDispatch != NULL) - { - hr=m_spExternalDispatch.CopyTo(ppDispatch); - } - else - hr = E_POINTER; - } - return hr; - } - // Called by IE4/MSHTML to allow the host an opportunity to modify the URL to be loaded - STDMETHOD(TranslateUrl)(DWORD dwTranslate, OLECHAR* pchURLIn, OLECHAR** ppchURLOut) - { - ATLASSERT(ppchURLOut != NULL); - if (ppchURLOut == NULL) - { - return E_POINTER; - } - *ppchURLOut = NULL; - - HRESULT hr = S_FALSE; - if (m_spIDocHostUIHandlerDispatch != NULL) - { - CComBSTR bstrURLOut; - hr = m_spIDocHostUIHandlerDispatch->TranslateUrl(dwTranslate, CComBSTR(pchURLIn), &bstrURLOut); - if (SUCCEEDED(hr) && bstrURLOut.Length() != 0) - { - UINT nLen = (bstrURLOut.Length() + 1) * 2; - *ppchURLOut = (OLECHAR*) CoTaskMemAlloc(nLen); - if (*ppchURLOut == NULL) - { - return E_OUTOFMEMORY; - } - Checked::memcpy_s(*ppchURLOut, nLen, bstrURLOut.m_str, nLen); - } - else - { - hr = S_FALSE; - } - } - return hr; - } - // Called on the host by IE4/MSHTML to allow the host to replace IE4/MSHTML's data object. - // This allows the host to block certain clipboard formats or support additional clipboard formats. - STDMETHOD(FilterDataObject)(IDataObject* pDO, IDataObject** ppDORet) - { - ATLASSERT(ppDORet != NULL); - if (ppDORet == NULL) - return E_POINTER; - *ppDORet = NULL; - - HRESULT hr = S_FALSE; - if (m_spIDocHostUIHandlerDispatch != NULL) - { - CComPtr spUnk; - hr = m_spIDocHostUIHandlerDispatch->FilterDataObject(pDO, &spUnk); - if (spUnk) - hr = QueryInterface(__uuidof(IDataObject), (void**)ppDORet); - if (FAILED(hr) || *ppDORet == NULL) - hr = S_FALSE; - } - return hr; - } -#endif - - HRESULT FireAmbientPropertyChange(DISPID dispChanged) - { - HRESULT hr = S_OK; - CComQIPtr spOleControl(m_spUnknown); - if (spOleControl != NULL) - hr = spOleControl->OnAmbientPropertyChange(dispChanged); - return hr; - } - -// IAxWinAmbientDispatch - - CComPtr m_spAmbientDispatch; - - STDMETHOD(Invoke)(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, - VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) - { - HRESULT hr = IDispatchImpl::Invoke - (dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); - if ((hr == DISP_E_MEMBERNOTFOUND || hr == TYPE_E_ELEMENTNOTFOUND) && m_spAmbientDispatch != NULL) - { - hr = m_spAmbientDispatch->Invoke(dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); - if (SUCCEEDED(hr) && (wFlags & DISPATCH_PROPERTYPUT) != 0) - { - hr = FireAmbientPropertyChange(dispIdMember); - } - } - return hr; - } - - STDMETHOD(put_AllowWindowlessActivation)(VARIANT_BOOL bAllowWindowless) - { - m_bCanWindowlessActivate = bAllowWindowless; - return S_OK; - } - STDMETHOD(get_AllowWindowlessActivation)(VARIANT_BOOL* pbAllowWindowless) - { - ATLASSERT(pbAllowWindowless != NULL); - if (pbAllowWindowless == NULL) - return E_POINTER; - - *pbAllowWindowless = m_bCanWindowlessActivate ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE; - return S_OK; - } - STDMETHOD(put_BackColor)(OLE_COLOR clrBackground) - { - m_clrBackground = clrBackground; - FireAmbientPropertyChange(DISPID_AMBIENT_BACKCOLOR); - InvalidateRect(0, FALSE); - return S_OK; - } - STDMETHOD(get_BackColor)(OLE_COLOR* pclrBackground) - { - ATLASSERT(pclrBackground != NULL); - if (pclrBackground == NULL) - return E_POINTER; - - *pclrBackground = m_clrBackground; - return S_OK; - } - STDMETHOD(put_ForeColor)(OLE_COLOR clrForeground) - { - m_clrForeground = clrForeground; - FireAmbientPropertyChange(DISPID_AMBIENT_FORECOLOR); - return S_OK; - } - STDMETHOD(get_ForeColor)(OLE_COLOR* pclrForeground) - { - ATLASSERT(pclrForeground != NULL); - if (pclrForeground == NULL) - return E_POINTER; - - *pclrForeground = m_clrForeground; - return S_OK; - } - STDMETHOD(put_LocaleID)(LCID lcidLocaleID) - { - m_lcidLocaleID = lcidLocaleID; - FireAmbientPropertyChange(DISPID_AMBIENT_LOCALEID); - return S_OK; - } - STDMETHOD(get_LocaleID)(LCID* plcidLocaleID) - { - ATLASSERT(plcidLocaleID != NULL); - if (plcidLocaleID == NULL) - return E_POINTER; - - *plcidLocaleID = m_lcidLocaleID; - return S_OK; - } - STDMETHOD(put_UserMode)(VARIANT_BOOL bUserMode) - { - m_bUserMode = bUserMode; - FireAmbientPropertyChange(DISPID_AMBIENT_USERMODE); - return S_OK; - } - STDMETHOD(get_UserMode)(VARIANT_BOOL* pbUserMode) - { - ATLASSERT(pbUserMode != NULL); - if (pbUserMode == NULL) - return E_POINTER; - - *pbUserMode = m_bUserMode ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE; - return S_OK; - } - STDMETHOD(put_DisplayAsDefault)(VARIANT_BOOL bDisplayAsDefault) - { - m_bDisplayAsDefault = bDisplayAsDefault; - FireAmbientPropertyChange(DISPID_AMBIENT_DISPLAYASDEFAULT); - return S_OK; - } - STDMETHOD(get_DisplayAsDefault)(VARIANT_BOOL* pbDisplayAsDefault) - { - ATLASSERT(pbDisplayAsDefault != NULL); - if (pbDisplayAsDefault == NULL) - return E_POINTER; - - *pbDisplayAsDefault = m_bDisplayAsDefault ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE; - return S_OK; - } - STDMETHOD(put_Font)(IFontDisp* pFont) - { - m_spFont = pFont; - FireAmbientPropertyChange(DISPID_AMBIENT_FONT); - return S_OK; - } - STDMETHOD(get_Font)(IFontDisp** pFont) - { - ATLASSERT(pFont != NULL); - if (pFont == NULL) - return E_POINTER; - *pFont = NULL; - - if (m_spFont == NULL) - { - USES_CONVERSION_EX; - HFONT hSystemFont = (HFONT) GetStockObject(DEFAULT_GUI_FONT); - if (hSystemFont == NULL) - hSystemFont = (HFONT) GetStockObject(SYSTEM_FONT); - if (hSystemFont == NULL) - return AtlHresultFromLastError(); - LOGFONT logfont; - GetObject(hSystemFont, sizeof(logfont), &logfont); - FONTDESC fd; - fd.cbSizeofstruct = sizeof(FONTDESC); - fd.lpstrName = T2OLE_EX_DEF(logfont.lfFaceName); - fd.sWeight = (short)logfont.lfWeight; - fd.sCharset = logfont.lfCharSet; - fd.fItalic = logfont.lfItalic; - fd.fUnderline = logfont.lfUnderline; - fd.fStrikethrough = logfont.lfStrikeOut; - - long lfHeight = logfont.lfHeight; - if (lfHeight < 0) - lfHeight = -lfHeight; - - int ppi; - HDC hdc; - if (m_hWnd) - { - hdc = ::GetDC(m_hWnd); - if (hdc == NULL) - return AtlHresultFromLastError(); - ppi = GetDeviceCaps(hdc, LOGPIXELSY); - ::ReleaseDC(m_hWnd, hdc); - } - else - { - hdc = ::GetDC(GetDesktopWindow()); - if (hdc == NULL) - return AtlHresultFromLastError(); - ppi = GetDeviceCaps(hdc, LOGPIXELSY); - ::ReleaseDC(GetDesktopWindow(), hdc); - } - fd.cySize.Lo = lfHeight * 720000 / ppi; - fd.cySize.Hi = 0; - - OleCreateFontIndirect(&fd, __uuidof(IFontDisp), (void**) &m_spFont); - } - - return m_spFont.CopyTo(pFont); - } - STDMETHOD(put_MessageReflect)(VARIANT_BOOL bMessageReflect) - { - m_bMessageReflect = bMessageReflect; - FireAmbientPropertyChange(DISPID_AMBIENT_MESSAGEREFLECT); - return S_OK; - } - STDMETHOD(get_MessageReflect)(VARIANT_BOOL* pbMessageReflect) - { - - ATLASSERT(pbMessageReflect != NULL); - if (pbMessageReflect == NULL) - return E_POINTER; - - *pbMessageReflect = m_bMessageReflect ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE; - return S_OK; - } - STDMETHOD(get_ShowGrabHandles)(VARIANT_BOOL* pbShowGrabHandles) - { - *pbShowGrabHandles = ATL_VARIANT_FALSE; - return S_OK; - } - STDMETHOD(get_ShowHatching)(VARIANT_BOOL* pbShowHatching) - { - ATLASSERT(pbShowHatching != NULL); - if (pbShowHatching == NULL) - return E_POINTER; - - *pbShowHatching = ATL_VARIANT_FALSE; - return S_OK; - } - STDMETHOD(put_DocHostFlags)(DWORD dwDocHostFlags) - { - m_dwDocHostFlags = dwDocHostFlags; - FireAmbientPropertyChange(DISPID_UNKNOWN); - return S_OK; - } - STDMETHOD(get_DocHostFlags)(DWORD* pdwDocHostFlags) - { - ATLASSERT(pdwDocHostFlags != NULL); - if (pdwDocHostFlags == NULL) - return E_POINTER; - - *pdwDocHostFlags = m_dwDocHostFlags; - return S_OK; - } - STDMETHOD(put_DocHostDoubleClickFlags)(DWORD dwDocHostDoubleClickFlags) - { - m_dwDocHostDoubleClickFlags = dwDocHostDoubleClickFlags; - return S_OK; - } - STDMETHOD(get_DocHostDoubleClickFlags)(DWORD* pdwDocHostDoubleClickFlags) - { - ATLASSERT(pdwDocHostDoubleClickFlags != NULL); - if (pdwDocHostDoubleClickFlags == NULL) - return E_POINTER; - - *pdwDocHostDoubleClickFlags = m_dwDocHostDoubleClickFlags; - return S_OK; - } - STDMETHOD(put_AllowContextMenu)(VARIANT_BOOL bAllowContextMenu) - { - m_bAllowContextMenu = bAllowContextMenu; - return S_OK; - } - STDMETHOD(get_AllowContextMenu)(VARIANT_BOOL* pbAllowContextMenu) - { - ATLASSERT(pbAllowContextMenu != NULL); - if (pbAllowContextMenu == NULL) - return E_POINTER; - - *pbAllowContextMenu = m_bAllowContextMenu ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE; - return S_OK; - } - STDMETHOD(put_AllowShowUI)(VARIANT_BOOL bAllowShowUI) - { - m_bAllowShowUI = bAllowShowUI; - return S_OK; - } - STDMETHOD(get_AllowShowUI)(VARIANT_BOOL* pbAllowShowUI) - { - ATLASSERT(pbAllowShowUI != NULL); - if (pbAllowShowUI == NULL) - return E_POINTER; - - *pbAllowShowUI = m_bAllowShowUI ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE; - return S_OK; - } - STDMETHOD(put_OptionKeyPath)(BSTR bstrOptionKeyPath) throw() - { - m_bstrOptionKeyPath = bstrOptionKeyPath; - return S_OK; - } - STDMETHOD(get_OptionKeyPath)(BSTR* pbstrOptionKeyPath) - { - ATLASSERT(pbstrOptionKeyPath != NULL); - if (pbstrOptionKeyPath == NULL) - return E_POINTER; - - *pbstrOptionKeyPath = m_bstrOptionKeyPath; - return S_OK; - } - - STDMETHOD(SetAmbientDispatch)(IDispatch* pDispatch) - { - m_spAmbientDispatch = pDispatch; - return S_OK; - } - -// IObjectWithSite - STDMETHOD(SetSite)(IUnknown* pUnkSite) - { - HRESULT hr = IObjectWithSiteImpl::SetSite(pUnkSite); - - if (SUCCEEDED(hr) && m_spUnkSite) - { - // Look for "outer" IServiceProvider - hr = m_spUnkSite->QueryInterface(__uuidof(IServiceProvider), (void**)&m_spServices); - ATLASSERT( SUCCEEDED(hr) && "No ServiceProvider!" ); - } - - if (pUnkSite == NULL) - m_spServices.Release(); - - return hr; - } - -// IOleClientSite - STDMETHOD(SaveObject)() - { - ATLTRACENOTIMPL(_T("IOleClientSite::SaveObject")); - } - STDMETHOD(GetMoniker)(DWORD /*dwAssign*/, DWORD /*dwWhichMoniker*/, IMoniker** /*ppmk*/) - { - ATLTRACENOTIMPL(_T("IOleClientSite::GetMoniker")); - } - STDMETHOD(GetContainer)(IOleContainer** ppContainer) - { - ATLTRACE(atlTraceHosting, 2, _T("IOleClientSite::GetContainer\n")); - ATLASSERT(ppContainer != NULL); - - HRESULT hr = E_POINTER; - if (ppContainer) - { - hr = E_NOTIMPL; - (*ppContainer) = NULL; - if (m_spUnkSite) - hr = m_spUnkSite->QueryInterface(__uuidof(IOleContainer), (void**)ppContainer); - if (FAILED(hr)) - hr = QueryInterface(__uuidof(IOleContainer), (void**)ppContainer); - } - return hr; - } - STDMETHOD(ShowObject)() - { - ATLTRACE(atlTraceHosting, 2, _T("IOleClientSite::ShowObject\r\n")); - - HDC hdc = CWindowImpl::GetDC(); - if (hdc == NULL) - return E_FAIL; - if (m_spViewObject) - m_spViewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL, hdc, (RECTL*)&m_rcPos, (RECTL*)&m_rcPos, NULL, NULL); - CWindowImpl::ReleaseDC(hdc); - return S_OK; - } - STDMETHOD(OnShowWindow)(BOOL /*fShow*/) - { - ATLTRACENOTIMPL(_T("IOleClientSite::OnShowWindow")); - } - STDMETHOD(RequestNewObjectLayout)() - { - ATLTRACENOTIMPL(_T("IOleClientSite::RequestNewObjectLayout")); - } - -// IOleInPlaceSite - STDMETHOD(GetWindow)(HWND* phwnd) - { - *phwnd = m_hWnd; - return S_OK; - } - STDMETHOD(ContextSensitiveHelp)(BOOL /*fEnterMode*/) - { - ATLTRACENOTIMPL(_T("IOleInPlaceSite::ContextSensitiveHelp")); - } - STDMETHOD(CanInPlaceActivate)() - { - return S_OK; - } - STDMETHOD(OnInPlaceActivate)() - { - // should only be called once the first time control is inplace-activated - ATLASSUME(m_bInPlaceActive == FALSE); - ATLASSUME(m_spInPlaceObjectWindowless == NULL); - - m_bInPlaceActive = TRUE; - OleLockRunning(m_spOleObject, TRUE, FALSE); - m_bWindowless = FALSE; - m_spOleObject->QueryInterface(__uuidof(IOleInPlaceObject), (void**) &m_spInPlaceObjectWindowless); - return S_OK; - } - STDMETHOD(OnUIActivate)() - { - ATLTRACE(atlTraceHosting, 2, _T("IOleInPlaceSite::OnUIActivate\n")); - m_bUIActive = TRUE; - return S_OK; - } - STDMETHOD(GetWindowContext)(IOleInPlaceFrame** ppFrame, IOleInPlaceUIWindow** ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO pFrameInfo) - { - if (ppFrame != NULL) - *ppFrame = NULL; - if (ppDoc != NULL) - *ppDoc = NULL; - if (ppFrame == NULL || ppDoc == NULL || lprcPosRect == NULL || lprcClipRect == NULL) - { - ATLASSERT(false); - return E_POINTER; - } - - if (!m_spInPlaceFrame) - { - CComObject* pFrameWindow; - CComObject::CreateInstance(&pFrameWindow); - pFrameWindow->QueryInterface(__uuidof(IOleInPlaceFrame), (void**) &m_spInPlaceFrame); - ATLASSUME(m_spInPlaceFrame); - } - if (!m_spInPlaceUIWindow) - { - CComObject* pUIWindow; - CComObject::CreateInstance(&pUIWindow); - pUIWindow->QueryInterface(__uuidof(IOleInPlaceUIWindow), (void**) &m_spInPlaceUIWindow); - ATLASSUME(m_spInPlaceUIWindow); - } - HRESULT hr=S_OK; - hr=m_spInPlaceFrame.CopyTo(ppFrame); - if(FAILED(hr)) - { - return hr; - } - hr=m_spInPlaceUIWindow.CopyTo(ppDoc); - if(FAILED(hr)) - { - return hr; - } - GetClientRect(lprcPosRect); - GetClientRect(lprcClipRect); - - if (m_hAccel == NULL) - { - ACCEL ac = { 0,0,0 }; - m_hAccel = CreateAcceleratorTable(&ac, 1); - } - pFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO); - pFrameInfo->fMDIApp = m_bMDIApp; - pFrameInfo->hwndFrame = GetParent(); - pFrameInfo->haccel = m_hAccel; - pFrameInfo->cAccelEntries = (m_hAccel != NULL) ? 1 : 0; - - return hr; - } - STDMETHOD(Scroll)(SIZE /*scrollExtant*/) - { - ATLTRACENOTIMPL(_T("IOleInPlaceSite::Scroll")); - } - STDMETHOD(OnUIDeactivate)(BOOL /*fUndoable*/) - { - ATLTRACE(atlTraceHosting, 2, _T("IOleInPlaceSite::OnUIDeactivate\n")); - m_bUIActive = FALSE; - return S_OK; - } - STDMETHOD(OnInPlaceDeactivate)() - { - m_bInPlaceActive = FALSE; - m_spInPlaceObjectWindowless.Release(); - return S_OK; - } - STDMETHOD(DiscardUndoState)() - { - ATLTRACENOTIMPL(_T("IOleInPlaceSite::DiscardUndoState")); - } - STDMETHOD(DeactivateAndUndo)() - { - ATLTRACENOTIMPL(_T("IOleInPlaceSite::DeactivateAndUndo")); - } - STDMETHOD(OnPosRectChange)(LPCRECT lprcPosRect) - { - ATLTRACE2(atlTraceHosting, 0, _T("IOleInPlaceSite::OnPosRectChange")); - if (lprcPosRect==NULL) { return E_POINTER; } - - // Use MoveWindow() to resize the CAxHostWindow. - // The CAxHostWindow handler for OnSize() will - // take care of calling IOleInPlaceObject::SetObjectRects(). - - // Convert to parent window coordinates for MoveWindow(). - RECT rect = *lprcPosRect; - ClientToScreen( &rect ); - HWND hWnd = GetParent(); - - // Check to make sure it's a non-top-level window. - if(hWnd != NULL) - { - CWindow wndParent(hWnd); - wndParent.ScreenToClient(&rect); - wndParent.Detach (); - } - // Do the actual move. - MoveWindow( &rect); - - return S_OK; - } - -// IOleInPlaceSiteEx - STDMETHOD(OnInPlaceActivateEx)(BOOL* /*pfNoRedraw*/, DWORD dwFlags) - { - // should only be called once the first time control is inplace-activated - ATLASSUME(m_bInPlaceActive == FALSE); - ATLASSUME(m_spInPlaceObjectWindowless == NULL); - - m_bInPlaceActive = TRUE; - OleLockRunning(m_spOleObject, TRUE, FALSE); - HRESULT hr = E_FAIL; - if (dwFlags & ACTIVATE_WINDOWLESS) - { - m_bWindowless = TRUE; - hr = m_spOleObject->QueryInterface(__uuidof(IOleInPlaceObjectWindowless), (void**) &m_spInPlaceObjectWindowless); - } - if (FAILED(hr)) - { - m_bWindowless = FALSE; - hr = m_spOleObject->QueryInterface(__uuidof(IOleInPlaceObject), (void**) &m_spInPlaceObjectWindowless); - } - if (m_spInPlaceObjectWindowless) - m_spInPlaceObjectWindowless->SetObjectRects(&m_rcPos, &m_rcPos); - return S_OK; - } - STDMETHOD(OnInPlaceDeactivateEx)(BOOL /*fNoRedraw*/) - { - m_bInPlaceActive = FALSE; - m_spInPlaceObjectWindowless.Release(); - return S_OK; - } - STDMETHOD(RequestUIActivate)() - { - return S_OK; - } - -// IOleInPlaceSiteWindowless - HDC m_hDCScreen; - bool m_bDCReleased; - - STDMETHOD(CanWindowlessActivate)() - { - return m_bCanWindowlessActivate ? S_OK : S_FALSE; - } - STDMETHOD(GetCapture)() - { - return m_bCapture ? S_OK : S_FALSE; - } - STDMETHOD(SetCapture)(BOOL fCapture) - { - if (fCapture) - { - CWindow::SetCapture(); - m_bCapture = TRUE; - } - else - { - ReleaseCapture(); - m_bCapture = FALSE; - } - return S_OK; - } - STDMETHOD(GetFocus)() - { - return m_bHaveFocus ? S_OK : S_FALSE; - } - STDMETHOD(SetFocus)(BOOL fGotFocus) - { - m_bHaveFocus = fGotFocus; - return S_OK; - } - STDMETHOD(GetDC)(LPCRECT /*pRect*/, DWORD grfFlags, HDC* phDC) - { - if (phDC == NULL) - return E_POINTER; - if (!m_bDCReleased) - return E_FAIL; - - *phDC = CWindowImpl::GetDC(); - if (*phDC == NULL) - return E_FAIL; - - m_bDCReleased = false; - - if (grfFlags & OLEDC_NODRAW) - return S_OK; - - RECT rect; - GetClientRect(&rect); - if (grfFlags & OLEDC_OFFSCREEN) - { - HDC hDCOffscreen = CreateCompatibleDC(*phDC); - if (hDCOffscreen != NULL) - { - HBITMAP hBitmap = CreateCompatibleBitmap(*phDC, rect.right - rect.left, rect.bottom - rect.top); - if (hBitmap == NULL) - DeleteDC(hDCOffscreen); - else - { - HGDIOBJ hOldBitmap = SelectObject(hDCOffscreen, hBitmap); - if (hOldBitmap == NULL) - { - DeleteObject(hBitmap); - DeleteDC(hDCOffscreen); - } - else - { - DeleteObject(hOldBitmap); - m_hDCScreen = *phDC; - *phDC = hDCOffscreen; - } - } - } - } - - if (grfFlags & OLEDC_PAINTBKGND) - ::FillRect(*phDC, &rect, (HBRUSH) (COLOR_WINDOW+1)); - return S_OK; - } - STDMETHOD(ReleaseDC)(HDC hDC) - { - m_bDCReleased = true; - if (m_hDCScreen != NULL) - { - RECT rect; - GetClientRect(&rect); - // Offscreen DC has to be copied to screen DC before releasing the screen dc; - BitBlt(m_hDCScreen, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, hDC, 0, 0, SRCCOPY); - DeleteDC(hDC); - hDC = m_hDCScreen; - } - - CWindowImpl::ReleaseDC(hDC); - return S_OK; - } - STDMETHOD(InvalidateRect)(LPCRECT pRect, BOOL fErase) - { - CWindowImpl::InvalidateRect(pRect, fErase); - return S_OK; - } - STDMETHOD(InvalidateRgn)(HRGN hRGN, BOOL fErase) - { - CWindowImpl::InvalidateRgn(hRGN, fErase); - return S_OK; - } - STDMETHOD(ScrollRect)(INT /*dx*/, INT /*dy*/, LPCRECT /*pRectScroll*/, LPCRECT /*pRectClip*/) - { - return S_OK; - } - STDMETHOD(AdjustRect)(LPRECT /*prc*/) - { - return S_OK; - } - STDMETHOD(OnDefWindowMessage)(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT* plResult) - { - *plResult = DefWindowProc(msg, wParam, lParam); - return S_OK; - } - -// IOleControlSite - STDMETHOD(OnControlInfoChanged)() - { - return S_OK; - } - STDMETHOD(LockInPlaceActive)(BOOL /*fLock*/) - { - return S_OK; - } - STDMETHOD(GetExtendedControl)(IDispatch** ppDisp) - { - if (ppDisp == NULL) - return E_POINTER; - return m_spOleObject.QueryInterface(ppDisp); - } - STDMETHOD(TransformCoords)(POINTL* /*pPtlHimetric*/, POINTF* /*pPtfContainer*/, DWORD /*dwFlags*/) - { - ATLTRACENOTIMPL(_T("CAxHostWindow::TransformCoords")); - } - STDMETHOD(TranslateAccelerator)(LPMSG /*lpMsg*/, DWORD /*grfModifiers*/) - { - return S_FALSE; - } - STDMETHOD(OnFocus)(BOOL fGotFocus) - { - m_bHaveFocus = fGotFocus; - return S_OK; - } - STDMETHOD(ShowPropertyFrame)() - { - ATLTRACENOTIMPL(_T("CAxHostWindow::ShowPropertyFrame")); - } - -// IAdviseSink - STDMETHOD_(void, OnDataChange)(FORMATETC* /*pFormatetc*/, STGMEDIUM* /*pStgmed*/) - { - } - STDMETHOD_(void, OnViewChange)(DWORD /*dwAspect*/, LONG /*lindex*/) - { - } - STDMETHOD_(void, OnRename)(IMoniker* /*pmk*/) - { - } - STDMETHOD_(void, OnSave)() - { - } - STDMETHOD_(void, OnClose)() - { - } - -// IOleContainer - STDMETHOD(ParseDisplayName)(IBindCtx* /*pbc*/, LPOLESTR /*pszDisplayName*/, ULONG* /*pchEaten*/, IMoniker** /*ppmkOut*/) - { - ATLTRACENOTIMPL(_T("CAxHostWindow::ParseDisplayName")); - } - STDMETHOD(EnumObjects)(DWORD /*grfFlags*/, IEnumUnknown** ppenum) - { - if (ppenum == NULL) - return E_POINTER; - *ppenum = NULL; - typedef CComObject > > enumunk; - enumunk* p = NULL; -#pragma warning(push) -#pragma warning(disable: 6014) - /* prefast noise VSW 489981 */ - ATLTRY(p = new enumunk); -#pragma warning(pop) - if(p == NULL) - return E_OUTOFMEMORY; - IUnknown* pTemp = m_spUnknown; - // There is always only one object. - HRESULT hRes = p->Init(reinterpret_cast(&pTemp), reinterpret_cast(&pTemp + 1), GetControllingUnknown(), AtlFlagCopy); - if (SUCCEEDED(hRes)) - hRes = p->QueryInterface(__uuidof(IEnumUnknown), (void**)ppenum); - if (FAILED(hRes)) - delete p; - return hRes; - } - STDMETHOD(LockContainer)(BOOL fLock) - { - m_bLocked = fLock; - return S_OK; - } - - HRESULT ActivateAx(IUnknown* pUnkControl, bool bInited, IStream* pStream) - { - if (pUnkControl == NULL) - return S_OK; - - m_spUnknown = pUnkControl; - - HRESULT hr = S_OK; - pUnkControl->QueryInterface(__uuidof(IOleObject), (void**)&m_spOleObject); - if (m_spOleObject) - { - m_spOleObject->GetMiscStatus(DVASPECT_CONTENT, &m_dwMiscStatus); - if (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST) - { - CComQIPtr spClientSite(GetControllingUnknown()); - m_spOleObject->SetClientSite(spClientSite); - } - - if (!bInited) // If user hasn't initialized the control, initialize/load using IPersistStreamInit or IPersistStream - { - CComQIPtr spPSI(m_spOleObject); - if (spPSI) - { - if (pStream) - hr = spPSI->Load(pStream); - else - hr = spPSI->InitNew(); - } - else if (pStream) - { - CComQIPtr spPS(m_spOleObject); - if (spPS) - hr = spPS->Load(pStream); - } - - if (FAILED(hr)) // If the initialization of the control failed... - { - // Clean up and return - if (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST) - m_spOleObject->SetClientSite(NULL); - - m_dwMiscStatus = 0; - m_spOleObject.Release(); - m_spUnknown.Release(); - - return hr; - } - } - - if (0 == (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)) - { - CComQIPtr spClientSite(GetControllingUnknown()); - m_spOleObject->SetClientSite(spClientSite); - } - - m_dwViewObjectType = 0; - hr = m_spOleObject->QueryInterface(__uuidof(IViewObjectEx), (void**) &m_spViewObject); - if (FAILED(hr)) - { - hr = m_spOleObject->QueryInterface(__uuidof(IViewObject2), (void**) &m_spViewObject); - if (SUCCEEDED(hr)) - m_dwViewObjectType = 3; - } else - m_dwViewObjectType = 7; - - if (FAILED(hr)) - { - hr = m_spOleObject->QueryInterface(__uuidof(IViewObject), (void**) &m_spViewObject); - if (SUCCEEDED(hr)) - m_dwViewObjectType = 1; - } - CComQIPtr spAdviseSink(GetControllingUnknown()); - m_spOleObject->Advise(spAdviseSink, &m_dwOleObject); - if (m_spViewObject) - m_spViewObject->SetAdvise(DVASPECT_CONTENT, 0, spAdviseSink); - m_spOleObject->SetHostNames(OLESTR("AXWIN"), NULL); - - if ((m_dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME) == 0) - { - GetClientRect(&m_rcPos); - m_pxSize.cx = m_rcPos.right - m_rcPos.left; - m_pxSize.cy = m_rcPos.bottom - m_rcPos.top; - AtlPixelToHiMetric(&m_pxSize, &m_hmSize); - m_spOleObject->SetExtent(DVASPECT_CONTENT, &m_hmSize); - m_spOleObject->GetExtent(DVASPECT_CONTENT, &m_hmSize); - AtlHiMetricToPixel(&m_hmSize, &m_pxSize); - m_rcPos.right = m_rcPos.left + m_pxSize.cx; - m_rcPos.bottom = m_rcPos.top + m_pxSize.cy; - - CComQIPtr spClientSite(GetControllingUnknown()); - hr = m_spOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, spClientSite, 0, m_hWnd, &m_rcPos); - RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_INTERNALPAINT | RDW_FRAME); - } - } - CComPtr spSite; - pUnkControl->QueryInterface(__uuidof(IObjectWithSite), (void**)&spSite); - if (spSite != NULL) - spSite->SetSite(GetControllingUnknown()); - - return hr; - } - - -// pointers - CComPtr m_spUnknown; - CComPtr m_spOleObject; - CComPtr m_spInPlaceFrame; - CComPtr m_spInPlaceUIWindow; - CComPtr m_spViewObject; - CComPtr m_spInPlaceObjectWindowless; - CComPtr m_spExternalDispatch; -#ifndef _ATL_NO_DOCHOSTUIHANDLER - CComPtr m_spIDocHostUIHandlerDispatch; -#endif - IID m_iidSink; - DWORD m_dwViewObjectType; - DWORD m_dwAdviseSink; - -// state - unsigned long m_bInPlaceActive:1; - unsigned long m_bUIActive:1; - unsigned long m_bMDIApp:1; - unsigned long m_bWindowless:1; - unsigned long m_bCapture:1; - unsigned long m_bHaveFocus:1; - unsigned long m_bReleaseAll:1; - unsigned long m_bLocked:1; - - DWORD m_dwOleObject; - DWORD m_dwMiscStatus; - SIZEL m_hmSize; - SIZEL m_pxSize; - RECT m_rcPos; - - // Accelerator table - HACCEL m_hAccel; - - // Ambient property storage - unsigned long m_bCanWindowlessActivate:1; - unsigned long m_bUserMode:1; - unsigned long m_bDisplayAsDefault:1; - unsigned long m_bMessageReflect:1; - unsigned long m_bSubclassed:1; - unsigned long m_bAllowContextMenu:1; - unsigned long m_bAllowShowUI:1; - OLE_COLOR m_clrBackground; - OLE_COLOR m_clrForeground; - LCID m_lcidLocaleID; - CComPtr m_spFont; - CComPtr m_spServices; - DWORD m_dwDocHostFlags; - DWORD m_dwDocHostDoubleClickFlags; - CComBSTR m_bstrOptionKeyPath; - - void SubclassWindow(HWND hWnd) - { - m_bSubclassed = CWindowImpl::SubclassWindow(hWnd); - } - - void ReleaseWindow() - { - if (m_bSubclassed) - { - if(UnsubclassWindow(TRUE) != NULL) - m_bSubclassed = FALSE; - } - else - DestroyWindow(); - } - - // Reflection - LRESULT ReflectNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - HWND hWndChild = NULL; - - switch(uMsg) - { - case WM_COMMAND: - if(lParam != NULL) // not from a menu - hWndChild = (HWND)lParam; - break; - case WM_NOTIFY: - hWndChild = ((LPNMHDR)lParam)->hwndFrom; - break; - case WM_PARENTNOTIFY: - DefWindowProc(); - switch(LOWORD(wParam)) - { - case WM_CREATE: - case WM_DESTROY: - hWndChild = (HWND)lParam; - break; - default: - hWndChild = GetDlgItem(HIWORD(wParam)); - break; - } - break; - case WM_DRAWITEM: - { - DRAWITEMSTRUCT* pdis = ((LPDRAWITEMSTRUCT)lParam); - if (pdis->CtlType != ODT_MENU) // not from a menu - hWndChild = pdis->hwndItem; - else // Status bar control sends this message with type set to ODT_MENU - if (::IsWindow(pdis->hwndItem)) - hWndChild = pdis->hwndItem; - } - break; - case WM_MEASUREITEM: - { - MEASUREITEMSTRUCT* pmis = ((LPMEASUREITEMSTRUCT)lParam); - if(pmis->CtlType != ODT_MENU) // not from a menu - hWndChild = GetDlgItem(pmis->CtlID); - } - break; - case WM_COMPAREITEM: - // Sent only by combo or list box - hWndChild =((LPCOMPAREITEMSTRUCT)lParam)->hwndItem; - break; - case WM_DELETEITEM: - // Sent only by combo or list box - hWndChild = ((LPDELETEITEMSTRUCT)lParam)->hwndItem; - break; - case WM_VKEYTOITEM: - case WM_CHARTOITEM: - case WM_HSCROLL: - case WM_VSCROLL: - hWndChild = (HWND)lParam; - break; - case WM_CTLCOLORBTN: - case WM_CTLCOLORDLG: - case WM_CTLCOLOREDIT: - case WM_CTLCOLORLISTBOX: - case WM_CTLCOLORMSGBOX: - case WM_CTLCOLORSCROLLBAR: - case WM_CTLCOLORSTATIC: - hWndChild = (HWND)lParam; - break; - default: - break; - } - - if(hWndChild == NULL) - { - bHandled = FALSE; - return 1; - } - - if (m_bWindowless) - { - LRESULT lRes = 0; - if (m_bInPlaceActive && m_spInPlaceObjectWindowless) - m_spInPlaceObjectWindowless->OnWindowMessage(OCM__BASE + uMsg, wParam, lParam, &lRes); - return lRes; - } - - ATLASSERT(::IsWindow(hWndChild)); - return ::SendMessage(hWndChild, OCM__BASE + uMsg, wParam, lParam); - } - - STDMETHOD(QueryService)( REFGUID rsid, REFIID riid, void** ppvObj) - { - ATLASSERT(ppvObj != NULL); - if (ppvObj == NULL) - return E_POINTER; - *ppvObj = NULL; - - HRESULT hr = E_NOINTERFACE; - // Try for service on this object - - // No services currently - - // If that failed try to find the service on the outer object - if (FAILED(hr) && m_spServices) - hr = m_spServices->QueryService(rsid, riid, ppvObj); - - return hr; - } -}; - -static LRESULT CALLBACK AtlAxWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch(uMsg) - { - case WM_CREATE: - { - // create control from a PROGID in the title - // This is to make sure drag drop works - ::OleInitialize(NULL); - - CREATESTRUCT* lpCreate = (CREATESTRUCT*)lParam; - int nLen = ::GetWindowTextLength(hWnd); - CAutoStackPtr spName((TCHAR *)_malloca((nLen + 1) * sizeof(TCHAR))); - if(!spName) - { - return -1; - } - ::GetWindowText(hWnd, spName, nLen + 1); - ::SetWindowText(hWnd, _T("")); - IAxWinHostWindow* pAxWindow = NULL; - int nCreateSize = 0; - if (lpCreate && lpCreate->lpCreateParams) - nCreateSize = *((WORD*)lpCreate->lpCreateParams); - - HGLOBAL h = GlobalAlloc(GHND, nCreateSize); - CComPtr spStream; - if (h && nCreateSize) - { - BYTE* pBytes = (BYTE*) GlobalLock(h); - BYTE* pSource = ((BYTE*)(lpCreate->lpCreateParams)) + sizeof(WORD); - //Align to DWORD - //pSource += (((~((DWORD)pSource)) + 1) & 3); - Checked::memcpy_s(pBytes, nCreateSize, pSource, nCreateSize); - GlobalUnlock(h); - CreateStreamOnHGlobal(h, TRUE, &spStream); - } - - USES_CONVERSION_EX; - CComPtr spUnk; - HRESULT hRet = AtlAxCreateControlLic(T2COLE_EX_DEF(spName), hWnd, spStream, &spUnk, NULL); - if(FAILED(hRet)) - { -#ifdef _DEBUG - LPTSTR pszMsg = NULL; - ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL, hRet, 0, (LPTSTR)&pszMsg, 0, NULL); - ATLTRACE(atlTraceControls, 0, _T("Control creation failed for '%s'\n"), static_cast(spName)); - ATLTRACE(atlTraceControls, 0, _T("Error code: 0x%x - %s"), hRet, pszMsg); - ::LocalFree(pszMsg); -#endif - return -1; // abort window creation - } - hRet = spUnk->QueryInterface(__uuidof(IAxWinHostWindow), (void**)&pAxWindow); - if(FAILED(hRet)) - return -1; // abort window creation - - ::SetWindowLongPtr(hWnd, GWLP_USERDATA, (DWORD_PTR)pAxWindow); - // continue with DefWindowProc - } - break; - case WM_NCDESTROY: - { - IAxWinHostWindow* pAxWindow = (IAxWinHostWindow*)::GetWindowLongPtr(hWnd, GWLP_USERDATA); - if(pAxWindow != NULL) - pAxWindow->Release(); - OleUninitialize(); - } - break; - - case WM_PARENTNOTIFY: - { - if((UINT)wParam == WM_CREATE) - { - ATLASSERT(lParam); - // Set the control parent style for the AxWindow - DWORD dwExStyle = ::GetWindowLong((HWND)lParam, GWL_EXSTYLE); - if(dwExStyle & WS_EX_CONTROLPARENT) - { - dwExStyle = ::GetWindowLong(hWnd, GWL_EXSTYLE); - dwExStyle |= WS_EX_CONTROLPARENT; - ::SetWindowLong(hWnd, GWL_EXSTYLE, dwExStyle); - } - } - } - break; - - default: - break; - } - - return ::DefWindowProc(hWnd, uMsg, wParam, lParam); -} - -static LRESULT CALLBACK AtlAxWindowProc2(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch(uMsg) - { - case WM_CREATE: - { - // create control from a PROGID in the title - // This is to make sure drag drop works - ::OleInitialize(NULL); - - CREATESTRUCT* lpCreate = (CREATESTRUCT*)lParam; - int nLen = ::GetWindowTextLength(hWnd); - CAutoStackPtr spName((TCHAR *)_malloca((nLen + 1) * sizeof(TCHAR))); - if(!spName) - { - return -1; - } - ::GetWindowText(hWnd, spName, nLen + 1); - ::SetWindowText(hWnd, _T("")); - IAxWinHostWindowLic* pAxWindow = NULL; - int nCreateSize = 0; - if (lpCreate && lpCreate->lpCreateParams) - nCreateSize = *((WORD*)lpCreate->lpCreateParams); - - // Format of data in lpCreateParams - // int nCreateSize; // size of Create data in bytes - // WORD nMsg; //constant used to indicate type of DLGINIT data. See _DialogSplitHelper for values. - // DWORD dwLen; // Length of data strored for control in DLGINIT format in bytes. - // DWORD cchLicKey; // Length of licence key in OLECHAR's - // OLECHAR *szLicKey; // This will be present only if cchLicKey is greater than 0. This is of variable length and will contain cchLicKey OLECHAR's that represent the licence key. - // The following two fields will be present only if nMsg is WM_OCC_LOADFROMSTREAM_EX or WM_OCC_LOADFROMSTORAGE_EX. If present this information will be ignored since databinding is not supported. - // ULONG cbDataBinding; // Lenght of databinding information in bytes. - // BYTE *pbDataBindingInfo // cbDataBinding bytes that contain databinding information - // BYTE *pbControlData; // Actual control data persisted by the control. - - - HGLOBAL h = GlobalAlloc(GHND, nCreateSize); - CComPtr spStream; - if (h && nCreateSize) - { - BYTE* pBytes = (BYTE*) GlobalLock(h); - BYTE* pSource = ((BYTE*)(lpCreate->lpCreateParams)) + sizeof(WORD); - //Align to DWORD - //pSource += (((~((DWORD)pSource)) + 1) & 3); - Checked::memcpy_s(pBytes, nCreateSize, pSource, nCreateSize); - GlobalUnlock(h); - CreateStreamOnHGlobal(h, TRUE, &spStream); - } - - CComBSTR bstrLicKey; - HRESULT hRet = _DialogSplitHelper::ParseInitData(spStream, &bstrLicKey.m_str); - if (FAILED(hRet)) - return -1; - - USES_CONVERSION_EX; - CComPtr spUnk; - hRet = AtlAxCreateControlLic(T2COLE_EX_DEF(spName), hWnd, spStream, &spUnk, bstrLicKey); - if(FAILED(hRet)) - { -#ifdef _DEBUG - LPTSTR pszMsg = NULL; - ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL, hRet, 0, (LPTSTR)&pszMsg, 0, NULL); - ATLTRACE(atlTraceControls, 0, _T("Control creation failed for '%s'\n"), static_cast(spName)); - ATLTRACE(atlTraceControls, 0, _T("Error code: 0x%x - %s"), hRet, pszMsg); - ::LocalFree(pszMsg); -#endif - return -1; // abort window creation - } - hRet = spUnk->QueryInterface(__uuidof(IAxWinHostWindowLic), (void**)&pAxWindow); - if(FAILED(hRet)) - return -1; // abort window creation - ::SetWindowLongPtr(hWnd, GWLP_USERDATA, (DWORD_PTR)pAxWindow); - // continue with DefWindowProc - } - break; - case WM_NCDESTROY: - { - IAxWinHostWindowLic* pAxWindow = (IAxWinHostWindowLic*)::GetWindowLongPtr(hWnd, GWLP_USERDATA); - if(pAxWindow != NULL) - pAxWindow->Release(); - OleUninitialize(); - } - break; - - case WM_PARENTNOTIFY: - { - if((UINT)wParam == WM_CREATE) - { - ATLASSERT(lParam); - // Set the control parent style for the AxWindow - DWORD dwExStyle = ::GetWindowLong((HWND)lParam, GWL_EXSTYLE); - if(dwExStyle & WS_EX_CONTROLPARENT) - { - dwExStyle = ::GetWindowLong(hWnd, GWL_EXSTYLE); - dwExStyle |= WS_EX_CONTROLPARENT; - ::SetWindowLong(hWnd, GWL_EXSTYLE, dwExStyle); - } - } - } - break; - - default: - break; - } - - return ::DefWindowProc(hWnd, uMsg, wParam, lParam); -} - -//All exports go here -#ifndef _ATL_DLL - -inline HRSRC AtlFindResource(HMODULE hModule, LPCSTR lpName, LPCSTR lpType) -{ - return ::FindResourceA(hModule, lpName, lpType); -} - -inline HRSRC AtlFindResource(HMODULE hModule, LPCWSTR lpName, LPCWSTR lpType) -{ - return ::FindResourceW(hModule, lpName, lpType); -} - -class _AtlDialogBoxIndirectParamHelper -{ -public : - typedef INT_PTR ReturnType; - static ReturnType GetInvalidValue() - { - return -1; - } - static bool IsValidReturnVal(ReturnType nRet) - { - return (nRet != 0 && nRet != -1); - } -}; - -class _AtlCreateDialogIndirectParamHelper -{ -public : - typedef HWND ReturnType; - static ReturnType GetInvalidValue() - { - return NULL; - } - static bool IsValidReturnVal(ReturnType nRet) - { - return (nRet != 0); - } -}; - -template -typename Helper::ReturnType AtlAxDialogCreateT(HINSTANCE hInstance, StringType lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam) -{ - AtlAxWinInit(); - Helper::ReturnType nRet = Helper::GetInvalidValue(); - - HRSRC hDlg = AtlFindResource(hInstance, lpTemplateName, (StringType)RT_DIALOG); - if (hDlg != NULL) - { - HRSRC hDlgInit = AtlFindResource(hInstance, lpTemplateName, (StringType)_ATL_RT_DLGINIT); - HGLOBAL hData = NULL; - BYTE* pInitData = NULL; - - if (hDlgInit) - { - hData = ::LoadResource(hInstance, hDlgInit); - pInitData = (BYTE*) ::LockResource(hData); - } - - DWORD dwLastError = 0; - HGLOBAL hResource = LoadResource(hInstance, hDlg); - if (hResource != NULL) - { - DLGTEMPLATE* pDlg = (DLGTEMPLATE*) LockResource(hResource); - if (pDlg != NULL) - { - LPCDLGTEMPLATE lpDialogTemplate; - - lpDialogTemplate = _DialogSplitHelper::SplitDialogTemplate(pDlg, pInitData); - - nRet = (*pFunc)(hInstance, lpDialogTemplate, hWndParent, lpDialogProc, dwInitParam); - if (!Helper::IsValidReturnVal(nRet)) - { - dwLastError = ::GetLastError(); - } - if (lpDialogTemplate != pDlg) - GlobalFree(GlobalHandle(lpDialogTemplate)); - } - else - dwLastError = ::GetLastError(); - } - else - dwLastError = ::GetLastError(); - - if (dwLastError != 0) - SetLastError(dwLastError); - } - return nRet; -} - -ATLINLINE ATLAPI_(INT_PTR) AtlAxDialogBoxW(HINSTANCE hInstance, LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam) -{ - return AtlAxDialogCreateT( - hInstance, lpTemplateName, hWndParent, lpDialogProc, dwInitParam); -} - -ATLINLINE ATLAPI_(INT_PTR) AtlAxDialogBoxA(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam) -{ - return AtlAxDialogCreateT( - hInstance, lpTemplateName, hWndParent, lpDialogProc, dwInitParam); -} - -ATLINLINE ATLAPI_(HWND) AtlAxCreateDialogW(HINSTANCE hInstance, LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam) -{ - return AtlAxDialogCreateT( - hInstance, lpTemplateName, hWndParent, lpDialogProc, dwInitParam); -} - -ATLINLINE ATLAPI_(HWND) AtlAxCreateDialogA(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam) -{ - return AtlAxDialogCreateT(hInstance, lpTemplateName, hWndParent, lpDialogProc, dwInitParam); -} - -ATLINLINE ATLAPI AtlAxCreateControl(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, IUnknown** ppUnkContainer) -{ - return AtlAxCreateControlEx(lpszName, hWnd, pStream, ppUnkContainer, NULL, IID_NULL, NULL); -} - -ATLINLINE ATLAPI AtlAxCreateControlEx(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, - IUnknown** ppUnkContainer, IUnknown** ppUnkControl, REFIID iidSink, IUnknown* punkSink) -{ - return AtlAxCreateControlLicEx(lpszName, hWnd, pStream, ppUnkContainer, ppUnkControl, iidSink, punkSink, NULL); -} - -ATLINLINE ATLAPI AtlAxCreateControlLic(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, IUnknown** ppUnkContainer, BSTR bstrLic) -{ - return AtlAxCreateControlLicEx(lpszName, hWnd, pStream, ppUnkContainer, NULL, IID_NULL, NULL, bstrLic); -} - -ATLINLINE ATLAPI AtlAxCreateControlLicEx(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, - IUnknown** ppUnkContainer, IUnknown** ppUnkControl, REFIID iidSink, IUnknown* punkSink, BSTR bstrLic) -{ - AtlAxWinInit(); - HRESULT hr; - CComPtr spUnkContainer; - CComPtr spUnkControl; - - hr = CAxHostWindow::_CreatorClass::CreateInstance(NULL, __uuidof(IUnknown), (void**)&spUnkContainer); - if (SUCCEEDED(hr)) - { - CComPtr pAxWindow; - spUnkContainer->QueryInterface(__uuidof(IAxWinHostWindow), (void**)&pAxWindow); - CComBSTR bstrName(lpszName); - hr = pAxWindow->CreateControlLicEx(bstrName, hWnd, pStream, &spUnkControl, iidSink, punkSink, bstrLic); - } - if (ppUnkContainer != NULL) - { - if (SUCCEEDED(hr)) - { - *ppUnkContainer = spUnkContainer.p; - spUnkContainer.p = NULL; - } - else - *ppUnkContainer = NULL; - } - if (ppUnkControl != NULL) - { - if (SUCCEEDED(hr)) - { - *ppUnkControl = SUCCEEDED(hr) ? spUnkControl.p : NULL; - spUnkControl.p = NULL; - } - else - *ppUnkControl = NULL; - } - return hr; -} - -ATLINLINE ATLAPI AtlAxAttachControl(IUnknown* pControl, HWND hWnd, IUnknown** ppUnkContainer) -{ - AtlAxWinInit(); - if (pControl == NULL) - return E_INVALIDARG; - CComPtr spUnkContainer; - - HRESULT hr = CAxHostWindow::_CreatorClass::CreateInstance(NULL, __uuidof(IUnknown), (void**)&spUnkContainer); - if (SUCCEEDED(hr)) - { - CComPtr spAxWindow; - hr = spUnkContainer->QueryInterface(&spAxWindow); - if (SUCCEEDED(hr)) - hr = spAxWindow->AttachControl(pControl, hWnd); - } - if (ppUnkContainer != NULL) - { - *ppUnkContainer = SUCCEEDED(hr) ? spUnkContainer.Detach() : NULL; - } - return hr; -} - -#ifdef _ATL_DLL_IMPL -// global variable in ATL.DLL to keep track if AtlAxWin window class has been registered in ATL.DLL -bool __declspec(selectany) bAtlAxWinInitialized; -#endif - -//This either registers a global class (if AtlAxWinInit is in ATL.DLL) -// or it registers a local class -ATLINLINE ATLAPI_(BOOL) AtlAxWinInit() -{ - CComCritSecLock lock(_AtlWinModule.m_csWindowCreate, false); - if (FAILED(lock.Lock())) - { - ATLTRACE(atlTraceHosting, 0, _T("ERROR : Unable to lock critical section in AtlAxWinInit\n")); - ATLASSERT(0); - return FALSE; - } - WM_ATLGETHOST = RegisterWindowMessage(_T("WM_ATLGETHOST")); - WM_ATLGETCONTROL = RegisterWindowMessage(_T("WM_ATLGETCONTROL")); - WNDCLASSEX wc; -// first check if the class is already registered - wc.cbSize = sizeof(WNDCLASSEX); - BOOL bRet = ::GetClassInfoEx(_AtlBaseModule.GetModuleInstance(), CAxWindow::GetWndClassName(), &wc); - -// register class if not - - if(!bRet) - { - wc.cbSize = sizeof(WNDCLASSEX); -#ifdef _ATL_DLL_IMPL - wc.style = CS_GLOBALCLASS | CS_DBLCLKS; - bAtlAxWinInitialized = true; -#else - wc.style = CS_DBLCLKS; -#endif - wc.lpfnWndProc = AtlAxWindowProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = _AtlBaseModule.GetModuleInstance(); - wc.hIcon = NULL; - wc.hCursor = ::LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); - wc.lpszMenuName = NULL; - wc.lpszClassName = CAxWindow::GetWndClassName(); - wc.hIconSm = NULL; - - ATOM atom= ::RegisterClassEx(&wc); - if (atom) - { - _AtlWinModule.m_rgWindowClassAtoms.Add(atom); - bRet=TRUE; - }else - { - bRet=FALSE; - } - } - - if (bRet) - { - // first check if the class is already registered - memset(&wc, 0, sizeof(WNDCLASSEX)); - wc.cbSize = sizeof(WNDCLASSEX); - bRet = ::GetClassInfoEx(_AtlBaseModule.GetModuleInstance(), CAxWindow2::GetWndClassName(), &wc); - - // register class if not - - if(!bRet) - { - wc.cbSize = sizeof(WNDCLASSEX); -#ifdef _ATL_DLL_IMPL - wc.style = CS_GLOBALCLASS | CS_DBLCLKS; -#else - wc.style = CS_DBLCLKS; -#endif - wc.lpfnWndProc = AtlAxWindowProc2; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = _AtlBaseModule.GetModuleInstance(); - wc.hIcon = NULL; - wc.hCursor = ::LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); - wc.lpszMenuName = NULL; - wc.lpszClassName = CAxWindow2::GetWndClassName(); - wc.hIconSm = NULL; - ATOM atom= RegisterClassEx(&wc); - - if (atom) - { - _AtlWinModule.m_rgWindowClassAtoms.Add(atom); - bRet=TRUE; - }else - { - bRet=FALSE; - } - - } - } - return bRet; -} - -ATLINLINE ATLAPI AtlAxGetControl(HWND h, IUnknown** pp) -{ - ATLASSERT(WM_ATLGETCONTROL != 0); - if (pp == NULL) - return E_POINTER; - *pp = (IUnknown*)SendMessage(h, WM_ATLGETCONTROL, 0, 0); - return (*pp) ? S_OK : E_FAIL; -} - -ATLINLINE ATLAPI AtlAxGetHost(HWND h, IUnknown** pp) -{ - ATLASSERT(WM_ATLGETHOST != 0); - if (pp == NULL) - return E_POINTER; - *pp = (IUnknown*)SendMessage(h, WM_ATLGETHOST, 0, 0); - return (*pp) ? S_OK : E_FAIL; -} - -#endif // _ATL_DLL - -}; //namespace ATL -#pragma pack(pop) - -#ifndef _ATL_NO_PRAGMA_WARNINGS -#pragma warning (pop) -#endif //!_ATL_NO_PRAGMA_WARNINGS - -#endif // __ATLHOST_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atliface.h b/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atliface.h deleted file mode 100644 index 149a61369..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atliface.h +++ /dev/null @@ -1,2955 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#pragma warning( disable: 4049 ) /* more than 64k source lines */ - -/* this ALWAYS GENERATED file contains the definitions for the interfaces */ - - - /* File created by MIDL compiler version 6.00.0342 */ -/* at Mon Feb 12 21:31:09 2001 - */ -/* Compiler settings for atliface.idl: - Oicf, W1, Zp8, env=Win32 (32b run) - protocol : dce , ms_ext, c_ext - error checks: allocation ref bounds_check enum stub_data - VC __declspec() decoration level: - __declspec(uuid()), __declspec(selectany), __declspec(novtable) - DECLSPEC_UUID(), MIDL_INTERFACE() -*/ -//@@MIDL_FILE_HEADING( ) - - -/* verify that the version is high enough to compile this file*/ -#ifndef __REQUIRED_RPCNDR_H_VERSION__ -#define __REQUIRED_RPCNDR_H_VERSION__ 440 -#endif - -#include "rpc.h" -#include "rpcndr.h" - -#ifndef __RPCNDR_H_VERSION__ -#error this stub requires an updated version of -#endif // __RPCNDR_H_VERSION__ - -#ifndef COM_NO_WINDOWS_H -#include "windows.h" -#include "ole2.h" -#endif /*COM_NO_WINDOWS_H*/ - -#ifndef __atliface_h__ -#define __atliface_h__ - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -#pragma once -#endif - -/* Forward Declarations */ - -#ifndef __IRegistrarBase_FWD_DEFINED__ -#define __IRegistrarBase_FWD_DEFINED__ -typedef interface IRegistrarBase IRegistrarBase; -#endif /* __IRegistrarBase_FWD_DEFINED__ */ - - -#ifndef __IRegistrar_FWD_DEFINED__ -#define __IRegistrar_FWD_DEFINED__ -typedef interface IRegistrar IRegistrar; -#endif /* __IRegistrar_FWD_DEFINED__ */ - - -#ifndef __IDocHostUIHandlerDispatch_FWD_DEFINED__ -#define __IDocHostUIHandlerDispatch_FWD_DEFINED__ -typedef interface IDocHostUIHandlerDispatch IDocHostUIHandlerDispatch; -#endif /* __IDocHostUIHandlerDispatch_FWD_DEFINED__ */ - - -#ifndef __IAxWinHostWindow_FWD_DEFINED__ -#define __IAxWinHostWindow_FWD_DEFINED__ -typedef interface IAxWinHostWindow IAxWinHostWindow; -#endif /* __IAxWinHostWindow_FWD_DEFINED__ */ - - -#ifndef __IAxWinHostWindowLic_FWD_DEFINED__ -#define __IAxWinHostWindowLic_FWD_DEFINED__ -typedef interface IAxWinHostWindowLic IAxWinHostWindowLic; -#endif /* __IAxWinHostWindowLic_FWD_DEFINED__ */ - - -#ifndef __IAxWinAmbientDispatch_FWD_DEFINED__ -#define __IAxWinAmbientDispatch_FWD_DEFINED__ -typedef interface IAxWinAmbientDispatch IAxWinAmbientDispatch; -#endif /* __IAxWinAmbientDispatch_FWD_DEFINED__ */ - - -#ifndef __IAxWinAmbientDispatchEx_FWD_DEFINED__ -#define __IAxWinAmbientDispatchEx_FWD_DEFINED__ -typedef interface IAxWinAmbientDispatchEx IAxWinAmbientDispatchEx; -#endif /* __IAxWinAmbientDispatchEx_FWD_DEFINED__ */ - - -#ifndef __IInternalConnection_FWD_DEFINED__ -#define __IInternalConnection_FWD_DEFINED__ -typedef interface IInternalConnection IInternalConnection; -#endif /* __IInternalConnection_FWD_DEFINED__ */ - - -#ifndef __IAccessibleProxy_FWD_DEFINED__ -#define __IAccessibleProxy_FWD_DEFINED__ -typedef interface IAccessibleProxy IAccessibleProxy; -#endif /* __IAccessibleProxy_FWD_DEFINED__ */ - - -#ifndef __IAccessibleServer_FWD_DEFINED__ -#define __IAccessibleServer_FWD_DEFINED__ -typedef interface IAccessibleServer IAccessibleServer; -#endif /* __IAccessibleServer_FWD_DEFINED__ */ - - -/* header files for imported files */ -#include "oaidl.h" -#include "ocidl.h" -#include "oleacc.h" - -#ifdef __cplusplus -extern "C"{ -#endif - -void * __RPC_USER MIDL_user_allocate(size_t); -void __RPC_USER MIDL_user_free( void * ); - -/* interface __MIDL_itf_atliface_0000 */ -/* [local] */ - -EXTERN_C const CLSID CLSID_Registrar; - - -extern RPC_IF_HANDLE __MIDL_itf_atliface_0000_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_atliface_0000_v0_0_s_ifspec; - -#ifndef __IRegistrarBase_INTERFACE_DEFINED__ -#define __IRegistrarBase_INTERFACE_DEFINED__ - -/* interface IRegistrarBase */ -/* [unique][helpstring][uuid][object] */ - - -EXTERN_C const IID IID_IRegistrarBase; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("e21f8a85-b05d-4243-8183-c7cb405588f7") - IRegistrarBase : public IUnknown - { - public: - virtual HRESULT STDMETHODCALLTYPE AddReplacement( - /* [in] */ LPCOLESTR key, - /* [in] */ LPCOLESTR item) = 0; - - virtual HRESULT STDMETHODCALLTYPE ClearReplacements( void) = 0; - - }; - -#else /* C style interface */ - - typedef struct IRegistrarBaseVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IRegistrarBase * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IRegistrarBase * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IRegistrarBase * This); - - HRESULT ( STDMETHODCALLTYPE *AddReplacement )( - IRegistrarBase * This, - /* [in] */ LPCOLESTR key, - /* [in] */ LPCOLESTR item); - - HRESULT ( STDMETHODCALLTYPE *ClearReplacements )( - IRegistrarBase * This); - - END_INTERFACE - } IRegistrarBaseVtbl; - - interface IRegistrarBase - { - CONST_VTBL struct IRegistrarBaseVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IRegistrarBase_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IRegistrarBase_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IRegistrarBase_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IRegistrarBase_AddReplacement(This,key,item) \ - (This)->lpVtbl -> AddReplacement(This,key,item) - -#define IRegistrarBase_ClearReplacements(This) \ - (This)->lpVtbl -> ClearReplacements(This) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -HRESULT STDMETHODCALLTYPE IRegistrarBase_AddReplacement_Proxy( - IRegistrarBase * This, - /* [in] */ LPCOLESTR key, - /* [in] */ LPCOLESTR item); - - -void __RPC_STUB IRegistrarBase_AddReplacement_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IRegistrarBase_ClearReplacements_Proxy( - IRegistrarBase * This); - - -void __RPC_STUB IRegistrarBase_ClearReplacements_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IRegistrarBase_INTERFACE_DEFINED__ */ - - -#ifndef __IRegistrar_INTERFACE_DEFINED__ -#define __IRegistrar_INTERFACE_DEFINED__ - -/* interface IRegistrar */ -/* [unique][helpstring][uuid][object] */ - - -EXTERN_C const IID IID_IRegistrar; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("44EC053B-400F-11D0-9DCD-00A0C90391D3") - IRegistrar : public IRegistrarBase - { - public: - virtual HRESULT STDMETHODCALLTYPE ResourceRegisterSz( - /* [in] */ LPCOLESTR resFileName, - /* [in] */ LPCOLESTR szID, - /* [in] */ LPCOLESTR szType) = 0; - - virtual HRESULT STDMETHODCALLTYPE ResourceUnregisterSz( - /* [in] */ LPCOLESTR resFileName, - /* [in] */ LPCOLESTR szID, - /* [in] */ LPCOLESTR szType) = 0; - - virtual HRESULT STDMETHODCALLTYPE FileRegister( - /* [in] */ LPCOLESTR fileName) = 0; - - virtual HRESULT STDMETHODCALLTYPE FileUnregister( - /* [in] */ LPCOLESTR fileName) = 0; - - virtual HRESULT STDMETHODCALLTYPE StringRegister( - /* [in] */ LPCOLESTR data) = 0; - - virtual HRESULT STDMETHODCALLTYPE StringUnregister( - /* [in] */ LPCOLESTR data) = 0; - - virtual HRESULT STDMETHODCALLTYPE ResourceRegister( - /* [in] */ LPCOLESTR resFileName, - /* [in] */ UINT nID, - /* [in] */ LPCOLESTR szType) = 0; - - virtual HRESULT STDMETHODCALLTYPE ResourceUnregister( - /* [in] */ LPCOLESTR resFileName, - /* [in] */ UINT nID, - /* [in] */ LPCOLESTR szType) = 0; - - }; - -#else /* C style interface */ - - typedef struct IRegistrarVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IRegistrar * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IRegistrar * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IRegistrar * This); - - HRESULT ( STDMETHODCALLTYPE *AddReplacement )( - IRegistrar * This, - /* [in] */ LPCOLESTR key, - /* [in] */ LPCOLESTR item); - - HRESULT ( STDMETHODCALLTYPE *ClearReplacements )( - IRegistrar * This); - - HRESULT ( STDMETHODCALLTYPE *ResourceRegisterSz )( - IRegistrar * This, - /* [in] */ LPCOLESTR resFileName, - /* [in] */ LPCOLESTR szID, - /* [in] */ LPCOLESTR szType); - - HRESULT ( STDMETHODCALLTYPE *ResourceUnregisterSz )( - IRegistrar * This, - /* [in] */ LPCOLESTR resFileName, - /* [in] */ LPCOLESTR szID, - /* [in] */ LPCOLESTR szType); - - HRESULT ( STDMETHODCALLTYPE *FileRegister )( - IRegistrar * This, - /* [in] */ LPCOLESTR fileName); - - HRESULT ( STDMETHODCALLTYPE *FileUnregister )( - IRegistrar * This, - /* [in] */ LPCOLESTR fileName); - - HRESULT ( STDMETHODCALLTYPE *StringRegister )( - IRegistrar * This, - /* [in] */ LPCOLESTR data); - - HRESULT ( STDMETHODCALLTYPE *StringUnregister )( - IRegistrar * This, - /* [in] */ LPCOLESTR data); - - HRESULT ( STDMETHODCALLTYPE *ResourceRegister )( - IRegistrar * This, - /* [in] */ LPCOLESTR resFileName, - /* [in] */ UINT nID, - /* [in] */ LPCOLESTR szType); - - HRESULT ( STDMETHODCALLTYPE *ResourceUnregister )( - IRegistrar * This, - /* [in] */ LPCOLESTR resFileName, - /* [in] */ UINT nID, - /* [in] */ LPCOLESTR szType); - - END_INTERFACE - } IRegistrarVtbl; - - interface IRegistrar - { - CONST_VTBL struct IRegistrarVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IRegistrar_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IRegistrar_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IRegistrar_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IRegistrar_AddReplacement(This,key,item) \ - (This)->lpVtbl -> AddReplacement(This,key,item) - -#define IRegistrar_ClearReplacements(This) \ - (This)->lpVtbl -> ClearReplacements(This) - - -#define IRegistrar_ResourceRegisterSz(This,resFileName,szID,szType) \ - (This)->lpVtbl -> ResourceRegisterSz(This,resFileName,szID,szType) - -#define IRegistrar_ResourceUnregisterSz(This,resFileName,szID,szType) \ - (This)->lpVtbl -> ResourceUnregisterSz(This,resFileName,szID,szType) - -#define IRegistrar_FileRegister(This,fileName) \ - (This)->lpVtbl -> FileRegister(This,fileName) - -#define IRegistrar_FileUnregister(This,fileName) \ - (This)->lpVtbl -> FileUnregister(This,fileName) - -#define IRegistrar_StringRegister(This,data) \ - (This)->lpVtbl -> StringRegister(This,data) - -#define IRegistrar_StringUnregister(This,data) \ - (This)->lpVtbl -> StringUnregister(This,data) - -#define IRegistrar_ResourceRegister(This,resFileName,nID,szType) \ - (This)->lpVtbl -> ResourceRegister(This,resFileName,nID,szType) - -#define IRegistrar_ResourceUnregister(This,resFileName,nID,szType) \ - (This)->lpVtbl -> ResourceUnregister(This,resFileName,nID,szType) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -HRESULT STDMETHODCALLTYPE IRegistrar_ResourceRegisterSz_Proxy( - IRegistrar * This, - /* [in] */ LPCOLESTR resFileName, - /* [in] */ LPCOLESTR szID, - /* [in] */ LPCOLESTR szType); - - -void __RPC_STUB IRegistrar_ResourceRegisterSz_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IRegistrar_ResourceUnregisterSz_Proxy( - IRegistrar * This, - /* [in] */ LPCOLESTR resFileName, - /* [in] */ LPCOLESTR szID, - /* [in] */ LPCOLESTR szType); - - -void __RPC_STUB IRegistrar_ResourceUnregisterSz_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IRegistrar_FileRegister_Proxy( - IRegistrar * This, - /* [in] */ LPCOLESTR fileName); - - -void __RPC_STUB IRegistrar_FileRegister_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IRegistrar_FileUnregister_Proxy( - IRegistrar * This, - /* [in] */ LPCOLESTR fileName); - - -void __RPC_STUB IRegistrar_FileUnregister_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IRegistrar_StringRegister_Proxy( - IRegistrar * This, - /* [in] */ LPCOLESTR data); - - -void __RPC_STUB IRegistrar_StringRegister_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IRegistrar_StringUnregister_Proxy( - IRegistrar * This, - /* [in] */ LPCOLESTR data); - - -void __RPC_STUB IRegistrar_StringUnregister_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IRegistrar_ResourceRegister_Proxy( - IRegistrar * This, - /* [in] */ LPCOLESTR resFileName, - /* [in] */ UINT nID, - /* [in] */ LPCOLESTR szType); - - -void __RPC_STUB IRegistrar_ResourceRegister_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IRegistrar_ResourceUnregister_Proxy( - IRegistrar * This, - /* [in] */ LPCOLESTR resFileName, - /* [in] */ UINT nID, - /* [in] */ LPCOLESTR szType); - - -void __RPC_STUB IRegistrar_ResourceUnregister_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IRegistrar_INTERFACE_DEFINED__ */ - - -#ifndef __IDocHostUIHandlerDispatch_INTERFACE_DEFINED__ -#define __IDocHostUIHandlerDispatch_INTERFACE_DEFINED__ - -/* interface IDocHostUIHandlerDispatch */ -/* [object][unique][helpstring][uuid][local] */ - -typedef -enum tagDOCHOSTUIDBLCLKDispatch - { docHostUIDblClkDEFAULT = 0, - docHostUIDblClkSHOWPROPERTIES = 1, - docHostUIDblClkSHOWCODE = 2 - } DOCHOSTUIDBLCLKDispatch; - -typedef -enum tagDocHostUIFlagDispatch - { docHostUIFlagDIALOG = 1, - docHostUIFlagDISABLE_HELP_MENU = 2, - docHostUIFlagNO3DBORDER = 4, - docHostUIFlagSCROLL_NO = 8, - docHostUIFlagDISABLE_SCRIPT_INACTIVE = 16, - docHostUIFlagOPENNEWWIN = 32, - docHostUIFlagDISABLE_OFFSCREEN = 64, - docHostUIFlagFLAT_SCROLLBAR = 128, - docHostUIFlagDIV_BLOCKDEFAULT = 256, - docHostUIFlagACTIVATE_CLIENTHIT_ONLY = 512 - } DocHostUIFlagDispatch; - - -EXTERN_C const IID IID_IDocHostUIHandlerDispatch; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("425B5AF0-65F1-11d1-9611-0000F81E0D0D") - IDocHostUIHandlerDispatch : public IDispatch - { - public: - virtual HRESULT STDMETHODCALLTYPE ShowContextMenu( - /* [in] */ DWORD dwID, - /* [in] */ DWORD x, - /* [in] */ DWORD y, - /* [in] */ IUnknown *pcmdtReserved, - /* [in] */ IDispatch *pdispReserved, - /* [retval][out] */ HRESULT *dwRetVal) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetHostInfo( - /* [out][in] */ DWORD *pdwFlags, - /* [out][in] */ DWORD *pdwDoubleClick) = 0; - - virtual HRESULT STDMETHODCALLTYPE ShowUI( - /* [in] */ DWORD dwID, - /* [in] */ IUnknown *pActiveObject, - /* [in] */ IUnknown *pCommandTarget, - /* [in] */ IUnknown *pFrame, - /* [in] */ IUnknown *pDoc, - /* [retval][out] */ HRESULT *dwRetVal) = 0; - - virtual HRESULT STDMETHODCALLTYPE HideUI( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE UpdateUI( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnableModeless( - /* [in] */ VARIANT_BOOL fEnable) = 0; - - virtual HRESULT STDMETHODCALLTYPE OnDocWindowActivate( - /* [in] */ VARIANT_BOOL fActivate) = 0; - - virtual HRESULT STDMETHODCALLTYPE OnFrameWindowActivate( - /* [in] */ VARIANT_BOOL fActivate) = 0; - - virtual HRESULT STDMETHODCALLTYPE ResizeBorder( - /* [in] */ long left, - /* [in] */ long top, - /* [in] */ long right, - /* [in] */ long bottom, - /* [in] */ IUnknown *pUIWindow, - /* [in] */ VARIANT_BOOL fFrameWindow) = 0; - - virtual HRESULT STDMETHODCALLTYPE TranslateAccelerator( - /* [in] */ DWORD_PTR hWnd, - /* [in] */ DWORD nMessage, - /* [in] */ DWORD_PTR wParam, - /* [in] */ DWORD_PTR lParam, - /* [in] */ BSTR bstrGuidCmdGroup, - /* [in] */ DWORD nCmdID, - /* [retval][out] */ HRESULT *dwRetVal) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetOptionKeyPath( - /* [out] */ BSTR *pbstrKey, - /* [in] */ DWORD dw) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetDropTarget( - /* [in] */ IUnknown *pDropTarget, - /* [out] */ IUnknown **ppDropTarget) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetExternal( - /* [out] */ IDispatch **ppDispatch) = 0; - - virtual HRESULT STDMETHODCALLTYPE TranslateUrl( - /* [in] */ DWORD dwTranslate, - /* [in] */ BSTR bstrURLIn, - /* [out] */ BSTR *pbstrURLOut) = 0; - - virtual HRESULT STDMETHODCALLTYPE FilterDataObject( - /* [in] */ IUnknown *pDO, - /* [out] */ IUnknown **ppDORet) = 0; - - }; - -#else /* C style interface */ - - typedef struct IDocHostUIHandlerDispatchVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IDocHostUIHandlerDispatch * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IDocHostUIHandlerDispatch * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IDocHostUIHandlerDispatch * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IDocHostUIHandlerDispatch * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IDocHostUIHandlerDispatch * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IDocHostUIHandlerDispatch * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IDocHostUIHandlerDispatch * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - HRESULT ( STDMETHODCALLTYPE *ShowContextMenu )( - IDocHostUIHandlerDispatch * This, - /* [in] */ DWORD dwID, - /* [in] */ DWORD x, - /* [in] */ DWORD y, - /* [in] */ IUnknown *pcmdtReserved, - /* [in] */ IDispatch *pdispReserved, - /* [retval][out] */ HRESULT *dwRetVal); - - HRESULT ( STDMETHODCALLTYPE *GetHostInfo )( - IDocHostUIHandlerDispatch * This, - /* [out][in] */ DWORD *pdwFlags, - /* [out][in] */ DWORD *pdwDoubleClick); - - HRESULT ( STDMETHODCALLTYPE *ShowUI )( - IDocHostUIHandlerDispatch * This, - /* [in] */ DWORD dwID, - /* [in] */ IUnknown *pActiveObject, - /* [in] */ IUnknown *pCommandTarget, - /* [in] */ IUnknown *pFrame, - /* [in] */ IUnknown *pDoc, - /* [retval][out] */ HRESULT *dwRetVal); - - HRESULT ( STDMETHODCALLTYPE *HideUI )( - IDocHostUIHandlerDispatch * This); - - HRESULT ( STDMETHODCALLTYPE *UpdateUI )( - IDocHostUIHandlerDispatch * This); - - HRESULT ( STDMETHODCALLTYPE *EnableModeless )( - IDocHostUIHandlerDispatch * This, - /* [in] */ VARIANT_BOOL fEnable); - - HRESULT ( STDMETHODCALLTYPE *OnDocWindowActivate )( - IDocHostUIHandlerDispatch * This, - /* [in] */ VARIANT_BOOL fActivate); - - HRESULT ( STDMETHODCALLTYPE *OnFrameWindowActivate )( - IDocHostUIHandlerDispatch * This, - /* [in] */ VARIANT_BOOL fActivate); - - HRESULT ( STDMETHODCALLTYPE *ResizeBorder )( - IDocHostUIHandlerDispatch * This, - /* [in] */ long left, - /* [in] */ long top, - /* [in] */ long right, - /* [in] */ long bottom, - /* [in] */ IUnknown *pUIWindow, - /* [in] */ VARIANT_BOOL fFrameWindow); - - HRESULT ( STDMETHODCALLTYPE *TranslateAccelerator )( - IDocHostUIHandlerDispatch * This, - /* [in] */ DWORD_PTR hWnd, - /* [in] */ DWORD nMessage, - /* [in] */ DWORD_PTR wParam, - /* [in] */ DWORD_PTR lParam, - /* [in] */ BSTR bstrGuidCmdGroup, - /* [in] */ DWORD nCmdID, - /* [retval][out] */ HRESULT *dwRetVal); - - HRESULT ( STDMETHODCALLTYPE *GetOptionKeyPath )( - IDocHostUIHandlerDispatch * This, - /* [out] */ BSTR *pbstrKey, - /* [in] */ DWORD dw); - - HRESULT ( STDMETHODCALLTYPE *GetDropTarget )( - IDocHostUIHandlerDispatch * This, - /* [in] */ IUnknown *pDropTarget, - /* [out] */ IUnknown **ppDropTarget); - - HRESULT ( STDMETHODCALLTYPE *GetExternal )( - IDocHostUIHandlerDispatch * This, - /* [out] */ IDispatch **ppDispatch); - - HRESULT ( STDMETHODCALLTYPE *TranslateUrl )( - IDocHostUIHandlerDispatch * This, - /* [in] */ DWORD dwTranslate, - /* [in] */ BSTR bstrURLIn, - /* [out] */ BSTR *pbstrURLOut); - - HRESULT ( STDMETHODCALLTYPE *FilterDataObject )( - IDocHostUIHandlerDispatch * This, - /* [in] */ IUnknown *pDO, - /* [out] */ IUnknown **ppDORet); - - END_INTERFACE - } IDocHostUIHandlerDispatchVtbl; - - interface IDocHostUIHandlerDispatch - { - CONST_VTBL struct IDocHostUIHandlerDispatchVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IDocHostUIHandlerDispatch_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IDocHostUIHandlerDispatch_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IDocHostUIHandlerDispatch_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IDocHostUIHandlerDispatch_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IDocHostUIHandlerDispatch_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IDocHostUIHandlerDispatch_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IDocHostUIHandlerDispatch_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IDocHostUIHandlerDispatch_ShowContextMenu(This,dwID,x,y,pcmdtReserved,pdispReserved,dwRetVal) \ - (This)->lpVtbl -> ShowContextMenu(This,dwID,x,y,pcmdtReserved,pdispReserved,dwRetVal) - -#define IDocHostUIHandlerDispatch_GetHostInfo(This,pdwFlags,pdwDoubleClick) \ - (This)->lpVtbl -> GetHostInfo(This,pdwFlags,pdwDoubleClick) - -#define IDocHostUIHandlerDispatch_ShowUI(This,dwID,pActiveObject,pCommandTarget,pFrame,pDoc,dwRetVal) \ - (This)->lpVtbl -> ShowUI(This,dwID,pActiveObject,pCommandTarget,pFrame,pDoc,dwRetVal) - -#define IDocHostUIHandlerDispatch_HideUI(This) \ - (This)->lpVtbl -> HideUI(This) - -#define IDocHostUIHandlerDispatch_UpdateUI(This) \ - (This)->lpVtbl -> UpdateUI(This) - -#define IDocHostUIHandlerDispatch_EnableModeless(This,fEnable) \ - (This)->lpVtbl -> EnableModeless(This,fEnable) - -#define IDocHostUIHandlerDispatch_OnDocWindowActivate(This,fActivate) \ - (This)->lpVtbl -> OnDocWindowActivate(This,fActivate) - -#define IDocHostUIHandlerDispatch_OnFrameWindowActivate(This,fActivate) \ - (This)->lpVtbl -> OnFrameWindowActivate(This,fActivate) - -#define IDocHostUIHandlerDispatch_ResizeBorder(This,left,top,right,bottom,pUIWindow,fFrameWindow) \ - (This)->lpVtbl -> ResizeBorder(This,left,top,right,bottom,pUIWindow,fFrameWindow) - -#define IDocHostUIHandlerDispatch_TranslateAccelerator(This,hWnd,nMessage,wParam,lParam,bstrGuidCmdGroup,nCmdID,dwRetVal) \ - (This)->lpVtbl -> TranslateAccelerator(This,hWnd,nMessage,wParam,lParam,bstrGuidCmdGroup,nCmdID,dwRetVal) - -#define IDocHostUIHandlerDispatch_GetOptionKeyPath(This,pbstrKey,dw) \ - (This)->lpVtbl -> GetOptionKeyPath(This,pbstrKey,dw) - -#define IDocHostUIHandlerDispatch_GetDropTarget(This,pDropTarget,ppDropTarget) \ - (This)->lpVtbl -> GetDropTarget(This,pDropTarget,ppDropTarget) - -#define IDocHostUIHandlerDispatch_GetExternal(This,ppDispatch) \ - (This)->lpVtbl -> GetExternal(This,ppDispatch) - -#define IDocHostUIHandlerDispatch_TranslateUrl(This,dwTranslate,bstrURLIn,pbstrURLOut) \ - (This)->lpVtbl -> TranslateUrl(This,dwTranslate,bstrURLIn,pbstrURLOut) - -#define IDocHostUIHandlerDispatch_FilterDataObject(This,pDO,ppDORet) \ - (This)->lpVtbl -> FilterDataObject(This,pDO,ppDORet) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_ShowContextMenu_Proxy( - IDocHostUIHandlerDispatch * This, - /* [in] */ DWORD dwID, - /* [in] */ DWORD x, - /* [in] */ DWORD y, - /* [in] */ IUnknown *pcmdtReserved, - /* [in] */ IDispatch *pdispReserved, - /* [retval][out] */ HRESULT *dwRetVal); - - -void __RPC_STUB IDocHostUIHandlerDispatch_ShowContextMenu_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_GetHostInfo_Proxy( - IDocHostUIHandlerDispatch * This, - /* [out][in] */ DWORD *pdwFlags, - /* [out][in] */ DWORD *pdwDoubleClick); - - -void __RPC_STUB IDocHostUIHandlerDispatch_GetHostInfo_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_ShowUI_Proxy( - IDocHostUIHandlerDispatch * This, - /* [in] */ DWORD dwID, - /* [in] */ IUnknown *pActiveObject, - /* [in] */ IUnknown *pCommandTarget, - /* [in] */ IUnknown *pFrame, - /* [in] */ IUnknown *pDoc, - /* [retval][out] */ HRESULT *dwRetVal); - - -void __RPC_STUB IDocHostUIHandlerDispatch_ShowUI_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_HideUI_Proxy( - IDocHostUIHandlerDispatch * This); - - -void __RPC_STUB IDocHostUIHandlerDispatch_HideUI_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_UpdateUI_Proxy( - IDocHostUIHandlerDispatch * This); - - -void __RPC_STUB IDocHostUIHandlerDispatch_UpdateUI_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_EnableModeless_Proxy( - IDocHostUIHandlerDispatch * This, - /* [in] */ VARIANT_BOOL fEnable); - - -void __RPC_STUB IDocHostUIHandlerDispatch_EnableModeless_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_OnDocWindowActivate_Proxy( - IDocHostUIHandlerDispatch * This, - /* [in] */ VARIANT_BOOL fActivate); - - -void __RPC_STUB IDocHostUIHandlerDispatch_OnDocWindowActivate_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_OnFrameWindowActivate_Proxy( - IDocHostUIHandlerDispatch * This, - /* [in] */ VARIANT_BOOL fActivate); - - -void __RPC_STUB IDocHostUIHandlerDispatch_OnFrameWindowActivate_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_ResizeBorder_Proxy( - IDocHostUIHandlerDispatch * This, - /* [in] */ long left, - /* [in] */ long top, - /* [in] */ long right, - /* [in] */ long bottom, - /* [in] */ IUnknown *pUIWindow, - /* [in] */ VARIANT_BOOL fFrameWindow); - - -void __RPC_STUB IDocHostUIHandlerDispatch_ResizeBorder_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_TranslateAccelerator_Proxy( - IDocHostUIHandlerDispatch * This, - /* [in] */ DWORD_PTR hWnd, - /* [in] */ DWORD nMessage, - /* [in] */ DWORD_PTR wParam, - /* [in] */ DWORD_PTR lParam, - /* [in] */ BSTR bstrGuidCmdGroup, - /* [in] */ DWORD nCmdID, - /* [retval][out] */ HRESULT *dwRetVal); - - -void __RPC_STUB IDocHostUIHandlerDispatch_TranslateAccelerator_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_GetOptionKeyPath_Proxy( - IDocHostUIHandlerDispatch * This, - /* [out] */ BSTR *pbstrKey, - /* [in] */ DWORD dw); - - -void __RPC_STUB IDocHostUIHandlerDispatch_GetOptionKeyPath_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_GetDropTarget_Proxy( - IDocHostUIHandlerDispatch * This, - /* [in] */ IUnknown *pDropTarget, - /* [out] */ IUnknown **ppDropTarget); - - -void __RPC_STUB IDocHostUIHandlerDispatch_GetDropTarget_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_GetExternal_Proxy( - IDocHostUIHandlerDispatch * This, - /* [out] */ IDispatch **ppDispatch); - - -void __RPC_STUB IDocHostUIHandlerDispatch_GetExternal_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_TranslateUrl_Proxy( - IDocHostUIHandlerDispatch * This, - /* [in] */ DWORD dwTranslate, - /* [in] */ BSTR bstrURLIn, - /* [out] */ BSTR *pbstrURLOut); - - -void __RPC_STUB IDocHostUIHandlerDispatch_TranslateUrl_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_FilterDataObject_Proxy( - IDocHostUIHandlerDispatch * This, - /* [in] */ IUnknown *pDO, - /* [out] */ IUnknown **ppDORet); - - -void __RPC_STUB IDocHostUIHandlerDispatch_FilterDataObject_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IDocHostUIHandlerDispatch_INTERFACE_DEFINED__ */ - - -#ifndef __IAxWinHostWindow_INTERFACE_DEFINED__ -#define __IAxWinHostWindow_INTERFACE_DEFINED__ - -/* interface IAxWinHostWindow */ -/* [object][unique][helpstring][uuid] */ - - -EXTERN_C const IID IID_IAxWinHostWindow; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("B6EA2050-048A-11d1-82B9-00C04FB9942E") - IAxWinHostWindow : public IUnknown - { - public: - virtual HRESULT STDMETHODCALLTYPE CreateControl( - /* [in] */ LPCOLESTR lpTricsData, - /* [in] */ HWND hWnd, - /* [in] */ IStream *pStream) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateControlEx( - /* [in] */ LPCOLESTR lpTricsData, - /* [in] */ HWND hWnd, - /* [in] */ IStream *pStream, - /* [out] */ IUnknown **ppUnk, - /* [in] */ REFIID riidAdvise, - /* [in] */ IUnknown *punkAdvise) = 0; - - virtual HRESULT STDMETHODCALLTYPE AttachControl( - /* [in] */ IUnknown *pUnkControl, - /* [in] */ HWND hWnd) = 0; - - virtual HRESULT STDMETHODCALLTYPE QueryControl( - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetExternalDispatch( - /* [in] */ IDispatch *pDisp) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetExternalUIHandler( - /* [in] */ IDocHostUIHandlerDispatch *pDisp) = 0; - - }; - -#else /* C style interface */ - - typedef struct IAxWinHostWindowVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IAxWinHostWindow * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IAxWinHostWindow * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IAxWinHostWindow * This); - - HRESULT ( STDMETHODCALLTYPE *CreateControl )( - IAxWinHostWindow * This, - /* [in] */ LPCOLESTR lpTricsData, - /* [in] */ HWND hWnd, - /* [in] */ IStream *pStream); - - HRESULT ( STDMETHODCALLTYPE *CreateControlEx )( - IAxWinHostWindow * This, - /* [in] */ LPCOLESTR lpTricsData, - /* [in] */ HWND hWnd, - /* [in] */ IStream *pStream, - /* [out] */ IUnknown **ppUnk, - /* [in] */ REFIID riidAdvise, - /* [in] */ IUnknown *punkAdvise); - - HRESULT ( STDMETHODCALLTYPE *AttachControl )( - IAxWinHostWindow * This, - /* [in] */ IUnknown *pUnkControl, - /* [in] */ HWND hWnd); - - HRESULT ( STDMETHODCALLTYPE *QueryControl )( - IAxWinHostWindow * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - HRESULT ( STDMETHODCALLTYPE *SetExternalDispatch )( - IAxWinHostWindow * This, - /* [in] */ IDispatch *pDisp); - - HRESULT ( STDMETHODCALLTYPE *SetExternalUIHandler )( - IAxWinHostWindow * This, - /* [in] */ IDocHostUIHandlerDispatch *pDisp); - - END_INTERFACE - } IAxWinHostWindowVtbl; - - interface IAxWinHostWindow - { - CONST_VTBL struct IAxWinHostWindowVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IAxWinHostWindow_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IAxWinHostWindow_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IAxWinHostWindow_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IAxWinHostWindow_CreateControl(This,lpTricsData,hWnd,pStream) \ - (This)->lpVtbl -> CreateControl(This,lpTricsData,hWnd,pStream) - -#define IAxWinHostWindow_CreateControlEx(This,lpTricsData,hWnd,pStream,ppUnk,riidAdvise,punkAdvise) \ - (This)->lpVtbl -> CreateControlEx(This,lpTricsData,hWnd,pStream,ppUnk,riidAdvise,punkAdvise) - -#define IAxWinHostWindow_AttachControl(This,pUnkControl,hWnd) \ - (This)->lpVtbl -> AttachControl(This,pUnkControl,hWnd) - -#define IAxWinHostWindow_QueryControl(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryControl(This,riid,ppvObject) - -#define IAxWinHostWindow_SetExternalDispatch(This,pDisp) \ - (This)->lpVtbl -> SetExternalDispatch(This,pDisp) - -#define IAxWinHostWindow_SetExternalUIHandler(This,pDisp) \ - (This)->lpVtbl -> SetExternalUIHandler(This,pDisp) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -HRESULT STDMETHODCALLTYPE IAxWinHostWindow_CreateControl_Proxy( - IAxWinHostWindow * This, - /* [in] */ LPCOLESTR lpTricsData, - /* [in] */ HWND hWnd, - /* [in] */ IStream *pStream); - - -void __RPC_STUB IAxWinHostWindow_CreateControl_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IAxWinHostWindow_CreateControlEx_Proxy( - IAxWinHostWindow * This, - /* [in] */ LPCOLESTR lpTricsData, - /* [in] */ HWND hWnd, - /* [in] */ IStream *pStream, - /* [out] */ IUnknown **ppUnk, - /* [in] */ REFIID riidAdvise, - /* [in] */ IUnknown *punkAdvise); - - -void __RPC_STUB IAxWinHostWindow_CreateControlEx_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IAxWinHostWindow_AttachControl_Proxy( - IAxWinHostWindow * This, - /* [in] */ IUnknown *pUnkControl, - /* [in] */ HWND hWnd); - - -void __RPC_STUB IAxWinHostWindow_AttachControl_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IAxWinHostWindow_QueryControl_Proxy( - IAxWinHostWindow * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - -void __RPC_STUB IAxWinHostWindow_QueryControl_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IAxWinHostWindow_SetExternalDispatch_Proxy( - IAxWinHostWindow * This, - /* [in] */ IDispatch *pDisp); - - -void __RPC_STUB IAxWinHostWindow_SetExternalDispatch_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IAxWinHostWindow_SetExternalUIHandler_Proxy( - IAxWinHostWindow * This, - /* [in] */ IDocHostUIHandlerDispatch *pDisp); - - -void __RPC_STUB IAxWinHostWindow_SetExternalUIHandler_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IAxWinHostWindow_INTERFACE_DEFINED__ */ - - -#ifndef __IAxWinHostWindowLic_INTERFACE_DEFINED__ -#define __IAxWinHostWindowLic_INTERFACE_DEFINED__ - -/* interface IAxWinHostWindowLic */ -/* [object][unique][helpstring][uuid] */ - - -EXTERN_C const IID IID_IAxWinHostWindowLic; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("3935BDA8-4ED9-495c-8650-E01FC1E38A4B") - IAxWinHostWindowLic : public IAxWinHostWindow - { - public: - virtual HRESULT STDMETHODCALLTYPE CreateControlLic( - /* [in] */ LPCOLESTR lpTricsData, - /* [in] */ HWND hWnd, - /* [in] */ IStream *pStream, - /* [in] */ BSTR bstrLic) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateControlLicEx( - /* [in] */ LPCOLESTR lpTricsData, - /* [in] */ HWND hWnd, - /* [in] */ IStream *pStream, - /* [out] */ IUnknown **ppUnk, - /* [in] */ REFIID riidAdvise, - /* [in] */ IUnknown *punkAdvise, - /* [in] */ BSTR bstrLic) = 0; - - }; - -#else /* C style interface */ - - typedef struct IAxWinHostWindowLicVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IAxWinHostWindowLic * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IAxWinHostWindowLic * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IAxWinHostWindowLic * This); - - HRESULT ( STDMETHODCALLTYPE *CreateControl )( - IAxWinHostWindowLic * This, - /* [in] */ LPCOLESTR lpTricsData, - /* [in] */ HWND hWnd, - /* [in] */ IStream *pStream); - - HRESULT ( STDMETHODCALLTYPE *CreateControlEx )( - IAxWinHostWindowLic * This, - /* [in] */ LPCOLESTR lpTricsData, - /* [in] */ HWND hWnd, - /* [in] */ IStream *pStream, - /* [out] */ IUnknown **ppUnk, - /* [in] */ REFIID riidAdvise, - /* [in] */ IUnknown *punkAdvise); - - HRESULT ( STDMETHODCALLTYPE *AttachControl )( - IAxWinHostWindowLic * This, - /* [in] */ IUnknown *pUnkControl, - /* [in] */ HWND hWnd); - - HRESULT ( STDMETHODCALLTYPE *QueryControl )( - IAxWinHostWindowLic * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - HRESULT ( STDMETHODCALLTYPE *SetExternalDispatch )( - IAxWinHostWindowLic * This, - /* [in] */ IDispatch *pDisp); - - HRESULT ( STDMETHODCALLTYPE *SetExternalUIHandler )( - IAxWinHostWindowLic * This, - /* [in] */ IDocHostUIHandlerDispatch *pDisp); - - HRESULT ( STDMETHODCALLTYPE *CreateControlLic )( - IAxWinHostWindowLic * This, - /* [in] */ LPCOLESTR lpTricsData, - /* [in] */ HWND hWnd, - /* [in] */ IStream *pStream, - /* [in] */ BSTR bstrLic); - - HRESULT ( STDMETHODCALLTYPE *CreateControlLicEx )( - IAxWinHostWindowLic * This, - /* [in] */ LPCOLESTR lpTricsData, - /* [in] */ HWND hWnd, - /* [in] */ IStream *pStream, - /* [out] */ IUnknown **ppUnk, - /* [in] */ REFIID riidAdvise, - /* [in] */ IUnknown *punkAdvise, - /* [in] */ BSTR bstrLic); - - END_INTERFACE - } IAxWinHostWindowLicVtbl; - - interface IAxWinHostWindowLic - { - CONST_VTBL struct IAxWinHostWindowLicVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IAxWinHostWindowLic_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IAxWinHostWindowLic_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IAxWinHostWindowLic_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IAxWinHostWindowLic_CreateControl(This,lpTricsData,hWnd,pStream) \ - (This)->lpVtbl -> CreateControl(This,lpTricsData,hWnd,pStream) - -#define IAxWinHostWindowLic_CreateControlEx(This,lpTricsData,hWnd,pStream,ppUnk,riidAdvise,punkAdvise) \ - (This)->lpVtbl -> CreateControlEx(This,lpTricsData,hWnd,pStream,ppUnk,riidAdvise,punkAdvise) - -#define IAxWinHostWindowLic_AttachControl(This,pUnkControl,hWnd) \ - (This)->lpVtbl -> AttachControl(This,pUnkControl,hWnd) - -#define IAxWinHostWindowLic_QueryControl(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryControl(This,riid,ppvObject) - -#define IAxWinHostWindowLic_SetExternalDispatch(This,pDisp) \ - (This)->lpVtbl -> SetExternalDispatch(This,pDisp) - -#define IAxWinHostWindowLic_SetExternalUIHandler(This,pDisp) \ - (This)->lpVtbl -> SetExternalUIHandler(This,pDisp) - - -#define IAxWinHostWindowLic_CreateControlLic(This,lpTricsData,hWnd,pStream,bstrLic) \ - (This)->lpVtbl -> CreateControlLic(This,lpTricsData,hWnd,pStream,bstrLic) - -#define IAxWinHostWindowLic_CreateControlLicEx(This,lpTricsData,hWnd,pStream,ppUnk,riidAdvise,punkAdvise,bstrLic) \ - (This)->lpVtbl -> CreateControlLicEx(This,lpTricsData,hWnd,pStream,ppUnk,riidAdvise,punkAdvise,bstrLic) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -HRESULT STDMETHODCALLTYPE IAxWinHostWindowLic_CreateControlLic_Proxy( - IAxWinHostWindowLic * This, - /* [in] */ LPCOLESTR lpTricsData, - /* [in] */ HWND hWnd, - /* [in] */ IStream *pStream, - /* [in] */ BSTR bstrLic); - - -void __RPC_STUB IAxWinHostWindowLic_CreateControlLic_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IAxWinHostWindowLic_CreateControlLicEx_Proxy( - IAxWinHostWindowLic * This, - /* [in] */ LPCOLESTR lpTricsData, - /* [in] */ HWND hWnd, - /* [in] */ IStream *pStream, - /* [out] */ IUnknown **ppUnk, - /* [in] */ REFIID riidAdvise, - /* [in] */ IUnknown *punkAdvise, - /* [in] */ BSTR bstrLic); - - -void __RPC_STUB IAxWinHostWindowLic_CreateControlLicEx_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IAxWinHostWindowLic_INTERFACE_DEFINED__ */ - - -#ifndef __IAxWinAmbientDispatch_INTERFACE_DEFINED__ -#define __IAxWinAmbientDispatch_INTERFACE_DEFINED__ - -/* interface IAxWinAmbientDispatch */ -/* [unique][helpstring][uuid][dual][object] */ - - -EXTERN_C const IID IID_IAxWinAmbientDispatch; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("B6EA2051-048A-11d1-82B9-00C04FB9942E") - IAxWinAmbientDispatch : public IDispatch - { - public: - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AllowWindowlessActivation( - /* [in] */ VARIANT_BOOL bCanWindowlessActivate) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AllowWindowlessActivation( - /* [retval][out] */ VARIANT_BOOL *pbCanWindowlessActivate) = 0; - - virtual /* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_BackColor( - /* [in] */ OLE_COLOR clrBackground) = 0; - - virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_BackColor( - /* [retval][out] */ OLE_COLOR *pclrBackground) = 0; - - virtual /* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_ForeColor( - /* [in] */ OLE_COLOR clrForeground) = 0; - - virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ForeColor( - /* [retval][out] */ OLE_COLOR *pclrForeground) = 0; - - virtual /* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_LocaleID( - /* [in] */ LCID lcidLocaleID) = 0; - - virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LocaleID( - /* [retval][out] */ LCID *plcidLocaleID) = 0; - - virtual /* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_UserMode( - /* [in] */ VARIANT_BOOL bUserMode) = 0; - - virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_UserMode( - /* [retval][out] */ VARIANT_BOOL *pbUserMode) = 0; - - virtual /* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_DisplayAsDefault( - /* [in] */ VARIANT_BOOL bDisplayAsDefault) = 0; - - virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DisplayAsDefault( - /* [retval][out] */ VARIANT_BOOL *pbDisplayAsDefault) = 0; - - virtual /* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Font( - /* [in] */ IFontDisp *pFont) = 0; - - virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Font( - /* [retval][out] */ IFontDisp **pFont) = 0; - - virtual /* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_MessageReflect( - /* [in] */ VARIANT_BOOL bMsgReflect) = 0; - - virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_MessageReflect( - /* [retval][out] */ VARIANT_BOOL *pbMsgReflect) = 0; - - virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ShowGrabHandles( - /* [retval][out] */ VARIANT_BOOL *pbShowGrabHandles) = 0; - - virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ShowHatching( - /* [retval][out] */ VARIANT_BOOL *pbShowHatching) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_DocHostFlags( - /* [in] */ DWORD dwDocHostFlags) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DocHostFlags( - /* [retval][out] */ DWORD *pdwDocHostFlags) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_DocHostDoubleClickFlags( - /* [in] */ DWORD dwDocHostDoubleClickFlags) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DocHostDoubleClickFlags( - /* [retval][out] */ DWORD *pdwDocHostDoubleClickFlags) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AllowContextMenu( - /* [in] */ VARIANT_BOOL bAllowContextMenu) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AllowContextMenu( - /* [retval][out] */ VARIANT_BOOL *pbAllowContextMenu) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AllowShowUI( - /* [in] */ VARIANT_BOOL bAllowShowUI) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AllowShowUI( - /* [retval][out] */ VARIANT_BOOL *pbAllowShowUI) = 0; - - virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_OptionKeyPath( - /* [in] */ BSTR bstrOptionKeyPath) = 0; - - virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_OptionKeyPath( - /* [retval][out] */ BSTR *pbstrOptionKeyPath) = 0; - - }; - -#else /* C style interface */ - - typedef struct IAxWinAmbientDispatchVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IAxWinAmbientDispatch * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IAxWinAmbientDispatch * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IAxWinAmbientDispatch * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IAxWinAmbientDispatch * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IAxWinAmbientDispatch * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IAxWinAmbientDispatch * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IAxWinAmbientDispatch * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AllowWindowlessActivation )( - IAxWinAmbientDispatch * This, - /* [in] */ VARIANT_BOOL bCanWindowlessActivate); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AllowWindowlessActivation )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbCanWindowlessActivate); - - /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_BackColor )( - IAxWinAmbientDispatch * This, - /* [in] */ OLE_COLOR clrBackground); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BackColor )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ OLE_COLOR *pclrBackground); - - /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_ForeColor )( - IAxWinAmbientDispatch * This, - /* [in] */ OLE_COLOR clrForeground); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ForeColor )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ OLE_COLOR *pclrForeground); - - /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_LocaleID )( - IAxWinAmbientDispatch * This, - /* [in] */ LCID lcidLocaleID); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LocaleID )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ LCID *plcidLocaleID); - - /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_UserMode )( - IAxWinAmbientDispatch * This, - /* [in] */ VARIANT_BOOL bUserMode); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_UserMode )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbUserMode); - - /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DisplayAsDefault )( - IAxWinAmbientDispatch * This, - /* [in] */ VARIANT_BOOL bDisplayAsDefault); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DisplayAsDefault )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbDisplayAsDefault); - - /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Font )( - IAxWinAmbientDispatch * This, - /* [in] */ IFontDisp *pFont); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Font )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ IFontDisp **pFont); - - /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_MessageReflect )( - IAxWinAmbientDispatch * This, - /* [in] */ VARIANT_BOOL bMsgReflect); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_MessageReflect )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbMsgReflect); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ShowGrabHandles )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbShowGrabHandles); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ShowHatching )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbShowHatching); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DocHostFlags )( - IAxWinAmbientDispatch * This, - /* [in] */ DWORD dwDocHostFlags); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DocHostFlags )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ DWORD *pdwDocHostFlags); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DocHostDoubleClickFlags )( - IAxWinAmbientDispatch * This, - /* [in] */ DWORD dwDocHostDoubleClickFlags); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DocHostDoubleClickFlags )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ DWORD *pdwDocHostDoubleClickFlags); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AllowContextMenu )( - IAxWinAmbientDispatch * This, - /* [in] */ VARIANT_BOOL bAllowContextMenu); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AllowContextMenu )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbAllowContextMenu); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AllowShowUI )( - IAxWinAmbientDispatch * This, - /* [in] */ VARIANT_BOOL bAllowShowUI); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AllowShowUI )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbAllowShowUI); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_OptionKeyPath )( - IAxWinAmbientDispatch * This, - /* [in] */ BSTR bstrOptionKeyPath); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_OptionKeyPath )( - IAxWinAmbientDispatch * This, - /* [retval][out] */ BSTR *pbstrOptionKeyPath); - - END_INTERFACE - } IAxWinAmbientDispatchVtbl; - - interface IAxWinAmbientDispatch - { - CONST_VTBL struct IAxWinAmbientDispatchVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IAxWinAmbientDispatch_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IAxWinAmbientDispatch_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IAxWinAmbientDispatch_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IAxWinAmbientDispatch_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IAxWinAmbientDispatch_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IAxWinAmbientDispatch_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IAxWinAmbientDispatch_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IAxWinAmbientDispatch_put_AllowWindowlessActivation(This,bCanWindowlessActivate) \ - (This)->lpVtbl -> put_AllowWindowlessActivation(This,bCanWindowlessActivate) - -#define IAxWinAmbientDispatch_get_AllowWindowlessActivation(This,pbCanWindowlessActivate) \ - (This)->lpVtbl -> get_AllowWindowlessActivation(This,pbCanWindowlessActivate) - -#define IAxWinAmbientDispatch_put_BackColor(This,clrBackground) \ - (This)->lpVtbl -> put_BackColor(This,clrBackground) - -#define IAxWinAmbientDispatch_get_BackColor(This,pclrBackground) \ - (This)->lpVtbl -> get_BackColor(This,pclrBackground) - -#define IAxWinAmbientDispatch_put_ForeColor(This,clrForeground) \ - (This)->lpVtbl -> put_ForeColor(This,clrForeground) - -#define IAxWinAmbientDispatch_get_ForeColor(This,pclrForeground) \ - (This)->lpVtbl -> get_ForeColor(This,pclrForeground) - -#define IAxWinAmbientDispatch_put_LocaleID(This,lcidLocaleID) \ - (This)->lpVtbl -> put_LocaleID(This,lcidLocaleID) - -#define IAxWinAmbientDispatch_get_LocaleID(This,plcidLocaleID) \ - (This)->lpVtbl -> get_LocaleID(This,plcidLocaleID) - -#define IAxWinAmbientDispatch_put_UserMode(This,bUserMode) \ - (This)->lpVtbl -> put_UserMode(This,bUserMode) - -#define IAxWinAmbientDispatch_get_UserMode(This,pbUserMode) \ - (This)->lpVtbl -> get_UserMode(This,pbUserMode) - -#define IAxWinAmbientDispatch_put_DisplayAsDefault(This,bDisplayAsDefault) \ - (This)->lpVtbl -> put_DisplayAsDefault(This,bDisplayAsDefault) - -#define IAxWinAmbientDispatch_get_DisplayAsDefault(This,pbDisplayAsDefault) \ - (This)->lpVtbl -> get_DisplayAsDefault(This,pbDisplayAsDefault) - -#define IAxWinAmbientDispatch_put_Font(This,pFont) \ - (This)->lpVtbl -> put_Font(This,pFont) - -#define IAxWinAmbientDispatch_get_Font(This,pFont) \ - (This)->lpVtbl -> get_Font(This,pFont) - -#define IAxWinAmbientDispatch_put_MessageReflect(This,bMsgReflect) \ - (This)->lpVtbl -> put_MessageReflect(This,bMsgReflect) - -#define IAxWinAmbientDispatch_get_MessageReflect(This,pbMsgReflect) \ - (This)->lpVtbl -> get_MessageReflect(This,pbMsgReflect) - -#define IAxWinAmbientDispatch_get_ShowGrabHandles(This,pbShowGrabHandles) \ - (This)->lpVtbl -> get_ShowGrabHandles(This,pbShowGrabHandles) - -#define IAxWinAmbientDispatch_get_ShowHatching(This,pbShowHatching) \ - (This)->lpVtbl -> get_ShowHatching(This,pbShowHatching) - -#define IAxWinAmbientDispatch_put_DocHostFlags(This,dwDocHostFlags) \ - (This)->lpVtbl -> put_DocHostFlags(This,dwDocHostFlags) - -#define IAxWinAmbientDispatch_get_DocHostFlags(This,pdwDocHostFlags) \ - (This)->lpVtbl -> get_DocHostFlags(This,pdwDocHostFlags) - -#define IAxWinAmbientDispatch_put_DocHostDoubleClickFlags(This,dwDocHostDoubleClickFlags) \ - (This)->lpVtbl -> put_DocHostDoubleClickFlags(This,dwDocHostDoubleClickFlags) - -#define IAxWinAmbientDispatch_get_DocHostDoubleClickFlags(This,pdwDocHostDoubleClickFlags) \ - (This)->lpVtbl -> get_DocHostDoubleClickFlags(This,pdwDocHostDoubleClickFlags) - -#define IAxWinAmbientDispatch_put_AllowContextMenu(This,bAllowContextMenu) \ - (This)->lpVtbl -> put_AllowContextMenu(This,bAllowContextMenu) - -#define IAxWinAmbientDispatch_get_AllowContextMenu(This,pbAllowContextMenu) \ - (This)->lpVtbl -> get_AllowContextMenu(This,pbAllowContextMenu) - -#define IAxWinAmbientDispatch_put_AllowShowUI(This,bAllowShowUI) \ - (This)->lpVtbl -> put_AllowShowUI(This,bAllowShowUI) - -#define IAxWinAmbientDispatch_get_AllowShowUI(This,pbAllowShowUI) \ - (This)->lpVtbl -> get_AllowShowUI(This,pbAllowShowUI) - -#define IAxWinAmbientDispatch_put_OptionKeyPath(This,bstrOptionKeyPath) \ - (This)->lpVtbl -> put_OptionKeyPath(This,bstrOptionKeyPath) - -#define IAxWinAmbientDispatch_get_OptionKeyPath(This,pbstrOptionKeyPath) \ - (This)->lpVtbl -> get_OptionKeyPath(This,pbstrOptionKeyPath) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_AllowWindowlessActivation_Proxy( - IAxWinAmbientDispatch * This, - /* [in] */ VARIANT_BOOL bCanWindowlessActivate); - - -void __RPC_STUB IAxWinAmbientDispatch_put_AllowWindowlessActivation_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_AllowWindowlessActivation_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbCanWindowlessActivate); - - -void __RPC_STUB IAxWinAmbientDispatch_get_AllowWindowlessActivation_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_BackColor_Proxy( - IAxWinAmbientDispatch * This, - /* [in] */ OLE_COLOR clrBackground); - - -void __RPC_STUB IAxWinAmbientDispatch_put_BackColor_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_BackColor_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ OLE_COLOR *pclrBackground); - - -void __RPC_STUB IAxWinAmbientDispatch_get_BackColor_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_ForeColor_Proxy( - IAxWinAmbientDispatch * This, - /* [in] */ OLE_COLOR clrForeground); - - -void __RPC_STUB IAxWinAmbientDispatch_put_ForeColor_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_ForeColor_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ OLE_COLOR *pclrForeground); - - -void __RPC_STUB IAxWinAmbientDispatch_get_ForeColor_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_LocaleID_Proxy( - IAxWinAmbientDispatch * This, - /* [in] */ LCID lcidLocaleID); - - -void __RPC_STUB IAxWinAmbientDispatch_put_LocaleID_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_LocaleID_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ LCID *plcidLocaleID); - - -void __RPC_STUB IAxWinAmbientDispatch_get_LocaleID_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_UserMode_Proxy( - IAxWinAmbientDispatch * This, - /* [in] */ VARIANT_BOOL bUserMode); - - -void __RPC_STUB IAxWinAmbientDispatch_put_UserMode_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_UserMode_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbUserMode); - - -void __RPC_STUB IAxWinAmbientDispatch_get_UserMode_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_DisplayAsDefault_Proxy( - IAxWinAmbientDispatch * This, - /* [in] */ VARIANT_BOOL bDisplayAsDefault); - - -void __RPC_STUB IAxWinAmbientDispatch_put_DisplayAsDefault_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_DisplayAsDefault_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbDisplayAsDefault); - - -void __RPC_STUB IAxWinAmbientDispatch_get_DisplayAsDefault_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_Font_Proxy( - IAxWinAmbientDispatch * This, - /* [in] */ IFontDisp *pFont); - - -void __RPC_STUB IAxWinAmbientDispatch_put_Font_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_Font_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ IFontDisp **pFont); - - -void __RPC_STUB IAxWinAmbientDispatch_get_Font_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_MessageReflect_Proxy( - IAxWinAmbientDispatch * This, - /* [in] */ VARIANT_BOOL bMsgReflect); - - -void __RPC_STUB IAxWinAmbientDispatch_put_MessageReflect_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_MessageReflect_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbMsgReflect); - - -void __RPC_STUB IAxWinAmbientDispatch_get_MessageReflect_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_ShowGrabHandles_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbShowGrabHandles); - - -void __RPC_STUB IAxWinAmbientDispatch_get_ShowGrabHandles_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_ShowHatching_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbShowHatching); - - -void __RPC_STUB IAxWinAmbientDispatch_get_ShowHatching_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_DocHostFlags_Proxy( - IAxWinAmbientDispatch * This, - /* [in] */ DWORD dwDocHostFlags); - - -void __RPC_STUB IAxWinAmbientDispatch_put_DocHostFlags_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_DocHostFlags_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ DWORD *pdwDocHostFlags); - - -void __RPC_STUB IAxWinAmbientDispatch_get_DocHostFlags_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_DocHostDoubleClickFlags_Proxy( - IAxWinAmbientDispatch * This, - /* [in] */ DWORD dwDocHostDoubleClickFlags); - - -void __RPC_STUB IAxWinAmbientDispatch_put_DocHostDoubleClickFlags_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_DocHostDoubleClickFlags_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ DWORD *pdwDocHostDoubleClickFlags); - - -void __RPC_STUB IAxWinAmbientDispatch_get_DocHostDoubleClickFlags_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_AllowContextMenu_Proxy( - IAxWinAmbientDispatch * This, - /* [in] */ VARIANT_BOOL bAllowContextMenu); - - -void __RPC_STUB IAxWinAmbientDispatch_put_AllowContextMenu_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_AllowContextMenu_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbAllowContextMenu); - - -void __RPC_STUB IAxWinAmbientDispatch_get_AllowContextMenu_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_AllowShowUI_Proxy( - IAxWinAmbientDispatch * This, - /* [in] */ VARIANT_BOOL bAllowShowUI); - - -void __RPC_STUB IAxWinAmbientDispatch_put_AllowShowUI_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_AllowShowUI_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ VARIANT_BOOL *pbAllowShowUI); - - -void __RPC_STUB IAxWinAmbientDispatch_get_AllowShowUI_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_OptionKeyPath_Proxy( - IAxWinAmbientDispatch * This, - /* [in] */ BSTR bstrOptionKeyPath); - - -void __RPC_STUB IAxWinAmbientDispatch_put_OptionKeyPath_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_OptionKeyPath_Proxy( - IAxWinAmbientDispatch * This, - /* [retval][out] */ BSTR *pbstrOptionKeyPath); - - -void __RPC_STUB IAxWinAmbientDispatch_get_OptionKeyPath_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IAxWinAmbientDispatch_INTERFACE_DEFINED__ */ - - -#ifndef __IAxWinAmbientDispatchEx_INTERFACE_DEFINED__ -#define __IAxWinAmbientDispatchEx_INTERFACE_DEFINED__ - -/* interface IAxWinAmbientDispatchEx */ -/* [unique][helpstring][uuid][dual][object] */ - - -EXTERN_C const IID IID_IAxWinAmbientDispatchEx; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("B2D0778B-AC99-4c58-A5C8-E7724E5316B5") - IAxWinAmbientDispatchEx : public IAxWinAmbientDispatch - { - public: - virtual /* [id] */ HRESULT STDMETHODCALLTYPE SetAmbientDispatch( - /* [in] */ IDispatch *pDispatch) = 0; - - }; - -#else /* C style interface */ - - typedef struct IAxWinAmbientDispatchExVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IAxWinAmbientDispatchEx * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IAxWinAmbientDispatchEx * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IAxWinAmbientDispatchEx * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( - IAxWinAmbientDispatchEx * This, - /* [out] */ UINT *pctinfo); - - HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( - IAxWinAmbientDispatchEx * This, - /* [in] */ UINT iTInfo, - /* [in] */ LCID lcid, - /* [out] */ ITypeInfo **ppTInfo); - - HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( - IAxWinAmbientDispatchEx * This, - /* [in] */ REFIID riid, - /* [size_is][in] */ LPOLESTR *rgszNames, - /* [in] */ UINT cNames, - /* [in] */ LCID lcid, - /* [size_is][out] */ DISPID *rgDispId); - - /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( - IAxWinAmbientDispatchEx * This, - /* [in] */ DISPID dispIdMember, - /* [in] */ REFIID riid, - /* [in] */ LCID lcid, - /* [in] */ WORD wFlags, - /* [out][in] */ DISPPARAMS *pDispParams, - /* [out] */ VARIANT *pVarResult, - /* [out] */ EXCEPINFO *pExcepInfo, - /* [out] */ UINT *puArgErr); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AllowWindowlessActivation )( - IAxWinAmbientDispatchEx * This, - /* [in] */ VARIANT_BOOL bCanWindowlessActivate); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AllowWindowlessActivation )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ VARIANT_BOOL *pbCanWindowlessActivate); - - /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_BackColor )( - IAxWinAmbientDispatchEx * This, - /* [in] */ OLE_COLOR clrBackground); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BackColor )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ OLE_COLOR *pclrBackground); - - /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_ForeColor )( - IAxWinAmbientDispatchEx * This, - /* [in] */ OLE_COLOR clrForeground); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ForeColor )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ OLE_COLOR *pclrForeground); - - /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_LocaleID )( - IAxWinAmbientDispatchEx * This, - /* [in] */ LCID lcidLocaleID); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LocaleID )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ LCID *plcidLocaleID); - - /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_UserMode )( - IAxWinAmbientDispatchEx * This, - /* [in] */ VARIANT_BOOL bUserMode); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_UserMode )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ VARIANT_BOOL *pbUserMode); - - /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DisplayAsDefault )( - IAxWinAmbientDispatchEx * This, - /* [in] */ VARIANT_BOOL bDisplayAsDefault); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DisplayAsDefault )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ VARIANT_BOOL *pbDisplayAsDefault); - - /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Font )( - IAxWinAmbientDispatchEx * This, - /* [in] */ IFontDisp *pFont); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Font )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ IFontDisp **pFont); - - /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_MessageReflect )( - IAxWinAmbientDispatchEx * This, - /* [in] */ VARIANT_BOOL bMsgReflect); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_MessageReflect )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ VARIANT_BOOL *pbMsgReflect); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ShowGrabHandles )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ VARIANT_BOOL *pbShowGrabHandles); - - /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ShowHatching )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ VARIANT_BOOL *pbShowHatching); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DocHostFlags )( - IAxWinAmbientDispatchEx * This, - /* [in] */ DWORD dwDocHostFlags); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DocHostFlags )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ DWORD *pdwDocHostFlags); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DocHostDoubleClickFlags )( - IAxWinAmbientDispatchEx * This, - /* [in] */ DWORD dwDocHostDoubleClickFlags); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DocHostDoubleClickFlags )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ DWORD *pdwDocHostDoubleClickFlags); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AllowContextMenu )( - IAxWinAmbientDispatchEx * This, - /* [in] */ VARIANT_BOOL bAllowContextMenu); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AllowContextMenu )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ VARIANT_BOOL *pbAllowContextMenu); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AllowShowUI )( - IAxWinAmbientDispatchEx * This, - /* [in] */ VARIANT_BOOL bAllowShowUI); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AllowShowUI )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ VARIANT_BOOL *pbAllowShowUI); - - /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_OptionKeyPath )( - IAxWinAmbientDispatchEx * This, - /* [in] */ BSTR bstrOptionKeyPath); - - /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_OptionKeyPath )( - IAxWinAmbientDispatchEx * This, - /* [retval][out] */ BSTR *pbstrOptionKeyPath); - - /* [id] */ HRESULT ( STDMETHODCALLTYPE *SetAmbientDispatch )( - IAxWinAmbientDispatchEx * This, - /* [in] */ IDispatch *pDispatch); - - END_INTERFACE - } IAxWinAmbientDispatchExVtbl; - - interface IAxWinAmbientDispatchEx - { - CONST_VTBL struct IAxWinAmbientDispatchExVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IAxWinAmbientDispatchEx_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IAxWinAmbientDispatchEx_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IAxWinAmbientDispatchEx_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IAxWinAmbientDispatchEx_GetTypeInfoCount(This,pctinfo) \ - (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) - -#define IAxWinAmbientDispatchEx_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) - -#define IAxWinAmbientDispatchEx_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) - -#define IAxWinAmbientDispatchEx_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) - - -#define IAxWinAmbientDispatchEx_put_AllowWindowlessActivation(This,bCanWindowlessActivate) \ - (This)->lpVtbl -> put_AllowWindowlessActivation(This,bCanWindowlessActivate) - -#define IAxWinAmbientDispatchEx_get_AllowWindowlessActivation(This,pbCanWindowlessActivate) \ - (This)->lpVtbl -> get_AllowWindowlessActivation(This,pbCanWindowlessActivate) - -#define IAxWinAmbientDispatchEx_put_BackColor(This,clrBackground) \ - (This)->lpVtbl -> put_BackColor(This,clrBackground) - -#define IAxWinAmbientDispatchEx_get_BackColor(This,pclrBackground) \ - (This)->lpVtbl -> get_BackColor(This,pclrBackground) - -#define IAxWinAmbientDispatchEx_put_ForeColor(This,clrForeground) \ - (This)->lpVtbl -> put_ForeColor(This,clrForeground) - -#define IAxWinAmbientDispatchEx_get_ForeColor(This,pclrForeground) \ - (This)->lpVtbl -> get_ForeColor(This,pclrForeground) - -#define IAxWinAmbientDispatchEx_put_LocaleID(This,lcidLocaleID) \ - (This)->lpVtbl -> put_LocaleID(This,lcidLocaleID) - -#define IAxWinAmbientDispatchEx_get_LocaleID(This,plcidLocaleID) \ - (This)->lpVtbl -> get_LocaleID(This,plcidLocaleID) - -#define IAxWinAmbientDispatchEx_put_UserMode(This,bUserMode) \ - (This)->lpVtbl -> put_UserMode(This,bUserMode) - -#define IAxWinAmbientDispatchEx_get_UserMode(This,pbUserMode) \ - (This)->lpVtbl -> get_UserMode(This,pbUserMode) - -#define IAxWinAmbientDispatchEx_put_DisplayAsDefault(This,bDisplayAsDefault) \ - (This)->lpVtbl -> put_DisplayAsDefault(This,bDisplayAsDefault) - -#define IAxWinAmbientDispatchEx_get_DisplayAsDefault(This,pbDisplayAsDefault) \ - (This)->lpVtbl -> get_DisplayAsDefault(This,pbDisplayAsDefault) - -#define IAxWinAmbientDispatchEx_put_Font(This,pFont) \ - (This)->lpVtbl -> put_Font(This,pFont) - -#define IAxWinAmbientDispatchEx_get_Font(This,pFont) \ - (This)->lpVtbl -> get_Font(This,pFont) - -#define IAxWinAmbientDispatchEx_put_MessageReflect(This,bMsgReflect) \ - (This)->lpVtbl -> put_MessageReflect(This,bMsgReflect) - -#define IAxWinAmbientDispatchEx_get_MessageReflect(This,pbMsgReflect) \ - (This)->lpVtbl -> get_MessageReflect(This,pbMsgReflect) - -#define IAxWinAmbientDispatchEx_get_ShowGrabHandles(This,pbShowGrabHandles) \ - (This)->lpVtbl -> get_ShowGrabHandles(This,pbShowGrabHandles) - -#define IAxWinAmbientDispatchEx_get_ShowHatching(This,pbShowHatching) \ - (This)->lpVtbl -> get_ShowHatching(This,pbShowHatching) - -#define IAxWinAmbientDispatchEx_put_DocHostFlags(This,dwDocHostFlags) \ - (This)->lpVtbl -> put_DocHostFlags(This,dwDocHostFlags) - -#define IAxWinAmbientDispatchEx_get_DocHostFlags(This,pdwDocHostFlags) \ - (This)->lpVtbl -> get_DocHostFlags(This,pdwDocHostFlags) - -#define IAxWinAmbientDispatchEx_put_DocHostDoubleClickFlags(This,dwDocHostDoubleClickFlags) \ - (This)->lpVtbl -> put_DocHostDoubleClickFlags(This,dwDocHostDoubleClickFlags) - -#define IAxWinAmbientDispatchEx_get_DocHostDoubleClickFlags(This,pdwDocHostDoubleClickFlags) \ - (This)->lpVtbl -> get_DocHostDoubleClickFlags(This,pdwDocHostDoubleClickFlags) - -#define IAxWinAmbientDispatchEx_put_AllowContextMenu(This,bAllowContextMenu) \ - (This)->lpVtbl -> put_AllowContextMenu(This,bAllowContextMenu) - -#define IAxWinAmbientDispatchEx_get_AllowContextMenu(This,pbAllowContextMenu) \ - (This)->lpVtbl -> get_AllowContextMenu(This,pbAllowContextMenu) - -#define IAxWinAmbientDispatchEx_put_AllowShowUI(This,bAllowShowUI) \ - (This)->lpVtbl -> put_AllowShowUI(This,bAllowShowUI) - -#define IAxWinAmbientDispatchEx_get_AllowShowUI(This,pbAllowShowUI) \ - (This)->lpVtbl -> get_AllowShowUI(This,pbAllowShowUI) - -#define IAxWinAmbientDispatchEx_put_OptionKeyPath(This,bstrOptionKeyPath) \ - (This)->lpVtbl -> put_OptionKeyPath(This,bstrOptionKeyPath) - -#define IAxWinAmbientDispatchEx_get_OptionKeyPath(This,pbstrOptionKeyPath) \ - (This)->lpVtbl -> get_OptionKeyPath(This,pbstrOptionKeyPath) - - -#define IAxWinAmbientDispatchEx_SetAmbientDispatch(This,pDispatch) \ - (This)->lpVtbl -> SetAmbientDispatch(This,pDispatch) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -/* [id] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatchEx_SetAmbientDispatch_Proxy( - IAxWinAmbientDispatchEx * This, - /* [in] */ IDispatch *pDispatch); - - -void __RPC_STUB IAxWinAmbientDispatchEx_SetAmbientDispatch_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IAxWinAmbientDispatchEx_INTERFACE_DEFINED__ */ - - -#ifndef __IInternalConnection_INTERFACE_DEFINED__ -#define __IInternalConnection_INTERFACE_DEFINED__ - -/* interface IInternalConnection */ -/* [object][unique][helpstring][uuid] */ - - -EXTERN_C const IID IID_IInternalConnection; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("72AD0770-6A9F-11d1-BCEC-0060088F444E") - IInternalConnection : public IUnknown - { - public: - virtual HRESULT STDMETHODCALLTYPE AddConnection( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE ReleaseConnection( void) = 0; - - }; - -#else /* C style interface */ - - typedef struct IInternalConnectionVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IInternalConnection * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IInternalConnection * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IInternalConnection * This); - - HRESULT ( STDMETHODCALLTYPE *AddConnection )( - IInternalConnection * This); - - HRESULT ( STDMETHODCALLTYPE *ReleaseConnection )( - IInternalConnection * This); - - END_INTERFACE - } IInternalConnectionVtbl; - - interface IInternalConnection - { - CONST_VTBL struct IInternalConnectionVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IInternalConnection_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IInternalConnection_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IInternalConnection_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IInternalConnection_AddConnection(This) \ - (This)->lpVtbl -> AddConnection(This) - -#define IInternalConnection_ReleaseConnection(This) \ - (This)->lpVtbl -> ReleaseConnection(This) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -HRESULT STDMETHODCALLTYPE IInternalConnection_AddConnection_Proxy( - IInternalConnection * This); - - -void __RPC_STUB IInternalConnection_AddConnection_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IInternalConnection_ReleaseConnection_Proxy( - IInternalConnection * This); - - -void __RPC_STUB IInternalConnection_ReleaseConnection_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IInternalConnection_INTERFACE_DEFINED__ */ - - -/* interface __MIDL_itf_atliface_0257 */ -/* [local] */ - - -#pragma pack(push,_ATL_PACKING) -namespace ATL -{ -#ifdef __cplusplus -#include -#else -#define ATLAPI EXTERN_C HRESULT __declspec(dllimport) __stdcall -#define ATLAPI_(x) EXTERN_C __declspec(dllimport) x __stdcall -#define ATLINLINE -#endif // __cplusplus - -ATLAPI_(INT_PTR) AtlAxDialogBoxW(HINSTANCE hInstance, LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam); -ATLAPI_(INT_PTR) AtlAxDialogBoxA(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam); -#ifdef UNICODE -#define AtlAxDialogBox AtlAxDialogBoxW -#else -#define AtlAxDialogBox AtlAxDialogBoxA -#endif - -ATLAPI_(HWND) AtlAxCreateDialogW(HINSTANCE hInstance, LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam); -ATLAPI_(HWND) AtlAxCreateDialogA(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam); -#ifdef UNICODE -#define AtlAxCreateDialog AtlAxCreateDialogW -#else -#define AtlAxCreateDialog AtlAxCreateDialogA -#endif - -ATLAPI AtlAxCreateControl(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, IUnknown** ppUnkContainer); -#ifdef __cplusplus -ATLAPI AtlAxCreateControlEx(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, - IUnknown** ppUnkContainer, IUnknown** ppUnkControl, - REFIID iidSink=IID_NULL, IUnknown* punkSink=NULL); -ATLAPI AtlAxCreateControlLic(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, IUnknown** ppUnkContainer, BSTR bstrLic = NULL); -ATLAPI AtlAxCreateControlLicEx(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, - IUnknown** ppUnkContainer, IUnknown** ppUnkControl, - REFIID iidSink=IID_NULL, IUnknown* punkSink=NULL, BSTR bstrLic = NULL); -#else -ATLAPI AtlAxCreateControlEx(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, - IUnknown** ppUnkContainer, IUnknown** ppUnkControl, - REFIID iidSink, IUnknown* punkSink); -ATLAPI AtlAxCreateControlLic(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, IUnknown** ppUnkContainer, BSTR bstrLic); -ATLAPI AtlAxCreateControlLicEx(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, - IUnknown** ppUnkContainer, IUnknown** ppUnkControl, - REFIID iidSink, IUnknown* punkSink, BSTR bstrLic); -#endif // __cplusplus -ATLAPI AtlAxAttachControl(IUnknown* pControl, HWND hWnd, IUnknown** ppUnkContainer); -ATLAPI_(BOOL) AtlAxWinInit(); - -ATLAPI AtlAxGetHost(HWND h, IUnknown** pp); -ATLAPI AtlAxGetControl(HWND h, IUnknown** pp); - -}; //namespace ATL -#pragma pack(pop) - -extern RPC_IF_HANDLE __MIDL_itf_atliface_0257_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_atliface_0257_v0_0_s_ifspec; - -#ifndef __IAccessibleProxy_INTERFACE_DEFINED__ -#define __IAccessibleProxy_INTERFACE_DEFINED__ - -/* interface IAccessibleProxy */ -/* [unique][helpstring][dual][uuid][object] */ - - -EXTERN_C const IID IID_IAccessibleProxy; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("7A7D9DCF-B7A1-4019-9031-258268846980") - IAccessibleProxy : public IUnknown - { - public: - virtual HRESULT STDMETHODCALLTYPE SetServer( - /* [in] */ IAccessible *pAccessible, - /* [in] */ IAccessibleServer *pServer) = 0; - - }; - -#else /* C style interface */ - - typedef struct IAccessibleProxyVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IAccessibleProxy * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IAccessibleProxy * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IAccessibleProxy * This); - - HRESULT ( STDMETHODCALLTYPE *SetServer )( - IAccessibleProxy * This, - /* [in] */ IAccessible *pAccessible, - /* [in] */ IAccessibleServer *pServer); - - END_INTERFACE - } IAccessibleProxyVtbl; - - interface IAccessibleProxy - { - CONST_VTBL struct IAccessibleProxyVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IAccessibleProxy_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IAccessibleProxy_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IAccessibleProxy_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IAccessibleProxy_SetServer(This,pAccessible,pServer) \ - (This)->lpVtbl -> SetServer(This,pAccessible,pServer) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -HRESULT STDMETHODCALLTYPE IAccessibleProxy_SetServer_Proxy( - IAccessibleProxy * This, - /* [in] */ IAccessible *pAccessible, - /* [in] */ IAccessibleServer *pServer); - - -void __RPC_STUB IAccessibleProxy_SetServer_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IAccessibleProxy_INTERFACE_DEFINED__ */ - - -#ifndef __IAccessibleServer_INTERFACE_DEFINED__ -#define __IAccessibleServer_INTERFACE_DEFINED__ - -/* interface IAccessibleServer */ -/* [unique][helpstring][uuid][object] */ - - -EXTERN_C const IID IID_IAccessibleServer; - -#if defined(__cplusplus) && !defined(CINTERFACE) - - MIDL_INTERFACE("52C8FB5E-D779-4e77-AE9F-F611FA7E9D7A") - IAccessibleServer : public IUnknown - { - public: - virtual HRESULT STDMETHODCALLTYPE SetProxy( - /* [in] */ IAccessibleProxy *pUnknown) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetHWND( - /* [out] */ HWND *phWnd) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetEnumVariant( - /* [out] */ IEnumVARIANT **ppEnumVariant) = 0; - - }; - -#else /* C style interface */ - - typedef struct IAccessibleServerVtbl - { - BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - IAccessibleServer * This, - /* [in] */ REFIID riid, - /* [iid_is][out] */ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( - IAccessibleServer * This); - - ULONG ( STDMETHODCALLTYPE *Release )( - IAccessibleServer * This); - - HRESULT ( STDMETHODCALLTYPE *SetProxy )( - IAccessibleServer * This, - /* [in] */ IAccessibleProxy *pUnknown); - - HRESULT ( STDMETHODCALLTYPE *GetHWND )( - IAccessibleServer * This, - /* [out] */ HWND *phWnd); - - HRESULT ( STDMETHODCALLTYPE *GetEnumVariant )( - IAccessibleServer * This, - /* [out] */ IEnumVARIANT **ppEnumVariant); - - END_INTERFACE - } IAccessibleServerVtbl; - - interface IAccessibleServer - { - CONST_VTBL struct IAccessibleServerVtbl *lpVtbl; - }; - - - -#ifdef COBJMACROS - - -#define IAccessibleServer_QueryInterface(This,riid,ppvObject) \ - (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) - -#define IAccessibleServer_AddRef(This) \ - (This)->lpVtbl -> AddRef(This) - -#define IAccessibleServer_Release(This) \ - (This)->lpVtbl -> Release(This) - - -#define IAccessibleServer_SetProxy(This,pUnknown) \ - (This)->lpVtbl -> SetProxy(This,pUnknown) - -#define IAccessibleServer_GetHWND(This,phWnd) \ - (This)->lpVtbl -> GetHWND(This,phWnd) - -#define IAccessibleServer_GetEnumVariant(This,ppEnumVariant) \ - (This)->lpVtbl -> GetEnumVariant(This,ppEnumVariant) - -#endif /* COBJMACROS */ - - -#endif /* C style interface */ - - - -HRESULT STDMETHODCALLTYPE IAccessibleServer_SetProxy_Proxy( - IAccessibleServer * This, - /* [in] */ IAccessibleProxy *pUnknown); - - -void __RPC_STUB IAccessibleServer_SetProxy_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IAccessibleServer_GetHWND_Proxy( - IAccessibleServer * This, - /* [out] */ HWND *phWnd); - - -void __RPC_STUB IAccessibleServer_GetHWND_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - -HRESULT STDMETHODCALLTYPE IAccessibleServer_GetEnumVariant_Proxy( - IAccessibleServer * This, - /* [out] */ IEnumVARIANT **ppEnumVariant); - - -void __RPC_STUB IAccessibleServer_GetEnumVariant_Stub( - IRpcStubBuffer *This, - IRpcChannelBuffer *_pRpcChannelBuffer, - PRPC_MESSAGE _pRpcMessage, - DWORD *_pdwStubPhase); - - - -#endif /* __IAccessibleServer_INTERFACE_DEFINED__ */ - - -/* Additional Prototypes for ALL interfaces */ - -unsigned long __RPC_USER BSTR_UserSize( unsigned long *, unsigned long , BSTR * ); -unsigned char * __RPC_USER BSTR_UserMarshal( unsigned long *, unsigned char *, BSTR * ); -unsigned char * __RPC_USER BSTR_UserUnmarshal(unsigned long *, unsigned char *, BSTR * ); -void __RPC_USER BSTR_UserFree( unsigned long *, BSTR * ); - -unsigned long __RPC_USER HWND_UserSize( unsigned long *, unsigned long , HWND * ); -unsigned char * __RPC_USER HWND_UserMarshal( unsigned long *, unsigned char *, HWND * ); -unsigned char * __RPC_USER HWND_UserUnmarshal(unsigned long *, unsigned char *, HWND * ); -void __RPC_USER HWND_UserFree( unsigned long *, HWND * ); - -/* end of Additional Prototypes */ - -#ifdef __cplusplus -} -#endif - -#endif - - diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlmem.h b/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlmem.h deleted file mode 100644 index 07bdef274..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlmem.h +++ /dev/null @@ -1,250 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLMEM_H__ -#define __ATLMEM_H__ - -#pragma once - -#include -#include - - -#pragma pack(push,_ATL_PACKING) -namespace ATL -{ - -template< typename N > -inline N WINAPI AtlAlignUp( N n, ULONG nAlign ) throw() -{ - return( N( (n+(nAlign-1))&~(N( nAlign )-1) ) ); -} - -template< typename N > -inline N WINAPI AtlAlignDown( N n, ULONG nAlign ) throw() -{ - return( N( n&~(N( nAlign )-1) ) ); -} - -__interface __declspec(uuid("654F7EF5-CFDF-4df9-A450-6C6A13C622C0")) IAtlMemMgr -{ -public: - void* Allocate( size_t nBytes ) throw(); - void Free( void* p ) throw(); - void* Reallocate( void* p, size_t nBytes ) throw(); - size_t GetSize( void* p ) throw(); -}; - -#ifndef _ATL_MIN_CRT -class CCRTHeap : - public IAtlMemMgr -{ -public: - virtual void* Allocate( size_t nBytes ) throw() - { - return( malloc( nBytes ) ); - } - virtual void Free( void* p ) throw() - { - free( p ); - } - virtual void* Reallocate( void* p, size_t nBytes ) throw() - { - return( realloc( p, nBytes ) ); - } - virtual size_t GetSize( void* p ) throw() - { - return( _msize( p ) ); - } - -public: -}; - -#endif //!_ATL_MIN_CRT - -class CWin32Heap : - public IAtlMemMgr -{ -public: - CWin32Heap() throw() : - m_hHeap( NULL ), - m_bOwnHeap( false ) - { - } - CWin32Heap( HANDLE hHeap ) throw() : - m_hHeap( hHeap ), - m_bOwnHeap( false ) - { - ATLASSERT( hHeap != NULL ); - } - CWin32Heap( DWORD dwFlags, size_t nInitialSize, size_t nMaxSize = 0 ) : - m_hHeap( NULL ), - m_bOwnHeap( true ) - { - ATLASSERT( !(dwFlags&HEAP_GENERATE_EXCEPTIONS) ); - m_hHeap = ::HeapCreate( dwFlags, nInitialSize, nMaxSize ); - if( m_hHeap == NULL ) - { - AtlThrowLastWin32(); - } - } - virtual ~CWin32Heap() throw() - { - if( m_bOwnHeap && (m_hHeap != NULL) ) - { - BOOL bSuccess; - - bSuccess = ::HeapDestroy( m_hHeap ); - ATLASSERT( bSuccess ); - } - } - - void Attach( HANDLE hHeap, bool bTakeOwnership ) throw() - { - ATLASSERT( hHeap != NULL ); - ATLASSUME( m_hHeap == NULL ); - - m_hHeap = hHeap; - m_bOwnHeap = bTakeOwnership; - } - HANDLE Detach() throw() - { - HANDLE hHeap; - - hHeap = m_hHeap; - m_hHeap = NULL; - m_bOwnHeap = false; - - return( hHeap ); - } - -// IAtlMemMgr - virtual void* Allocate( size_t nBytes ) throw() - { - return( ::HeapAlloc( m_hHeap, 0, nBytes ) ); - } - virtual void Free( void* p ) throw() - { - if( p != NULL ) - { - BOOL bSuccess; - - bSuccess = ::HeapFree( m_hHeap, 0, p ); - ATLASSERT( bSuccess ); - } - } - virtual void* Reallocate( void* p, size_t nBytes ) throw() - { - if( p == NULL ) - { - return( Allocate( nBytes ) ); - } - - if (nBytes==0) - { - Free(p); - return NULL; - - - - } - return( ::HeapReAlloc( m_hHeap, 0, p, nBytes ) ); - - - - } - virtual size_t GetSize( void* p ) throw() - { - return( ::HeapSize( m_hHeap, 0, p ) ); - } - -public: - HANDLE m_hHeap; - bool m_bOwnHeap; -}; - -class CLocalHeap : - public IAtlMemMgr -{ -// IAtlMemMgr -public: - virtual void* Allocate( size_t nBytes ) throw() - { - return( ::LocalAlloc( LMEM_FIXED, nBytes ) ); - } - virtual void Free( void* p ) throw() - { - ::LocalFree( p ); - } - virtual void* Reallocate( void* p, size_t nBytes ) throw() - { - - if (p==NULL) - { - return ( Allocate(nBytes) ); - - } - if (nBytes==0) - { - Free(p); - return NULL; - } - - return( ::LocalReAlloc( p, nBytes, 0 ) ); - } - virtual size_t GetSize( void* p ) throw() - { - return( ::LocalSize( p ) ); - } -}; - -class CGlobalHeap : - public IAtlMemMgr -{ -// IAtlMemMgr -public: - virtual void* Allocate( size_t nBytes ) throw() - { - return( ::GlobalAlloc( LMEM_FIXED, nBytes ) ); - } - virtual void Free( void* p ) throw() - { - ::GlobalFree( p ); - } - virtual void* Reallocate( void* p, size_t nBytes ) throw() - { - - if (p==NULL) - { - return ( Allocate(nBytes) ); - - } - if (nBytes==0){ - Free(p); - return NULL; - } - return( ::GlobalReAlloc( p, nBytes, 0 ) ); - } - virtual size_t GetSize( void* p ) throw() - { - return( ::GlobalSize( p ) ); - } -}; - -}; // namespace ATL -#pragma pack(pop) - -#ifdef _OBJBASE_H_ -#include -#endif // _OBJBASE_H_ - -#endif //__ATLMEM_H__ - - diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlrc.h b/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlrc.h deleted file mode 100644 index ab52f9f3b..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlrc.h +++ /dev/null @@ -1,27 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#pragma once - -#ifndef __ATLRC_H__ - -#define ATL_RESID_BASE 0xD800 -#define ATL_STRING_BASE ATL_RESID_BASE - -#define ATL_IDS_DATETIME_INVALID (ATL_STRING_BASE + 0) -#define ATL_IDS_DATETIMESPAN_INVALID (ATL_STRING_BASE + 1) - -#define ATL_SERVICE_MANAGER_OPEN_ERROR (ATL_STRING_BASE + 10) -#define ATL_SERVICE_START_ERROR (ATL_STRING_BASE + 11) -#define ATL_SERVICE_OPEN_ERROR (ATL_STRING_BASE + 12) -#define ATL_SERVICE_DELETE_ERROR (ATL_STRING_BASE + 13) -#define ATL_SERVICE_STOP_ERROR (ATL_STRING_BASE + 14) - -#endif // __ATLRC_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlsimpcoll.h b/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlsimpcoll.h deleted file mode 100644 index 48a30a789..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlsimpcoll.h +++ /dev/null @@ -1,488 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLSIMPCOLL_H__ -#define __ATLSIMPCOLL_H__ - -#pragma once - -#include -#include -#include - -#pragma push_macro("malloc") -#undef malloc -#pragma push_macro("calloc") -#undef calloc -#pragma push_macro("realloc") -#undef realloc -#pragma push_macro("_recalloc") -#undef _recalloc -#pragma push_macro("free") -#undef free - -#pragma warning(push) -#pragma warning(disable: 4800) // forcing 'int' value to bool - - -#pragma pack(push,_ATL_PACKING) -namespace ATL -{ - -#pragma push_macro("new") -#undef new - -///////////////////////////////////////////////////////////////////////////// -// Collection helpers - CSimpleArray & CSimpleMap - -// template class helpers with functions for comparing elements -// override if using complex types without operator== -template -class CSimpleArrayEqualHelper -{ -public: - static bool IsEqual(const T& t1, const T& t2) - { - return (t1 == t2); - } -}; - -template -class CSimpleArrayEqualHelperFalse -{ -public: - static bool IsEqual(const T&, const T&) - { - ATLASSERT(false); - return false; - } -}; - -template -class CSimpleMapEqualHelper -{ -public: - static bool IsEqualKey(const TKey& k1, const TKey& k2) - { - return CSimpleArrayEqualHelper::IsEqual(k1, k2); - } - - static bool IsEqualValue(const TVal& v1, const TVal& v2) - { - return CSimpleArrayEqualHelper::IsEqual(v1, v2); - } -}; - -template -class CSimpleMapEqualHelperFalse -{ -public: - static bool IsEqualKey(const TKey& k1, const TKey& k2) - { - return CSimpleArrayEqualHelper::IsEqual(k1, k2); - } - - static bool IsEqualValue(const TVal&, const TVal&) - { - ATLASSERT(FALSE); - return false; - } -}; - -template > -class CSimpleArray -{ -public: -// Construction/destruction - CSimpleArray() : m_aT(NULL), m_nSize(0), m_nAllocSize(0) - { } - - ~CSimpleArray(); - - CSimpleArray(const CSimpleArray< T, TEqual >& src) : m_aT(NULL), m_nSize(0), m_nAllocSize(0) - { - if (src.GetSize()) - { - m_aT = (T*)calloc(src.GetSize(), sizeof(T)); - if (m_aT != NULL) - { - m_nAllocSize = src.GetSize(); - for (int i=0; i& operator=(const CSimpleArray< T, TEqual >& src) - { - if (GetSize() != src.GetSize()) - { - RemoveAll(); - m_aT = (T*)calloc(src.GetSize(), sizeof(T)); - if (m_aT != NULL) - m_nAllocSize = src.GetSize(); - } - else - { - for (int i = GetSize(); i > 0; i--) - RemoveAt(i - 1); - } - for (int i=0; iINT_MAX/sizeof(T)) - { - - - return FALSE; - - } - - - - aT = (T*)_recalloc(m_aT, nNewAllocSize, sizeof(T)); - if(aT == NULL) - return FALSE; - m_nAllocSize = nNewAllocSize; - m_aT = aT; - - } - InternalSetAtIndex(m_nSize, t); - m_nSize++; - return TRUE; - } - BOOL Remove(const T& t) - { - int nIndex = Find(t); - if(nIndex == -1) - return FALSE; - return RemoveAt(nIndex); - } - BOOL RemoveAt(int nIndex) - { - ATLASSERT(nIndex >= 0 && nIndex < m_nSize); - if (nIndex < 0 || nIndex >= m_nSize) - return FALSE; - m_aT[nIndex].~T(); - if(nIndex != (m_nSize - 1)) - Checked::memmove_s((void*)(m_aT + nIndex), (m_nSize - nIndex) * sizeof(T), (void*)(m_aT + nIndex + 1), (m_nSize - (nIndex + 1)) * sizeof(T)); - m_nSize--; - return TRUE; - } - void RemoveAll() - { - if(m_aT != NULL) - { - for(int i = 0; i < m_nSize; i++) - m_aT[i].~T(); - free(m_aT); - m_aT = NULL; - } - m_nSize = 0; - m_nAllocSize = 0; - } - const T& operator[] (int nIndex) const - { - ATLASSERT(nIndex >= 0 && nIndex < m_nSize); - if(nIndex < 0 || nIndex >= m_nSize) - { - _AtlRaiseException((DWORD)EXCEPTION_ARRAY_BOUNDS_EXCEEDED); - } - return m_aT[nIndex]; - } - T& operator[] (int nIndex) - { - ATLASSERT(nIndex >= 0 && nIndex < m_nSize); - if(nIndex < 0 || nIndex >= m_nSize) - { - _AtlRaiseException((DWORD)EXCEPTION_ARRAY_BOUNDS_EXCEEDED); - } - return m_aT[nIndex]; - } - T* GetData() const - { - return m_aT; - } - - int Find(const T& t) const - { - for(int i = 0; i < m_nSize; i++) - { - if(TEqual::IsEqual(m_aT[i], t)) - return i; - } - return -1; // not found - } - - BOOL SetAtIndex(int nIndex, const T& t) - { - if (nIndex < 0 || nIndex >= m_nSize) - return FALSE; - InternalSetAtIndex(nIndex, t); - return TRUE; - } - -// Implementation - class Wrapper - { - public: - Wrapper(const T& _t) : t(_t) - { - } - template - void * __cdecl operator new(size_t, _Ty* p) - { - return p; - } - template - void __cdecl operator delete(void* /* pv */, _Ty* /* p */) - { - } - T t; - }; - -// Implementation - void InternalSetAtIndex(int nIndex, const T& t) - { - new(m_aT + nIndex) Wrapper(t); - } - - typedef T _ArrayElementType; - T* m_aT; - int m_nSize; - int m_nAllocSize; - -}; - -#define CSimpleValArray CSimpleArray - - template inline CSimpleArray::~CSimpleArray() - { - RemoveAll(); - } - -// intended for small number of simple types or pointers -template > -class CSimpleMap -{ -public: - TKey* m_aKey; - TVal* m_aVal; - int m_nSize; - - typedef TKey _ArrayKeyType; - typedef TVal _ArrayElementType; - -// Construction/destruction - CSimpleMap() : m_aKey(NULL), m_aVal(NULL), m_nSize(0) - { } - - ~CSimpleMap() - { - RemoveAll(); - } - -// Operations - int GetSize() const - { - return m_nSize; - } - BOOL Add(const TKey& key, const TVal& val) - { - TKey* pKey; - pKey = (TKey*)_recalloc(m_aKey, (m_nSize + 1), sizeof(TKey)); - if(pKey == NULL) - return FALSE; - m_aKey = pKey; - TVal* pVal; - pVal = (TVal*)_recalloc(m_aVal, (m_nSize + 1), sizeof(TVal)); - if(pVal == NULL) - return FALSE; - m_aVal = pVal; - InternalSetAtIndex(m_nSize, key, val); - m_nSize++; - return TRUE; - } - BOOL Remove(const TKey& key) - { - int nIndex = FindKey(key); - if(nIndex == -1) - return FALSE; - return RemoveAt(nIndex); - } - BOOL RemoveAt(int nIndex) - { - ATLASSERT(nIndex >= 0 && nIndex < m_nSize); - if (nIndex < 0 || nIndex >= m_nSize) - return FALSE; - m_aKey[nIndex].~TKey(); - m_aVal[nIndex].~TVal(); - if(nIndex != (m_nSize - 1)) - { - Checked::memmove_s((void*)(m_aKey + nIndex), (m_nSize - nIndex) * sizeof(TKey), (void*)(m_aKey + nIndex + 1), (m_nSize - (nIndex + 1)) * sizeof(TKey)); - Checked::memmove_s((void*)(m_aVal + nIndex), (m_nSize - nIndex) * sizeof(TVal), (void*)(m_aVal + nIndex + 1), (m_nSize - (nIndex + 1)) * sizeof(TVal)); - } - TKey* pKey; - pKey = (TKey*)_recalloc(m_aKey, (m_nSize - 1), sizeof(TKey)); - if(pKey != NULL || m_nSize == 1) - m_aKey = pKey; - TVal* pVal; - pVal = (TVal*)_recalloc(m_aVal, (m_nSize - 1), sizeof(TVal)); - if(pVal != NULL || m_nSize == 1) - m_aVal = pVal; - m_nSize--; - return TRUE; - } - void RemoveAll() - { - if(m_aKey != NULL) - { - for(int i = 0; i < m_nSize; i++) - { - m_aKey[i].~TKey(); - m_aVal[i].~TVal(); - } - free(m_aKey); - m_aKey = NULL; - } - if(m_aVal != NULL) - { - free(m_aVal); - m_aVal = NULL; - } - - m_nSize = 0; - } - BOOL SetAt(const TKey& key, const TVal& val) - { - int nIndex = FindKey(key); - if(nIndex == -1) - return FALSE; - ATLASSERT(nIndex >= 0 && nIndex < m_nSize); - m_aKey[nIndex].~TKey(); - m_aVal[nIndex].~TVal(); - InternalSetAtIndex(nIndex, key, val); - return TRUE; - } - TVal Lookup(const TKey& key) const - { - int nIndex = FindKey(key); - if(nIndex == -1) - return NULL; // must be able to convert - return GetValueAt(nIndex); - } - TKey ReverseLookup(const TVal& val) const - { - int nIndex = FindVal(val); - if(nIndex == -1) - return NULL; // must be able to convert - return GetKeyAt(nIndex); - } - TKey& GetKeyAt(int nIndex) const - { - ATLASSERT(nIndex >= 0 && nIndex < m_nSize); - if(nIndex < 0 || nIndex >= m_nSize) - _AtlRaiseException((DWORD)EXCEPTION_ARRAY_BOUNDS_EXCEEDED); - - return m_aKey[nIndex]; - } - TVal& GetValueAt(int nIndex) const - { - ATLASSERT(nIndex >= 0 && nIndex < m_nSize); - if(nIndex < 0 || nIndex >= m_nSize) - _AtlRaiseException((DWORD)EXCEPTION_ARRAY_BOUNDS_EXCEEDED); - - return m_aVal[nIndex]; - } - - int FindKey(const TKey& key) const - { - for(int i = 0; i < m_nSize; i++) - { - if(TEqual::IsEqualKey(m_aKey[i], key)) - return i; - } - return -1; // not found - } - int FindVal(const TVal& val) const - { - for(int i = 0; i < m_nSize; i++) - { - if(TEqual::IsEqualValue(m_aVal[i], val)) - return i; - } - return -1; // not found - } - - BOOL SetAtIndex(int nIndex, const TKey& key, const TVal& val) - { - if (nIndex < 0 || nIndex >= m_nSize) - return FALSE; - InternalSetAtIndex(nIndex, key, val); - return TRUE; - } - - -// Implementation - - template - class Wrapper - { - public: - Wrapper(const T& _t) : t(_t) - { - } - template - void *operator new(size_t, _Ty* p) - { - return p; - } - template - void operator delete(void* /* pv */, _Ty* /* p */) - { - } - T t; - }; - void InternalSetAtIndex(int nIndex, const TKey& key, const TVal& val) - { - new(m_aKey + nIndex) Wrapper(key); - new(m_aVal + nIndex) Wrapper(val); - } -}; - -#pragma pop_macro("new") - -}; // namespace ATL -#pragma pack(pop) - -#pragma warning(pop) - -#pragma pop_macro("free") -#pragma pop_macro("realloc") -#pragma pop_macro("_recalloc") -#pragma pop_macro("malloc") -#pragma pop_macro("calloc") - - -#endif // __ATLSIMPCOLL_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlsimpstr.h b/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlsimpstr.h deleted file mode 100644 index ebf2f4b85..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlsimpstr.h +++ /dev/null @@ -1,1015 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLSIMPSTR_H__ -#define __ATLSIMPSTR_H__ - -#pragma once - -#include -#include -#include -#include - -extern "C" -{ - LONG __cdecl _InterlockedIncrement( LONG volatile * pn ); - LONG __cdecl _InterlockedDecrement( LONG volatile * pn ); -}; - -#pragma intrinsic( _InterlockedIncrement ) -#pragma intrinsic( _InterlockedDecrement ) - -#pragma pack(push,_ATL_PACKING) -namespace ATL -{ - -struct CStringData; - -__interface IAtlStringMgr -{ -public: - // Allocate a new CStringData - CStringData* Allocate( int nAllocLength, int nCharSize ) throw(); - // Free an existing CStringData - void Free( CStringData* pData ) throw(); - // Change the size of an existing CStringData - CStringData* Reallocate( CStringData* pData, int nAllocLength, int nCharSize ) throw(); - // Get the CStringData for a Nil string - CStringData* GetNilString() throw(); - IAtlStringMgr* Clone() throw(); -}; - -#ifdef _M_IX86 -#ifndef _M_CEE -#define _AtlInterlockedIncrement _InterlockedIncrement -#define _AtlInterlockedDecrement _InterlockedDecrement -#else -#define _AtlInterlockedIncrement InterlockedIncrement -#define _AtlInterlockedDecrement InterlockedDecrement -/* managed code must use the non-intrinsics */ -#ifdef InterlockedIncrement -#undef InterlockedIncrement -#endif -#ifdef InterlockedDecrement -#undef InterlockedDecrement -#endif -#endif // !_M_CEE -#else -#define _AtlInterlockedIncrement InterlockedIncrement -#define _AtlInterlockedDecrement InterlockedDecrement -#endif // _M_IX86_ - -struct CStringData -{ - IAtlStringMgr* pStringMgr; // String manager for this CStringData - int nDataLength; // Length of currently used data in XCHARs (not including terminating null) - int nAllocLength; // Length of allocated data in XCHARs (not including terminating null) - long nRefs; // Reference count: negative == locked - // XCHAR data[nAllocLength+1] // A CStringData is always followed in memory by the actual array of character data - - void* data() throw() - { - return (this+1); - } - - void AddRef() throw() - { - ATLASSERT(nRefs > 0); - _AtlInterlockedIncrement(&nRefs); - } - bool IsLocked() const throw() - { - return nRefs < 0; - } - bool IsShared() const throw() - { - return( nRefs > 1 ); - } - void Lock() throw() - { - ATLASSERT( nRefs <= 1 ); - nRefs--; // Locked buffers can't be shared, so no interlocked operation necessary - if( nRefs == 0 ) - { - nRefs = -1; - } - } - void Release() throw() - { - ATLASSERT( nRefs != 0 ); - - if( _AtlInterlockedDecrement( &nRefs ) <= 0 ) - { - pStringMgr->Free( this ); - } - } - void Unlock() throw() - { - ATLASSERT( IsLocked() ); - - if(IsLocked()) - { - nRefs++; // Locked buffers can't be shared, so no interlocked operation necessary - if( nRefs == 0 ) - { - nRefs = 1; - } - } - } -}; - -class CNilStringData : - public CStringData -{ -public: - CNilStringData() throw() - { - pStringMgr = NULL; - nRefs = 2; // Never gets freed by IAtlStringMgr - nDataLength = 0; - nAllocLength = 0; - achNil[0] = 0; - achNil[1] = 0; - } - - void SetManager( __in IAtlStringMgr* pMgr ) throw() - { - ATLASSERT( pStringMgr == NULL ); - pStringMgr = pMgr; - } - -public: - wchar_t achNil[2]; -}; - -template< typename BaseType, const int t_nSize > -class CStaticString -{ -public: - CStaticString( __in const BaseType* psz ) : - m_psz( psz ) - { - } - - operator const BaseType*() const - { - return m_psz; - } - - static int __cdecl GetLength() - { - return (t_nSize/sizeof( BaseType ))-1; - } - -private: - const BaseType* m_psz; - -private: - CStaticString( const CStaticString& str ) throw(); - CStaticString& operator=( const CStaticString& str ) throw(); -}; - -#define _ST( psz ) ATL::CStaticString< TCHAR, sizeof( _T( psz ) ) >( _T( psz ) ) -#define _SA( psz ) ATL::CStaticString< char, sizeof( psz ) >( psz ) -#define _SW( psz ) ATL::CStaticString< wchar_t, sizeof( L##psz ) >( L##psz ) -#define _SO( psz ) _SW( psz ) - -template< typename BaseType = char > -class ChTraitsBase -{ -public: - typedef char XCHAR; - typedef LPSTR PXSTR; - typedef LPCSTR PCXSTR; - typedef wchar_t YCHAR; - typedef LPWSTR PYSTR; - typedef LPCWSTR PCYSTR; -}; - -template<> -class ChTraitsBase< wchar_t > -{ -public: - typedef wchar_t XCHAR; - typedef LPWSTR PXSTR; - typedef LPCWSTR PCXSTR; - typedef char YCHAR; - typedef LPSTR PYSTR; - typedef LPCSTR PCYSTR; -}; - -template< typename TCharType, bool t_bMFCDLL = false > -class CStrBufT; - -template< typename BaseType , bool t_bMFCDLL = false> -class CSimpleStringT -{ -public: - typedef typename ChTraitsBase< BaseType >::XCHAR XCHAR; - typedef typename ChTraitsBase< BaseType >::PXSTR PXSTR; - typedef typename ChTraitsBase< BaseType >::PCXSTR PCXSTR; - typedef typename ChTraitsBase< BaseType >::YCHAR YCHAR; - typedef typename ChTraitsBase< BaseType >::PYSTR PYSTR; - typedef typename ChTraitsBase< BaseType >::PCYSTR PCYSTR; - -public: - explicit CSimpleStringT( __in IAtlStringMgr* pStringMgr ) - { - ATLENSURE( pStringMgr != NULL ); - CStringData* pData = pStringMgr->GetNilString(); - Attach( pData ); - } - - CSimpleStringT( __in const CSimpleStringT& strSrc ) - { - CStringData* pSrcData = strSrc.GetData(); - CStringData* pNewData = CloneData( pSrcData ); - Attach( pNewData ); - } - - CSimpleStringT( __in const CSimpleStringT& strSrc ) - { - CStringData* pSrcData = strSrc.GetData(); - CStringData* pNewData = CloneData( pSrcData ); - Attach( pNewData ); - } - - CSimpleStringT( __in PCXSTR pszSrc, __in IAtlStringMgr* pStringMgr ) - { - ATLENSURE( pStringMgr != NULL ); - - int nLength = StringLength( pszSrc ); - CStringData* pData = pStringMgr->Allocate( nLength, sizeof( XCHAR ) ); - if( pData == NULL ) - { - ThrowMemoryException(); - } - Attach( pData ); - SetLength( nLength ); -#if _SECURE_ATL - CopyChars( m_pszData, nLength, pszSrc, nLength ); -#else - CopyChars( m_pszData, pszSrc, nLength ); -#endif - } - CSimpleStringT( __in_ecount(nLength) const XCHAR* pchSrc, __in int nLength, __in IAtlStringMgr* pStringMgr ) - { - ATLENSURE( pStringMgr != NULL ); - - if(pchSrc == NULL && nLength != 0) - AtlThrow(E_INVALIDARG); - - CStringData* pData = pStringMgr->Allocate( nLength, sizeof( XCHAR ) ); - if( pData == NULL ) - { - ThrowMemoryException(); - } - Attach( pData ); - SetLength( nLength ); -#if _SECURE_ATL - CopyChars( m_pszData, nLength, pchSrc, nLength ); -#else - CopyChars( m_pszData, pchSrc, nLength ); -#endif - } - ~CSimpleStringT() throw() - { - CStringData* pData = GetData(); - pData->Release(); - } - - operator CSimpleStringT&() - { - return *(CSimpleStringT*)this; - } - - CSimpleStringT& operator=( __in const CSimpleStringT& strSrc ) - { - CStringData* pSrcData = strSrc.GetData(); - CStringData* pOldData = GetData(); - if( pSrcData != pOldData) - { - if( pOldData->IsLocked() || pSrcData->pStringMgr != pOldData->pStringMgr ) - { - SetString( strSrc.GetString(), strSrc.GetLength() ); - } - else - { - CStringData* pNewData = CloneData( pSrcData ); - pOldData->Release(); - Attach( pNewData ); - } - } - - return( *this ); - } - - CSimpleStringT& operator=( __in const CSimpleStringT& strSrc ) - { - CStringData* pSrcData = strSrc.GetData(); - CStringData* pOldData = GetData(); - if( pSrcData != pOldData) - { - if( pOldData->IsLocked() || pSrcData->pStringMgr != pOldData->pStringMgr ) - { - SetString( strSrc.GetString(), strSrc.GetLength() ); - } - else - { - CStringData* pNewData = CloneData( pSrcData ); - pOldData->Release(); - Attach( pNewData ); - } - } - - return( *this ); - } - - CSimpleStringT& operator=( __in PCXSTR pszSrc ) - { - SetString( pszSrc ); - - return( *this ); - } - - CSimpleStringT& operator+=( __in const CSimpleStringT& strSrc ) - { - Append( strSrc ); - - return( *this ); - } - template - CSimpleStringT& operator+=( __in const CSimpleStringT& strSrc ) - { - Append( strSrc ); - - return( *this ); - } - - CSimpleStringT& operator+=( __in PCXSTR pszSrc ) - { - Append( pszSrc ); - - return( *this ); - } - template< int t_nSize > - CSimpleStringT& operator+=( __in const CStaticString< XCHAR, t_nSize >& strSrc ) - { - Append( static_cast(strSrc), strSrc.GetLength() ); - - return( *this ); - } - CSimpleStringT& operator+=( __in char ch ) - { - AppendChar( XCHAR( ch ) ); - - return( *this ); - } - CSimpleStringT& operator+=( __in unsigned char ch ) - { - AppendChar( XCHAR( ch ) ); - - return( *this ); - } - CSimpleStringT& operator+=( __in wchar_t ch ) - { - AppendChar( XCHAR( ch ) ); - - return( *this ); - } - - XCHAR operator[]( __in int iChar ) const - { - ATLASSERT( (iChar >= 0) && (iChar <= GetLength()) ); // Indexing the '\0' is OK - - if( (iChar < 0) || (iChar > GetLength()) ) - AtlThrow(E_INVALIDARG); - - return( m_pszData[iChar] ); - } - - operator PCXSTR() const throw() - { - return( m_pszData ); - } - - void Append( __in PCXSTR pszSrc ) - { - Append( pszSrc, StringLength( pszSrc ) ); - } - void Append( __in_ecount(nLength) PCXSTR pszSrc, __in int nLength ) - { - // See comment in SetString() about why we do this - UINT_PTR nOffset = pszSrc-GetString(); - - UINT nOldLength = GetLength(); - if (nOldLength < 0) - { - // protects from underflow - nOldLength = 0; - } - int nNewLength = nOldLength+nLength; - PXSTR pszBuffer = GetBuffer( nNewLength ); - if( nOffset <= nOldLength ) - { - pszSrc = pszBuffer+nOffset; - // No need to call CopyCharsOverlapped, since the destination is - // beyond the end of the original buffer - } -#if _SECURE_ATL - CopyChars( pszBuffer+nOldLength, nLength, pszSrc, nLength ); -#else - CopyChars( pszBuffer+nOldLength, pszSrc, nLength ); -#endif - ReleaseBufferSetLength( nNewLength ); - } - void AppendChar( __in XCHAR ch ) - { - UINT nOldLength = GetLength(); - int nNewLength = nOldLength+1; - PXSTR pszBuffer = GetBuffer( nNewLength ); - pszBuffer[nOldLength] = ch; - ReleaseBufferSetLength( nNewLength ); - } - void Append( __in const CSimpleStringT& strSrc ) - { - Append( strSrc.GetString(), strSrc.GetLength() ); - } - template - void Append( __in const CSimpleStringT& strSrc ) - { - Append( strSrc.GetString(), strSrc.GetLength() ); - } - void Empty() throw() - { - CStringData* pOldData = GetData(); - IAtlStringMgr* pStringMgr = pOldData->pStringMgr; - if( pOldData->nDataLength == 0 ) - { - return; - } - - if( pOldData->IsLocked() ) - { - // Don't reallocate a locked buffer that's shrinking - SetLength( 0 ); - } - else - { - pOldData->Release(); - CStringData* pNewData = pStringMgr->GetNilString(); - Attach( pNewData ); - } - } - void FreeExtra() - { - CStringData* pOldData = GetData(); - int nLength = pOldData->nDataLength; - IAtlStringMgr* pStringMgr = pOldData->pStringMgr; - if( pOldData->nAllocLength == nLength ) - { - return; - } - - if( !pOldData->IsLocked() ) // Don't reallocate a locked buffer that's shrinking - { - CStringData* pNewData = pStringMgr->Allocate( nLength, sizeof( XCHAR ) ); - if( pNewData == NULL ) - { - SetLength( nLength ); - return; - } - -#if _SECURE_ATL - CopyChars( PXSTR( pNewData->data() ), nLength, - PCXSTR( pOldData->data() ), nLength ); -#else - CopyChars( PXSTR( pNewData->data() ), PCXSTR( pOldData->data() ), nLength ); -#endif - - pOldData->Release(); - Attach( pNewData ); - SetLength( nLength ); - } - } - - int GetAllocLength() const throw() - { - return( GetData()->nAllocLength ); - } - XCHAR GetAt( __in int iChar ) const - { - ATLASSERT( (iChar >= 0) && (iChar <= GetLength()) ); // Indexing the '\0' is OK - if( (iChar < 0) || (iChar > GetLength()) ) - AtlThrow(E_INVALIDARG); - - return( m_pszData[iChar] ); - } - PXSTR GetBuffer() - { - CStringData* pData = GetData(); - if( pData->IsShared() ) - { - Fork( pData->nDataLength ); - } - - return( m_pszData ); - } - __out_ecount(nMinBufferLength + 1) PXSTR GetBuffer( __in int nMinBufferLength ) - { - return( PrepareWrite( nMinBufferLength ) ); - } - __out_ecount(nLength + 1) PXSTR GetBufferSetLength( __in int nLength ) - { - PXSTR pszBuffer = GetBuffer( nLength ); - SetLength( nLength ); - - return( pszBuffer ); - } - int GetLength() const throw() - { - return( GetData()->nDataLength ); - } - IAtlStringMgr* GetManager() const throw() - { - IAtlStringMgr* pStringMgr = GetData()->pStringMgr; - return pStringMgr ? pStringMgr->Clone() : NULL; - } - - __out_ecount(m_nLength) PCXSTR GetString() const throw() - { - return( m_pszData ); - } - bool IsEmpty() const throw() - { - return( GetLength() == 0 ); - } - PXSTR LockBuffer() - { - CStringData* pData = GetData(); - if( pData->IsShared() ) - { - Fork( pData->nDataLength ); - pData = GetData(); // Do it again, because the fork might have changed it - } - pData->Lock(); - - return( m_pszData ); - } - void UnlockBuffer() throw() - { - CStringData* pData = GetData(); - pData->Unlock(); - } - void Preallocate( __in int nLength ) - { - PrepareWrite( nLength ); - } - void ReleaseBuffer( __in int nNewLength = -1 ) - { - if( nNewLength == -1 ) - { - nNewLength = StringLength( m_pszData ); - } - SetLength( nNewLength ); - } - void ReleaseBufferSetLength( __in int nNewLength ) - { - ATLASSERT( nNewLength >= 0 ); - SetLength( nNewLength ); - } - void Truncate( __in int nNewLength ) - { - ATLASSERT( nNewLength <= GetLength() ); - GetBuffer( nNewLength ); - ReleaseBufferSetLength( nNewLength ); - } - void SetAt( __in int iChar, __in XCHAR ch ) - { - ATLASSERT( (iChar >= 0) && (iChar < GetLength()) ); - - if( (iChar < 0) || (iChar >= GetLength()) ) - AtlThrow(E_INVALIDARG); - - int nLength = GetLength(); - PXSTR pszBuffer = GetBuffer(); - pszBuffer[iChar] = ch; - ReleaseBufferSetLength( nLength ); - - } - void SetManager( __in IAtlStringMgr* pStringMgr ) - { - ATLASSERT( IsEmpty() ); - - CStringData* pData = GetData(); - pData->Release(); - pData = pStringMgr->GetNilString(); - Attach( pData ); - } - void SetString( __in PCXSTR pszSrc ) - { - SetString( pszSrc, StringLength( pszSrc ) ); - } - void SetString( __in_ecount(nLength) PCXSTR pszSrc, __in int nLength ) - { - if( nLength == 0 ) - { - Empty(); - } - else - { - // It is possible that pszSrc points to a location inside of our - // buffer. GetBuffer() might change m_pszData if (1) the buffer - // is shared or (2) the buffer is too small to hold the new - // string. We detect this aliasing, and modify pszSrc to point - // into the newly allocated buffer instead. - - if(pszSrc == NULL) - AtlThrow(E_INVALIDARG); - - UINT nOldLength = GetLength(); - UINT_PTR nOffset = pszSrc-GetString(); - // If 0 <= nOffset <= nOldLength, then pszSrc points into our - // buffer - - PXSTR pszBuffer = GetBuffer( nLength ); - if( nOffset <= nOldLength ) - { -#if _SECURE_ATL - CopyCharsOverlapped( pszBuffer, nLength, - pszBuffer+nOffset, nLength ); -#else - CopyCharsOverlapped( pszBuffer, pszBuffer+nOffset, nLength ); -#endif - } - else - { -#if _SECURE_ATL - CopyChars( pszBuffer, nLength, pszSrc, nLength ); -#else - CopyChars( pszBuffer, pszSrc, nLength ); -#endif - } - ReleaseBufferSetLength( nLength ); - } - } - -public: - friend CSimpleStringT operator+( - __in const CSimpleStringT& str1, - __in const CSimpleStringT& str2 ) - { - CSimpleStringT s( str1.GetManager() ); - - Concatenate( s, str1, str1.GetLength(), str2, str2.GetLength() ); - - return( s ); - } - - friend CSimpleStringT operator+( - __in const CSimpleStringT& str1, - __in PCXSTR psz2 ) - { - CSimpleStringT s( str1.GetManager() ); - - Concatenate( s, str1, str1.GetLength(), psz2, StringLength( psz2 ) ); - - return( s ); - } - - friend CSimpleStringT operator+( - __in PCXSTR psz1, - __in const CSimpleStringT& str2 ) - { - CSimpleStringT s( str2.GetManager() ); - - Concatenate( s, psz1, StringLength( psz1 ), str2, str2.GetLength() ); - - return( s ); - } - - _ATL_INSECURE_DEPRECATE("CSimpleStringT::CopyChars must be passed a buffer size") - static void __cdecl CopyChars - ( __out_ecount(nChars) XCHAR* pchDest, __in_ecount(nChars) const XCHAR* pchSrc, __in int nChars ) throw() - { - #pragma warning (push) - #pragma warning(disable : 4996) - memcpy( pchDest, pchSrc, nChars*sizeof( XCHAR ) ); - #pragma warning (pop) - } - static void __cdecl CopyChars - ( __out_ecount_part(nDestLen,nChars) XCHAR* pchDest, __in size_t nDestLen, __in_ecount(nChars) const XCHAR* pchSrc, __in int nChars ) throw() - { - memcpy_s( pchDest, nDestLen*sizeof( XCHAR ), - pchSrc, nChars*sizeof( XCHAR ) ); - } - - _ATL_INSECURE_DEPRECATE("CSimpleStringT::CopyCharsOverlapped must be passed a buffer size") - static void __cdecl CopyCharsOverlapped - ( __out_ecount(nChars) XCHAR* pchDest, __in_ecount(nChars) const XCHAR* pchSrc, __in int nChars ) throw() - { - #pragma warning (push) - #pragma warning(disable : 4996) - memmove( pchDest, pchSrc, nChars*sizeof( XCHAR ) ); - #pragma warning (pop) - } - static void __cdecl CopyCharsOverlapped - ( __out_ecount_part(nDestLen, nDestLen) XCHAR* pchDest, __in size_t nDestLen, __in_ecount(nChars) const XCHAR* pchSrc, __in int nChars ) throw() - { - memmove_s( pchDest, nDestLen*sizeof( XCHAR ), - pchSrc, nChars*sizeof( XCHAR ) ); - } -#ifdef _ATL_MIN_CRT - ATL_NOINLINE static int __cdecl StringLength( __in_z_opt PCXSTR psz ) throw() - { - int nLength = 0; - if( psz != NULL ) - { - const XCHAR* pch = psz; - while( *pch != 0 ) - { - nLength++; - pch++; - } - } - - return( nLength ); - } -#else - static int __cdecl StringLength( __in_z_opt const char* psz ) throw() - { - if( psz == NULL ) - { - return( 0 ); - } - return( int( strlen( psz ) ) ); - } - static int __cdecl StringLength( __in_z_opt const wchar_t* psz ) throw() - { - if( psz == NULL ) - { - return( 0 ); - } - return( int( wcslen( psz ) ) ); - } -#endif - -protected: - static void __cdecl Concatenate( __out CSimpleStringT& strResult, __in_ecount(nLength1) PCXSTR psz1, __in int nLength1, __in_ecount(nLength2) PCXSTR psz2, __in int nLength2 ) - { - int nNewLength = nLength1+nLength2; - PXSTR pszBuffer = strResult.GetBuffer( nNewLength ); -#if _SECURE_ATL - CopyChars( pszBuffer, nLength1, psz1, nLength1 ); - CopyChars( pszBuffer+nLength1, nLength2, psz2, nLength2 ); -#else - CopyChars( pszBuffer, psz1, nLength1 ); - CopyChars( pszBuffer+nLength1, psz2, nLength2 ); -#endif - strResult.ReleaseBufferSetLength( nNewLength ); - } - ATL_NOINLINE __declspec( noreturn ) static void __cdecl ThrowMemoryException() - { - AtlThrow( E_OUTOFMEMORY ); - } - -// Implementation -private: - void Attach( __in CStringData* pData ) throw() - { - m_pszData = static_cast< PXSTR >( pData->data() ); - } - ATL_NOINLINE void Fork( __in int nLength ) - { - CStringData* pOldData = GetData(); - int nOldLength = pOldData->nDataLength; - CStringData* pNewData = pOldData->pStringMgr->Clone()->Allocate( nLength, sizeof( XCHAR ) ); - if( pNewData == NULL ) - { - ThrowMemoryException(); - } - int nCharsToCopy = ((nOldLength < nLength) ? nOldLength : nLength)+1; // Copy '\0' -#if _SECURE_ATL - CopyChars( PXSTR( pNewData->data() ), nCharsToCopy, - PCXSTR( pOldData->data() ), nCharsToCopy ); -#else - CopyChars( PXSTR( pNewData->data() ), PCXSTR( pOldData->data() ), nCharsToCopy ); -#endif - pNewData->nDataLength = nOldLength; - pOldData->Release(); - Attach( pNewData ); - } - CStringData* GetData() const throw() - { - return( reinterpret_cast< CStringData* >( m_pszData )-1 ); - } - PXSTR PrepareWrite( __in int nLength ) - { - CStringData* pOldData = GetData(); - int nShared = 1-pOldData->nRefs; // nShared < 0 means true, >= 0 means false - int nTooShort = pOldData->nAllocLength-nLength; // nTooShort < 0 means true, >= 0 means false - if( (nShared|nTooShort) < 0 ) // If either sign bit is set (i.e. either is less than zero), we need to copy data - { - PrepareWrite2( nLength ); - } - - return( m_pszData ); - } - ATL_NOINLINE void PrepareWrite2( __in int nLength ) - { - CStringData* pOldData = GetData(); - if( pOldData->nDataLength > nLength ) - { - nLength = pOldData->nDataLength; - } - if( pOldData->IsShared() ) - { - Fork( nLength ); - } - else if( pOldData->nAllocLength < nLength ) - { - // Grow exponentially, until we hit 1K. - int nNewLength = pOldData->nAllocLength; - if( nNewLength > 1024 ) - { - nNewLength += 1024; - } - else - { - nNewLength *= 2; - } - if( nNewLength < nLength ) - { - nNewLength = nLength; - } - Reallocate( nNewLength ); - } - } - ATL_NOINLINE void Reallocate( __in int nLength ) - { - CStringData* pOldData = GetData(); - ATLASSERT( pOldData->nAllocLength < nLength ); - IAtlStringMgr* pStringMgr = pOldData->pStringMgr; - if ( pOldData->nAllocLength >= nLength || nLength <= 0) - { - ThrowMemoryException(); - return; - } - CStringData* pNewData = pStringMgr->Reallocate( pOldData, nLength, sizeof( XCHAR ) ); - if( pNewData == NULL ) - { - ThrowMemoryException(); - } - Attach( pNewData ); - } - - void SetLength( __in int nLength ) - { - ATLASSERT( nLength >= 0 ); - ATLASSERT( nLength <= GetData()->nAllocLength ); - - if( nLength < 0 || nLength > GetData()->nAllocLength) - AtlThrow(E_INVALIDARG); - - GetData()->nDataLength = nLength; - m_pszData[nLength] = 0; - } - - static CStringData* __cdecl CloneData( __in CStringData* pData ) - { - CStringData* pNewData = NULL; - - IAtlStringMgr* pNewStringMgr = pData->pStringMgr->Clone(); - if( !pData->IsLocked() && (pNewStringMgr == pData->pStringMgr) ) - { - pNewData = pData; - pNewData->AddRef(); - } - else - { - pNewData = pNewStringMgr->Allocate( pData->nDataLength, sizeof( XCHAR ) ); - if( pNewData == NULL ) - { - ThrowMemoryException(); - } - pNewData->nDataLength = pData->nDataLength; -#if _SECURE_ATL - CopyChars( PXSTR( pNewData->data() ), pData->nDataLength+1, - PCXSTR( pData->data() ), pData->nDataLength+1 ); // Copy '\0' -#else - CopyChars( PXSTR( pNewData->data() ), PCXSTR( pData->data() ), pData->nDataLength+1 ); // Copy '\0' -#endif - } - - return( pNewData ); - } - -public : - typedef CStrBufT CStrBuf; -private: - PXSTR m_pszData; - - friend class CSimpleStringT; -}; - -template< typename TCharType, bool t_bMFCDLL > -class CStrBufT -{ -public: - typedef CSimpleStringT< TCharType, t_bMFCDLL> StringType; - typedef typename StringType::XCHAR XCHAR; - typedef typename StringType::PXSTR PXSTR; - typedef typename StringType::PCXSTR PCXSTR; - - static const DWORD AUTO_LENGTH = 0x01; // Automatically determine the new length of the string at release. The string must be null-terminated. - static const DWORD SET_LENGTH = 0x02; // Set the length of the string object at GetBuffer time - -public: - explicit CStrBufT( __in StringType& str ) throw( ... ) : - m_str( str ), - m_pszBuffer( NULL ), -#ifdef _DEBUG - m_nBufferLength( str.GetLength() ), -#endif - m_nLength( str.GetLength() ) - { - m_pszBuffer = m_str.GetBuffer(); - } - - CStrBufT( __in StringType& str, __in int nMinLength, __in DWORD dwFlags = AUTO_LENGTH ) throw( ... ) : - m_str( str ), - m_pszBuffer( NULL ), -#ifdef _DEBUG - m_nBufferLength( nMinLength ), -#endif - m_nLength( (dwFlags&AUTO_LENGTH) ? -1 : nMinLength ) - { - if( dwFlags&SET_LENGTH ) - { - m_pszBuffer = m_str.GetBufferSetLength( nMinLength ); - } - else - { - m_pszBuffer = m_str.GetBuffer( nMinLength ); - } - } - - ~CStrBufT() - { - m_str.ReleaseBuffer( m_nLength ); - } - - operator PXSTR() throw() - { - return( m_pszBuffer ); - } - operator PCXSTR() const throw() - { - return( m_pszBuffer ); - } - - void SetLength( __in int nLength ) - { - ATLASSERT( nLength >= 0 ); - ATLASSERT( nLength <= m_nBufferLength ); - - if( nLength < 0 ) - AtlThrow(E_INVALIDARG); - - m_nLength = nLength; - } - -// Implementation -private: - StringType& m_str; - PXSTR m_pszBuffer; - int m_nLength; -#ifdef _DEBUG - int m_nBufferLength; -#endif - -// Private copy constructor and copy assignment operator to prevent accidental use -private: - CStrBufT( const CStrBufT& ) throw(); - CStrBufT& operator=( const CStrBufT& ) throw(); -}; - -typedef CSimpleStringT< TCHAR > CSimpleString; -typedef CSimpleStringT< char > CSimpleStringA; -typedef CSimpleStringT< wchar_t > CSimpleStringW; -typedef CStrBufT< TCHAR > CStrBuf; -typedef CStrBufT< char > CStrBufA; -typedef CStrBufT< wchar_t > CStrBufW; - -}; // namespace ATL -#pragma pack(pop) - -#endif // __ATLSIMPSTR_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlstdthunk.h b/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlstdthunk.h deleted file mode 100644 index 46d7bc316..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlstdthunk.h +++ /dev/null @@ -1,326 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLSTDTHUNK_H__ -#define __ATLSTDTHUNK_H__ - -#pragma once - -#pragma push_macro("malloc") -#undef malloc -#pragma push_macro("realloc") -#undef realloc -#pragma push_macro("free") -#undef free -#pragma push_macro("new") -#undef new -#pragma push_macro("HeapAlloc") -#undef HeapAlloc -#pragma push_macro("HeapFree") -#undef HeapFree -#pragma push_macro("GetProcessHeap") -#undef GetProcessHeap - - - - - - -namespace ATL -{ - -///////////////////////////////////////////////////////////////////////////// -// Thunks for __stdcall member functions - -#if defined(_M_IX86) -PVOID __stdcall __AllocStdCallThunk(VOID); -VOID __stdcall __FreeStdCallThunk(PVOID); - -#pragma pack(push,1) -struct _stdcallthunk -{ - DWORD m_mov; // mov dword ptr [esp+0x4], pThis (esp+0x4 is hWnd) - DWORD m_this; // - BYTE m_jmp; // jmp WndProc - DWORD m_relproc; // relative jmp - BOOL Init(DWORD_PTR proc, void* pThis) - { - m_mov = 0x042444C7; //C7 44 24 0C - m_this = PtrToUlong(pThis); - m_jmp = 0xe9; - m_relproc = DWORD((INT_PTR)proc - ((INT_PTR)this+sizeof(_stdcallthunk))); - // write block from data cache and - // flush from instruction cache - FlushInstructionCache(GetCurrentProcess(), this, sizeof(_stdcallthunk)); - return TRUE; - } - //some thunks will dynamically allocate the memory for the code - void* GetCodeAddress() - { - return this; - } - void* operator new(size_t) - { - return __AllocStdCallThunk(); - } - void operator delete(void* pThunk) - { - __FreeStdCallThunk(pThunk); - } -}; -#pragma pack(pop) - -#elif defined(_M_AMD64) -PVOID __AllocStdCallThunk(VOID); -VOID __FreeStdCallThunk(PVOID); -#pragma pack(push,2) -struct _stdcallthunk -{ - USHORT RcxMov; // mov rcx, pThis - ULONG64 RcxImm; // - USHORT RaxMov; // mov rax, target - ULONG64 RaxImm; // - USHORT RaxJmp; // jmp target - BOOL Init(DWORD_PTR proc, void *pThis) - { - RcxMov = 0xb948; // mov rcx, pThis - RcxImm = (ULONG64)pThis; // - RaxMov = 0xb848; // mov rax, target - RaxImm = (ULONG64)proc; // - RaxJmp = 0xe0ff; // jmp rax - FlushInstructionCache(GetCurrentProcess(), this, sizeof(_stdcallthunk)); - return TRUE; - } - //some thunks will dynamically allocate the memory for the code - void* GetCodeAddress() - { - return this; - } - void* operator new(size_t) - { - return __AllocStdCallThunk(); - } - void operator delete(void* pThunk) - { - __FreeStdCallThunk(pThunk); - } -}; -#pragma pack(pop) -#elif defined (_M_ALPHA) -// For ALPHA we will stick the this pointer into a0, which is where -// the HWND is. However, we don't actually need the HWND so this is OK. -#pragma pack(push,4) -struct _stdcallthunk //this should come out to 20 bytes -{ - DWORD ldah_at; // ldah at, HIWORD(func) - DWORD ldah_a0; // ldah a0, HIWORD(this) - DWORD lda_at; // lda at, LOWORD(func)(at) - DWORD lda_a0; // lda a0, LOWORD(this)(a0) - DWORD jmp; // jmp zero,(at),0 - BOOL Init(DWORD_PTR proc, void* pThis) - { - ldah_at = (0x279f0000 | HIWORD(proc)) + (LOWORD(proc)>>15); - ldah_a0 = (0x261f0000 | HIWORD(pThis)) + (LOWORD(pThis)>>15); - lda_at = 0x239c0000 | LOWORD(proc); - lda_a0 = 0x22100000 | LOWORD(pThis); - jmp = 0x6bfc0000; - // write block from data cache and - // flush from instruction cache - FlushInstructionCache(GetCurrentProcess(), this, sizeof(_stdcallthunk)); - return TRUE; - } - void* GetCodeAddress() - { - return this; - } -}; -#pragma pack(pop) -#elif defined(_SH3_) -#pragma pack(push,4) -struct _stdcallthunk // this should come out to 16 bytes -{ - WORD m_mov_r0; // mov.l pFunc,r0 - WORD m_mov_r1; // mov.l pThis,r1 - WORD m_jmp; // jmp @r0 - WORD m_nop; // nop - DWORD m_pFunc; - DWORD m_pThis; - BOOL Init(DWORD_PTR proc, void* pThis) - { - m_mov_r0 = 0xd001; - m_mov_r1 = 0xd402; - m_jmp = 0x402b; - m_nop = 0x0009; - m_pFunc = (DWORD)proc; - m_pThis = (DWORD)pThis; - // write block from data cache and - // flush from instruction cache - FlushInstructionCache(GetCurrentProcess(), this, sizeof(_stdcallthunk)); - return TRUE; - } - void* GetCodeAddress() - { - return this; - } -}; -#pragma pack(pop) -#elif defined(_MIPS_) -#pragma pack(push,4) -struct _stdcallthunk -{ - WORD m_pFuncHi; - WORD m_lui_t0; // lui t0,PFUNC_HIGH - WORD m_pFuncLo; - WORD m_ori_t0; // ori t0,t0,PFUNC_LOW - WORD m_pThisHi; - WORD m_lui_a0; // lui a0,PTHIS_HIGH - DWORD m_jr_t0; // jr t0 - WORD m_pThisLo; - WORD m_ori_a0; // ori a0,PTHIS_LOW - BOOL Init(DWORD_PTR proc, void* pThis) - { - m_pFuncHi = HIWORD(proc); - m_lui_t0 = 0x3c08; - m_pFuncLo = LOWORD(proc); - m_ori_t0 = 0x3508; - m_pThisHi = HIWORD(pThis); - m_lui_a0 = 0x3c04; - m_jr_t0 = 0x01000008; - m_pThisLo = LOWORD(pThis); - m_ori_a0 = 0x3484; - // write block from data cache and - // flush from instruction cache - FlushInstructionCache(GetCurrentProcess(), this, sizeof(_stdcallthunk)); - return TRUE; - } - void* GetCodeAddress() - { - return this; - } -}; -#pragma pack(pop) -#elif defined(_ARM_) -#pragma pack(push,4) -struct _stdcallthunk // this should come out to 16 bytes -{ - DWORD m_mov_r0; // mov r0, pThis - DWORD m_mov_pc; // mov pc, pFunc - DWORD m_pThis; - DWORD m_pFunc; - BOOL Init(DWORD_PTR proc, void* pThis) - { - m_mov_r0 = 0xE59F0000; - m_mov_pc = 0xE59FF000; - m_pThis = (DWORD)pThis; - m_pFunc = (DWORD)proc; - // write block from data cache and - // flush from instruction cache - FlushInstructionCache(GetCurrentProcess(), this, sizeof(_stdcallthunk)); - return TRUE; - } - void* GetCodeAddress() - { - return this; - } -}; -#pragma pack(pop) -#elif defined(_M_IA64) -#pragma pack(push,8) -extern "C" void _StdCallThunkProcProc(void); -struct _FuncDesc -{ - void* pfn; - void* gp; -}; -struct _stdcallthunk -{ - _FuncDesc m_funcdesc; - void* m_pFunc; - void* m_pThis; - BOOL Init(DWORD_PTR proc, void* pThis) - { - m_funcdesc.pfn = ((_FuncDesc*)(&_StdCallThunkProcProc))->pfn; // Pointer to actual beginning of StdCallThunkProc - m_funcdesc.gp = &m_pFunc; - m_pFunc = reinterpret_cast< void* >( proc ); - m_pThis = pThis; - ::FlushInstructionCache( GetCurrentProcess(), this, sizeof( _stdcallthunk ) ); - return TRUE; - } - void* GetCodeAddress() - { - return( &m_funcdesc ); - } -}; -#pragma pack(pop) -//IA64 thunks do not currently use the atlhunk.cpp allocator. -#else -#error Only ARM, ALPHA, SH3, MIPS, IA64, AMD64 and X86 supported -#endif - - -#if defined(_M_IX86) || defined (_M_AMD64) - -#pragma pack(push,8) -class CDynamicStdCallThunk -{ -public: - _stdcallthunk *pThunk; - - CDynamicStdCallThunk() - { - pThunk = NULL; - } - - ~CDynamicStdCallThunk() - { - if (pThunk) - { - delete pThunk; - } - } - - BOOL Init(DWORD_PTR proc, void *pThis) - { - if (pThunk == NULL) - { - pThunk = new _stdcallthunk; - if (pThunk == NULL) - { - return FALSE; - } - } - return pThunk->Init(proc, pThis); - } - - - void* GetCodeAddress() - { - return pThunk->GetCodeAddress(); - } -}; - -#pragma pack(pop) -typedef CDynamicStdCallThunk CStdCallThunk; -#else -typedef _stdcallthunk CStdCallThunk; -#endif // _M_IX86 || _M_AMD64 - -} // namespace ATL - - -#pragma pop_macro("GetProcessHeap") -#pragma pop_macro("HeapAlloc") -#pragma pop_macro("HeapFree") -#pragma pop_macro("new") -#pragma pop_macro("free") -#pragma pop_macro("realloc") -#pragma pop_macro("malloc") - -#endif // __ATLSTDTHUNK_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atltrace.h b/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atltrace.h deleted file mode 100644 index 22517a6f2..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atltrace.h +++ /dev/null @@ -1,449 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __ATLTRACE_H__ -#define __ATLTRACE_H__ - -#pragma once - -#include -#include - -#ifdef _DEBUG -#include -#include -#endif - -#ifdef _DEBUG -#include - -extern "C" IMAGE_DOS_HEADER __ImageBase; -#endif // _DEBUG - - -#pragma pack(push,_ATL_PACKING) -namespace ATL -{ - -// Declare a global instance of this class to automatically register a custom trace category at startup -class CTraceCategory -{ -public: - explicit CTraceCategory( LPCTSTR pszCategoryName, UINT nStartingLevel = 0 ) throw(); - -#ifdef _DEBUG - UINT GetLevel() const throw(); - void SetLevel( UINT nLevel ) throw(); - ATLTRACESTATUS GetStatus() const throw(); - void SetStatus( ATLTRACESTATUS eStatus) throw(); -#endif - - operator DWORD_PTR() const throw(); - -public: -#ifdef _DEBUG - DWORD_PTR m_dwCategory; -#endif -}; - -#ifdef _DEBUG - -class CTrace -{ -public: - typedef int (__cdecl *fnCrtDbgReport_t)(int,const char *,int,const char *,const char *,...); - -private: - CTrace( -#ifdef _ATL_NO_DEBUG_CRT - fnCrtDbgReport_t pfnCrtDbgReport = NULL) -#else - fnCrtDbgReport_t pfnCrtDbgReport = _CrtDbgReport) -#endif - : m_hInst(reinterpret_cast(&__ImageBase)), - m_dwModule( 0 ) - { - m_dwModule = AtlTraceRegister(m_hInst, pfnCrtDbgReport); - } - - ~CTrace() - { - AtlTraceUnregister(m_dwModule); - } - -public: - bool ChangeCategory(DWORD_PTR dwCategory, UINT nLevel, ATLTRACESTATUS eStatus) - { - return 0 != - AtlTraceModifyCategory(0, dwCategory, nLevel, eStatus); - } - - bool GetCategory(DWORD_PTR dwCategory, UINT *pnLevel, ATLTRACESTATUS *peStatus) - { - ATLASSERT(pnLevel && peStatus); - return 0 != AtlTraceGetCategory(0, dwCategory, pnLevel, peStatus); - } - UINT GetLevel() - { - ATLTRACESTATUS eStatus; - UINT nLevel; - AtlTraceGetModule(0, m_dwModule, &nLevel, &eStatus); - - return nLevel; - } - void SetLevel(UINT nLevel) - { - AtlTraceModifyModule(0, m_dwModule, nLevel, ATLTRACESTATUS_ENABLED); - } - ATLTRACESTATUS GetStatus() - { - ATLTRACESTATUS eStatus; - UINT nLevel; - AtlTraceGetModule(0, m_dwModule, &nLevel, &eStatus); - - return eStatus; - } - void SetStatus(ATLTRACESTATUS eStatus) - { - ATLTRACESTATUS eOldStatus; - UINT nLevel; - AtlTraceGetModule(0, m_dwModule, &nLevel, &eOldStatus); - AtlTraceModifyModule(0, m_dwModule, nLevel, eStatus); - } - void __cdecl TraceV(const char *pszFileName, int nLine, - DWORD_PTR dwCategory, UINT nLevel, LPCSTR pszFmt, va_list args) const; - void __cdecl TraceV(const char *pszFileName, int nLine, - DWORD_PTR dwCategory, UINT nLevel, LPCWSTR pszFmt, va_list args) const; - - DWORD_PTR RegisterCategory(LPCSTR pszCategory) - {return(AtlTraceRegisterCategoryA(m_dwModule, pszCategory));} -#ifdef _UNICODE - DWORD_PTR RegisterCategory(LPCWSTR pszCategory) - {return(AtlTraceRegisterCategoryU(m_dwModule, pszCategory));} -#endif - - bool LoadSettings(LPCTSTR pszFileName = NULL) const - {return 0 != AtlTraceLoadSettings(pszFileName);} - void SaveSettings(LPCTSTR pszFileName = NULL) const - {AtlTraceSaveSettings(pszFileName);} - -public: - static CTrace s_trace; - -protected: - HINSTANCE m_hInst; - DWORD_PTR m_dwModule; -}; - - inline void __cdecl CTrace::TraceV(const char *pszFileName, int nLine, - DWORD_PTR dwCategory, UINT nLevel, LPCSTR pszFmt, va_list args) const - { - AtlTraceVA(m_dwModule, pszFileName, nLine, dwCategory, nLevel, pszFmt, args); - } - inline void __cdecl CTrace::TraceV(const char *pszFileName, int nLine, - DWORD_PTR dwCategory, UINT nLevel, LPCWSTR pszFmt, va_list args) const - { - AtlTraceVU(m_dwModule, pszFileName, nLine, dwCategory, nLevel, pszFmt, args); - } - -extern CTraceCategory atlTraceGeneral; - -class CTraceFileAndLineInfo -{ -public: - CTraceFileAndLineInfo(const char *pszFileName, int nLineNo) - : m_pszFileName(pszFileName), m_nLineNo(nLineNo) - {} - -#pragma warning(push) -#pragma warning(disable : 4793) - void __cdecl operator()(DWORD_PTR dwCategory, UINT nLevel, const char *pszFmt, ...) const - { - va_list ptr; va_start(ptr, pszFmt); - ATL::CTrace::s_trace.TraceV(m_pszFileName, m_nLineNo, dwCategory, nLevel, pszFmt, ptr); - va_end(ptr); - } -#pragma warning(pop) - -#pragma warning(push) -#pragma warning(disable : 4793) - void __cdecl operator()(DWORD_PTR dwCategory, UINT nLevel, const wchar_t *pszFmt, ...) const - { - va_list ptr; va_start(ptr, pszFmt); - ATL::CTrace::s_trace.TraceV(m_pszFileName, m_nLineNo, dwCategory, nLevel, pszFmt, ptr); - va_end(ptr); - } -#pragma warning(pop) - -#pragma warning(push) -#pragma warning(disable : 4793) - void __cdecl operator()(const char *pszFmt, ...) const - { - va_list ptr; va_start(ptr, pszFmt); - ATL::CTrace::s_trace.TraceV(m_pszFileName, m_nLineNo, atlTraceGeneral, 0, pszFmt, ptr); - va_end(ptr); - } -#pragma warning(pop) - -#pragma warning(push) -#pragma warning(disable : 4793) - void __cdecl operator()(const wchar_t *pszFmt, ...) const - { - va_list ptr; va_start(ptr, pszFmt); - ATL::CTrace::s_trace.TraceV(m_pszFileName, m_nLineNo, atlTraceGeneral, 0, pszFmt, ptr); - va_end(ptr); - } -#pragma warning(pop) - -private: - /* unimplemented */ - CTraceFileAndLineInfo &__cdecl operator=(const CTraceFileAndLineInfo &right); - - const char *const m_pszFileName; - const int m_nLineNo; -}; - -#endif // _DEBUG - -#ifdef _DEBUG - -inline CTraceCategory::CTraceCategory( LPCTSTR pszCategoryName, UINT nStartingLevel ) throw() : - m_dwCategory( 0 ) -{ - m_dwCategory = ATL::CTrace::s_trace.RegisterCategory( pszCategoryName ); - ATL::CTrace::s_trace.ChangeCategory( m_dwCategory, nStartingLevel, ATLTRACESTATUS_INHERIT); -} - -inline CTraceCategory::operator DWORD_PTR() const throw() -{ - return( m_dwCategory ); -} - -inline UINT CTraceCategory::GetLevel() const throw() -{ - UINT nLevel; - ATLTRACESTATUS eStatus; - ATL::CTrace::s_trace.GetCategory( m_dwCategory, &nLevel, &eStatus ); - - return( nLevel ); -} - -inline void CTraceCategory::SetLevel( UINT nLevel ) throw() -{ - ATL::CTrace::s_trace.ChangeCategory( m_dwCategory, nLevel, ATLTRACESTATUS_ENABLED ); -} - -inline ATLTRACESTATUS CTraceCategory::GetStatus() const throw() -{ - UINT nLevel; - ATLTRACESTATUS eStatus; - ATL::CTrace::s_trace.GetCategory( m_dwCategory, &nLevel, &eStatus ); - - return( eStatus ); -} - -inline void CTraceCategory::SetStatus( ATLTRACESTATUS eStatus ) throw() -{ - UINT nLevel; - ATLTRACESTATUS eOldStatus; - ATL::CTrace::s_trace.GetCategory( m_dwCategory, &nLevel, &eOldStatus ); - ATL::CTrace::s_trace.ChangeCategory( m_dwCategory, nLevel, eStatus ); -} - -#else // !_DEBUG - -inline CTraceCategory::CTraceCategory( LPCTSTR pszCategoryName, UINT nStartingLevel ) throw() -{ - (void)pszCategoryName; - (void)nStartingLevel; -} - -inline CTraceCategory::operator DWORD_PTR() const throw() -{ - return( 0 ); -} - -#endif // _DEBUG - -} // namespace ATL - -namespace ATL -{ - -#ifdef _DEBUG -#define DECLARE_TRACE_CATEGORY( name ) extern ATL::CTraceCategory name; -#else -#define DECLARE_TRACE_CATEGORY( name ) const DWORD_PTR name = 0; -#endif - -DECLARE_TRACE_CATEGORY( atlTraceGeneral ) -DECLARE_TRACE_CATEGORY( atlTraceCOM ) -DECLARE_TRACE_CATEGORY( atlTraceQI ) -DECLARE_TRACE_CATEGORY( atlTraceRegistrar ) -DECLARE_TRACE_CATEGORY( atlTraceRefcount ) -DECLARE_TRACE_CATEGORY( atlTraceWindowing ) -DECLARE_TRACE_CATEGORY( atlTraceControls ) -DECLARE_TRACE_CATEGORY( atlTraceHosting ) -DECLARE_TRACE_CATEGORY( atlTraceDBClient ) -DECLARE_TRACE_CATEGORY( atlTraceDBProvider ) -DECLARE_TRACE_CATEGORY( atlTraceSnapin ) -DECLARE_TRACE_CATEGORY( atlTraceNotImpl ) -DECLARE_TRACE_CATEGORY( atlTraceAllocation ) -DECLARE_TRACE_CATEGORY( atlTraceException ) -DECLARE_TRACE_CATEGORY( atlTraceTime ) -DECLARE_TRACE_CATEGORY( atlTraceCache ) -DECLARE_TRACE_CATEGORY( atlTraceStencil ) -DECLARE_TRACE_CATEGORY( atlTraceString ) -DECLARE_TRACE_CATEGORY( atlTraceMap ) -DECLARE_TRACE_CATEGORY( atlTraceUtil ) -DECLARE_TRACE_CATEGORY( atlTraceSecurity ) -DECLARE_TRACE_CATEGORY( atlTraceSync ) -DECLARE_TRACE_CATEGORY( atlTraceISAPI ) - -// atlTraceUser categories are no longer needed. Just declare your own trace category using CTraceCategory. -DECLARE_TRACE_CATEGORY( atlTraceUser ) -DECLARE_TRACE_CATEGORY( atlTraceUser2 ) -DECLARE_TRACE_CATEGORY( atlTraceUser3 ) -DECLARE_TRACE_CATEGORY( atlTraceUser4 ) - -#pragma deprecated( atlTraceUser ) -#pragma deprecated( atlTraceUser2 ) -#pragma deprecated( atlTraceUser3 ) -#pragma deprecated( atlTraceUser4 ) - -#ifdef _DEBUG - -#ifndef _ATL_NO_DEBUG_CRT -class CNoUIAssertHook -{ -public: - CNoUIAssertHook() - { - ATLASSERT( s_pfnPrevHook == NULL ); - s_pfnPrevHook = _CrtSetReportHook(CrtHookProc); - } - ~CNoUIAssertHook() - { - _CrtSetReportHook(s_pfnPrevHook); - s_pfnPrevHook = NULL; - } - -private: - static int __cdecl CrtHookProc(__in int eReportType, __in_z char* pszMessage, __out int* pnRetVal) - { - - if (eReportType == _CRT_ASSERT) - { - ::OutputDebugStringA( "ASSERTION FAILED\n" ); - ::OutputDebugStringA( pszMessage ); - //If caller doesn't want retVal, so be it. - if (pnRetVal != NULL) - { - *pnRetVal = 1; - } - return TRUE; - } - - if (s_pfnPrevHook != NULL) - { - return s_pfnPrevHook(eReportType, pszMessage, pnRetVal); - } - else - { - return FALSE; - } - } - -private: - static _CRT_REPORT_HOOK s_pfnPrevHook; -}; - -__declspec( selectany ) _CRT_REPORT_HOOK CNoUIAssertHook::s_pfnPrevHook = NULL; - -#define DECLARE_NOUIASSERT() ATL::CNoUIAssertHook _g_NoUIAssertHook; - -#endif // _ATL_NO_DEBUG_CRT - -#ifndef ATLTRACE -#define ATLTRACE ATL::CTraceFileAndLineInfo(__FILE__, __LINE__) -#define ATLTRACE2 ATLTRACE -#endif - -#pragma warning(push) -#pragma warning(disable : 4793) -inline void __cdecl AtlTrace(LPCSTR pszFormat, ...) -{ - va_list ptr; - va_start(ptr, pszFormat); - ATL::CTrace::s_trace.TraceV(NULL, -1, atlTraceGeneral, 0, pszFormat, ptr); - va_end(ptr); -} -#pragma warning(pop) - -#pragma warning(push) -#pragma warning(disable : 4793) -inline void __cdecl AtlTrace(LPCWSTR pszFormat, ...) -{ - va_list ptr; - va_start(ptr, pszFormat); - ATL::CTrace::s_trace.TraceV(NULL, -1, atlTraceGeneral, 0, pszFormat, ptr); - va_end(ptr); -} -#pragma warning(pop) - -#pragma warning(push) -#pragma warning(disable : 4793) -inline void __cdecl AtlTrace2(DWORD_PTR dwCategory, UINT nLevel, LPCSTR pszFormat, ...) -{ - va_list ptr; - va_start(ptr, pszFormat); - ATL::CTrace::s_trace.TraceV(NULL, -1, dwCategory, nLevel, pszFormat, ptr); - va_end(ptr); -} -#pragma warning(pop) - -#pragma warning(push) -#pragma warning(disable : 4793) -inline void __cdecl AtlTrace2(DWORD_PTR dwCategory, UINT nLevel, LPCWSTR pszFormat, ...) -{ - va_list ptr; - va_start(ptr, pszFormat); - ATL::CTrace::s_trace.TraceV(NULL, -1, dwCategory, nLevel, pszFormat, ptr); - va_end(ptr); -} -#pragma warning(pop) - -#define ATLTRACENOTIMPL(funcname) do { ATLTRACE(ATL::atlTraceNotImpl, 0, _T("ATL: %s not implemented.\n"), funcname); return E_NOTIMPL; } while(0) - -#else // !DEBUG - -#pragma warning(push) -#pragma warning(disable : 4793) -inline void __cdecl AtlTraceNull(...){} -inline void __cdecl AtlTrace(LPCSTR , ...){} -inline void __cdecl AtlTrace2(DWORD_PTR, UINT, LPCSTR , ...){} -inline void __cdecl AtlTrace(LPCWSTR , ...){} -inline void __cdecl AtlTrace2(DWORD_PTR, UINT, LPCWSTR , ...){} -#pragma warning(pop) - -#ifndef ATLTRACE - -#define ATLTRACE __noop -#define ATLTRACE2 __noop -#endif //ATLTRACE -#define ATLTRACENOTIMPL(funcname) return E_NOTIMPL -#define DECLARE_NOUIASSERT() - -#endif //!_DEBUG - -}; // namespace ATL -#pragma pack(pop) - -#endif // __ATLTRACE_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlwin.h b/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlwin.h deleted file mode 100644 index 20178a8c2..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/atlwin.h +++ /dev/null @@ -1,4728 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef _ATL_NO_PRAGMA_WARNINGS -#pragma warning (push) -#pragma warning(disable : 4668) // is not defined as a preprocessor macro, replacing with '0' for '#if/#elif -#pragma warning(disable : 4820) // padding added after member -#pragma warning(disable : 4571) //catch(...) blocks compiled with /EHs do NOT catch or re-throw Structured Exceptions -#endif //!_ATL_NO_PRAGMA_WARNINGS - -#ifndef __ATLWIN_H__ -#define __ATLWIN_H__ - -#pragma once - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#ifndef __ATLBASE_H__ - #error atlwin.h requires atlbase.h to be included first -#endif - -#include -#include -#include - -// protect template members from windowsx.h macros -#ifdef _INC_WINDOWSX -#undef SubclassWindow -#endif //_INC_WINDOWSX - -#ifdef SetWindowLongPtrA -#undef SetWindowLongPtrA -inline LONG_PTR SetWindowLongPtrA( HWND hWnd, int nIndex, LONG_PTR dwNewLong ) -{ - return( ::SetWindowLongA( hWnd, nIndex, LONG( dwNewLong ) ) ); -} -#endif - -#ifdef SetWindowLongPtrW -#undef SetWindowLongPtrW -inline LONG_PTR SetWindowLongPtrW( HWND hWnd, int nIndex, LONG_PTR dwNewLong ) -{ - return( ::SetWindowLongW( hWnd, nIndex, LONG( dwNewLong ) ) ); -} -#endif - -#ifdef GetWindowLongPtrA -#undef GetWindowLongPtrA -inline LONG_PTR GetWindowLongPtrA( HWND hWnd, int nIndex ) -{ - return( ::GetWindowLongA( hWnd, nIndex ) ); -} -#endif - -#ifdef GetWindowLongPtrW -#undef GetWindowLongPtrW -inline LONG_PTR GetWindowLongPtrW( HWND hWnd, int nIndex ) -{ - return( ::GetWindowLongW( hWnd, nIndex ) ); -} -#endif - -#ifndef _ATL_NO_DEFAULT_LIBS -#pragma comment(lib, "gdi32.lib") -#endif // !_ATL_NO_DEFAULT_LIBS - -#pragma pack(push,_ATL_PACKING) -namespace ATL -{ -//#endif - -///////////////////////////////////////////////////////////////////////////// -// Dual argument helper classes - -class _U_RECT -{ -public: - _U_RECT(LPRECT lpRect) : m_lpRect(lpRect) - { } - _U_RECT(RECT& rc) : m_lpRect(&rc) - { } - LPRECT m_lpRect; -}; - -class _U_MENUorID -{ -public: - _U_MENUorID(HMENU hMenu) : m_hMenu(hMenu) - { } - _U_MENUorID(UINT nID) : m_hMenu((HMENU)(UINT_PTR)nID) - { } - HMENU m_hMenu; -}; - -class _U_STRINGorID -{ -public: - _U_STRINGorID(LPCTSTR lpString) : m_lpstr(lpString) - { } - _U_STRINGorID(UINT nID) : m_lpstr(MAKEINTRESOURCE(nID)) - { } - LPCTSTR m_lpstr; -}; - -struct _ATL_WNDCLASSINFOA; -struct _ATL_WNDCLASSINFOW; - -ATLAPIINL_(ATOM) AtlWinModuleRegisterWndClassInfoA(_ATL_WIN_MODULE* pWinModule, _ATL_BASE_MODULE* pBaseModule, _ATL_WNDCLASSINFOA* p, WNDPROC* pProc); -inline ATOM AtlModuleRegisterWndClassInfoA(_ATL_MODULE* /*pM*/, _ATL_WNDCLASSINFOA* p, WNDPROC* pProc) -{ - return AtlWinModuleRegisterWndClassInfoA(&_AtlWinModule, &_AtlBaseModule, p, pProc); -} - -ATLAPIINL_(ATOM) AtlWinModuleRegisterWndClassInfoW(_ATL_WIN_MODULE* pWinModule, _ATL_BASE_MODULE* pBaseModule, _ATL_WNDCLASSINFOW* p, WNDPROC* pProc); -inline ATOM AtlModuleRegisterWndClassInfoW(_ATL_MODULE* /*pM*/, _ATL_WNDCLASSINFOW* p, WNDPROC* pProc) -{ - return AtlWinModuleRegisterWndClassInfoW(&_AtlWinModule, &_AtlBaseModule, p, pProc); -} - -ATLAPIINL_(ATOM) AtlWinModuleRegisterClassExA(_ATL_WIN_MODULE* pWinModule, const WNDCLASSEXA *lpwc); -inline ATOM AtlModuleRegisterClassExA(_ATL_MODULE* /*pM*/, const WNDCLASSEXA *lpwc) -{ - return AtlWinModuleRegisterClassExA(&_AtlWinModule, lpwc); -} - -ATLAPIINL_(ATOM) AtlWinModuleRegisterClassExW(_ATL_WIN_MODULE* pWinModule, const WNDCLASSEXW *lpwc); -inline ATOM AtlModuleRegisterClassExW(_ATL_MODULE* /*pM*/, const WNDCLASSEXW *lpwc) -{ - return AtlWinModuleRegisterClassExW(&_AtlWinModule, lpwc); -} - - -#ifdef UNICODE -#define AtlWinModuleRegisterWndClassInfo AtlWinModuleRegisterWndClassInfoW -#define AtlWinModuleRegisterClassEx AtlWinModuleRegisterClassExW -#define AtlModuleRegisterWndClassInfo AtlModuleRegisterWndClassInfoW -#define AtlModuleRegisterClassEx AtlModuleRegisterClassExW -#else -#define AtlWinModuleRegisterWndClassInfo AtlWinModuleRegisterWndClassInfoA -#define AtlWinModuleRegisterClassEx AtlWinModuleRegisterClassExA -#define AtlModuleRegisterWndClassInfo AtlModuleRegisterWndClassInfoA -#define AtlModuleRegisterClassEx AtlModuleRegisterClassExA -#endif - - -#define HIMETRIC_PER_INCH 2540 -#define MAP_PIX_TO_LOGHIM(x,ppli) MulDiv(HIMETRIC_PER_INCH, (x), (ppli)) -#define MAP_LOGHIM_TO_PIX(x,ppli) MulDiv((ppli), (x), HIMETRIC_PER_INCH) - -ATLAPI_(HDC) AtlCreateTargetDC(HDC hdc, DVTARGETDEVICE* ptd); -ATLAPI_(void) AtlHiMetricToPixel(const SIZEL * lpSizeInHiMetric, LPSIZEL lpSizeInPix); -ATLAPI_(void) AtlPixelToHiMetric(const SIZEL * lpSizeInPix, LPSIZEL lpSizeInHiMetric); - -#ifndef GET_X_LPARAM -#define GET_X_LPARAM(lParam) ((int)(short)LOWORD(lParam)) -#endif -#ifndef GET_Y_LPARAM -#define GET_Y_LPARAM(lParam) ((int)(short)HIWORD(lParam)) -#endif - - -}; //namespace ATL -//#endif - - - -namespace ATL -{ - -///////////////////////////////////////////////////////////////////////////// -// _ATL_MSG - extended MSG structure - -struct _ATL_MSG : public MSG -{ -public: -// Additional data members - int cbSize; - BOOL bHandled; - -// Constructors - _ATL_MSG() : cbSize(sizeof(_ATL_MSG)), bHandled(TRUE) - { - hwnd = NULL; - message = 0; - wParam = 0; - lParam = 0; - time = 0; - pt.x = pt.y = 0; - } - _ATL_MSG(HWND hWnd, UINT uMsg, WPARAM wParamIn, LPARAM lParamIn, DWORD dwTime, POINT ptIn, BOOL bHandledIn) : cbSize(sizeof(_ATL_MSG)), bHandled(bHandledIn) - { - hwnd = hWnd; - message = uMsg; - wParam = wParamIn; - lParam = lParamIn; - time = dwTime; - pt = ptIn; - } - _ATL_MSG(HWND hWnd, UINT uMsg, WPARAM wParamIn, LPARAM lParamIn, BOOL bHandledIn = TRUE) : cbSize(sizeof(_ATL_MSG)), bHandled(bHandledIn) - { - hwnd = hWnd; - message = uMsg; - wParam = wParamIn; - lParam = lParamIn; - time = 0; - pt.x = pt.y = 0; - } - _ATL_MSG(MSG& msg, BOOL bHandledIn = TRUE) : cbSize(sizeof(_ATL_MSG)), bHandled(bHandledIn) - { - hwnd = msg.hwnd; - message = msg.message; - wParam = msg.wParam; - lParam = msg.lParam; - time = msg.time; - pt = msg.pt; - } -}; - -struct _ATL_WNDCLASSINFOA -{ - WNDCLASSEXA m_wc; - LPCSTR m_lpszOrigName; - WNDPROC pWndProc; - LPCSTR m_lpszCursorID; - BOOL m_bSystemCursor; - ATOM m_atom; - CHAR m_szAutoName[5+sizeof(void*)*CHAR_BIT]; - ATOM Register(WNDPROC* p) - { - return AtlWinModuleRegisterWndClassInfoA(&_AtlWinModule, &_AtlBaseModule, this, p); - } -}; - -struct _ATL_WNDCLASSINFOW -{ - WNDCLASSEXW m_wc; - LPCWSTR m_lpszOrigName; - WNDPROC pWndProc; - LPCWSTR m_lpszCursorID; - BOOL m_bSystemCursor; - ATOM m_atom; - WCHAR m_szAutoName[5+sizeof(void*)*CHAR_BIT]; - ATOM Register(WNDPROC* p) - { - return AtlWinModuleRegisterWndClassInfoW(&_AtlWinModule, &_AtlBaseModule, this, p); - } -}; - -}; // namespace ATL - - - -namespace ATL -{ - -///////////////////////////////////////////////////////////////////////////// -// Forward declarations - -class CWindow; -#ifndef _ATL_NO_HOSTING -template class CAxWindowT; -template class CAxWindow2T; -#endif //!_ATL_NO_HOSTING -class CMessageMap; -class CDynamicChain; -typedef _ATL_WNDCLASSINFOA CWndClassInfoA; -typedef _ATL_WNDCLASSINFOW CWndClassInfoW; -#ifdef UNICODE -#define CWndClassInfo CWndClassInfoW -#else -#define CWndClassInfo CWndClassInfoA -#endif -template class CWindowImpl; -template class CWindowWithReflectorImpl; -template class CDialogImpl; -#ifndef _ATL_NO_HOSTING -template class CAxDialogImpl; -#endif //!_ATL_NO_HOSTING -template class CSimpleDialog; -template class CContainedWindowT; - -///////////////////////////////////////////////////////////////////////////// -// Helper functions for cracking dialog templates - -class _DialogSplitHelper -{ -public: - // Constants used in DLGINIT resources for OLE control containers - // NOTE: These are NOT real Windows messages they are simply tags - // used in the control resource and are never used as 'messages' - enum - { - ATL_WM_OCC_LOADFROMSTREAM = 0x0376, - ATL_WM_OCC_LOADFROMSTORAGE = 0x0377, - ATL_WM_OCC_INITNEW = 0x0378, - ATL_WM_OCC_LOADFROMSTREAM_EX = 0x037A, - ATL_WM_OCC_LOADFROMSTORAGE_EX = 0x037B, - ATL_DISPID_DATASOURCE = 0x80010001, - ATL_DISPID_DATAFIELD = 0x80010002, - }; - -//local struct used for implementation -#pragma pack(push, 1) - struct DLGINITSTRUCT - { - WORD nIDC; - WORD message; - DWORD dwSize; - }; - struct DLGTEMPLATEEX - { - WORD dlgVer; - WORD signature; - DWORD helpID; - DWORD exStyle; - DWORD style; - WORD cDlgItems; - short x; - short y; - short cx; - short cy; - - // Everything else in this structure is variable length, - // and therefore must be determined dynamically - - // sz_Or_Ord menu; // name or ordinal of a menu resource - // sz_Or_Ord windowClass; // name or ordinal of a window class - // WCHAR title[titleLen]; // title string of the dialog box - // short pointsize; // only if DS_SETFONT is set - // short weight; // only if DS_SETFONT is set - // short bItalic; // only if DS_SETFONT is set - // WCHAR font[fontLen]; // typeface name, if DS_SETFONT is set - }; - struct DLGITEMTEMPLATEEX - { - DWORD helpID; - DWORD exStyle; - DWORD style; - short x; - short y; - short cx; - short cy; - DWORD id; - - // Everything else in this structure is variable length, - // and therefore must be determined dynamically - - // sz_Or_Ord windowClass; // name or ordinal of a window class - // sz_Or_Ord title; // title string or ordinal of a resource - // WORD extraCount; // bytes following creation data - }; -#pragma pack(pop) - - static BOOL IsDialogEx(const DLGTEMPLATE* pTemplate) - { - return ((DLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF; - } - - inline static WORD& DlgTemplateItemCount(DLGTEMPLATE* pTemplate) - { - if (IsDialogEx(pTemplate)) - return reinterpret_cast(pTemplate)->cDlgItems; - else - return pTemplate->cdit; - } - - inline static const WORD& DlgTemplateItemCount(const DLGTEMPLATE* pTemplate) - { - if (IsDialogEx(pTemplate)) - return reinterpret_cast(pTemplate)->cDlgItems; - else - return pTemplate->cdit; - } - - static DLGITEMTEMPLATE* FindFirstDlgItem(const DLGTEMPLATE* pTemplate) - { - BOOL bDialogEx = IsDialogEx(pTemplate); - - WORD* pw; - DWORD dwStyle; - if (bDialogEx) - { - pw = (WORD*)((DLGTEMPLATEEX*)pTemplate + 1); - dwStyle = ((DLGTEMPLATEEX*)pTemplate)->style; - } - else - { - pw = (WORD*)(pTemplate + 1); - dwStyle = pTemplate->style; - } - - // Check for presence of menu and skip it if there is one - // 0x0000 means there is no menu - // 0xFFFF means there is a menu ID following - // Everything else means that this is a NULL terminated Unicode string - // which identifies the menu resource - if (*pw == 0xFFFF) - pw += 2; // Has menu ID, so skip 2 words - else - while (*pw++); // Either No menu, or string, skip past terminating NULL - - // Check for presence of class name string - // 0x0000 means "Use system dialog class name" - // 0xFFFF means there is a window class (atom) specified - // Everything else means that this is a NULL terminated Unicode string - // which identifies the menu resource - if (*pw == 0xFFFF) - pw += 2; // Has class atom, so skip 2 words - else - while (*pw++); // Either No class, or string, skip past terminating NULL - - // Skip caption string - while (*pw++); - - // If we have DS_SETFONT, there is extra font information which we must now skip - if (dwStyle & DS_SETFONT) - { - // If it is a regular DLGTEMPLATE there is only a short for the point size - // and a string specifying the font (typefacename). If this is a DLGTEMPLATEEX - // then there is also the font weight, and bItalic which must be skipped - if (bDialogEx) - pw += 3; // Skip font size, weight, (italic, charset) - else - pw += 1; // Skip font size - while (*pw++); // Skip typeface name - } - - // Dword-align and return - return (DLGITEMTEMPLATE*)(((DWORD_PTR)pw + 3) & ~3); - } - - // Given the current dialog item and whether this is an extended dialog - // return a pointer to the next DLGITEMTEMPLATE* - static DLGITEMTEMPLATE* FindNextDlgItem(DLGITEMTEMPLATE* pItem, BOOL bDialogEx) - { - WORD* pw; - - // First skip fixed size header information, size of which depends - // if this is a DLGITEMTEMPLATE or DLGITEMTEMPLATEEX - if (bDialogEx) - pw = (WORD*)((DLGITEMTEMPLATEEX*)pItem + 1); - else - pw = (WORD*)(pItem + 1); - - if (*pw == 0xFFFF) // Skip class name ordinal or string - pw += 2; // (WORDs) - else - while (*pw++); - - if (*pw == 0xFFFF) // Skip title ordinal or string - pw += 2; // (WORDs) - else - while (*pw++); - - WORD cbExtra = *pw++; // Skip extra data - - // cbExtra includes the size WORD in DIALOG resource. - if (cbExtra != 0 && !bDialogEx) - cbExtra -= 2; - - // Dword-align and return - return (DLGITEMTEMPLATE*)(((DWORD_PTR)pw + cbExtra + 3) & ~3); - } - - // Find the initialization data (Stream) for the control specified by the ID - // If found, return the pointer into the data and the length of the data - static DWORD FindCreateData(DWORD dwID, BYTE* pInitData, BYTE** pData) - { - while (pInitData) - { - // Read the DLGINIT header - WORD nIDC = *((UNALIGNED WORD*)pInitData); - pInitData += sizeof(WORD); - BYTE* pTemp = pInitData; - WORD nMsg = *((UNALIGNED WORD*)pInitData); - pInitData += sizeof(WORD); - DWORD dwLen = *((UNALIGNED DWORD*)pInitData); - pInitData += sizeof(DWORD); - - // If the header is for the control specified get the other info - if (nIDC == dwID) - { - if (nMsg == (WORD)ATL_WM_OCC_INITNEW) - { - ATLASSERT(dwLen == 0); - return 0; - } - *pData = pTemp; - return dwLen + sizeof(WORD) + sizeof(DWORD); - } - - // It's not the right control, skip past data - pInitData += dwLen; - } - return 0; - } - - static bool IsActiveXControl(DLGITEMTEMPLATE* pItem, BOOL bDialogEx) - { - LPWSTR pszClassName; - pszClassName = bDialogEx ? - (LPWSTR)(((DLGITEMTEMPLATEEX*)pItem) + 1) : - (LPWSTR)(pItem + 1); - if (pszClassName[0] == L'{') - return true; - return false; - } - - // Convert MSDEV (MFC) style DLGTEMPLATE with controls to regular DLGTEMPLATE - static DLGTEMPLATE* SplitDialogTemplate(DLGTEMPLATE* pTemplate, BYTE* /*pInitData*/) - { - // Calculate the size of the DLGTEMPLATE for allocating the new one - DLGITEMTEMPLATE* pFirstItem = FindFirstDlgItem(pTemplate); - ULONG_PTR cbHeader = (BYTE*)pFirstItem - (BYTE*)pTemplate; - ULONG_PTR cbNewTemplate = cbHeader; - - BOOL bDialogEx = IsDialogEx(pTemplate); - - int iItem; - int nItems = (int)DlgTemplateItemCount(pTemplate); - LPWSTR pszClassName; - BOOL bHasOleControls = FALSE; - - // Make first pass through the dialog template. On this pass, we're - // interested in determining: - // 1. Does this template contain any ActiveX Controls? - // 2. If so, how large a buffer is needed for a template containing - // only the non-OLE controls? - - DLGITEMTEMPLATE* pItem = pFirstItem; - DLGITEMTEMPLATE* pNextItem = pItem; - for (iItem = 0; iItem < nItems; iItem++) - { - pNextItem = FindNextDlgItem(pItem, bDialogEx); - - pszClassName = bDialogEx ? - (LPWSTR)(((DLGITEMTEMPLATEEX*)pItem) + 1) : - (LPWSTR)(pItem + 1); - - // Check if the class name begins with a '{' - // If it does, that means it is an ActiveX Control in MSDEV (MFC) format - if (pszClassName[0] == L'{') - { - // Item is an ActiveX control. - bHasOleControls = TRUE; - } - else - { - // Item is not an ActiveX Control: make room for it in new template. - cbNewTemplate += (BYTE*)pNextItem - (BYTE*)pItem; - } - - pItem = pNextItem; - } - - // No OLE controls were found, so there's no reason to go any further. - if (!bHasOleControls) - return pTemplate; - - // Copy entire header into new template. - BYTE* pNew = (BYTE*)GlobalAlloc(GMEM_FIXED, cbNewTemplate); - DLGTEMPLATE* pNewTemplate = (DLGTEMPLATE*)pNew; - Checked::memcpy_s(pNew, cbNewTemplate, pTemplate, cbHeader); - pNew += cbHeader; - -#if _SECURE_ATL - ULONG_PTR cbNewTemplateLast = cbNewTemplate; - cbNewTemplate -= cbHeader; - ATLENSURE(cbNewTemplate <= cbNewTemplateLast); -#endif - - // Initialize item count in new header to zero. - DlgTemplateItemCount(pNewTemplate) = 0; - - pItem = pFirstItem; - pNextItem = pItem; - - // Second pass through the dialog template. On this pass, we want to: - // 1. Copy all the non-OLE controls into the new template. - for (iItem = 0; iItem < nItems; iItem++) - { - pNextItem = FindNextDlgItem(pItem, bDialogEx); - - pszClassName = bDialogEx ? - (LPWSTR)(((DLGITEMTEMPLATEEX*)pItem) + 1) : - (LPWSTR)(pItem + 1); - - if (pszClassName[0] != L'{') - { - // Item is not an OLE control: copy it to the new template. - ULONG_PTR cbItem = (BYTE*)pNextItem - (BYTE*)pItem; - ATLASSERT(cbItem >= (bDialogEx ? - sizeof(DLGITEMTEMPLATEEX) : - sizeof(DLGITEMTEMPLATE))); - Checked::memcpy_s(pNew, cbNewTemplate, pItem, cbItem); - pNew += cbItem; -#if _SECURE_ATL - cbNewTemplateLast = cbNewTemplate; - cbNewTemplate -= cbItem; - ATLENSURE(cbNewTemplate <= cbNewTemplateLast); -#endif - - // Incrememt item count in new header. - ++DlgTemplateItemCount(pNewTemplate); - } - - pItem = pNextItem; - } - return pNewTemplate; - } - - static HRESULT ParseInitData(IStream* pStream, BSTR* pLicKey) - { - *pLicKey = NULL; - if(pStream == NULL) - return S_OK; // nothing to do - - ULONG uRead; - HRESULT hr; - - WORD nMsg; - hr = pStream->Read(&nMsg, sizeof(WORD), &uRead); - if (FAILED(hr)) - return hr; - - DWORD dwLen; - hr = pStream->Read(&dwLen, sizeof(DWORD), &uRead); - if (FAILED(hr)) - return hr; - - DWORD cchLicKey; - hr = pStream->Read(&cchLicKey, sizeof(DWORD), &uRead); - if (FAILED(hr)) - return hr; - - if (cchLicKey > 0) - { - CComBSTR bstr(cchLicKey); - if (bstr.Length() == 0) - return E_OUTOFMEMORY; - memset(bstr.m_str, 0, (cchLicKey + 1) * sizeof(OLECHAR)); - hr = pStream->Read(bstr.m_str, cchLicKey * sizeof(OLECHAR), &uRead); - if (FAILED(hr)) - return hr; - *pLicKey = bstr.Detach(); - } - - // Extended (DATABINDING) stream format is not supported, - // we reject databinding info but preserve other information - if (nMsg == (WORD)ATL_WM_OCC_LOADFROMSTREAM_EX || - nMsg == (WORD)ATL_WM_OCC_LOADFROMSTORAGE_EX) - { - // Read the size of the section - ULONG cbOffset; - hr = pStream->Read(&cbOffset, sizeof(ULONG), &uRead); - if (FAILED(hr)) - return hr; - BYTE pTemp[1000]; - cbOffset -= sizeof(ULONG); - - while (cbOffset > 0) - { - pStream->Read(pTemp, (cbOffset < 1000 ? cbOffset : 1000), &uRead); - cbOffset -= uRead; - } - return S_OK; - } - if (nMsg == (WORD)ATL_WM_OCC_LOADFROMSTREAM) - { - return S_OK; - } - return E_FAIL; - } -}; - -///////////////////////////////////////////////////////////////////////////// -// CWindow - client side for a Windows window - -class CWindow -{ -public: - static RECT rcDefault; - HWND m_hWnd; - - CWindow(HWND hWnd = NULL) throw() : - m_hWnd(hWnd) - { - } - - CWindow& operator=(HWND hWnd) throw() - { - m_hWnd = hWnd; - return *this; - } - - static LPCTSTR GetWndClassName() throw() - { - return NULL; - } - - void Attach(HWND hWndNew) throw() - { - ATLASSUME(m_hWnd == NULL); - ATLASSERT((hWndNew == NULL) || ::IsWindow(hWndNew)); - m_hWnd = hWndNew; - } - - HWND Detach() throw() - { - HWND hWnd = m_hWnd; - m_hWnd = NULL; - return hWnd; - } - - HWND Create(LPCTSTR lpstrWndClass, HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) throw() - { - ATLASSUME(m_hWnd == NULL); - if(rect.m_lpRect == NULL) - rect.m_lpRect = &rcDefault; - m_hWnd = ::CreateWindowEx(dwExStyle, lpstrWndClass, szWindowName, - dwStyle, rect.m_lpRect->left, rect.m_lpRect->top, rect.m_lpRect->right - rect.m_lpRect->left, - rect.m_lpRect->bottom - rect.m_lpRect->top, hWndParent, MenuOrID.m_hMenu, - _AtlBaseModule.GetModuleInstance(), lpCreateParam); - return m_hWnd; - } - - BOOL DestroyWindow() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - - if(!::DestroyWindow(m_hWnd)) - return FALSE; - - m_hWnd = NULL; - return TRUE; - } - -// Attributes - - operator HWND() const throw() - { - return m_hWnd; - } - - DWORD GetStyle() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::GetWindowLong(m_hWnd, GWL_STYLE); - } - - DWORD GetExStyle() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::GetWindowLong(m_hWnd, GWL_EXSTYLE); - } - - LONG GetWindowLong(int nIndex) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetWindowLong(m_hWnd, nIndex); - } - - LONG_PTR GetWindowLongPtr(int nIndex) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetWindowLongPtr(m_hWnd, nIndex); - } - - LONG SetWindowLong(int nIndex, LONG dwNewLong) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetWindowLong(m_hWnd, nIndex, dwNewLong); - } - - LONG_PTR SetWindowLongPtr(int nIndex, LONG_PTR dwNewLong) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetWindowLongPtr(m_hWnd, nIndex, dwNewLong); - } - - WORD GetWindowWord(int nIndex) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetWindowWord(m_hWnd, nIndex); - } - - WORD SetWindowWord(int nIndex, WORD wNewWord) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetWindowWord(m_hWnd, nIndex, wNewWord); - } - -// Message Functions - - LRESULT SendMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SendMessage(m_hWnd,message,wParam,lParam); - } - - BOOL PostMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::PostMessage(m_hWnd,message,wParam,lParam); - } - - BOOL SendNotifyMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SendNotifyMessage(m_hWnd, message, wParam, lParam); - } - - // support for C style macros - static LRESULT SendMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) throw() - { - ATLASSERT(::IsWindow(hWnd)); - return ::SendMessage(hWnd, message, wParam, lParam); - } - -// Window Text Functions - - BOOL SetWindowText(LPCTSTR lpszString) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetWindowText(m_hWnd, lpszString); - } - - int GetWindowText(__out_ecount_part_z(nMaxCount, return + 1) LPTSTR lpszStringBuf, __in int nMaxCount) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetWindowText(m_hWnd, lpszStringBuf, nMaxCount); - } - int GetWindowText(CSimpleString& strText) const - { - int nLength; - LPTSTR pszText; - - nLength = GetWindowTextLength(); - pszText = strText.GetBuffer(nLength+1); - nLength = GetWindowText(pszText, nLength+1); - strText.ReleaseBuffer(nLength); - - return nLength; - } - int GetWindowTextLength() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetWindowTextLength(m_hWnd); - } - -// Font Functions - - void SetFont(HFONT hFont, BOOL bRedraw = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(bRedraw, 0)); - } - - HFONT GetFont() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HFONT)::SendMessage(m_hWnd, WM_GETFONT, 0, 0); - } - -// Menu Functions (non-child windows only) - - HMENU GetMenu() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HMENU)::GetMenu(m_hWnd); - } - - BOOL SetMenu(HMENU hMenu) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetMenu(m_hWnd, hMenu); - } - - BOOL DrawMenuBar() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::DrawMenuBar(m_hWnd); - } - - HMENU GetSystemMenu(BOOL bRevert) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HMENU)::GetSystemMenu(m_hWnd, bRevert); - } - - BOOL HiliteMenuItem(HMENU hMenu, UINT uItemHilite, UINT uHilite) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::HiliteMenuItem(m_hWnd, hMenu, uItemHilite, uHilite); - } - -// Window Size and Position Functions - - BOOL IsIconic() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::IsIconic(m_hWnd); - } - - BOOL IsZoomed() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::IsZoomed(m_hWnd); - } - - BOOL MoveWindow(int x, int y, int nWidth, int nHeight, BOOL bRepaint = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::MoveWindow(m_hWnd, x, y, nWidth, nHeight, bRepaint); - } - - BOOL MoveWindow(LPCRECT lpRect, BOOL bRepaint = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::MoveWindow(m_hWnd, lpRect->left, lpRect->top, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top, bRepaint); - } - - BOOL SetWindowPos(HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetWindowPos(m_hWnd, hWndInsertAfter, x, y, cx, cy, nFlags); - } - - BOOL SetWindowPos(HWND hWndInsertAfter, LPCRECT lpRect, UINT nFlags) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetWindowPos(m_hWnd, hWndInsertAfter, lpRect->left, lpRect->top, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top, nFlags); - } - - UINT ArrangeIconicWindows() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ArrangeIconicWindows(m_hWnd); - } - - BOOL BringWindowToTop() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::BringWindowToTop(m_hWnd); - } - - BOOL GetWindowRect(LPRECT lpRect) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetWindowRect(m_hWnd, lpRect); - } - - BOOL GetClientRect(LPRECT lpRect) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetClientRect(m_hWnd, lpRect); - } - - BOOL GetWindowPlacement(WINDOWPLACEMENT FAR* lpwndpl) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetWindowPlacement(m_hWnd, lpwndpl); - } - - BOOL SetWindowPlacement(const WINDOWPLACEMENT FAR* lpwndpl) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetWindowPlacement(m_hWnd, lpwndpl); - } - -// Coordinate Mapping Functions - - BOOL ClientToScreen(LPPOINT lpPoint) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ClientToScreen(m_hWnd, lpPoint); - } - - BOOL ClientToScreen(LPRECT lpRect) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - if(!::ClientToScreen(m_hWnd, (LPPOINT)lpRect)) - return FALSE; - return ::ClientToScreen(m_hWnd, ((LPPOINT)lpRect)+1); - } - - BOOL ScreenToClient(LPPOINT lpPoint) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ScreenToClient(m_hWnd, lpPoint); - } - - BOOL ScreenToClient(LPRECT lpRect) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - if(!::ScreenToClient(m_hWnd, (LPPOINT)lpRect)) - return FALSE; - return ::ScreenToClient(m_hWnd, ((LPPOINT)lpRect)+1); - } - - int MapWindowPoints(HWND hWndTo, LPPOINT lpPoint, UINT nCount) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::MapWindowPoints(m_hWnd, hWndTo, lpPoint, nCount); - } - - int MapWindowPoints(HWND hWndTo, LPRECT lpRect) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::MapWindowPoints(m_hWnd, hWndTo, (LPPOINT)lpRect, 2); - } - -// Update and Painting Functions - - HDC BeginPaint(LPPAINTSTRUCT lpPaint) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::BeginPaint(m_hWnd, lpPaint); - } - - void EndPaint(LPPAINTSTRUCT lpPaint) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::EndPaint(m_hWnd, lpPaint); - } - - HDC GetDC() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetDC(m_hWnd); - } - - HDC GetWindowDC() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetWindowDC(m_hWnd); - } - - int ReleaseDC(HDC hDC) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ReleaseDC(m_hWnd, hDC); - } - - void Print(HDC hDC, DWORD dwFlags) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_PRINT, (WPARAM)hDC, dwFlags); - } - - void PrintClient(HDC hDC, DWORD dwFlags) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_PRINTCLIENT, (WPARAM)hDC, dwFlags); - } - - BOOL UpdateWindow() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::UpdateWindow(m_hWnd); - } - - void SetRedraw(BOOL bRedraw = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_SETREDRAW, (WPARAM)bRedraw, 0); - } - - BOOL GetUpdateRect(LPRECT lpRect, BOOL bErase = FALSE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetUpdateRect(m_hWnd, lpRect, bErase); - } - - int GetUpdateRgn(HRGN hRgn, BOOL bErase = FALSE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetUpdateRgn(m_hWnd, hRgn, bErase); - } - - BOOL Invalidate(BOOL bErase = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::InvalidateRect(m_hWnd, NULL, bErase); - } - - BOOL InvalidateRect(LPCRECT lpRect, BOOL bErase = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::InvalidateRect(m_hWnd, lpRect, bErase); - } - - BOOL ValidateRect(LPCRECT lpRect) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ValidateRect(m_hWnd, lpRect); - } - - void InvalidateRgn(HRGN hRgn, BOOL bErase = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::InvalidateRgn(m_hWnd, hRgn, bErase); - } - - BOOL ValidateRgn(HRGN hRgn) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ValidateRgn(m_hWnd, hRgn); - } - - BOOL ShowWindow(int nCmdShow) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ShowWindow(m_hWnd, nCmdShow); - } - - BOOL IsWindowVisible() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::IsWindowVisible(m_hWnd); - } - - BOOL ShowOwnedPopups(BOOL bShow = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ShowOwnedPopups(m_hWnd, bShow); - } - - HDC GetDCEx(HRGN hRgnClip, DWORD flags) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetDCEx(m_hWnd, hRgnClip, flags); - } - - BOOL LockWindowUpdate(BOOL bLock = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::LockWindowUpdate(bLock ? m_hWnd : NULL); - } - - BOOL RedrawWindow(LPCRECT lpRectUpdate = NULL, HRGN hRgnUpdate = NULL, UINT flags = RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::RedrawWindow(m_hWnd, lpRectUpdate, hRgnUpdate, flags); - } - -// Timer Functions - - UINT_PTR SetTimer(UINT_PTR nIDEvent, UINT nElapse, void (CALLBACK* lpfnTimer)(HWND, UINT, UINT_PTR, DWORD) = NULL) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetTimer(m_hWnd, nIDEvent, nElapse, (TIMERPROC)lpfnTimer); - } - - BOOL KillTimer(UINT_PTR nIDEvent) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::KillTimer(m_hWnd, nIDEvent); - } - -// Window State Functions - - BOOL IsWindowEnabled() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::IsWindowEnabled(m_hWnd); - } - - BOOL EnableWindow(BOOL bEnable = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::EnableWindow(m_hWnd, bEnable); - } - - HWND SetActiveWindow() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetActiveWindow(m_hWnd); - } - - HWND SetCapture() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetCapture(m_hWnd); - } - - HWND SetFocus() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetFocus(m_hWnd); - } - -// Dialog-Box Item Functions - - BOOL CheckDlgButton(int nIDButton, UINT nCheck) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::CheckDlgButton(m_hWnd, nIDButton, nCheck); - } - - BOOL CheckRadioButton(int nIDFirstButton, int nIDLastButton, int nIDCheckButton) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::CheckRadioButton(m_hWnd, nIDFirstButton, nIDLastButton, nIDCheckButton); - } - - int DlgDirList(__inout_z LPTSTR lpPathSpec, __in int nIDListBox, __in int nIDStaticPath, __in UINT nFileType) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::DlgDirList(m_hWnd, lpPathSpec, nIDListBox, nIDStaticPath, nFileType); - } - - int DlgDirListComboBox(__inout_z LPTSTR lpPathSpec, __in int nIDComboBox, __in int nIDStaticPath, __in UINT nFileType) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::DlgDirListComboBox(m_hWnd, lpPathSpec, nIDComboBox, nIDStaticPath, nFileType); - } - - BOOL DlgDirSelect(__out_ecount_z(nCount) LPTSTR lpString, __in int nCount, __in int nIDListBox) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::DlgDirSelectEx(m_hWnd, lpString, nCount, nIDListBox); - } - - BOOL DlgDirSelectComboBox(__out_ecount_z(nCount) LPTSTR lpString, __in int nCount, __in int nIDComboBox) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::DlgDirSelectComboBoxEx(m_hWnd, lpString, nCount, nIDComboBox); - } - - UINT GetDlgItemInt(int nID, BOOL* lpTrans = NULL, BOOL bSigned = TRUE) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetDlgItemInt(m_hWnd, nID, lpTrans, bSigned); - } - - UINT GetDlgItemText(__in int nID, __out_ecount_part_z(nMaxCount, return + 1) LPTSTR lpStr, __in int nMaxCount) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetDlgItemText(m_hWnd, nID, lpStr, nMaxCount); - } - - UINT GetDlgItemText(int nID, CSimpleString& strText) const - { - HWND hItem; - - ATLASSERT(::IsWindow(m_hWnd)); - hItem = GetDlgItem(nID); - if (hItem != NULL) - { - int nLength; - LPTSTR pszText; - - nLength = ::GetWindowTextLength(hItem); - pszText = strText.GetBuffer(nLength+1); - nLength = ::GetWindowText(hItem, pszText, nLength+1); - strText.ReleaseBuffer(nLength); - - return nLength; - } - else - { - strText.Empty(); - - return 0; - } - } -#ifdef _OLEAUTO_H_ - BOOL GetDlgItemText(int nID, BSTR& bstrText) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - - HWND hWndCtl = GetDlgItem(nID); - if(hWndCtl == NULL) - return FALSE; - - return CWindow(hWndCtl).GetWindowText(bstrText); - } -#endif // _OLEAUTO_H_ - CWindow GetNextDlgGroupItem(HWND hWndCtl, BOOL bPrevious = FALSE) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return CWindow(::GetNextDlgGroupItem(m_hWnd, hWndCtl, bPrevious)); - } - - CWindow GetNextDlgTabItem(HWND hWndCtl, BOOL bPrevious = FALSE) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return CWindow(::GetNextDlgTabItem(m_hWnd, hWndCtl, bPrevious)); - } - - UINT IsDlgButtonChecked(int nIDButton) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::IsDlgButtonChecked(m_hWnd, nIDButton); - } - - LRESULT SendDlgItemMessage(int nID, UINT message, WPARAM wParam = 0, LPARAM lParam = 0) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SendDlgItemMessage(m_hWnd, nID, message, wParam, lParam); - } - - BOOL SetDlgItemInt(int nID, UINT nValue, BOOL bSigned = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetDlgItemInt(m_hWnd, nID, nValue, bSigned); - } - - BOOL SetDlgItemText(int nID, LPCTSTR lpszString) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetDlgItemText(m_hWnd, nID, lpszString); - } - -#ifndef _ATL_NO_HOSTING - HRESULT GetDlgControl(int nID, REFIID iid, void** ppCtrl) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(ppCtrl != NULL); - if (ppCtrl == NULL) - return E_POINTER; - *ppCtrl = NULL; - HRESULT hr = HRESULT_FROM_WIN32(ERROR_CONTROL_ID_NOT_FOUND); - HWND hWndCtrl = GetDlgItem(nID); - if (hWndCtrl != NULL) - { - *ppCtrl = NULL; - CComPtr spUnk; - hr = AtlAxGetControl(hWndCtrl, &spUnk); - if (SUCCEEDED(hr)) - hr = spUnk->QueryInterface(iid, ppCtrl); - } - return hr; - } - HRESULT GetDlgHost(int nID, REFIID iid, void** ppHost) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - ATLASSERT(ppHost != NULL); - if (ppHost == NULL) - return E_POINTER; - *ppHost = NULL; - HRESULT hr = HRESULT_FROM_WIN32(ERROR_CONTROL_ID_NOT_FOUND); - HWND hWndCtrl = GetDlgItem(nID); - if (hWndCtrl != NULL) - { - CComPtr spUnk; - hr = AtlAxGetHost(hWndCtrl, &spUnk); - if (SUCCEEDED(hr)) - hr = spUnk->QueryInterface(iid, ppHost); - } - return hr; - } -#endif //!_ATL_NO_HOSTING - -// Scrolling Functions - - int GetScrollPos(int nBar) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetScrollPos(m_hWnd, nBar); - } - - BOOL GetScrollRange(int nBar, LPINT lpMinPos, LPINT lpMaxPos) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetScrollRange(m_hWnd, nBar, lpMinPos, lpMaxPos); - } - - BOOL ScrollWindow(int xAmount, int yAmount, LPCRECT lpRect = NULL, LPCRECT lpClipRect = NULL) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ScrollWindow(m_hWnd, xAmount, yAmount, lpRect, lpClipRect); - } - - int ScrollWindowEx(int dx, int dy, LPCRECT lpRectScroll, LPCRECT lpRectClip, HRGN hRgnUpdate, LPRECT lpRectUpdate, UINT uFlags) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ScrollWindowEx(m_hWnd, dx, dy, lpRectScroll, lpRectClip, hRgnUpdate, lpRectUpdate, uFlags); - } - - int ScrollWindowEx(int dx, int dy, UINT uFlags, LPCRECT lpRectScroll = NULL, LPCRECT lpRectClip = NULL, HRGN hRgnUpdate = NULL, LPRECT lpRectUpdate = NULL) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ScrollWindowEx(m_hWnd, dx, dy, lpRectScroll, lpRectClip, hRgnUpdate, lpRectUpdate, uFlags); - } - - int SetScrollPos(int nBar, int nPos, BOOL bRedraw = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetScrollPos(m_hWnd, nBar, nPos, bRedraw); - } - - BOOL SetScrollRange(int nBar, int nMinPos, int nMaxPos, BOOL bRedraw = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetScrollRange(m_hWnd, nBar, nMinPos, nMaxPos, bRedraw); - } - - BOOL ShowScrollBar(UINT nBar, BOOL bShow = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ShowScrollBar(m_hWnd, nBar, bShow); - } - - BOOL EnableScrollBar(UINT uSBFlags, UINT uArrowFlags = ESB_ENABLE_BOTH) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::EnableScrollBar(m_hWnd, uSBFlags, uArrowFlags); - } - -// Window Access Functions - - CWindow ChildWindowFromPoint(POINT point) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return CWindow(::ChildWindowFromPoint(m_hWnd, point)); - } - - CWindow ChildWindowFromPointEx(POINT point, UINT uFlags) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return CWindow(::ChildWindowFromPointEx(m_hWnd, point, uFlags)); - } - - CWindow GetTopWindow() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return CWindow(::GetTopWindow(m_hWnd)); - } - - CWindow GetWindow(UINT nCmd) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return CWindow(::GetWindow(m_hWnd, nCmd)); - } - - CWindow GetLastActivePopup() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return CWindow(::GetLastActivePopup(m_hWnd)); - } - - BOOL IsChild(HWND hWnd) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::IsChild(m_hWnd, hWnd); - } - - CWindow GetParent() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return CWindow(::GetParent(m_hWnd)); - } - - CWindow SetParent(HWND hWndNewParent) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return CWindow(::SetParent(m_hWnd, hWndNewParent)); - } - -// Window Tree Access - - int GetDlgCtrlID() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetDlgCtrlID(m_hWnd); - } - - int SetDlgCtrlID(int nID) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SetWindowLong(m_hWnd, GWL_ID, nID); - } - - CWindow GetDlgItem(int nID) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return CWindow(::GetDlgItem(m_hWnd, nID)); - } - -// Alert Functions - - BOOL FlashWindow(BOOL bInvert) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::FlashWindow(m_hWnd, bInvert); - } - - int MessageBox(LPCTSTR lpszText, LPCTSTR lpszCaption = _T(""), UINT nType = MB_OK) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::MessageBox(m_hWnd, lpszText, lpszCaption, nType); - } - -// Clipboard Functions - - BOOL ChangeClipboardChain(HWND hWndNewNext) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ChangeClipboardChain(m_hWnd, hWndNewNext); - } - - HWND SetClipboardViewer() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetClipboardViewer(m_hWnd); - } - - BOOL OpenClipboard() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::OpenClipboard(m_hWnd); - } - -// Caret Functions - - BOOL CreateCaret(HBITMAP hBitmap) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::CreateCaret(m_hWnd, hBitmap, 0, 0); - } - - BOOL CreateSolidCaret(int nWidth, int nHeight) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::CreateCaret(m_hWnd, (HBITMAP)0, nWidth, nHeight); - } - - BOOL CreateGrayCaret(int nWidth, int nHeight) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::CreateCaret(m_hWnd, (HBITMAP)1, nWidth, nHeight); - } - - BOOL HideCaret() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::HideCaret(m_hWnd); - } - - BOOL ShowCaret() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ShowCaret(m_hWnd); - } - -#ifdef _INC_SHELLAPI -// Drag-Drop Functions - void DragAcceptFiles(BOOL bAccept = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); ::DragAcceptFiles(m_hWnd, bAccept); - } -#endif - -// Icon Functions - - HICON SetIcon(HICON hIcon, BOOL bBigIcon = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HICON)::SendMessage(m_hWnd, WM_SETICON, bBigIcon, (LPARAM)hIcon); - } - - HICON GetIcon(BOOL bBigIcon = TRUE) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (HICON)::SendMessage(m_hWnd, WM_GETICON, bBigIcon, 0); - } - -// Help Functions - - BOOL WinHelp(LPCTSTR lpszHelp, UINT nCmd = HELP_CONTEXT, DWORD dwData = 0) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::WinHelp(m_hWnd, lpszHelp, nCmd, dwData); - } - - BOOL SetWindowContextHelpId(DWORD dwContextHelpId) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetWindowContextHelpId(m_hWnd, dwContextHelpId); - } - - DWORD GetWindowContextHelpId() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetWindowContextHelpId(m_hWnd); - } - -// Hot Key Functions - - int SetHotKey(WORD wVirtualKeyCode, WORD wModifiers) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (int)::SendMessage(m_hWnd, WM_SETHOTKEY, MAKEWORD(wVirtualKeyCode, wModifiers), 0); - } - - DWORD GetHotKey() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return (DWORD)::SendMessage(m_hWnd, WM_GETHOTKEY, 0, 0); - } - -// Misc. Operations - -//N new - BOOL GetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetScrollInfo(m_hWnd, nBar, lpScrollInfo); - } - int SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetScrollInfo(m_hWnd, nBar, lpScrollInfo, bRedraw); - } - BOOL IsDialogMessage(LPMSG lpMsg) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::IsDialogMessage(m_hWnd, lpMsg); - } - - void NextDlgCtrl() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_NEXTDLGCTL, 0, 0L); - } - void PrevDlgCtrl() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_NEXTDLGCTL, 1, 0L); - } - void GotoDlgCtrl(HWND hWndCtrl) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - ::SendMessage(m_hWnd, WM_NEXTDLGCTL, (WPARAM)hWndCtrl, 1L); - } - - BOOL ResizeClient(int nWidth, int nHeight, BOOL bRedraw = TRUE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - - RECT rcWnd; - if(!GetClientRect(&rcWnd)) - return FALSE; - - if(nWidth != -1) - rcWnd.right = nWidth; - if(nHeight != -1) - rcWnd.bottom = nHeight; - - if(!::AdjustWindowRectEx(&rcWnd, GetStyle(), (!(GetStyle() & WS_CHILD) && (GetMenu() != NULL)), GetExStyle())) - return FALSE; - - UINT uFlags = SWP_NOZORDER | SWP_NOMOVE; - if(!bRedraw) - uFlags |= SWP_NOREDRAW; - - return SetWindowPos(NULL, 0, 0, rcWnd.right - rcWnd.left, rcWnd.bottom - rcWnd.top, uFlags); - } - - int GetWindowRgn(HRGN hRgn) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetWindowRgn(m_hWnd, hRgn); - } - int SetWindowRgn(HRGN hRgn, BOOL bRedraw = FALSE) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::SetWindowRgn(m_hWnd, hRgn, bRedraw); - } - HDWP DeferWindowPos(HDWP hWinPosInfo, HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT uFlags) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::DeferWindowPos(hWinPosInfo, m_hWnd, hWndInsertAfter, x, y, cx, cy, uFlags); - } - DWORD GetWindowThreadID() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::GetWindowThreadProcessId(m_hWnd, NULL); - } - DWORD GetWindowProcessID() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - DWORD dwProcessID; - ::GetWindowThreadProcessId(m_hWnd, &dwProcessID); - return dwProcessID; - } - BOOL IsWindow() const throw() - { - return ::IsWindow(m_hWnd); - } - BOOL IsWindowUnicode() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::IsWindowUnicode(m_hWnd); - } - BOOL IsParentDialog() throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - TCHAR szBuf[8]; // "#32770" + NUL character - if (GetClassName(GetParent(), szBuf, sizeof(szBuf)/sizeof(szBuf[0])) == 0) - return FALSE; - return lstrcmp(szBuf, _T("#32770")) == 0; - } - BOOL ShowWindowAsync(int nCmdShow) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::ShowWindowAsync(m_hWnd, nCmdShow); - } - - CWindow GetDescendantWindow(int nID) const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - - // GetDlgItem recursive (return first found) - // breadth-first for 1 level, then depth-first for next level - - // use GetDlgItem since it is a fast USER function - HWND hWndChild, hWndTmp; - if((hWndChild = ::GetDlgItem(m_hWnd, nID)) != NULL) - { - if(::GetTopWindow(hWndChild) != NULL) - { - // children with the same ID as their parent have priority - CWindow wnd(hWndChild); - hWndTmp = wnd.GetDescendantWindow(nID); - if(hWndTmp != NULL) - return CWindow(hWndTmp); - } - return CWindow(hWndChild); - } - - // walk each child - for(hWndChild = ::GetTopWindow(m_hWnd); hWndChild != NULL; - hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT)) - { - CWindow wnd(hWndChild); - hWndTmp = wnd.GetDescendantWindow(nID); - if(hWndTmp != NULL) - return CWindow(hWndTmp); - } - - return CWindow(NULL); // not found - } - - void SendMessageToDescendants(UINT message, WPARAM wParam = 0, LPARAM lParam = 0, BOOL bDeep = TRUE) throw() - { - for(HWND hWndChild = ::GetTopWindow(m_hWnd); hWndChild != NULL; - hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT)) - { - ::SendMessage(hWndChild, message, wParam, lParam); - - if(bDeep && ::GetTopWindow(hWndChild) != NULL) - { - // send to child windows after parent - CWindow wnd(hWndChild); - wnd.SendMessageToDescendants(message, wParam, lParam, bDeep); - } - } - } - - BOOL CenterWindow(HWND hWndCenter = NULL) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - - // determine owner window to center against - DWORD dwStyle = GetStyle(); - if(hWndCenter == NULL) - { - if(dwStyle & WS_CHILD) - hWndCenter = ::GetParent(m_hWnd); - else - hWndCenter = ::GetWindow(m_hWnd, GW_OWNER); - } - - // get coordinates of the window relative to its parent - RECT rcDlg; - ::GetWindowRect(m_hWnd, &rcDlg); - RECT rcArea; - RECT rcCenter; - HWND hWndParent; - if(!(dwStyle & WS_CHILD)) - { - // don't center against invisible or minimized windows - if(hWndCenter != NULL) - { - DWORD dwStyleCenter = ::GetWindowLong(hWndCenter, GWL_STYLE); - if(!(dwStyleCenter & WS_VISIBLE) || (dwStyleCenter & WS_MINIMIZE)) - hWndCenter = NULL; - } - - // center within screen coordinates - ::SystemParametersInfo(SPI_GETWORKAREA, NULL, &rcArea, NULL); - if(hWndCenter == NULL) - rcCenter = rcArea; - else - ::GetWindowRect(hWndCenter, &rcCenter); - } - else - { - // center within parent client coordinates - hWndParent = ::GetParent(m_hWnd); - ATLASSERT(::IsWindow(hWndParent)); - - ::GetClientRect(hWndParent, &rcArea); - ATLASSERT(::IsWindow(hWndCenter)); - ::GetClientRect(hWndCenter, &rcCenter); - ::MapWindowPoints(hWndCenter, hWndParent, (POINT*)&rcCenter, 2); - } - - int DlgWidth = rcDlg.right - rcDlg.left; - int DlgHeight = rcDlg.bottom - rcDlg.top; - - // find dialog's upper left based on rcCenter - int xLeft = (rcCenter.left + rcCenter.right) / 2 - DlgWidth / 2; - int yTop = (rcCenter.top + rcCenter.bottom) / 2 - DlgHeight / 2; - - // if the dialog is outside the screen, move it inside - if(xLeft < rcArea.left) - xLeft = rcArea.left; - else if(xLeft + DlgWidth > rcArea.right) - xLeft = rcArea.right - DlgWidth; - - if(yTop < rcArea.top) - yTop = rcArea.top; - else if(yTop + DlgHeight > rcArea.bottom) - yTop = rcArea.bottom - DlgHeight; - - // map screen coordinates to child coordinates - return ::SetWindowPos(m_hWnd, NULL, xLeft, yTop, -1, -1, - SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); - } - - BOOL ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - - DWORD dwStyle = ::GetWindowLong(m_hWnd, GWL_STYLE); - DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd; - if(dwStyle == dwNewStyle) - return FALSE; - - ::SetWindowLong(m_hWnd, GWL_STYLE, dwNewStyle); - if(nFlags != 0) - { - ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, - SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags); - } - - return TRUE; - } - - BOOL ModifyStyleEx(DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0) throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - - DWORD dwStyle = ::GetWindowLong(m_hWnd, GWL_EXSTYLE); - DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd; - if(dwStyle == dwNewStyle) - return FALSE; - - ::SetWindowLong(m_hWnd, GWL_EXSTYLE, dwNewStyle); - if(nFlags != 0) - { - ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, - SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags); - } - - return TRUE; - } - -#ifdef _OLEAUTO_H_ - BOOL GetWindowText(BSTR* pbstrText) throw() - { - return GetWindowText(*pbstrText); - } - BOOL GetWindowText(BSTR& bstrText) throw() - { - USES_CONVERSION_EX; - ATLASSERT(::IsWindow(m_hWnd)); - ::SysFreeString(bstrText); - bstrText = NULL; - - int nLen = ::GetWindowTextLength(m_hWnd); - - - CTempBuffer lpszText; - if(nLen>0) - { - ATLTRY(lpszText.Allocate(nLen+1)); - if (lpszText == NULL) - { - return FALSE; - } - - if(!::GetWindowText(m_hWnd, lpszText, nLen+1)) - { - return FALSE; - } - } - - bstrText = ::SysAllocString(T2OLE_EX_DEF(lpszText)); -#pragma warning(push) -#pragma warning(disable:4068) -#pragma prefast(push) -#pragma prefast(disable:325, "We are deliberately checking if this has already been allocated") - return nLen==0 ? TRUE : ((bstrText != NULL) ? TRUE : FALSE); -#pragma prefast(pop) -#pragma warning(pop) - } -#endif // _OLEAUTO_H_ - CWindow GetTopLevelParent() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - - HWND hWndParent = m_hWnd; - HWND hWndTmp; - while((hWndTmp = ::GetParent(hWndParent)) != NULL) - hWndParent = hWndTmp; - - return CWindow(hWndParent); - } - - CWindow GetTopLevelWindow() const throw() - { - ATLASSERT(::IsWindow(m_hWnd)); - - HWND hWndParent; - HWND hWndTmp = m_hWnd; - - do - { - hWndParent = hWndTmp; - hWndTmp = (::GetWindowLong(hWndParent, GWL_STYLE) & WS_CHILD) ? ::GetParent(hWndParent) : ::GetWindow(hWndParent, GW_OWNER); - } - while(hWndTmp != NULL); - - return CWindow(hWndParent); - } -}; - -_declspec(selectany) RECT CWindow::rcDefault = { CW_USEDEFAULT, CW_USEDEFAULT, 0, 0 }; - -///////////////////////////////////////////////////////////////////////////// -// CAxWindow - client side for an ActiveX host window - -#ifndef _ATL_NO_HOSTING - -template -class CAxWindowT : public TBase -{ -public: -// Constructors - CAxWindowT(HWND hWnd = NULL) : TBase(hWnd) - { - AtlAxWinInit(); - } - - CAxWindowT< TBase >& operator=(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return _T(ATLAXWIN_CLASS); - } - -// Operations - HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return CWindow::Create(GetWndClassName(), hWndParent, rect, szWindowName, dwStyle, dwExStyle, MenuOrID, lpCreateParam); - } - - HRESULT CreateControl(LPCOLESTR lpszName, IStream* pStream = NULL, IUnknown** ppUnkContainer = NULL) - { - return CreateControlEx(lpszName, pStream, ppUnkContainer); - } - - HRESULT CreateControl(DWORD dwResID, IStream* pStream = NULL, IUnknown** ppUnkContainer = NULL) - { - return CreateControlEx(dwResID, pStream, ppUnkContainer); - } - - HRESULT CreateControlEx(LPCOLESTR lpszName, IStream* pStream = NULL, - IUnknown** ppUnkContainer = NULL, IUnknown** ppUnkControl = NULL, - REFIID iidSink = IID_NULL, IUnknown* punkSink = NULL) - { - ATLASSERT(::IsWindow(m_hWnd)); - // We must have a valid window! - - // Get a pointer to the container object connected to this window - CComPtr spWinHost; - HRESULT hr = QueryHost(&spWinHost); - - // If QueryHost failed, there is no host attached to this window - // We assume that the user wants to create a new host and subclass the current window - if (FAILED(hr)) - return AtlAxCreateControlEx(lpszName, m_hWnd, pStream, ppUnkContainer, ppUnkControl, iidSink, punkSink); - - // Create the control requested by the caller - CComPtr pControl; - if (SUCCEEDED(hr)) - hr = spWinHost->CreateControlEx(lpszName, m_hWnd, pStream, &pControl, iidSink, punkSink); - - // Send back the necessary interface pointers - if (SUCCEEDED(hr)) - { - if (ppUnkControl) - *ppUnkControl = pControl.Detach(); - - if (ppUnkContainer) - { - hr = spWinHost.QueryInterface(ppUnkContainer); - ATLASSERT(SUCCEEDED(hr)); // This should not fail! - } - } - - return hr; - } - - HRESULT CreateControlEx(DWORD dwResID, IStream* pStream = NULL, - IUnknown** ppUnkContainer = NULL, IUnknown** ppUnkControl = NULL, - REFIID iidSink = IID_NULL, IUnknown* punkSink = NULL) - { - TCHAR szModule[MAX_PATH]; - DWORD dwFLen = GetModuleFileName(_AtlBaseModule.GetModuleInstance(), szModule, MAX_PATH); - if( dwFLen == 0 ) - return AtlHresultFromLastError(); - else if( dwFLen == MAX_PATH ) - return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - - CComBSTR bstrURL(OLESTR("res://")); - HRESULT hr=bstrURL.Append(szModule); - if(FAILED(hr)) - { - return hr; - } - hr=bstrURL.Append(OLESTR("/")); - if(FAILED(hr)) - { - return hr; - } - TCHAR szResID[11]; -#if _SECURE_ATL && !defined(_ATL_MIN_CRT) - if (_stprintf_s(szResID, _countof(szResID), _T("%0d"), dwResID) == -1) - { - return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - } -#else - wsprintf(szResID, _T("%0d"), dwResID); -#endif - hr=bstrURL.Append(szResID); - if(FAILED(hr)) - { - return hr; - } - - ATLASSERT(::IsWindow(m_hWnd)); - return CreateControlEx(bstrURL, pStream, ppUnkContainer, ppUnkControl, iidSink, punkSink); - } - - HRESULT AttachControl(IUnknown* pControl, IUnknown** ppUnkContainer) - { - ATLASSERT(::IsWindow(m_hWnd)); - // We must have a valid window! - - // Get a pointer to the container object connected to this window - CComPtr spWinHost; - HRESULT hr = QueryHost(&spWinHost); - - // If QueryHost failed, there is no host attached to this window - // We assume that the user wants to create a new host and subclass the current window - if (FAILED(hr)) - return AtlAxAttachControl(pControl, m_hWnd, ppUnkContainer); - - // Attach the control specified by the caller - if (SUCCEEDED(hr)) - hr = spWinHost->AttachControl(pControl, m_hWnd); - - // Get the IUnknown interface of the container - if (SUCCEEDED(hr) && ppUnkContainer) - { - hr = spWinHost.QueryInterface(ppUnkContainer); - ATLASSERT(SUCCEEDED(hr)); // This should not fail! - } - - return hr; - } - - HRESULT QueryHost(REFIID iid, void** ppUnk) - { - ATLASSERT(ppUnk != NULL); - if (ppUnk == NULL) - return E_POINTER; - HRESULT hr; - *ppUnk = NULL; - CComPtr spUnk; - hr = AtlAxGetHost(m_hWnd, &spUnk); - if (SUCCEEDED(hr)) - hr = spUnk->QueryInterface(iid, ppUnk); - return hr; - } - template - HRESULT QueryHost(Q** ppUnk) - { - return QueryHost(__uuidof(Q), (void**)ppUnk); - } - HRESULT QueryControl(REFIID iid, void** ppUnk) - { - ATLASSERT(ppUnk != NULL); - if (ppUnk == NULL) - return E_POINTER; - HRESULT hr; - *ppUnk = NULL; - CComPtr spUnk; - hr = AtlAxGetControl(m_hWnd, &spUnk); - if (SUCCEEDED(hr)) - hr = spUnk->QueryInterface(iid, ppUnk); - return hr; - } - template - HRESULT QueryControl(Q** ppUnk) - { - return QueryControl(__uuidof(Q), (void**)ppUnk); - } - HRESULT SetExternalDispatch(IDispatch* pDisp) - { - HRESULT hr; - CComPtr spHost; - hr = QueryHost(__uuidof(IAxWinHostWindow), (void**)&spHost); - if (SUCCEEDED(hr)) - hr = spHost->SetExternalDispatch(pDisp); - return hr; - } - HRESULT SetExternalUIHandler(IDocHostUIHandlerDispatch* pUIHandler) - { - HRESULT hr; - CComPtr spHost; - hr = QueryHost(__uuidof(IAxWinHostWindow), (void**)&spHost); - if (SUCCEEDED(hr)) - hr = spHost->SetExternalUIHandler(pUIHandler); - return hr; - } -}; - -typedef CAxWindowT CAxWindow; - -template -class CAxWindow2T : public CAxWindowT -{ -public: -// Constructors - CAxWindow2T(HWND hWnd = NULL) : CAxWindowT(hWnd) - { - } - - CAxWindow2T< TBase >& operator=(HWND hWnd) - { - m_hWnd = hWnd; - return *this; - } - -// Attributes - static LPCTSTR GetWndClassName() - { - return _T(ATLAXWINLIC_CLASS); - } - -// Operations - HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - return CWindow::Create(GetWndClassName(), hWndParent, rect, szWindowName, dwStyle, dwExStyle, MenuOrID, lpCreateParam); - } - - HRESULT CreateControlLic(LPCOLESTR lpszName, IStream* pStream = NULL, IUnknown** ppUnkContainer = NULL, BSTR bstrLicKey = NULL) - { - return CreateControlLicEx(lpszName, pStream, ppUnkContainer, NULL, IID_NULL, NULL, bstrLicKey); - } - - HRESULT CreateControlLic(DWORD dwResID, IStream* pStream = NULL, IUnknown** ppUnkContainer = NULL, BSTR bstrLicKey = NULL) - { - return CreateControlLicEx(dwResID, pStream, ppUnkContainer, NULL, IID_NULL, NULL, bstrLicKey); - } - - HRESULT CreateControlLicEx(LPCOLESTR lpszName, IStream* pStream = NULL, - IUnknown** ppUnkContainer = NULL, IUnknown** ppUnkControl = NULL, - REFIID iidSink = IID_NULL, IUnknown* punkSink = NULL, BSTR bstrLicKey = NULL) - { - ATLASSERT(::IsWindow(m_hWnd)); - // We must have a valid window! - - // Get a pointer to the container object connected to this window - CComPtr spWinHost; - HRESULT hr = QueryHost(&spWinHost); - - // If QueryHost failed, there is no host attached to this window - // We assume that the user wants to create a new host and subclass the current window - if (FAILED(hr)) - return AtlAxCreateControlLicEx(lpszName, m_hWnd, pStream, ppUnkContainer, ppUnkControl, iidSink, punkSink, bstrLicKey); - - // Create the control requested by the caller - CComPtr pControl; - if (SUCCEEDED(hr)) - hr = spWinHost->CreateControlLicEx(lpszName, m_hWnd, pStream, &pControl, iidSink, punkSink, bstrLicKey); - - // Send back the necessary interface pointers - if (SUCCEEDED(hr)) - { - if (ppUnkControl) - *ppUnkControl = pControl.Detach(); - - if (ppUnkContainer) - { - hr = spWinHost.QueryInterface(ppUnkContainer); - ATLASSERT(SUCCEEDED(hr)); // This should not fail! - } - } - - return hr; - } - - HRESULT CreateControlLicEx(DWORD dwResID, IStream* pStream = NULL, - IUnknown** ppUnkContainer = NULL, IUnknown** ppUnkControl = NULL, - REFIID iidSink = IID_NULL, IUnknown* punkSink = NULL, BSTR bstrLickey = NULL) - { - TCHAR szModule[MAX_PATH]; - DWORD dwFLen = GetModuleFileName(_AtlBaseModule.GetModuleInstance(), szModule, MAX_PATH); - if( dwFLen == 0 ) - return AtlHresultFromLastError(); - else if( dwFLen == MAX_PATH ) - return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - - CComBSTR bstrURL(OLESTR("res://")); - bstrURL.Append(szModule); - bstrURL.Append(OLESTR("/")); - TCHAR szResID[11]; -#if _SECURE_ATL && !defined(_ATL_MIN_CRT) - if (_stprintf_s(szResID, _countof(szResID), _T("%0d"), dwResID) == -1) - { - return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - } -#else - wsprintf(szResID, _T("%0d"), dwResID); -#endif - bstrURL.Append(szResID); - - ATLASSERT(::IsWindow(m_hWnd)); - return CreateControlLicEx(bstrURL, pStream, ppUnkContainer, ppUnkControl, iidSink, punkSink, bstrLickey); - } -}; - -typedef CAxWindow2T CAxWindow2; - - -#endif //_ATL_NO_HOSTING - -///////////////////////////////////////////////////////////////////////////// -// WindowProc thunks - -class CWndProcThunk -{ -public: - _AtlCreateWndData cd; - CStdCallThunk thunk; - - BOOL Init(WNDPROC proc, void* pThis) - { - return thunk.Init((DWORD_PTR)proc, pThis); - } - WNDPROC GetWNDPROC() - { - return (WNDPROC)thunk.GetCodeAddress(); - } -}; - -///////////////////////////////////////////////////////////////////////////// -// CMessageMap - abstract class that provides an interface for message maps - -class ATL_NO_VTABLE CMessageMap -{ -public: - virtual BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, - LRESULT& lResult, DWORD dwMsgMapID) = 0; -}; - -///////////////////////////////////////////////////////////////////////////// -// Message map - -#define BEGIN_MSG_MAP(theClass) \ -public: \ - BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) \ - { \ - BOOL bHandled = TRUE; \ - (hWnd); \ - (uMsg); \ - (wParam); \ - (lParam); \ - (lResult); \ - (bHandled); \ - switch(dwMsgMapID) \ - { \ - case 0: - -#define ALT_MSG_MAP(msgMapID) \ - break; \ - case msgMapID: - -#define MESSAGE_HANDLER(msg, func) \ - if(uMsg == msg) \ - { \ - bHandled = TRUE; \ - lResult = func(uMsg, wParam, lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define MESSAGE_RANGE_HANDLER(msgFirst, msgLast, func) \ - if(uMsg >= msgFirst && uMsg <= msgLast) \ - { \ - bHandled = TRUE; \ - lResult = func(uMsg, wParam, lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define COMMAND_HANDLER(id, code, func) \ - if(uMsg == WM_COMMAND && id == LOWORD(wParam) && code == HIWORD(wParam)) \ - { \ - bHandled = TRUE; \ - lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define COMMAND_ID_HANDLER(id, func) \ - if(uMsg == WM_COMMAND && id == LOWORD(wParam)) \ - { \ - bHandled = TRUE; \ - lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define COMMAND_CODE_HANDLER(code, func) \ - if(uMsg == WM_COMMAND && code == HIWORD(wParam)) \ - { \ - bHandled = TRUE; \ - lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define COMMAND_RANGE_HANDLER(idFirst, idLast, func) \ - if(uMsg == WM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \ - { \ - bHandled = TRUE; \ - lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define COMMAND_RANGE_CODE_HANDLER(idFirst, idLast, code, func) \ - if(uMsg == WM_COMMAND && code == HIWORD(wParam) && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \ - { \ - bHandled = TRUE; \ - lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define NOTIFY_HANDLER(id, cd, func) \ - if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code) \ - { \ - bHandled = TRUE; \ - lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define NOTIFY_ID_HANDLER(id, func) \ - if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) \ - { \ - bHandled = TRUE; \ - lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define NOTIFY_CODE_HANDLER(cd, func) \ - if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \ - { \ - bHandled = TRUE; \ - lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define NOTIFY_RANGE_HANDLER(idFirst, idLast, func) \ - if(uMsg == WM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \ - { \ - bHandled = TRUE; \ - lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define NOTIFY_RANGE_CODE_HANDLER(idFirst, idLast, cd, func) \ - if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \ - { \ - bHandled = TRUE; \ - lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define CHAIN_MSG_MAP(theChainClass) \ - { \ - if(theChainClass::ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult)) \ - return TRUE; \ - } - -#define CHAIN_MSG_MAP_MEMBER(theChainMember) \ - { \ - if(theChainMember.ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult)) \ - return TRUE; \ - } - -#define CHAIN_MSG_MAP_ALT(theChainClass, msgMapID) \ - { \ - if(theChainClass::ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, msgMapID)) \ - return TRUE; \ - } - -#define CHAIN_MSG_MAP_ALT_MEMBER(theChainMember, msgMapID) \ - { \ - if(theChainMember.ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, msgMapID)) \ - return TRUE; \ - } - -#define CHAIN_MSG_MAP_DYNAMIC(dynaChainID) \ - { \ - if(CDynamicChain::CallChain(dynaChainID, hWnd, uMsg, wParam, lParam, lResult)) \ - return TRUE; \ - } - -#define END_MSG_MAP() \ - break; \ - default: \ - ATLTRACE(ATL::atlTraceWindowing, 0, _T("Invalid message map ID (%i)\n"), dwMsgMapID); \ - ATLASSERT(FALSE); \ - break; \ - } \ - return FALSE; \ - } - - -// Handler prototypes: -// LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); -// LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); -// LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled); - - -// Empty message map macro - -#define DECLARE_EMPTY_MSG_MAP() \ -public: \ - BOOL ProcessWindowMessage(HWND, UINT, WPARAM, LPARAM, LRESULT&, DWORD = 0) \ - { \ - return FALSE; \ - } - -// Message forwarding and reflection macros - -#define FORWARD_NOTIFICATIONS() \ - { \ - bHandled = TRUE; \ - lResult = ForwardNotifications(uMsg, wParam, lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECT_NOTIFICATIONS() \ - { \ - bHandled = TRUE; \ - lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define DEFAULT_REFLECTION_HANDLER() \ - if(DefaultReflectionHandler(hWnd, uMsg, wParam, lParam, lResult)) \ - return TRUE; - -#define REFLECTED_COMMAND_HANDLER(id, code, func) \ - if(uMsg == OCM_COMMAND && id == LOWORD(wParam) && code == HIWORD(wParam)) \ - { \ - bHandled = TRUE; \ - lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECTED_COMMAND_ID_HANDLER(id, func) \ - if(uMsg == OCM_COMMAND && id == LOWORD(wParam)) \ - { \ - bHandled = TRUE; \ - lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECTED_COMMAND_CODE_HANDLER(code, func) \ - if(uMsg == OCM_COMMAND && code == HIWORD(wParam)) \ - { \ - bHandled = TRUE; \ - lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECTED_COMMAND_RANGE_HANDLER(idFirst, idLast, func) \ - if(uMsg == OCM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \ - { \ - bHandled = TRUE; \ - lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECTED_COMMAND_RANGE_CODE_HANDLER(idFirst, idLast, code, func) \ - if(uMsg == OCM_COMMAND && code == HIWORD(wParam) && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \ - { \ - bHandled = TRUE; \ - lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECTED_NOTIFY_HANDLER(id, cd, func) \ - if(uMsg == OCM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code) \ - { \ - bHandled = TRUE; \ - lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECTED_NOTIFY_ID_HANDLER(id, func) \ - if(uMsg == OCM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) \ - { \ - bHandled = TRUE; \ - lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECTED_NOTIFY_CODE_HANDLER(cd, func) \ - if(uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \ - { \ - bHandled = TRUE; \ - lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECTED_NOTIFY_RANGE_HANDLER(idFirst, idLast, func) \ - if(uMsg == OCM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \ - { \ - bHandled = TRUE; \ - lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -#define REFLECTED_NOTIFY_RANGE_CODE_HANDLER(idFirst, idLast, cd, func) \ - if(uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \ - { \ - bHandled = TRUE; \ - lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ - if(bHandled) \ - return TRUE; \ - } - -///////////////////////////////////////////////////////////////////////////// -// CDynamicChain - provides support for dynamic chaining - -class CDynamicChain -{ -public: - struct ATL_CHAIN_ENTRY - { - DWORD m_dwChainID; - CMessageMap* m_pObject; - DWORD m_dwMsgMapID; - }; - - CSimpleArray m_aChainEntry; - - CDynamicChain() - { } - - ~CDynamicChain() - { - for(int i = 0; i < m_aChainEntry.GetSize(); i++) - { - if(m_aChainEntry[i] != NULL) - delete m_aChainEntry[i]; - } - } - - BOOL SetChainEntry(DWORD dwChainID, CMessageMap* pObject, DWORD dwMsgMapID = 0) - { - // first search for an existing entry - - int i; - for(i = 0; i < m_aChainEntry.GetSize(); i++) - { - if(m_aChainEntry[i] != NULL && m_aChainEntry[i]->m_dwChainID == dwChainID) - { - m_aChainEntry[i]->m_pObject = pObject; - m_aChainEntry[i]->m_dwMsgMapID = dwMsgMapID; - return TRUE; - } - } - - // create a new one - - ATL_CHAIN_ENTRY* pEntry = NULL; - ATLTRY(pEntry = new ATL_CHAIN_ENTRY); - - if(pEntry == NULL) - return FALSE; - - pEntry->m_dwChainID = dwChainID; - pEntry->m_pObject = pObject; - pEntry->m_dwMsgMapID = dwMsgMapID; - - // search for an empty one - - for(i = 0; i < m_aChainEntry.GetSize(); i++) - { - if(m_aChainEntry[i] == NULL) - { - m_aChainEntry[i] = pEntry; - return TRUE; - } - } - - // add a new one - - BOOL bRet = m_aChainEntry.Add(pEntry); - - if(!bRet) - { - delete pEntry; - return FALSE; - } - - return TRUE; - } - - BOOL RemoveChainEntry(DWORD dwChainID) - { - for(int i = 0; i < m_aChainEntry.GetSize(); i++) - { - if(m_aChainEntry[i] != NULL && m_aChainEntry[i]->m_dwChainID == dwChainID) - { - delete m_aChainEntry[i]; - m_aChainEntry[i] = NULL; - return TRUE; - } - } - - return FALSE; - } - - BOOL CallChain(DWORD dwChainID, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult) - { - for(int i = 0; i < m_aChainEntry.GetSize(); i++) - { - if(m_aChainEntry[i] != NULL && m_aChainEntry[i]->m_dwChainID == dwChainID) - return (m_aChainEntry[i]->m_pObject)->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, m_aChainEntry[i]->m_dwMsgMapID); - } - - return FALSE; - } -}; - -///////////////////////////////////////////////////////////////////////////// -// CWndClassInfo - Manages Windows class information - -#define DECLARE_WND_CLASS(WndClassName) \ -static ATL::CWndClassInfo& GetWndClassInfo() \ -{ \ - static ATL::CWndClassInfo wc = \ - { \ - { sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS, StartWindowProc, \ - 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName, NULL }, \ - NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \ - }; \ - return wc; \ -} - -#define DECLARE_WND_CLASS_EX(WndClassName, style, bkgnd) \ -static ATL::CWndClassInfo& GetWndClassInfo() \ -{ \ - static ATL::CWndClassInfo wc = \ - { \ - { sizeof(WNDCLASSEX), style, StartWindowProc, \ - 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName, NULL }, \ - NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \ - }; \ - return wc; \ -} - -#define DECLARE_WND_SUPERCLASS(WndClassName, OrigWndClassName) \ -static ATL::CWndClassInfo& GetWndClassInfo() \ -{ \ - static ATL::CWndClassInfo wc = \ - { \ - { sizeof(WNDCLASSEX), 0, StartWindowProc, \ - 0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName, NULL }, \ - OrigWndClassName, NULL, NULL, TRUE, 0, _T("") \ - }; \ - return wc; \ -} - -///////////////////////////////////////////////////////////////////////////// -// CWinTraits - Defines various default values for a window - -template -class CWinTraits -{ -public: - static DWORD GetWndStyle(DWORD dwStyle) - { - return dwStyle == 0 ? t_dwStyle : dwStyle; - } - static DWORD GetWndExStyle(DWORD dwExStyle) - { - return dwExStyle == 0 ? t_dwExStyle : dwExStyle; - } -}; - -typedef CWinTraits CControlWinTraits; -typedef CWinTraits CFrameWinTraits; -typedef CWinTraits CMDIChildWinTraits; - -typedef CWinTraits<0, 0> CNullTraits; - -template -class CWinTraitsOR -{ -public: - static DWORD GetWndStyle(DWORD dwStyle) - { - return dwStyle | t_dwStyle | TWinTraits::GetWndStyle(dwStyle); - } - static DWORD GetWndExStyle(DWORD dwExStyle) - { - return dwExStyle | t_dwExStyle | TWinTraits::GetWndExStyle(dwExStyle); - } -}; - -///////////////////////////////////////////////////////////////////////////// -// CWindowImpl - Implements a window - -template -class ATL_NO_VTABLE CWindowImplRoot : public TBase, public CMessageMap -{ -public: - CWndProcThunk m_thunk; - const _ATL_MSG* m_pCurrentMsg; - DWORD m_dwState; - - enum { WINSTATE_DESTROYED = 0x00000001 }; - -// Constructor/destructor - CWindowImplRoot() : m_pCurrentMsg(NULL), m_dwState(0) - { } - - virtual ~CWindowImplRoot() - { -#ifdef _DEBUG - if(m_hWnd != NULL) // should be cleared in WindowProc - { - ATLTRACE(atlTraceWindowing, 0, _T("ERROR - Object deleted before window was destroyed\n")); - ATLASSERT(FALSE); - } -#endif //_DEBUG - } - -// Current message - const _ATL_MSG* GetCurrentMessage() const - { - return m_pCurrentMsg; - } - - // "handled" management for cracked handlers - BOOL IsMsgHandled() const - { - const _ATL_MSG* pMsg = GetCurrentMessage(); - ATLASSERT(pMsg != NULL); - ATLASSERT(pMsg->cbSize >= sizeof(_ATL_MSG)); - return pMsg->bHandled; - } - void SetMsgHandled(BOOL bHandled) - { - _ATL_MSG* pMsg = (_ATL_MSG*)GetCurrentMessage(); // override const - ATLASSERT(pMsg != NULL); - ATLASSERT(pMsg->cbSize >= sizeof(_ATL_MSG)); - pMsg->bHandled = bHandled; - } - -// Message forwarding and reflection support - LRESULT ForwardNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); - LRESULT ReflectNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); - static BOOL DefaultReflectionHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult); -}; - -template -LRESULT CWindowImplRoot< TBase >::ForwardNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) -{ - LRESULT lResult = 0; - switch(uMsg) - { - case WM_COMMAND: - case WM_NOTIFY: - case WM_PARENTNOTIFY: - case WM_DRAWITEM: - case WM_MEASUREITEM: - case WM_COMPAREITEM: - case WM_DELETEITEM: - case WM_VKEYTOITEM: - case WM_CHARTOITEM: - case WM_HSCROLL: - case WM_VSCROLL: - case WM_CTLCOLORBTN: - case WM_CTLCOLORDLG: - case WM_CTLCOLOREDIT: - case WM_CTLCOLORLISTBOX: - case WM_CTLCOLORMSGBOX: - case WM_CTLCOLORSCROLLBAR: - case WM_CTLCOLORSTATIC: - lResult = GetParent().SendMessage(uMsg, wParam, lParam); - break; - default: - bHandled = FALSE; - break; - } - return lResult; -} - -template -LRESULT CWindowImplRoot< TBase >::ReflectNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) -{ - HWND hWndChild = NULL; - - switch(uMsg) - { - case WM_COMMAND: - if(lParam != NULL) // not from a menu - hWndChild = (HWND)lParam; - break; - case WM_NOTIFY: - hWndChild = ((LPNMHDR)lParam)->hwndFrom; - break; - case WM_PARENTNOTIFY: - switch(LOWORD(wParam)) - { - case WM_CREATE: - case WM_DESTROY: - hWndChild = (HWND)lParam; - break; - default: - hWndChild = GetDlgItem(HIWORD(wParam)); - break; - } - break; - case WM_DRAWITEM: - if(wParam) // not from a menu - hWndChild = ((LPDRAWITEMSTRUCT)lParam)->hwndItem; - break; - case WM_MEASUREITEM: - if(wParam) // not from a menu - hWndChild = GetDlgItem(((LPMEASUREITEMSTRUCT)lParam)->CtlID); - break; - case WM_COMPAREITEM: - if(wParam) // not from a menu - hWndChild = ((LPCOMPAREITEMSTRUCT)lParam)->hwndItem; - break; - case WM_DELETEITEM: - if(wParam) // not from a menu - hWndChild = ((LPDELETEITEMSTRUCT)lParam)->hwndItem; - - break; - case WM_VKEYTOITEM: - case WM_CHARTOITEM: - case WM_HSCROLL: - case WM_VSCROLL: - hWndChild = (HWND)lParam; - break; - case WM_CTLCOLORBTN: - case WM_CTLCOLORDLG: - case WM_CTLCOLOREDIT: - case WM_CTLCOLORLISTBOX: - case WM_CTLCOLORMSGBOX: - case WM_CTLCOLORSCROLLBAR: - case WM_CTLCOLORSTATIC: - hWndChild = (HWND)lParam; - break; - default: - break; - } - - if(hWndChild == NULL) - { - bHandled = FALSE; - return 1; - } - - ATLASSERT(::IsWindow(hWndChild)); - return ::SendMessage(hWndChild, OCM__BASE + uMsg, wParam, lParam); -} - -template -BOOL CWindowImplRoot< TBase >::DefaultReflectionHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult) -{ - switch(uMsg) - { - case OCM_COMMAND: - case OCM_NOTIFY: - case OCM_PARENTNOTIFY: - case OCM_DRAWITEM: - case OCM_MEASUREITEM: - case OCM_COMPAREITEM: - case OCM_DELETEITEM: - case OCM_VKEYTOITEM: - case OCM_CHARTOITEM: - case OCM_HSCROLL: - case OCM_VSCROLL: - case OCM_CTLCOLORBTN: - case OCM_CTLCOLORDLG: - case OCM_CTLCOLOREDIT: - case OCM_CTLCOLORLISTBOX: - case OCM_CTLCOLORMSGBOX: - case OCM_CTLCOLORSCROLLBAR: - case OCM_CTLCOLORSTATIC: - lResult = ::DefWindowProc(hWnd, uMsg - OCM__BASE, wParam, lParam); - return TRUE; - default: - break; - } - return FALSE; -} - -template -class ATL_NO_VTABLE CWindowImplBaseT : public CWindowImplRoot< TBase > -{ -public: - WNDPROC m_pfnSuperWindowProc; - - CWindowImplBaseT() : m_pfnSuperWindowProc(::DefWindowProc) - {} - - static DWORD GetWndStyle(DWORD dwStyle) - { - return TWinTraits::GetWndStyle(dwStyle); - } - static DWORD GetWndExStyle(DWORD dwExStyle) - { - return TWinTraits::GetWndExStyle(dwExStyle); - } - - virtual WNDPROC GetWindowProc() - { - return WindowProc; - } - static LRESULT CALLBACK StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - HWND Create(HWND hWndParent, _U_RECT rect, LPCTSTR szWindowName, - DWORD dwStyle, DWORD dwExStyle, _U_MENUorID MenuOrID, ATOM atom, LPVOID lpCreateParam = NULL); - BOOL DestroyWindow() - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::DestroyWindow(m_hWnd); - } - BOOL SubclassWindow(HWND hWnd); - HWND UnsubclassWindow(BOOL bForce = FALSE); - - LRESULT DefWindowProc() - { - const _ATL_MSG* pMsg = m_pCurrentMsg; - LRESULT lRes = 0; - if (pMsg != NULL) - lRes = DefWindowProc(pMsg->message, pMsg->wParam, pMsg->lParam); - return lRes; - } - - LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) - { -#ifdef STRICT - return ::CallWindowProc(m_pfnSuperWindowProc, m_hWnd, uMsg, wParam, lParam); -#else - return ::CallWindowProc((FARPROC)m_pfnSuperWindowProc, m_hWnd, uMsg, wParam, lParam); -#endif - } - - virtual void OnFinalMessage(HWND /*hWnd*/) - { - // override to do something, if needed - } -}; - -typedef CWindowImplBaseT CWindowImplBase; - -template -LRESULT CALLBACK CWindowImplBaseT< TBase, TWinTraits >::StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - CWindowImplBaseT< TBase, TWinTraits >* pThis = (CWindowImplBaseT< TBase, TWinTraits >*)_AtlWinModule.ExtractCreateWndData(); - ATLASSERT(pThis != NULL); - if(!pThis) - { - return 0; - } - pThis->m_hWnd = hWnd; - - // Initialize the thunk. This is allocated in CWindowImplBaseT::Create, - // so failure is unexpected here. - - pThis->m_thunk.Init(pThis->GetWindowProc(), pThis); - WNDPROC pProc = pThis->m_thunk.GetWNDPROC(); - WNDPROC pOldProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc); -#ifdef _DEBUG - // check if somebody has subclassed us already since we discard it - if(pOldProc != StartWindowProc) - ATLTRACE(atlTraceWindowing, 0, _T("Subclassing through a hook discarded.\n")); -#else - (pOldProc); // avoid unused warning -#endif - return pProc(hWnd, uMsg, wParam, lParam); -} - -template -LRESULT CALLBACK CWindowImplBaseT< TBase, TWinTraits >::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - CWindowImplBaseT< TBase, TWinTraits >* pThis = (CWindowImplBaseT< TBase, TWinTraits >*)hWnd; - // set a ptr to this message and save the old value - _ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam); - const _ATL_MSG* pOldMsg = pThis->m_pCurrentMsg; - pThis->m_pCurrentMsg = &msg; - // pass to the message map to process - LRESULT lRes; - BOOL bRet = pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0); - // restore saved value for the current message - ATLASSERT(pThis->m_pCurrentMsg == &msg); - - // do the default processing if message was not handled - if(!bRet) - { - if(uMsg != WM_NCDESTROY) - lRes = pThis->DefWindowProc(uMsg, wParam, lParam); - else - { - // unsubclass, if needed - LONG_PTR pfnWndProc = ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC); - lRes = pThis->DefWindowProc(uMsg, wParam, lParam); - if(pThis->m_pfnSuperWindowProc != ::DefWindowProc && ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC) == pfnWndProc) - ::SetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC, (LONG_PTR)pThis->m_pfnSuperWindowProc); - // mark window as destryed - pThis->m_dwState |= WINSTATE_DESTROYED; - } - } - if((pThis->m_dwState & WINSTATE_DESTROYED) && pOldMsg== NULL) - { - // clear out window handle - HWND hWndThis = pThis->m_hWnd; - pThis->m_hWnd = NULL; - pThis->m_dwState &= ~WINSTATE_DESTROYED; - // clean up after window is destroyed - pThis->m_pCurrentMsg = pOldMsg; - pThis->OnFinalMessage(hWndThis); - }else { - pThis->m_pCurrentMsg = pOldMsg; - } - return lRes; -} - -template -HWND CWindowImplBaseT< TBase, TWinTraits >::Create(HWND hWndParent, _U_RECT rect, LPCTSTR szWindowName, - DWORD dwStyle, DWORD dwExStyle, _U_MENUorID MenuOrID, ATOM atom, LPVOID lpCreateParam) -{ - BOOL result; - ATLASSUME(m_hWnd == NULL); - - // Allocate the thunk structure here, where we can fail gracefully. - result = m_thunk.Init(NULL,NULL); - if (result == FALSE) { - SetLastError(ERROR_OUTOFMEMORY); - return NULL; - } - - if(atom == 0) - return NULL; - - _AtlWinModule.AddCreateWndData(&m_thunk.cd, this); - - if(MenuOrID.m_hMenu == NULL && (dwStyle & WS_CHILD)) - MenuOrID.m_hMenu = (HMENU)(UINT_PTR)this; - if(rect.m_lpRect == NULL) - rect.m_lpRect = &TBase::rcDefault; - - HWND hWnd = ::CreateWindowEx(dwExStyle, MAKEINTATOM(atom), szWindowName, - dwStyle, rect.m_lpRect->left, rect.m_lpRect->top, rect.m_lpRect->right - rect.m_lpRect->left, - rect.m_lpRect->bottom - rect.m_lpRect->top, hWndParent, MenuOrID.m_hMenu, - _AtlBaseModule.GetModuleInstance(), lpCreateParam); - - ATLASSUME(m_hWnd == hWnd); - - return hWnd; -} - -template -BOOL CWindowImplBaseT< TBase, TWinTraits >::SubclassWindow(HWND hWnd) -{ - BOOL result; - ATLASSUME(m_hWnd == NULL); - ATLASSERT(::IsWindow(hWnd)); - - // Allocate the thunk structure here, where we can fail gracefully. - - result = m_thunk.Init(GetWindowProc(), this); - if (result == FALSE) - { - return FALSE; - } - WNDPROC pProc = m_thunk.GetWNDPROC(); - WNDPROC pfnWndProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc); - if(pfnWndProc == NULL) - return FALSE; - m_pfnSuperWindowProc = pfnWndProc; - m_hWnd = hWnd; - return TRUE; -} - -// Use only if you want to subclass before window is destroyed, -// WindowProc will automatically subclass when window goes away -template -HWND CWindowImplBaseT< TBase, TWinTraits >::UnsubclassWindow(BOOL bForce /*= FALSE*/) -{ - ATLASSUME(m_hWnd != NULL); - - WNDPROC pOurProc = m_thunk.GetWNDPROC(); - WNDPROC pActiveProc = (WNDPROC)::GetWindowLongPtr(m_hWnd, GWLP_WNDPROC); - - HWND hWnd = NULL; - if (bForce || pOurProc == pActiveProc) - { - if(!::SetWindowLongPtr(m_hWnd, GWLP_WNDPROC, (LONG_PTR)m_pfnSuperWindowProc)) - return NULL; - - m_pfnSuperWindowProc = ::DefWindowProc; - hWnd = m_hWnd; - m_hWnd = NULL; - } - return hWnd; -} - -template -class ATL_NO_VTABLE CWindowImpl : public CWindowImplBaseT< TBase, TWinTraits > -{ -public: - DECLARE_WND_CLASS(NULL) - - static LPCTSTR GetWndCaption() - { - return NULL; - } - - HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - if (T::GetWndClassInfo().m_lpszOrigName == NULL) - T::GetWndClassInfo().m_lpszOrigName = GetWndClassName(); - ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc); - - dwStyle = T::GetWndStyle(dwStyle); - dwExStyle = T::GetWndExStyle(dwExStyle); - - // set caption - if (szWindowName == NULL) - szWindowName = T::GetWndCaption(); - - return CWindowImplBaseT< TBase, TWinTraits >::Create(hWndParent, rect, szWindowName, - dwStyle, dwExStyle, MenuOrID, atom, lpCreateParam); - } -}; - -template -class ATL_NO_VTABLE CWindowWithReflectorImpl : public CWindowImpl< T, TBase, TWinTraits > -{ -public: - HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - m_wndReflector.Create(hWndParent, rect, NULL, WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, Reflector::REFLECTOR_MAP_ID); - RECT rcPos = { 0, 0, rect.m_lpRect->right, rect.m_lpRect->bottom }; - return CWindowImpl< T, TBase, TWinTraits >::Create(m_wndReflector, rcPos, szWindowName, dwStyle, dwExStyle, MenuOrID, lpCreateParam); - } - -// message map and handlers - typedef CWindowWithReflectorImpl< T, TBase, TWinTraits > thisClass; - BEGIN_MSG_MAP(thisClass) - MESSAGE_HANDLER(WM_NCDESTROY, OnNcDestroy) - MESSAGE_HANDLER(WM_WINDOWPOSCHANGING, OnWindowPosChanging) - END_MSG_MAP() - - LRESULT OnNcDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - m_wndReflector.DestroyWindow(); - bHandled = FALSE; - return 1; - } - LRESULT OnWindowPosChanging(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) - { - WINDOWPOS* pWP = (WINDOWPOS*)lParam; - m_wndReflector.SetWindowPos(m_wndReflector.GetParent(), pWP->x, pWP->y, pWP->cx, pWP->cy, pWP->flags); - pWP->flags |= SWP_NOMOVE; - pWP->x = 0; - pWP->y = 0; - return DefWindowProc(uMsg, wParam, lParam); - } - - // reflector window stuff - class Reflector : public CWindowImpl - { - public: - enum { REFLECTOR_MAP_ID = 69 }; - DECLARE_WND_CLASS_EX(_T("ATLReflectorWindow"), 0, -1) - BEGIN_MSG_MAP(Reflector) - REFLECT_NOTIFICATIONS() - END_MSG_MAP() - } m_wndReflector; -}; - -///////////////////////////////////////////////////////////////////////////// -// CDialogImpl - Implements a dialog box - -#define _ATL_RT_DLGINIT MAKEINTRESOURCE(240) - -template -class ATL_NO_VTABLE CDialogImplBaseT : public CWindowImplRoot< TBase > -{ -public: - virtual ~CDialogImplBaseT() - { - } - virtual DLGPROC GetDialogProc() - { - return DialogProc; - } - static INT_PTR CALLBACK StartDialogProc(HWND hWnd, UINT uMsg, - WPARAM wParam, LPARAM lParam); - static INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - BOOL MapDialogRect(LPRECT lpRect) - { - ATLASSERT(::IsWindow(m_hWnd)); - return ::MapDialogRect(m_hWnd, lpRect); - } - virtual void OnFinalMessage(HWND /*hWnd*/) - { - // override to do something, if needed - } - // has no meaning for a dialog, but needed for handlers that use it - LRESULT DefWindowProc() - { - return 0; - } - // initialize combobox and comboboxex from RT_DLGINIT resource if any - BOOL ExecuteDlgInit(int iDlgID) - { - BOOL bSuccess = TRUE; - HINSTANCE hInst = _AtlBaseModule.GetResourceInstance(); - HRSRC hrsrc = ::FindResource(hInst, MAKEINTRESOURCE(iDlgID), _ATL_RT_DLGINIT); - if (hrsrc) - { - HGLOBAL hResData = ::LoadResource(hInst, hrsrc); - if (hResData) - { - UNALIGNED WORD* pDlgInit = (UNALIGNED WORD*)::LockResource(hResData); - if (pDlgInit) - { - while (bSuccess && NULL != *pDlgInit) - { - WORD wID = *pDlgInit++; - WORD wMsg = *pDlgInit++; - DWORD dwSize = *((UNALIGNED DWORD*&)pDlgInit)++; - - // CB_ADDSTRING is stored as 0x403 - if (0x403 == wMsg) - { - CA2T szText(reinterpret_cast(pDlgInit)); - if (-1 == SendDlgItemMessage(wID, CB_ADDSTRING, 0, reinterpret_cast(static_cast(szText)))) - { - bSuccess = FALSE; - } - } - // CBEM_INSERTITEM is stored as 0x1234 - else if (0x1234 == wMsg) - { - COMBOBOXEXITEM item; - item.mask = CBEIF_TEXT; - item.iItem = -1; - item.pszText = CA2T(reinterpret_cast(pDlgInit)); - if (-1 == SendDlgItemMessage(wID, CBEM_INSERTITEM, 0, (LPARAM)&item)) - { - bSuccess = FALSE; - } - } - pDlgInit = (LPWORD)((LPBYTE)pDlgInit + dwSize); - } - } - } - } - return bSuccess; - } -}; - -template -INT_PTR CALLBACK CDialogImplBaseT< TBase >::StartDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - CDialogImplBaseT< TBase >* pThis = (CDialogImplBaseT< TBase >*)_AtlWinModule.ExtractCreateWndData(); - ATLASSERT(pThis != NULL); - if(!pThis) - { - return 0; - } - pThis->m_hWnd = hWnd; - // Initialize the thunk. This was allocated in CDialogImpl::DoModal or - // CDialogImpl::Create, so failure is unexpected here. - - pThis->m_thunk.Init((WNDPROC)pThis->GetDialogProc(), pThis); - DLGPROC pProc = (DLGPROC)pThis->m_thunk.GetWNDPROC(); - DLGPROC pOldProc = (DLGPROC)::SetWindowLongPtr(hWnd, DWLP_DLGPROC, (LONG_PTR)pProc); -#ifdef _DEBUG - // check if somebody has subclassed us already since we discard it - if(pOldProc != StartDialogProc) - ATLTRACE(atlTraceWindowing, 0, _T("Subclassing through a hook discarded.\n")); -#else - pOldProc; // avoid unused warning -#endif - return pProc(hWnd, uMsg, wParam, lParam); -} - -template -INT_PTR CALLBACK CDialogImplBaseT< TBase >::DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - CDialogImplBaseT< TBase >* pThis = (CDialogImplBaseT< TBase >*)hWnd; - // set a ptr to this message and save the old value - _ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam); - const _ATL_MSG* pOldMsg = pThis->m_pCurrentMsg; - pThis->m_pCurrentMsg = &msg; - // pass to the message map to process - LRESULT lRes; - BOOL bRet = pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0); - // restore saved value for the current message - ATLASSERT(pThis->m_pCurrentMsg == &msg); - pThis->m_pCurrentMsg = pOldMsg; - // set result if message was handled - if(bRet) - { - switch (uMsg) - { - case WM_COMPAREITEM: - case WM_VKEYTOITEM: - case WM_CHARTOITEM: - case WM_INITDIALOG: - case WM_QUERYDRAGICON: - case WM_CTLCOLORMSGBOX: - case WM_CTLCOLOREDIT: - case WM_CTLCOLORLISTBOX: - case WM_CTLCOLORBTN: - case WM_CTLCOLORDLG: - case WM_CTLCOLORSCROLLBAR: - case WM_CTLCOLORSTATIC: - // return directly - bRet = (BOOL)lRes; - break; - default: - // return in DWL_MSGRESULT - ::SetWindowLongPtr(pThis->m_hWnd, DWLP_MSGRESULT, lRes); - break; - } - } - else if(uMsg == WM_NCDESTROY) - { - // mark dialog as destryed - pThis->m_dwState |= WINSTATE_DESTROYED; - } - - if((pThis->m_dwState & WINSTATE_DESTROYED) && pThis->m_pCurrentMsg == NULL) - { - // clear out window handle - HWND hWndThis = pThis->m_hWnd; - pThis->m_hWnd = NULL; - pThis->m_dwState &= ~WINSTATE_DESTROYED; - // clean up after dialog is destroyed - pThis->OnFinalMessage(hWndThis); - } - return bRet; -} - -typedef CDialogImplBaseT CDialogImplBase; - -template -class ATL_NO_VTABLE CDialogImpl : public CDialogImplBaseT< TBase > -{ -public: -#ifdef _DEBUG - bool m_bModal; - CDialogImpl() : m_bModal(false) { } -#endif //_DEBUG - // modal dialogs - INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow(), LPARAM dwInitParam = NULL) - { - BOOL result; - - ATLASSUME(m_hWnd == NULL); - - // Allocate the thunk structure here, where we can fail - // gracefully. - - result = m_thunk.Init(NULL,NULL); - if (result == FALSE) - { - SetLastError(ERROR_OUTOFMEMORY); - return -1; - } - - _AtlWinModule.AddCreateWndData(&m_thunk.cd, (CDialogImplBaseT< TBase >*)this); -#ifdef _DEBUG - m_bModal = true; -#endif //_DEBUG - return ::DialogBoxParam(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(static_cast(this)->IDD), - hWndParent, T::StartDialogProc, dwInitParam); - } - BOOL EndDialog(int nRetCode) - { - ATLASSERT(::IsWindow(m_hWnd)); -#ifdef _DEBUG - ATLASSUME(m_bModal); // must be a modal dialog -#endif //_DEBUG - return ::EndDialog(m_hWnd, nRetCode); - } - // modeless dialogs - HWND Create(HWND hWndParent, LPARAM dwInitParam = NULL) - { - BOOL result; - - ATLASSUME(m_hWnd == NULL); - - // Allocate the thunk structure here, where we can fail - // gracefully. - - result = m_thunk.Init(NULL,NULL); - if (result == FALSE) - { - SetLastError(ERROR_OUTOFMEMORY); - return NULL; - } - - _AtlWinModule.AddCreateWndData(&m_thunk.cd, (CDialogImplBaseT< TBase >*)this); -#ifdef _DEBUG - m_bModal = false; -#endif //_DEBUG - HWND hWnd = ::CreateDialogParam(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(static_cast(this)->IDD), - hWndParent, T::StartDialogProc, dwInitParam); - ATLASSUME(m_hWnd == hWnd); - return hWnd; - } - // for CComControl - HWND Create(HWND hWndParent, RECT&, LPARAM dwInitParam = NULL) - { - return Create(hWndParent, dwInitParam); - } - BOOL DestroyWindow() - { - ATLASSERT(::IsWindow(m_hWnd)); -#ifdef _DEBUG - ATLASSERT(!m_bModal); // must not be a modal dialog -#endif //_DEBUG - return ::DestroyWindow(m_hWnd); - } -}; - -///////////////////////////////////////////////////////////////////////////// -// CAxDialogImpl - Implements a dialog box that hosts ActiveX controls - -#ifndef _ATL_NO_HOSTING - - -template -class ATL_NO_VTABLE CAxDialogImpl : public CDialogImplBaseT< TBase > -{ -public: -#ifdef _DEBUG - bool m_bModal; - CAxDialogImpl() : m_bModal(false) { } -#endif //_DEBUG - int GetIDD() - { - return( static_cast(this)->IDD ); - } - virtual DLGPROC GetDialogProc() - { - return DialogProc; - } - static INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - // modal dialogs - INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow(), LPARAM dwInitParam = NULL) - { - ATLASSUME(m_hWnd == NULL); - _AtlWinModule.AddCreateWndData(&m_thunk.cd, (CDialogImplBaseT< TBase >*)this); -#ifdef _DEBUG - m_bModal = true; -#endif //_DEBUG - return AtlAxDialogBox(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(static_cast(this)->IDD), - hWndParent, T::StartDialogProc, dwInitParam); - } - BOOL EndDialog(int nRetCode) - { - ATLASSERT(::IsWindow(m_hWnd)); -#ifdef _DEBUG - ATLASSUME(m_bModal); // must be a modal dialog -#endif //_DEBUG - return ::EndDialog(m_hWnd, nRetCode); - } - // modeless dialogs - HWND Create(HWND hWndParent, LPARAM dwInitParam = NULL) - { - ATLASSUME(m_hWnd == NULL); - _AtlWinModule.AddCreateWndData(&m_thunk.cd, (CDialogImplBaseT< TBase >*)this); -#ifdef _DEBUG - m_bModal = false; -#endif //_DEBUG - HWND hWnd = AtlAxCreateDialog(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(static_cast(this)->IDD), - hWndParent, T::StartDialogProc, dwInitParam); - ATLASSUME(m_hWnd == hWnd); - return hWnd; - } - // for CComControl - HWND Create(HWND hWndParent, RECT&, LPARAM dwInitParam = NULL) - { - return Create(hWndParent, dwInitParam); - } - BOOL DestroyWindow() - { - ATLASSERT(::IsWindow(m_hWnd)); -#ifdef _DEBUG - ATLASSERT(!m_bModal); // must not be a modal dialog -#endif //_DEBUG - return ::DestroyWindow(m_hWnd); - } - -// Event handling support and Message map - HRESULT AdviseSinkMap(bool bAdvise) - { - if(!bAdvise && m_hWnd == NULL) - { - // window is gone, controls are already unadvised - ATLTRACE(atlTraceControls, 1, _T("CAxDialogImpl::AdviseSinkMap called after the window was destroyed\n")); - return S_OK; - } - HRESULT hRet = E_NOTIMPL; - __if_exists(T::_GetSinkMapFinder) - { - T* pT = static_cast(this); - hRet = AtlAdviseSinkMap(pT, bAdvise); - } - return hRet; - } - - typedef CAxDialogImpl< T, TBase > thisClass; - BEGIN_MSG_MAP(thisClass) - MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) - MESSAGE_HANDLER(WM_DESTROY, OnDestroy) - END_MSG_MAP() - - virtual HRESULT CreateActiveXControls(UINT nID) - { - // Load dialog template and InitData - HRSRC hDlgInit = ::FindResource(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(nID), (LPTSTR)_ATL_RT_DLGINIT); - BYTE* pInitData = NULL; - HGLOBAL hData = NULL; - HRESULT hr = S_OK; - if (hDlgInit != NULL) - { - hData = ::LoadResource(_AtlBaseModule.GetResourceInstance(), hDlgInit); - if (hData != NULL) - pInitData = (BYTE*) ::LockResource(hData); - } - - HRSRC hDlg = ::FindResource(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(nID), (LPTSTR)RT_DIALOG); - if (hDlg != NULL) - { - HGLOBAL hResource = ::LoadResource(_AtlBaseModule.GetResourceInstance(), hDlg); - DLGTEMPLATE* pDlg = NULL; - if (hResource != NULL) - { - pDlg = (DLGTEMPLATE*) ::LockResource(hResource); - if (pDlg != NULL) - { - // Get first control on the template - BOOL bDialogEx = _DialogSplitHelper::IsDialogEx(pDlg); - WORD nItems = _DialogSplitHelper::DlgTemplateItemCount(pDlg); - - // Get first control on the dialog - DLGITEMTEMPLATE* pItem = _DialogSplitHelper::FindFirstDlgItem(pDlg); - HWND hWndPrev = GetWindow(GW_CHILD); - - // Create all ActiveX cotnrols in the dialog template and place them in the correct tab order (z-order) - for (WORD nItem = 0; nItem < nItems; nItem++) - { - DWORD wID = bDialogEx ? ((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->id : pItem->id; - if (_DialogSplitHelper::IsActiveXControl(pItem, bDialogEx)) - { - BYTE* pData = NULL; - DWORD dwLen = _DialogSplitHelper::FindCreateData(wID, pInitData, &pData); - CComPtr spStream; - if (dwLen != 0) - { - HGLOBAL h = GlobalAlloc(GHND, dwLen); - if (h != NULL) - { - BYTE* pBytes = (BYTE*) GlobalLock(h); - BYTE* pSource = pData; - Checked::memcpy_s(pBytes, dwLen, pSource, dwLen); - GlobalUnlock(h); - CreateStreamOnHGlobal(h, TRUE, &spStream); - } - else - { - hr = E_OUTOFMEMORY; - break; - } - } - - CComBSTR bstrLicKey; - hr = _DialogSplitHelper::ParseInitData(spStream, &bstrLicKey.m_str); - if (SUCCEEDED(hr)) - { - CAxWindow2 wnd; - // Get control caption. - LPWSTR pszClassName = - bDialogEx ? - (LPWSTR)(((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem) + 1) : - (LPWSTR)(pItem + 1); - // Get control rect. - RECT rect; - rect.left = - bDialogEx ? - ((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->x : - pItem->x; - rect.top = - bDialogEx ? - ((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->y : - pItem->y; - rect.right = rect.left + - (bDialogEx ? - ((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->cx : - pItem->cx); - rect.bottom = rect.top + - (bDialogEx ? - ((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->cy : - pItem->cy); - - // Convert from dialog units to screen units - MapDialogRect(&rect); - - // Create AxWindow with a NULL caption. - wnd.Create(m_hWnd, - &rect, - NULL, - (bDialogEx ? - ((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->style : - pItem->style) | WS_TABSTOP, - bDialogEx ? - ((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->exStyle : - 0, - bDialogEx ? - ((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->id : - pItem->id, - NULL); - - if (wnd != NULL) - { - // Set the Help ID - if (bDialogEx && ((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->helpID != 0) - wnd.SetWindowContextHelpId(((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->helpID); - // Try to create the ActiveX control. - hr = wnd.CreateControlLic(pszClassName, spStream, NULL, bstrLicKey); - if (FAILED(hr)) - break; - // Set the correct tab position. - if (nItem == 0) - hWndPrev = HWND_TOP; - wnd.SetWindowPos(hWndPrev, 0,0,0,0,SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); - hWndPrev = wnd; - } - else - { - hr = AtlHresultFromLastError(); - } - } - } - else - { - if (nItem != 0) - hWndPrev = ::GetWindow(hWndPrev, GW_HWNDNEXT); - } - pItem = _DialogSplitHelper::FindNextDlgItem(pItem, bDialogEx); - } - } - else - hr = AtlHresultFromLastError(); - } - else - hr = AtlHresultFromLastError(); - } - return hr; - } - - LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - // initialize controls in dialog with DLGINIT resource section - ExecuteDlgInit(static_cast(this)->IDD); - AdviseSinkMap(true); - bHandled = FALSE; - return 1; - } - - LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) - { - AdviseSinkMap(false); - bHandled = FALSE; - return 1; - } - -// Accelerators handling - needs to be called from a message loop - BOOL IsDialogMessage(LPMSG pMsg) - { - if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) && - (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST)) - return FALSE; - - // find a direct child of the dialog from the window that has focus - HWND hWndCtl = ::GetFocus(); - if(IsChild(hWndCtl) && ::GetParent(hWndCtl) != m_hWnd) - { - do - { - hWndCtl = ::GetParent(hWndCtl); - } - while (::GetParent(hWndCtl) != m_hWnd); - } - // give controls a chance to translate this message - if (::SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)pMsg) == 1) - return TRUE; - - // do the Windows default thing - return CDialogImplBaseT< TBase >::IsDialogMessage(pMsg); - } -}; - -template -INT_PTR CALLBACK CAxDialogImpl< T, TBase >::DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - CAxDialogImpl< T, TBase >* pThis = (CAxDialogImpl< T, TBase >*)hWnd; - if (uMsg == WM_INITDIALOG) - { - HRESULT hr; - if (FAILED(hr = pThis->CreateActiveXControls(pThis->GetIDD()))) - { - pThis->DestroyWindow(); - SetLastError(hr & 0x0000FFFF); - return FALSE; - } - } - return CDialogImplBaseT< TBase >::DialogProc(hWnd, uMsg, wParam, lParam); -} -#endif //_ATL_NO_HOSTING - -///////////////////////////////////////////////////////////////////////////// -// CSimpleDialog - Prebuilt modal dialog that uses standard buttons - -template -class CSimpleDialog : public CDialogImplBase -{ -public: - INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow()) - { - ATLASSUME(m_hWnd == NULL); - _AtlWinModule.AddCreateWndData(&m_thunk.cd, (CDialogImplBase*)this); - INT_PTR nRet = ::DialogBox(_AtlBaseModule.GetResourceInstance(), - MAKEINTRESOURCE(t_wDlgTemplateID), hWndParent, StartDialogProc); - m_hWnd = NULL; - return nRet; - } - - typedef CSimpleDialog thisClass; - BEGIN_MSG_MAP(thisClass) - MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) - COMMAND_RANGE_HANDLER(IDOK, IDNO, OnCloseCmd) - END_MSG_MAP() - - LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) - { - // initialize controls in dialog with DLGINIT resource section - ExecuteDlgInit(t_wDlgTemplateID); - if(t_bCenter) - CenterWindow(GetParent()); - return TRUE; - } - - LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) - { - ::EndDialog(m_hWnd, wID); - return 0; - } -}; - -///////////////////////////////////////////////////////////////////////////// -// CContainedWindow - Implements a contained window - -template -class CContainedWindowT : public TBase -{ -public: - CWndProcThunk m_thunk; - LPCTSTR m_lpszClassName; - WNDPROC m_pfnSuperWindowProc; - CMessageMap* m_pObject; - DWORD m_dwMsgMapID; - const _ATL_MSG* m_pCurrentMsg; - - // If you use this constructor you must supply - // the Window Class Name, Object* and Message Map ID - // Later to the Create call - CContainedWindowT() : m_pCurrentMsg(NULL) - { } - - CContainedWindowT(LPTSTR lpszClassName, CMessageMap* pObject, DWORD dwMsgMapID = 0) - : m_lpszClassName(lpszClassName), - m_pfnSuperWindowProc(::DefWindowProc), - m_pObject(pObject), m_dwMsgMapID(dwMsgMapID), - m_pCurrentMsg(NULL) - { } - - CContainedWindowT(CMessageMap* pObject, DWORD dwMsgMapID = 0) - : m_lpszClassName(TBase::GetWndClassName()), - m_pfnSuperWindowProc(::DefWindowProc), - m_pObject(pObject), m_dwMsgMapID(dwMsgMapID), - m_pCurrentMsg(NULL) - { } - - void SwitchMessageMap(DWORD dwMsgMapID) - { - m_dwMsgMapID = dwMsgMapID; - } - - const _ATL_MSG* GetCurrentMessage() const - { - return m_pCurrentMsg; - } - - LRESULT DefWindowProc() - { - const _ATL_MSG* pMsg = m_pCurrentMsg; - LRESULT lRes = 0; - if (pMsg != NULL) - lRes = DefWindowProc(pMsg->message, pMsg->wParam, pMsg->lParam); - return lRes; - } - - LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) - { -#ifdef STRICT - return ::CallWindowProc(m_pfnSuperWindowProc, m_hWnd, uMsg, wParam, lParam); -#else - return ::CallWindowProc((FARPROC)m_pfnSuperWindowProc, m_hWnd, uMsg, wParam, lParam); -#endif - } - static LRESULT CALLBACK StartWindowProc(HWND hWnd, UINT uMsg, - WPARAM wParam, LPARAM lParam) - { - CContainedWindowT< TBase >* pThis = (CContainedWindowT< TBase >*)_AtlWinModule.ExtractCreateWndData(); - ATLASSERT(pThis != NULL); - if(!pThis) - { - return 0; - } - pThis->m_hWnd = hWnd; - - // Initialize the thunk. This was allocated in CContainedWindowT::Create, - // so failure is unexpected here. - - pThis->m_thunk.Init(WindowProc, pThis); - WNDPROC pProc = pThis->m_thunk.GetWNDPROC(); - WNDPROC pOldProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc); -#ifdef _DEBUG - // check if somebody has subclassed us already since we discard it - if(pOldProc != StartWindowProc) - ATLTRACE(atlTraceWindowing, 0, _T("Subclassing through a hook discarded.\n")); -#else - pOldProc; // avoid unused warning -#endif - return pProc(hWnd, uMsg, wParam, lParam); - } - - static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) - { - CContainedWindowT< TBase >* pThis = (CContainedWindowT< TBase >*)hWnd; - ATLASSERT(pThis); - if(!pThis) - { - return 0; - } - ATLASSERT(pThis->m_hWnd != NULL); - ATLASSERT(pThis->m_pObject != NULL); - if(!pThis->m_hWnd || !pThis->m_pObject) - { - return 0; - } - // set a ptr to this message and save the old value - _ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam); - const _ATL_MSG* pOldMsg = pThis->m_pCurrentMsg; - pThis->m_pCurrentMsg = &msg; - // pass to the message map to process - LRESULT lRes; - BOOL bRet = pThis->m_pObject->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, pThis->m_dwMsgMapID); - // restore saved value for the current message - ATLASSERT(pThis->m_pCurrentMsg == &msg); - pThis->m_pCurrentMsg = pOldMsg; - // do the default processing if message was not handled - if(!bRet) - { - if(uMsg != WM_NCDESTROY) - lRes = pThis->DefWindowProc(uMsg, wParam, lParam); - else - { - // unsubclass, if needed - LONG_PTR pfnWndProc = ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC); - lRes = pThis->DefWindowProc(uMsg, wParam, lParam); - if(pThis->m_pfnSuperWindowProc != ::DefWindowProc && ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC) == pfnWndProc) - ::SetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC, (LONG_PTR)pThis->m_pfnSuperWindowProc); - // clear out window handle - pThis->m_hWnd = NULL; - } - } - return lRes; - } - - ATOM RegisterWndSuperclass() - { - USES_ATL_SAFE_ALLOCA; - ATOM atom = 0; - size_t cchBuff = _tcslen(m_lpszClassName) + 14; - LPTSTR szBuff = (LPTSTR)_ATL_SAFE_ALLOCA( (cchBuff * sizeof(TCHAR)), _ATL_SAFE_ALLOCA_DEF_THRESHOLD); - - WNDCLASSEX wc; - wc.cbSize = sizeof(WNDCLASSEX); - - // Try global class - if(!::GetClassInfoEx(NULL, m_lpszClassName, &wc)) - { - // try local class - if(!::GetClassInfoEx(_AtlBaseModule.GetModuleInstance(), m_lpszClassName, &wc)) - return atom; - } - - m_pfnSuperWindowProc = wc.lpfnWndProc; - Checked::tcscpy_s(szBuff, cchBuff, _T("ATL:")); - Checked::tcscat_s(szBuff, cchBuff, m_lpszClassName); - - WNDCLASSEX wc1; - wc1.cbSize = sizeof(WNDCLASSEX); - atom = (ATOM)::GetClassInfoEx(_AtlBaseModule.GetModuleInstance(), szBuff, &wc1); - - if(atom == 0) // register class - { - wc.lpszClassName = szBuff; - wc.lpfnWndProc = StartWindowProc; - wc.hInstance = _AtlBaseModule.GetModuleInstance(); - wc.style &= ~CS_GLOBALCLASS; // we don't register global classes - - atom = AtlWinModuleRegisterClassEx(&_AtlWinModule, &wc); - } - return atom; - } - - HWND Create(HWND hWndParent, _U_RECT rect, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, - _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - BOOL result; - ATLASSUME(m_hWnd == NULL); - - ATOM atom = RegisterWndSuperclass(); - if(atom == 0) - return NULL; - - // Allocate the thunk structure here, where we can fail gracefully. - - result = m_thunk.Init(NULL,NULL); - if (result == FALSE) - { - SetLastError(ERROR_OUTOFMEMORY); - return NULL; - } - - _AtlWinModule.AddCreateWndData(&m_thunk.cd, this); - - if(MenuOrID.m_hMenu == NULL && (dwStyle & WS_CHILD)) - MenuOrID.m_hMenu = (HMENU)(UINT_PTR)this; - if(rect.m_lpRect == NULL) - rect.m_lpRect = &TBase::rcDefault; - - dwStyle = TWinTraits::GetWndStyle(dwStyle); - dwExStyle = TWinTraits::GetWndExStyle(dwExStyle); - - HWND hWnd = ::CreateWindowEx(dwExStyle, MAKEINTATOM(atom), szWindowName, - dwStyle, - rect.m_lpRect->left, rect.m_lpRect->top, - rect.m_lpRect->right - rect.m_lpRect->left, - rect.m_lpRect->bottom - rect.m_lpRect->top, - hWndParent, MenuOrID.m_hMenu, - _AtlBaseModule.GetModuleInstance(), lpCreateParam); - ATLASSUME(m_hWnd == hWnd); - return hWnd; - } - - HWND Create(CMessageMap* pObject, DWORD dwMsgMapID, HWND hWndParent, _U_RECT rect, - LPCTSTR szWindowName = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, - _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - m_lpszClassName = TBase::GetWndClassName(); - m_pfnSuperWindowProc = ::DefWindowProc; - m_pObject = pObject; - m_dwMsgMapID = dwMsgMapID; - return Create(hWndParent, rect, szWindowName, dwStyle, dwExStyle, MenuOrID, lpCreateParam); - } - - HWND Create(LPCTSTR lpszClassName, CMessageMap* pObject, DWORD dwMsgMapID, HWND hWndParent, _U_RECT rect, LPCTSTR szWindowName = NULL, - DWORD dwStyle = 0, DWORD dwExStyle = 0, _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) - { - m_lpszClassName = lpszClassName; - m_pfnSuperWindowProc = ::DefWindowProc; - m_pObject = pObject; - m_dwMsgMapID = dwMsgMapID; - return Create(hWndParent, rect, szWindowName, dwStyle, dwExStyle, MenuOrID, lpCreateParam); - } - - BOOL SubclassWindow(HWND hWnd) - { - BOOL result; - ATLASSUME(m_hWnd == NULL); - ATLASSERT(::IsWindow(hWnd)); - - result = m_thunk.Init(WindowProc, this); - if (result == FALSE) - { - return result; - } - - WNDPROC pProc = m_thunk.GetWNDPROC(); - WNDPROC pfnWndProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc); - if(pfnWndProc == NULL) - return FALSE; - m_pfnSuperWindowProc = pfnWndProc; - m_hWnd = hWnd; - return TRUE; - } - - // Use only if you want to subclass before window is destroyed, - // WindowProc will automatically subclass when window goes away - HWND UnsubclassWindow(BOOL bForce = FALSE) - { - ATLASSUME(m_hWnd != NULL); - - WNDPROC pOurProc = m_thunk.GetWNDPROC(); - WNDPROC pActiveProc = (WNDPROC)::GetWindowLongPtr(m_hWnd, GWLP_WNDPROC); - - HWND hWnd = NULL; - if (bForce || pOurProc == pActiveProc) - { - if(!::SetWindowLongPtr(m_hWnd, GWLP_WNDPROC, (LONG_PTR)m_pfnSuperWindowProc)) - return NULL; - - m_pfnSuperWindowProc = ::DefWindowProc; - hWnd = m_hWnd; - m_hWnd = NULL; - } - return hWnd; - } - LRESULT ReflectNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - HWND hWndChild = NULL; - - switch(uMsg) - { - case WM_COMMAND: - if(lParam != NULL) // not from a menu - hWndChild = (HWND)lParam; - break; - case WM_NOTIFY: - hWndChild = ((LPNMHDR)lParam)->hwndFrom; - break; - case WM_PARENTNOTIFY: - switch(LOWORD(wParam)) - { - case WM_CREATE: - case WM_DESTROY: - hWndChild = (HWND)lParam; - break; - default: - hWndChild = GetDlgItem(HIWORD(wParam)); - break; - } - break; - case WM_DRAWITEM: - if(wParam) // not from a menu - hWndChild = ((LPDRAWITEMSTRUCT)lParam)->hwndItem; - break; - case WM_MEASUREITEM: - if(wParam) // not from a menu - hWndChild = GetDlgItem(((LPMEASUREITEMSTRUCT)lParam)->CtlID); - break; - case WM_COMPAREITEM: - if(wParam) // not from a menu - hWndChild = ((LPCOMPAREITEMSTRUCT)lParam)->hwndItem; - break; - case WM_DELETEITEM: - if(wParam) // not from a menu - hWndChild = ((LPDELETEITEMSTRUCT)lParam)->hwndItem; - - break; - case WM_VKEYTOITEM: - case WM_CHARTOITEM: - case WM_HSCROLL: - case WM_VSCROLL: - hWndChild = (HWND)lParam; - break; - case WM_CTLCOLORBTN: - case WM_CTLCOLORDLG: - case WM_CTLCOLOREDIT: - case WM_CTLCOLORLISTBOX: - case WM_CTLCOLORMSGBOX: - case WM_CTLCOLORSCROLLBAR: - case WM_CTLCOLORSTATIC: - hWndChild = (HWND)lParam; - break; - default: - break; - } - - if(hWndChild == NULL) - { - bHandled = FALSE; - return 1; - } - - ATLASSERT(::IsWindow(hWndChild)); - return ::SendMessage(hWndChild, OCM__BASE + uMsg, wParam, lParam); - } -}; - -typedef CContainedWindowT CContainedWindow; - -///////////////////////////////////////////////////////////////////////////// -// _DialogSizeHelper - helpers for calculating the size of a dialog template - -class _DialogSizeHelper -{ -public: -//local struct used for implementation -#pragma pack(push, 1) - struct _ATL_DLGTEMPLATEEX - { - WORD dlgVer; - WORD signature; - DWORD helpID; - DWORD exStyle; - DWORD style; - WORD cDlgItems; - short x; - short y; - short cx; - short cy; - }; -#pragma pack(pop) - - static void GetDialogSize(const DLGTEMPLATE* pTemplate, SIZE* pSize, bool bPropertyPage = false) - { - // If the dialog has a font we use it otherwise we default - // to the system font. - TCHAR szFace[LF_FACESIZE]; - WORD wFontSize = 0; - GetSizeInDialogUnits(pTemplate, pSize); - BOOL bFont = GetFont(pTemplate, szFace, &wFontSize); - if (bFont) - { - ConvertDialogUnitsToPixels(szFace, wFontSize, pSize, bPropertyPage); - } - else - { - ConvertDialogUnitsToPixels(NULL, 0, pSize, bPropertyPage); - } - } - - static void GetFontDimensions(LPCTSTR pszFontFace, WORD wFontSize, SIZE* pSizeChar, LONG *ptmHeight) - { - if (pszFontFace != NULL) - { - // Attempt to create the font to be used in the dialog box - HDC hDC = ::GetDC(NULL); - if (hDC != NULL) - { - LOGFONT lf; - memset(&lf, 0, sizeof(LOGFONT)); - lf.lfHeight = -MulDiv(wFontSize, GetDeviceCaps(hDC, LOGPIXELSY), 72); - lf.lfWeight = FW_NORMAL; - lf.lfCharSet = DEFAULT_CHARSET; - Checked::tcsncpy_s(lf.lfFaceName, _countof(lf.lfFaceName), pszFontFace, _TRUNCATE); - - HFONT hNewFont = CreateFontIndirect(&lf); - if (hNewFont != NULL) - { - TEXTMETRIC tm; - SIZE size; - HFONT hFontOld = (HFONT)SelectObject(hDC, hNewFont); - GetTextMetrics(hDC, &tm); - ::GetTextExtentPoint(hDC, - _T("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"), 52, - &size); - SelectObject(hDC, hFontOld); - DeleteObject(hNewFont); - *ptmHeight = tm.tmHeight; - pSizeChar->cy = tm.tmHeight + tm.tmExternalLeading; - pSizeChar->cx = (size.cx + 26) / 52; - ::ReleaseDC(NULL, hDC); - return; - } - ::ReleaseDC(NULL, hDC); - } - } - // Could not create font or no font name was not specified - LONG nDlgBaseUnits = GetDialogBaseUnits(); - pSizeChar->cx = LOWORD(nDlgBaseUnits); - *ptmHeight = pSizeChar->cy = HIWORD(nDlgBaseUnits); - } - -// ID of the dialog template used for property sheet in comctl32.dll -#define IDD_PROPSHEET_ID 1006 - - static void ConvertDialogUnitsToPixels(LPCTSTR pszFontFace, WORD wFontSize, SIZE* pSizePixel, bool bPropertyPage = false) - { - LONG tmHeight; - SIZE sizeFontChar; - GetFontDimensions(pszFontFace, wFontSize, &sizeFontChar, &tmHeight); - if (bPropertyPage) - { - // Get the font used by the property sheet - HINSTANCE hInst = LoadLibrary(_T("COMCTL32.DLL")); - if (hInst != NULL) - { - HRSRC hResource = ::FindResource(hInst, - MAKEINTRESOURCE(IDD_PROPSHEET_ID), - RT_DIALOG); - if (hResource != NULL) - { - HGLOBAL hTemplate = LoadResource(hInst, hResource); - if (hTemplate != NULL) - { - TCHAR szFace[LF_FACESIZE]; - WORD wSize; - BOOL bFont; - bFont = _DialogSizeHelper::GetFont((DLGTEMPLATE*)hTemplate, szFace, &wSize); - FreeLibrary(hInst); - if (bFont) - { - SIZE sizeSheetFontChar; - LONG tmHeightSheetFont; - GetFontDimensions(szFace, wSize, &sizeSheetFontChar, &tmHeightSheetFont); - // Now translate to pixels compensating for the calculations made by OLEAUT32 and Dialog manager - - // Calculate the size of pixels using property sheet font. - pSizePixel->cx = MulDiv(pSizePixel->cx, sizeFontChar.cx, 4); - pSizePixel->cy = MulDiv(pSizePixel->cy, sizeSheetFontChar.cy, 8); - - // Inflate/Deflate the height to compensate for the correct font. - pSizePixel->cy = MulDiv(pSizePixel->cy, tmHeight, tmHeightSheetFont); - return ; - } - } - } - } - } - // Not property page or could not load Property sheet resource. - // Translate dialog units to pixels - pSizePixel->cx = MulDiv(pSizePixel->cx, sizeFontChar.cx, 4); - pSizePixel->cy = MulDiv(pSizePixel->cy, sizeFontChar.cy, 8); - } - - static BOOL IsDialogEx(const DLGTEMPLATE* pTemplate) - { - return ((_ATL_DLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF; - } - - static BOOL HasFont(const DLGTEMPLATE* pTemplate) - { - return (DS_SETFONT & - (IsDialogEx(pTemplate) ? - ((_ATL_DLGTEMPLATEEX*)pTemplate)->style : pTemplate->style)); - } - - static BYTE* GetFontSizeField(const DLGTEMPLATE* pTemplate) - { - BOOL bDialogEx = IsDialogEx(pTemplate); - WORD* pw; - - if (bDialogEx) - pw = (WORD*)((_ATL_DLGTEMPLATEEX*)pTemplate + 1); - else - pw = (WORD*)(pTemplate + 1); - - if (*pw == (WORD)-1) // Skip menu name string or ordinal - pw += 2; // WORDs - else - while(*pw++); - - if (*pw == (WORD)-1) // Skip class name string or ordinal - pw += 2; // WORDs - else - while(*pw++); - - while (*pw++); // Skip caption string - - return (BYTE*)pw; - } - - static BOOL GetFont(__in const DLGTEMPLATE* pTemplate, __out_ecount_z(LF_FACESIZE) TCHAR* pszFace, __out WORD* pFontSize) - { - ATLENSURE(pTemplate!=NULL); - if (!HasFont(pTemplate)) - return FALSE; - ATLENSURE(pszFace!=NULL); - ATLENSURE(pFontSize!=NULL); - - BYTE* pb = GetFontSizeField(pTemplate); - *pFontSize = *(WORD*)pb; - // Skip over font attributes to get to the font name - pb += sizeof(WORD) * (IsDialogEx(pTemplate) ? 3 : 1); - CW2T pszFaceTemp(reinterpret_cast(pb)); - Checked::tcsncpy_s(pszFace, LF_FACESIZE, pszFaceTemp, _TRUNCATE); - if (_tcslen(pszFace) >= LF_FACESIZE) - { // NUL not appended - pszFace[LF_FACESIZE-1] = _T('\0'); - } - return TRUE; - } - - static void GetSizeInDialogUnits(const DLGTEMPLATE* pTemplate, SIZE* pSize) - { - if (IsDialogEx(pTemplate)) - { - pSize->cx = ((_ATL_DLGTEMPLATEEX*)pTemplate)->cx; - pSize->cy = ((_ATL_DLGTEMPLATEEX*)pTemplate)->cy; - } - else - { - pSize->cx = pTemplate->cx; - pSize->cy = pTemplate->cy; - } - } -}; - -inline void AtlGetDialogSize(const DLGTEMPLATE* pTemplate, SIZE* pSize, bool bPropertyPage = false) -{ - ATLASSERT(pTemplate != NULL); - ATLASSERT(pSize != NULL); - _DialogSizeHelper::GetDialogSize(pTemplate, pSize, bPropertyPage); -} - -}; //namespace ATL - -#ifndef _ATL_NO_HOSTING - -#include - -#endif - -#endif // __ATLWIN_H__ - - - -namespace ATL -{ - -class AtlModuleRegisterWndClassInfoParamA -{ -public: - typedef LPSTR PXSTR; - typedef LPCSTR PCXSTR; - typedef _ATL_WNDCLASSINFOA _ATL_WNDCLASSINFO; - typedef WNDCLASSEXA WNDCLASSEX; - - static BOOL GetClassInfoEx(HINSTANCE hinst, PCXSTR lpszClass, WNDCLASSEX* lpwcx) - { - return ::GetClassInfoExA(hinst, lpszClass, lpwcx); - } - - _ATL_INSECURE_DEPRECATE("You must pass an output buffer size to AtlModuleRegisterWndClassInfoParamA::FormatWindowClassName") - static void FormatWindowClassName(__out_z PXSTR szBuffer, __in void* unique) - { -#pragma warning(push) -#pragma warning(disable:4996) -#if defined(_WIN64) // || or Windows 2000 - ::wsprintfA(szBuffer, "ATL:%p", unique); -#else - ::wsprintfA(szBuffer, "ATL:%8.8X", reinterpret_cast(unique)); -#endif -#pragma warning(pop) - } - - static void FormatWindowClassName(__out_ecount_z(dwBuffSize) PXSTR szBuffer, __in DWORD dwBuffSize, __in void* unique) - { -#if !defined(_ATL_MIN_CRT) - sprintf_s(szBuffer, dwBuffSize, "ATL:%p", unique); -#else - // in MIN_CRT we cannot use sprintf_s, so we simply call _itoa to generate the string - size_t cchPrefix = strlen("ATL:"); - Checked::strcpy_s(szBuffer, dwBuffSize, "ATL:"); - Checked::ui64toa_s((unsigned __int64)unique, szBuffer + cchPrefix, dwBuffSize - cchPrefix, 16); -#endif - } - - static HCURSOR LoadCursor(HINSTANCE hInstance, PCXSTR lpCursorName) - { - return ::LoadCursorA(hInstance, lpCursorName); - } - - static ATOM RegisterClassEx(_ATL_WIN_MODULE* pWinModule, const WNDCLASSEX* lpwcx) - { - return AtlWinModuleRegisterClassExA(pWinModule, lpwcx); - } -}; - -class AtlModuleRegisterWndClassInfoParamW -{ -public: - typedef LPWSTR PXSTR; - typedef LPCWSTR PCXSTR; - typedef _ATL_WNDCLASSINFOW _ATL_WNDCLASSINFO; - typedef WNDCLASSEXW WNDCLASSEX; - - static BOOL GetClassInfoEx(HINSTANCE hinst, PCXSTR lpszClass, WNDCLASSEX* lpwcx) - { - return ::GetClassInfoExW(hinst, lpszClass, lpwcx); - } - - _ATL_INSECURE_DEPRECATE("You must pass an output buffer size to AtlModuleRegisterWndClassInfoParamW::FormatWindowClassName") - static void FormatWindowClassName(__out_z PXSTR szBuffer, __in void* unique) - { -#pragma warning(push) -#pragma warning(disable:4996) -#if defined(_WIN64) // || or Windows 2000 - ::wsprintfW(szBuffer, L"ATL:%p", unique); -#else - ::wsprintfW(szBuffer, L"ATL:%8.8X", reinterpret_cast(unique)); -#endif -#pragma warning(pop) - } - - static void FormatWindowClassName(__out_ecount_z(dwBuffSize) PXSTR szBuffer, __in DWORD dwBuffSize, __in void* unique) - { -#if !defined(_ATL_MIN_CRT) - swprintf_s(szBuffer, dwBuffSize, L"ATL:%p", unique); -#else - // in MIN_CRT we cannot use sprintf_s, so we simply call _itoa to generate the string - size_t cchPrefix = wcslen(L"ATL:"); - Checked::wcscpy_s(szBuffer, dwBuffSize, L"ATL:"); - Checked::ui64tow_s((unsigned __int64)unique, szBuffer + cchPrefix, dwBuffSize - cchPrefix, 16); -#endif - } - - static HCURSOR LoadCursor(HINSTANCE hInstance, PCXSTR lpCursorName) - { - return ::LoadCursorW(hInstance, lpCursorName); - } - - static ATOM RegisterClassEx(_ATL_WIN_MODULE* pWinModule, const WNDCLASSEX* lpwcx) - { - return AtlWinModuleRegisterClassExW(pWinModule, lpwcx); - } -}; - -ATLINLINE ATLAPIINL_(ATOM) AtlWinModuleRegisterClassExA(_ATL_WIN_MODULE* pWinModule, const WNDCLASSEXA *lpwc) -{ - if (pWinModule == NULL || lpwc == NULL) - return 0; - ATOM atom = ::RegisterClassExA(lpwc); - BOOL bRet = pWinModule->m_rgWindowClassAtoms.Add(atom); - ATLASSERT(bRet); - (bRet); - return atom; -} - -ATLINLINE ATLAPIINL_(ATOM) AtlWinModuleRegisterClassExW(_ATL_WIN_MODULE* pWinModule, const WNDCLASSEXW *lpwc) -{ - if (pWinModule == NULL || lpwc == NULL) - return 0; - ATOM atom = ::RegisterClassExW(lpwc); - BOOL bRet = pWinModule->m_rgWindowClassAtoms.Add(atom); - ATLASSERT(bRet); - (bRet); - return atom; -} - - -template -ATLINLINE ATOM AtlModuleRegisterWndClassInfoT(_ATL_BASE_MODULE* pBaseModule, _ATL_WIN_MODULE* pWinModule, typename T::_ATL_WNDCLASSINFO* p, WNDPROC* pProc, T) -{ - if (pBaseModule == NULL || pWinModule == NULL || p == NULL || pProc == NULL) - { - ATLTRACE(atlTraceWindowing, 0, _T("ERROR : Invalid Arguments to AtlModuleRegisterWndClassInfoT\n")); - ATLASSERT(0); - return 0; - } - - if (p->m_atom == 0) - { - ATL::CComCritSecLock lock(pWinModule->m_csWindowCreate, false); - if (FAILED(lock.Lock())) - { - ATLTRACE(atlTraceWindowing, 0, _T("ERROR : Unable to lock critical section in AtlModuleRegisterWndClassInfoT\n")); - ATLASSERT(0); - return 0; - } - if(p->m_atom == 0) - { - if (p->m_lpszOrigName != NULL) - { - ATLASSERT(pProc != NULL); - T::PCXSTR lpsz = p->m_wc.lpszClassName; - WNDPROC proc = p->m_wc.lpfnWndProc; - - T::WNDCLASSEX wc; - wc.cbSize = sizeof(T::WNDCLASSEX); - // Try global class - if(!T::GetClassInfoEx(NULL, p->m_lpszOrigName, &wc)) - { - // try process local - if(!T::GetClassInfoEx(pBaseModule->m_hInst, p->m_lpszOrigName, &wc)) - { - ATLTRACE(atlTraceWindowing, 0, "ERROR : Could not obtain Window Class information for %s\n", p->m_lpszOrigName); - return 0; - } - } - p->m_wc = wc; - p->pWndProc = p->m_wc.lpfnWndProc; - p->m_wc.lpszClassName = lpsz; - p->m_wc.lpfnWndProc = proc; - } - else - { - p->m_wc.hCursor = T::LoadCursor(p->m_bSystemCursor ? NULL : pBaseModule->m_hInstResource, - p->m_lpszCursorID); - } - - p->m_wc.hInstance = pBaseModule->m_hInst; - p->m_wc.style &= ~CS_GLOBALCLASS; // we don't register global classes - if (p->m_wc.lpszClassName == NULL) - { -#if _SECURE_ATL - T::FormatWindowClassName(p->m_szAutoName, _countof(p->m_szAutoName), &p->m_wc); -#else - T::FormatWindowClassName(p->m_szAutoName, &p->m_wc); -#endif - p->m_wc.lpszClassName = p->m_szAutoName; - } - T::WNDCLASSEX wcTemp; - wcTemp = p->m_wc; - p->m_atom = static_cast(T::GetClassInfoEx(p->m_wc.hInstance, p->m_wc.lpszClassName, &wcTemp)); - if (p->m_atom == 0) - { - p->m_atom = T::RegisterClassEx(pWinModule, &p->m_wc); - } - } - } - - if (p->m_lpszOrigName != NULL) - { - ATLASSERT(pProc != NULL); - ATLASSERT(p->pWndProc != NULL); - *pProc = p->pWndProc; - } - return p->m_atom; -} - -ATLINLINE ATLAPIINL_(ATOM) AtlWinModuleRegisterWndClassInfoA(_ATL_WIN_MODULE* pWinModule, _ATL_BASE_MODULE* pBaseModule, _ATL_WNDCLASSINFOA* p, WNDPROC* pProc) -{ - AtlModuleRegisterWndClassInfoParamA templateParameter; - return AtlModuleRegisterWndClassInfoT(pBaseModule, pWinModule, p, pProc, templateParameter); -} - -ATLINLINE ATLAPIINL_(ATOM) AtlWinModuleRegisterWndClassInfoW(_ATL_WIN_MODULE* pWinModule, _ATL_BASE_MODULE* pBaseModule, _ATL_WNDCLASSINFOW* p, WNDPROC* pProc) -{ - AtlModuleRegisterWndClassInfoParamW templateParameter; - return AtlModuleRegisterWndClassInfoT(pBaseModule, pWinModule, p, pProc, templateParameter); -} - -//All exports go here -#ifndef _ATL_DLL - -ATLINLINE ATLAPI_(HDC) AtlCreateTargetDC(HDC hdc, DVTARGETDEVICE* ptd) -{ - USES_CONVERSION_EX; - - // cases hdc, ptd, hdc is metafile, hic -// NULL, NULL, n/a, Display -// NULL, !NULL, n/a, ptd -// !NULL, NULL, FALSE, hdc -// !NULL, NULL, TRUE, display -// !NULL, !NULL, FALSE, ptd -// !NULL, !NULL, TRUE, ptd - - if (ptd != NULL) - { - LPDEVMODEOLE lpDevMode; - LPOLESTR lpszDriverName; - LPOLESTR lpszDeviceName; - LPOLESTR lpszPortName; - - if (ptd->tdExtDevmodeOffset == 0) - lpDevMode = NULL; - else - lpDevMode = (LPDEVMODEOLE) ((LPSTR)ptd + ptd->tdExtDevmodeOffset); - - lpszDriverName = (LPOLESTR)((BYTE*)ptd + ptd->tdDriverNameOffset); - lpszDeviceName = (LPOLESTR)((BYTE*)ptd + ptd->tdDeviceNameOffset); - lpszPortName = (LPOLESTR)((BYTE*)ptd + ptd->tdPortNameOffset); - - return ::CreateDC(OLE2CT_EX_DEF(lpszDriverName), OLE2CT_EX_DEF(lpszDeviceName), OLE2CT_EX_DEF(lpszPortName), DEVMODEOLE2T_EX(lpDevMode)); - } - else if (hdc == NULL || GetDeviceCaps(hdc, TECHNOLOGY) == DT_METAFILE) - return ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL); - else - return hdc; -} - - -///////////////////////////////////////////////////////////////////////////// -// Windowing : Conversion helpers - -ATLINLINE ATLAPI_(void) AtlHiMetricToPixel(const SIZEL * lpSizeInHiMetric, LPSIZEL lpSizeInPix) -{ - ATLENSURE_THROW(lpSizeInHiMetric!=NULL, E_POINTER); - ATLENSURE_THROW(lpSizeInPix!=NULL, E_POINTER); - int nPixelsPerInchX; // Pixels per logical inch along width - int nPixelsPerInchY; // Pixels per logical inch along height - - HDC hDCScreen = GetDC(NULL); - ATLASSERT(hDCScreen != NULL); - nPixelsPerInchX = GetDeviceCaps(hDCScreen, LOGPIXELSX); - nPixelsPerInchY = GetDeviceCaps(hDCScreen, LOGPIXELSY); - ReleaseDC(NULL, hDCScreen); - - lpSizeInPix->cx = MAP_LOGHIM_TO_PIX(lpSizeInHiMetric->cx, nPixelsPerInchX); - lpSizeInPix->cy = MAP_LOGHIM_TO_PIX(lpSizeInHiMetric->cy, nPixelsPerInchY); -} - -ATLINLINE ATLAPI_(void) AtlPixelToHiMetric(const SIZEL * lpSizeInPix, LPSIZEL lpSizeInHiMetric) -{ - ATLENSURE_THROW(lpSizeInPix!=NULL, E_POINTER); - ATLENSURE_THROW(lpSizeInHiMetric!=NULL, E_POINTER); - int nPixelsPerInchX; // Pixels per logical inch along width - int nPixelsPerInchY; // Pixels per logical inch along height - - HDC hDCScreen = GetDC(NULL); - ATLASSERT(hDCScreen != NULL); - nPixelsPerInchX = GetDeviceCaps(hDCScreen, LOGPIXELSX); - nPixelsPerInchY = GetDeviceCaps(hDCScreen, LOGPIXELSY); - ReleaseDC(NULL, hDCScreen); - - lpSizeInHiMetric->cx = MAP_PIX_TO_LOGHIM(lpSizeInPix->cx, nPixelsPerInchX); - lpSizeInHiMetric->cy = MAP_PIX_TO_LOGHIM(lpSizeInPix->cy, nPixelsPerInchY); -} -#endif // !_ATL_DLL - -} //namespace ATL - - -#pragma pack(pop) - -#ifndef _ATL_NO_PRAGMA_WARNINGS -#pragma warning (pop) -#endif diff --git a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/statreg.h b/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/statreg.h deleted file mode 100644 index 2f183ea56..000000000 --- a/prog/3rdPartyLibs/wtl-8.1/include/vc8_atl/statreg.h +++ /dev/null @@ -1,1470 +0,0 @@ -// This is a part of the Active Template Library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Active Template Library Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Active Template Library product. - -#ifndef __STATREG_H__ -#define __STATREG_H__ - -#pragma once - -#ifndef __cplusplus - #error ATL requires C++ compilation (use a .cpp suffix) -#endif - -#ifndef __ATLBASE_H__ - #error statreg.h requires atlbase.h to be included first -#endif - -#pragma warning(push) -#pragma warning(disable:4571) //catch(...) blocks compiled with /EHs do NOT catch or re-throw Structured Exceptions - -#define E_ATL_REGISTRAR_DESC 0x0201 -#define E_ATL_NOT_IN_MAP 0x0202 -#define E_ATL_UNEXPECTED_EOS 0x0203 -#define E_ATL_VALUE_SET_FAILED 0x0204 -#define E_ATL_RECURSE_DELETE_FAILED 0x0205 -#define E_ATL_EXPECTING_EQUAL 0x0206 -#define E_ATL_CREATE_KEY_FAILED 0x0207 -#define E_ATL_DELETE_KEY_FAILED 0x0208 -#define E_ATL_OPEN_KEY_FAILED 0x0209 -#define E_ATL_CLOSE_KEY_FAILED 0x020A -#define E_ATL_UNABLE_TO_COERCE 0x020B -#define E_ATL_BAD_HKEY 0x020C -#define E_ATL_MISSING_OPENKEY_TOKEN 0x020D -#define E_ATL_CONVERT_FAILED 0x020E -#define E_ATL_TYPE_NOT_SUPPORTED 0x020F -#define E_ATL_COULD_NOT_CONCAT 0x0210 -#define E_ATL_COMPOUND_KEY 0x0211 -#define E_ATL_INVALID_MAPKEY 0x0212 -#define E_ATL_UNSUPPORTED_VT 0x0213 -#define E_ATL_VALUE_GET_FAILED 0x0214 -#define E_ATL_VALUE_TOO_LARGE 0x0215 -#define E_ATL_MISSING_VALUE_DELIMETER 0x0216 -#define E_ATL_DATA_NOT_BYTE_ALIGNED 0x0217 - -#pragma pack(push,_ATL_PACKING) -namespace ATL -{ -const TCHAR chDirSep = _T('\\'); -const TCHAR chRightBracket = _T('}'); -const TCHAR chLeftBracket = _T('{'); -const TCHAR chQuote = _T('\''); -const TCHAR chEquals = _T('='); -const LPCTSTR szStringVal = _T("S"); -const LPCTSTR multiszStringVal = _T("M"); -const LPCTSTR szDwordVal = _T("D"); -const LPCTSTR szBinaryVal = _T("B"); -const LPCTSTR szValToken = _T("Val"); -const LPCTSTR szForceRemove = _T("ForceRemove"); -const LPCTSTR szNoRemove = _T("NoRemove"); -const LPCTSTR szDelete = _T("Delete"); - - -// Implementation helper -class CExpansionVectorEqualHelper -{ -public: - static bool IsEqualKey(const LPTSTR k1, const LPTSTR k2) - { - if (lstrcmpi(k1, k2) == 0) - return true; - return false; - } - - // Not used - static bool IsEqualValue(const LPCOLESTR /*v1*/, const LPCOLESTR /*v2*/) - { - return false; - } -}; - -// Implementation helper -class CExpansionVector : public CSimpleMap -{ -public: - ~CExpansionVector() - { - ClearReplacements(); - } - - BOOL Add(LPCTSTR lpszKey, LPCOLESTR lpszValue) - { - ATLASSERT(lpszKey != NULL && lpszValue != NULL); - if (lpszKey == NULL || lpszValue == NULL) - return FALSE; - - HRESULT hRes = S_OK; - - size_t cbKey = (lstrlen(lpszKey)+1)*sizeof(TCHAR); - TCHAR* szKey = NULL; - - ATLTRY(szKey = new TCHAR[cbKey];) - CAutoVectorPtr spKey; - spKey.Attach(szKey); - - size_t cbValue = (ocslen(lpszValue)+1)*sizeof(OLECHAR); - LPOLESTR szValue = NULL; - ATLTRY(szValue = new OLECHAR[cbValue];) - CAutoVectorPtr spValue; - spValue.Attach(szValue); - - if (szKey == NULL || szValue == NULL) - hRes = E_OUTOFMEMORY; - else - { - Checked::memcpy_s(szKey, cbKey, lpszKey, cbKey); - Checked::memcpy_s(szValue, cbValue, lpszValue, cbValue); - if (!CSimpleMap::Add(szKey, szValue)) - hRes = E_OUTOFMEMORY; - } - if (SUCCEEDED(hRes)) - { - spKey.Detach(); - spValue.Detach(); - } - return SUCCEEDED(hRes); - } - HRESULT ClearReplacements() - { - for (int i = 0; i < GetSize(); i++) - { - delete []GetKeyAt(i); - delete []GetValueAt(i); - } - RemoveAll(); - return S_OK; - } -}; - -class CRegObject; - -class CRegParser -{ -public: - CRegParser(CRegObject* pRegObj); - - HRESULT PreProcessBuffer(__in_z LPTSTR lpszReg, __deref_out_z LPTSTR* ppszReg); - HRESULT RegisterBuffer(__in_z LPTSTR szReg, BOOL bRegister); - -protected: - - void SkipWhiteSpace(); - HRESULT NextToken(__out_ecount_z(MAX_VALUE) LPTSTR szToken); - HRESULT AddValue(__in CRegKey& rkParent, __in_z_opt LPCTSTR szValueName, __out_ecount_z(MAX_VALUE) LPTSTR szToken); - BOOL CanForceRemoveKey(LPCTSTR szKey); - BOOL HasSubKeys(HKEY hkey); - BOOL HasValues(HKEY hkey); - HRESULT RegisterSubkeys(__out_ecount_z(MAX_VALUE) LPTSTR szToken, __in HKEY hkParent, __in BOOL bRegister, __in BOOL bInRecovery = FALSE); - BOOL IsSpace(TCHAR ch); - LPTSTR m_pchCur; - - CRegObject* m_pRegObj; - - HRESULT GenerateError(UINT) {return DISP_E_EXCEPTION;} - //HRESULT HandleReplacements(LPTSTR& szToken); - HRESULT SkipAssignment(__inout_ecount_z(MAX_VALUE) LPTSTR szToken); - - BOOL EndOfVar() { return chQuote == *m_pchCur && chQuote != *CharNext(m_pchCur); } - static LPTSTR StrChr(__in_z LPTSTR lpsz, __in TCHAR ch); - static HKEY HKeyFromString(__in_z LPTSTR szToken); - static BYTE ChToByte(const TCHAR ch); - static BOOL VTFromRegType(LPCTSTR szValueType, VARTYPE& vt); - static const TCHAR* const rgszNeverDelete[]; - static const int cbNeverDelete; - static const int MAX_VALUE = 4096; - static const int MAX_TYPE = 4096; - - // Implementation Helper - class CParseBuffer - { - public: - int nPos; - int nSize; - LPTSTR p; - CParseBuffer(int nInitial) - { - if (nInitial < 100) - nInitial = 1000; - nPos = 0; - nSize = nInitial; - p = (LPTSTR) ::ATL::AtlCoTaskMemCAlloc(nSize,static_cast(sizeof(TCHAR))); - if (p != NULL) - *p = NULL; - } - ~CParseBuffer() - { - CoTaskMemFree(p); - } - BOOL Append(const TCHAR* pch, int nChars) - { - ATLASSERT(p != NULL); - int newSize = nPos + nChars + 1; - if ((newSize <= nPos) || (newSize <= nChars)) - return FALSE; - - if (newSize >= nSize) - { - while (newSize >= nSize) { - if (nSize > INT_MAX / 2) - return FALSE; - nSize *= 2; - } - LPTSTR pTemp = (LPTSTR)::ATL::AtlCoTaskMemRecalloc(p, nSize, sizeof(TCHAR)); - if (pTemp == NULL) - return FALSE; - p = pTemp; - } - if ((nPos < 0) || (nPos >= nSize) || nSize - nPos > nSize) - return FALSE; - -#pragma warning(push) -#pragma warning(disable: 22008) - /* Prefast false warning is fired here despite the all above checks */ - Checked::memcpy_s(p + nPos, (nSize-nPos) * sizeof(TCHAR), pch, int(nChars * sizeof(TCHAR))); - nPos += nChars; - *(p + nPos) = NULL; -#pragma warning(pop) - return TRUE; - } - - BOOL AddChar(const TCHAR* pch) - { -#ifndef _UNICODE - int nChars = int(CharNext(pch) - pch); -#else - int nChars = 1; -#endif - return Append(pch, nChars); - - } - BOOL AddString(LPCOLESTR lpsz) - { - if (lpsz == NULL) - { - return FALSE; - } - USES_CONVERSION_EX; - LPCTSTR lpszT = OLE2CT_EX(lpsz, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); - if (lpszT == NULL) - { - return FALSE; - } - return Append(lpszT, (int)lstrlen(lpszT)); - } - LPTSTR Detach() - { - LPTSTR lp = p; - p = NULL; - nSize = nPos = 0; - return lp; - } - - }; -}; - -#if defined(_ATL_DLL) || defined(_ATL_DLL_IMPL) -class ATL_NO_VTABLE CRegObject - : public IRegistrar -#else -class CRegObject : public IRegistrarBase -#endif -{ -public: - -#if defined(_ATL_DLL) || defined(_ATL_DLL_IMPL) - -#else - STDMETHOD(QueryInterface)(const IID &,void ** ) - { - ATLASSERT(_T("statically linked in CRegObject is not a com object. Do not callthis function")); - return E_NOTIMPL; - } - - STDMETHOD_(ULONG, AddRef)(void) - { - ATLASSERT(_T("statically linked in CRegObject is not a com object. Do not callthis function")); - return 1; - } - STDMETHOD_(ULONG, Release)(void) - { - ATLASSERT(_T("statically linked in CRegObject is not a com object. Do not callthis function")); - return 0; - } -#endif - virtual ~CRegObject(){ClearReplacements();} - HRESULT FinalConstruct() { return m_csMap.Init(); } - void FinalRelease() {} - - - // Map based methods - HRESULT STDMETHODCALLTYPE AddReplacement(LPCOLESTR lpszKey, LPCOLESTR lpszItem); - HRESULT STDMETHODCALLTYPE ClearReplacements(); - LPCOLESTR StrFromMap(__in_z LPTSTR lpszKey); - - // Register via a given mechanism - HRESULT STDMETHODCALLTYPE ResourceRegister(LPCOLESTR pszFileName, UINT nID, LPCOLESTR pszType); - HRESULT STDMETHODCALLTYPE ResourceRegisterSz(LPCOLESTR pszFileName, LPCOLESTR pszID, LPCOLESTR pszType); - HRESULT STDMETHODCALLTYPE ResourceUnregister(LPCOLESTR pszFileName, UINT nID, LPCOLESTR pszType); - HRESULT STDMETHODCALLTYPE ResourceUnregisterSz(LPCOLESTR pszFileName, LPCOLESTR pszID, LPCOLESTR pszType); - HRESULT STDMETHODCALLTYPE FileRegister(LPCOLESTR bstrFileName) - { - return CommonFileRegister(bstrFileName, TRUE); - } - - HRESULT STDMETHODCALLTYPE FileUnregister(LPCOLESTR bstrFileName) - { - return CommonFileRegister(bstrFileName, FALSE); - } - - HRESULT STDMETHODCALLTYPE StringRegister(LPCOLESTR bstrData) - { - return RegisterWithString(bstrData, TRUE); - } - - HRESULT STDMETHODCALLTYPE StringUnregister(LPCOLESTR bstrData) - { - return RegisterWithString(bstrData, FALSE); - } - -protected: - - HRESULT CommonFileRegister(LPCOLESTR pszFileName, BOOL bRegister); - HRESULT RegisterFromResource(LPCOLESTR pszFileName, LPCTSTR pszID, LPCTSTR pszType, BOOL bRegister); - HRESULT RegisterWithString(LPCOLESTR pszData, BOOL bRegister); - - static HRESULT GenerateError(UINT) {return DISP_E_EXCEPTION;} - - CExpansionVector m_RepMap; - CComObjectThreadModel::AutoDeleteCriticalSection m_csMap; -}; - -inline HRESULT STDMETHODCALLTYPE CRegObject::AddReplacement(LPCOLESTR lpszKey, LPCOLESTR lpszItem) -{ - if (lpszKey == NULL || lpszItem == NULL) - return E_INVALIDARG; - m_csMap.Lock(); - USES_CONVERSION_EX; - - LPCTSTR lpszT = OLE2CT_EX(lpszKey, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); - -#ifndef _UNICODE - if(lpszT == NULL) - return E_OUTOFMEMORY; -#endif - - BOOL bRet = m_RepMap.Add(lpszT, lpszItem); - m_csMap.Unlock(); - return bRet ? S_OK : E_OUTOFMEMORY; -} - -inline HRESULT CRegObject::RegisterFromResource(LPCOLESTR bstrFileName, LPCTSTR szID, - LPCTSTR szType, BOOL bRegister) -{ - USES_CONVERSION_EX; - - HRESULT hr; - CRegParser parser(this); - HINSTANCE hInstResDll; - HRSRC hrscReg; - HGLOBAL hReg; - DWORD dwSize; - LPSTR szRegA; - CTempBuffer szReg; - - LPCTSTR lpszBSTRFileName = OLE2CT_EX(bstrFileName, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if (lpszBSTRFileName == NULL) - { - return E_OUTOFMEMORY; - } -#endif // _UNICODE - - hInstResDll = LoadLibraryEx(lpszBSTRFileName, NULL, LOAD_LIBRARY_AS_DATAFILE); - - if (NULL == hInstResDll) - { - ATLTRACE(atlTraceRegistrar, 0, _T("Failed to LoadLibrary on %s\n"), bstrFileName); - hr = AtlHresultFromLastError(); - goto ReturnHR; - } - - hrscReg =FindResource((HMODULE)hInstResDll, szID, szType); - - if (NULL == hrscReg) - { - ATLTRACE(atlTraceRegistrar, 0, (HIWORD(szID) == NULL) ? - _T("Failed to FindResource on ID:%d TYPE:%s\n") : - _T("Failed to FindResource on ID:%s TYPE:%s\n"), - szID, szType); - hr = AtlHresultFromLastError(); - goto ReturnHR; - } - hReg = LoadResource((HMODULE)hInstResDll, hrscReg); - - if (NULL == hReg) - { - ATLTRACE(atlTraceRegistrar, 0, _T("Failed to LoadResource\n")); - hr = AtlHresultFromLastError(); - goto ReturnHR; - } - - dwSize = SizeofResource((HMODULE)hInstResDll, hrscReg); - szRegA = (LPSTR)hReg; - - // Allocate extra space for NULL. - if (dwSize + 1 < dwSize) - return E_OUTOFMEMORY; - ATLTRY(szReg.Allocate(dwSize + 1)); - if (szReg == NULL) - { - hr = E_OUTOFMEMORY; - goto ReturnHR; - } - -#ifdef _UNICODE - DWORD uniSize = ::MultiByteToWideChar(_AtlGetConversionACP(), 0, szRegA, dwSize, szReg, dwSize); - if (uniSize == 0) - { - hr = AtlHresultFromLastError(); - goto ReturnHR; - } - // Append a NULL at the end. - szReg[uniSize] = NULL; -#else - Checked::memcpy_s(szReg, dwSize, szRegA, dwSize); - // Append a NULL at the end. - szReg[dwSize] = NULL; -#endif - - - - hr = parser.RegisterBuffer(szReg, bRegister); - -ReturnHR: - - if (NULL != hInstResDll) - FreeLibrary((HMODULE)hInstResDll); - return hr; -} - -inline HRESULT STDMETHODCALLTYPE CRegObject::ResourceRegister(LPCOLESTR szFileName, UINT nID, LPCOLESTR szType) -{ - USES_CONVERSION_EX; - - LPCTSTR lpszT = OLE2CT_EX(szType, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if (lpszT == NULL) - { - return E_OUTOFMEMORY; - } -#endif // _UNICODE - - return RegisterFromResource(szFileName, MAKEINTRESOURCE(nID), lpszT, TRUE); -} - -inline HRESULT STDMETHODCALLTYPE CRegObject::ResourceRegisterSz(LPCOLESTR szFileName, LPCOLESTR szID, LPCOLESTR szType) -{ - USES_CONVERSION_EX; - if (szID == NULL || szType == NULL) - return E_INVALIDARG; - - LPCTSTR lpszID = OLE2CT_EX(szID, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); - LPCTSTR lpszType = OLE2CT_EX(szType, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if (lpszID == NULL || lpszType==NULL) - { - return E_OUTOFMEMORY; - } -#endif // _UNICODE - return RegisterFromResource(szFileName, lpszID, lpszType, TRUE); -} - -inline HRESULT STDMETHODCALLTYPE CRegObject::ResourceUnregister(LPCOLESTR szFileName, UINT nID, LPCOLESTR szType) -{ - USES_CONVERSION_EX; - - LPCTSTR lpszT = OLE2CT_EX(szType, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if (lpszT == NULL) - { - return E_OUTOFMEMORY; - } -#endif // _UNICODE - return RegisterFromResource(szFileName, MAKEINTRESOURCE(nID), lpszT, FALSE); -} - -inline HRESULT STDMETHODCALLTYPE CRegObject::ResourceUnregisterSz(LPCOLESTR szFileName, LPCOLESTR szID, LPCOLESTR szType) -{ - USES_CONVERSION_EX; - if (szID == NULL || szType == NULL) - return E_INVALIDARG; - - LPCTSTR lpszID = OLE2CT_EX(szID, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); - LPCTSTR lpszType = OLE2CT_EX(szType, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if (lpszID == NULL || lpszType == NULL) - { - return E_OUTOFMEMORY; - } -#endif // _UNICODE - - return RegisterFromResource(szFileName, lpszID, lpszType, FALSE); -} - -inline HRESULT CRegObject::RegisterWithString(LPCOLESTR bstrData, BOOL bRegister) -{ - USES_CONVERSION_EX; - CRegParser parser(this); - - LPCTSTR szReg = OLE2CT_EX(bstrData, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if (szReg == NULL) - { - return E_OUTOFMEMORY; - } -#endif // _UNICODE - - HRESULT hr = parser.RegisterBuffer((LPTSTR)szReg, bRegister); - - return hr; -} - -inline HRESULT CRegObject::ClearReplacements() -{ - m_csMap.Lock(); - HRESULT hr = m_RepMap.ClearReplacements(); - m_csMap.Unlock(); - return hr; -} - - -inline LPCOLESTR CRegObject::StrFromMap(__in_z LPTSTR lpszKey) -{ - m_csMap.Lock(); - LPCOLESTR lpsz = m_RepMap.Lookup(lpszKey); - if (lpsz == NULL) // not found!! - ATLTRACE(atlTraceRegistrar, 0, _T("Map Entry not found\n")); - m_csMap.Unlock(); - return lpsz; -} - -inline HRESULT CRegObject::CommonFileRegister(LPCOLESTR bstrFileName, BOOL bRegister) -{ - USES_CONVERSION_EX; - - CRegParser parser(this); - - LPCTSTR lpszBSTRFileName = OLE2CT_EX(bstrFileName, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); -#ifndef _UNICODE - if (lpszBSTRFileName == NULL) - { - return E_OUTOFMEMORY; - } -#endif // _UNICODE - - HANDLE hFile = CreateFile(lpszBSTRFileName, GENERIC_READ, 0, NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_READONLY, - NULL); - if (INVALID_HANDLE_VALUE == hFile) - { - ATLTRACE2(atlTraceRegistrar, 0, _T("Failed to CreateFile on %s\n"), lpszBSTRFileName); - return AtlHresultFromLastError(); - } - - HRESULT hRes = S_OK; - DWORD cbRead; - DWORD cbFile = GetFileSize(hFile, NULL); // No HiOrder DWORD required - - CTempBuffer szReg; - // Extra space for NULL. - ATLTRY(szReg.Allocate(cbFile + 1)); - if (szReg == NULL) - { - hRes = E_OUTOFMEMORY; - goto ReturnHR; - } - - if (ReadFile(hFile, szReg, cbFile, &cbRead, NULL) == 0) - { - ATLTRACE2(atlTraceRegistrar, 0, "Read Failed on file%s\n", lpszBSTRFileName); - hRes = AtlHresultFromLastError(); - } - if (SUCCEEDED(hRes)) - { - szReg[cbRead] = NULL; - -#ifdef _UNICODE - CTempBuffer szConverted; - ATLTRY(szConverted.Allocate(cbFile + 1)); - if (szConverted == NULL) - { - hRes = E_OUTOFMEMORY; - goto ReturnHR; - - } - if (::MultiByteToWideChar(_AtlGetConversionACP(), 0, szReg, cbFile + 1, szConverted, cbFile + 1) == 0) - { - hRes = AtlHresultFromLastError(); - goto ReturnHR; - } - - - - -#else - LPTSTR szConverted = szReg; -#endif - hRes = parser.RegisterBuffer(szConverted, bRegister); - } -ReturnHR: - CloseHandle(hFile); - return hRes; -} - -__declspec(selectany) const TCHAR* const CRegParser::rgszNeverDelete[] = -{ - _T("AppID"), - _T("CLSID"), - _T("Component Categories"), - _T("FileType"), - _T("Interface"), - _T("Hardware"), - _T("Mime"), - _T("SAM"), - _T("SECURITY"), - _T("SYSTEM"), - _T("Software"), - _T("TypeLib") -}; - -__declspec(selectany) const int CRegParser::cbNeverDelete = sizeof(rgszNeverDelete) / sizeof(LPCTSTR*); - - -inline BOOL CRegParser::VTFromRegType(LPCTSTR szValueType, VARTYPE& vt) -{ - struct typemap - { - LPCTSTR lpsz; - VARTYPE vt; - }; -#pragma warning (push) -#pragma warning (disable : 4640) // construction of local static object is not thread-safe - - static const typemap map[] = { - {szStringVal, VT_BSTR}, - {multiszStringVal, VT_BSTR | VT_BYREF}, - {szDwordVal, VT_UI4}, - {szBinaryVal, VT_UI1} - }; - -#pragma warning (pop) - - for (int i=0;i= szOrig + MAX_VALUE) - return GenerateError(E_ATL_VALUE_TOO_LARGE); - - for (int i = 0; i < (int)nChars; i++, szToken++, pchPrev++) - *szToken = *pchPrev; - } - - if (NULL == *m_pchCur) - { - ATLTRACE(atlTraceRegistrar, 0, _T("NextToken : Unexpected End of File\n")); - return GenerateError(E_ATL_UNEXPECTED_EOS); - } - - *szToken = NULL; - m_pchCur = CharNext(m_pchCur); - } - - else - { - // Handle non-quoted ie parse up till first "White Space" - while (NULL != *m_pchCur && !IsSpace(*m_pchCur)) - { - LPTSTR pchPrev = m_pchCur; - m_pchCur = CharNext(m_pchCur); - - INT_PTR nChars = m_pchCur - pchPrev; - - // Make sure we have room for nChars plus terminating NULL - if ((szToken + nChars + 1) >= szOrig + MAX_VALUE) - return GenerateError(E_ATL_VALUE_TOO_LARGE); - - for (int i = 0; i < (int)nChars; i++, szToken++, pchPrev++) - *szToken = *pchPrev; - } - - *szToken = NULL; - } - return S_OK; -} - -inline HRESULT CRegParser::AddValue(__in CRegKey& rkParent, __in_z_opt LPCTSTR szValueName, __out_ecount_z(MAX_VALUE) LPTSTR szToken) -{ - HRESULT hr; - - TCHAR szValue[MAX_VALUE]; - VARTYPE vt = VT_EMPTY; - LONG lRes = ERROR_SUCCESS; - UINT nIDRes = 0; - - if (FAILED(hr = NextToken(szValue))) - return hr; - if (!VTFromRegType(szValue, vt)) - { - ATLTRACE(atlTraceRegistrar, 0, _T("%s Type not supported\n"), szValue); - return GenerateError(E_ATL_TYPE_NOT_SUPPORTED); - } - - SkipWhiteSpace(); - if (FAILED(hr = NextToken(szValue))) - return hr; - - switch (vt) - { - case VT_BSTR: - { - lRes = rkParent.SetStringValue(szValueName, szValue); - ATLTRACE(atlTraceRegistrar, 2, _T("Setting Value %s at %s\n"), szValue, !szValueName ? _T("default") : szValueName); - break; - } - case VT_BSTR | VT_BYREF: - { - ATLTRACE(atlTraceRegistrar, 2, _T("Setting Value %s at %s\n"), szValue, !szValueName ? _T("default") : szValueName); - int nLen = lstrlen(szValue) + 2; //Allocate space for double null termination. - CTempBuffer pszDestValue; - //nLen should be >= the max size of the target buffer. - ATLTRY(pszDestValue.Allocate(nLen)); - if (pszDestValue != NULL) - { - TCHAR* p = pszDestValue; - TCHAR* q = szValue; - nLen = 0; - while (*q != _T('\0')) - { - TCHAR* r = CharNext(q); - if (*q == _T('\\') && *r == _T('0')) - { - *p++ = NULL; - q = CharNext(r); - } - else - { - *p = *q; -#ifndef _UNICODE - if (IsDBCSLeadByte(*q)) - { - p++; - q++; - //Protect from Lead byte followed by the zero terminator.May skip beyond the end of the string. - if (*q == _T('\0')) { break; } - *p = *q; - } -#endif - p++; - q++; - } - nLen ++; - } - //Always terminate with 2 NULLs. - *p = NULL; - p++; - *p = NULL; - lRes = rkParent.SetMultiStringValue(szValueName, pszDestValue); - } - else - { - lRes = ERROR_OUTOFMEMORY; - } - } - break; - case VT_UI4: - { - ULONG ulVal; - USES_CONVERSION_EX; - - LPOLESTR lpszV = T2OLE_EX(szValue, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); - #ifndef _UNICODE - if(lpszV == NULL) - return E_OUTOFMEMORY; - #endif - VarUI4FromStr(lpszV, 0, 0, &ulVal); - - lRes = rkParent.SetDWORDValue(szValueName, ulVal); - ATLTRACE(atlTraceRegistrar, 2, _T("Setting Value %d at %s\n"), ulVal, !szValueName ? _T("default") : szValueName); - break; - } - case VT_UI1: - { - int cbValue = lstrlen(szValue); - if (cbValue & 0x00000001) - { - ATLTRACE(atlTraceRegistrar, 0, _T("Binary Data does not fall on BYTE boundries\n")); - return E_FAIL; - } - int cbValDiv2 = cbValue/2; - CTempBuffer rgBinary; - ATLTRY(rgBinary.Allocate(cbValDiv2)); - if (rgBinary == NULL) - return E_FAIL; - memset(rgBinary, 0, cbValDiv2); - for (int irg = 0; irg < cbValue; irg++) - rgBinary[(irg/2)] |= (ChToByte(szValue[irg])) << (4*(1 - (irg & 0x00000001))); - lRes = RegSetValueEx(rkParent, szValueName, 0, REG_BINARY, rgBinary, cbValDiv2); - break; - } - } - - if (ERROR_SUCCESS != lRes) - { - nIDRes = E_ATL_VALUE_SET_FAILED; - return AtlHresultFromWin32(lRes); - } - - if (FAILED(hr = NextToken(szToken))) - return hr; - - return S_OK; -} - -inline BOOL CRegParser::CanForceRemoveKey(LPCTSTR szKey) -{ - for (int iNoDel = 0; iNoDel < cbNeverDelete; iNoDel++) - if (!lstrcmpi(szKey, rgszNeverDelete[iNoDel])) - return FALSE; // We cannot delete it - - return TRUE; -} - -inline BOOL CRegParser::HasSubKeys(HKEY hkey) -{ - DWORD cbSubKeys = 0; - - if (RegQueryInfoKey(hkey, NULL, NULL, NULL, - &cbSubKeys, NULL, NULL, - NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) - { - ATLTRACE(atlTraceRegistrar, 0, _T("Should not be here!!\n")); - ATLASSERT(FALSE); - return FALSE; - } - - return cbSubKeys > 0; -} - -inline BOOL CRegParser::HasValues(HKEY hkey) -{ - DWORD cbValues = 0; - - LONG lResult = RegQueryInfoKey(hkey, NULL, NULL, NULL, - NULL, NULL, NULL, - &cbValues, NULL, NULL, NULL, NULL); - if (ERROR_SUCCESS != lResult) - { - ATLTRACE(atlTraceRegistrar, 0, _T("RegQueryInfoKey Failed ")); - ATLASSERT(FALSE); - return FALSE; - } - - if (1 == cbValues) - { - DWORD cbMaxName= MAX_VALUE; - TCHAR szValueName[MAX_VALUE]; - // Check to see if the Value is default or named - lResult = RegEnumValue(hkey, 0, szValueName, &cbMaxName, NULL, NULL, NULL, NULL); - if (ERROR_SUCCESS == lResult && (szValueName[0] != NULL)) - return TRUE; // Named Value means we have a value - return FALSE; - } - - return cbValues > 0; // More than 1 means we have a non-default value -} - -inline HRESULT CRegParser::SkipAssignment(__inout_ecount_z(MAX_VALUE) LPTSTR szToken) -{ - HRESULT hr; - TCHAR szValue[MAX_VALUE]; - - if (*szToken == chEquals) - { - if (FAILED(hr = NextToken(szToken))) - return hr; - // Skip assignment - SkipWhiteSpace(); - if (FAILED(hr = NextToken(szValue))) - return hr; - if (FAILED(hr = NextToken(szToken))) - return hr; - } - - return S_OK; -} - -inline HRESULT CRegParser::PreProcessBuffer(__in_z LPTSTR lpszReg, __deref_out_z LPTSTR* ppszReg) -{ - ATLASSERT(lpszReg != NULL); - ATLASSERT(ppszReg != NULL); - - if (lpszReg == NULL || ppszReg == NULL) - return E_POINTER; - - *ppszReg = NULL; - int nSize = lstrlen(lpszReg)*2; - CParseBuffer pb(nSize); - if (pb.p == NULL) - return E_OUTOFMEMORY; - m_pchCur = lpszReg; - HRESULT hr = S_OK; - - while (*m_pchCur != NULL) // look for end - { - if (*m_pchCur == _T('%')) - { - m_pchCur = CharNext(m_pchCur); - if (*m_pchCur == _T('%')) - { - if (!pb.AddChar(m_pchCur)) - { - hr = E_OUTOFMEMORY; - break; - } - } - else - { - LPTSTR lpszNext = StrChr(m_pchCur, _T('%')); - if (lpszNext == NULL) - { - ATLTRACE(atlTraceRegistrar, 0, _T("Error no closing %% found\n")); - hr = GenerateError(E_ATL_UNEXPECTED_EOS); - break; - } - if ((lpszNext-m_pchCur) > 31) - { - hr = E_FAIL; - break; - } - int nLength = int(lpszNext - m_pchCur); - TCHAR buf[32]; - Checked::tcsncpy_s(buf, _countof(buf), m_pchCur, nLength); - LPCOLESTR lpszVar = m_pRegObj->StrFromMap(buf); - if (lpszVar == NULL) - { - hr = GenerateError(E_ATL_NOT_IN_MAP); - break; - } - if (!pb.AddString(lpszVar)) - { - hr = E_OUTOFMEMORY; - break; - } - - while (m_pchCur != lpszNext) - m_pchCur = CharNext(m_pchCur); - } - } - else - { - if (!pb.AddChar(m_pchCur)) - { - hr = E_OUTOFMEMORY; - break; - } - } - - m_pchCur = CharNext(m_pchCur); - } - if (SUCCEEDED(hr)) - *ppszReg = pb.Detach(); - return hr; -} - -inline HRESULT CRegParser::RegisterBuffer(__in_z LPTSTR szBuffer, __in BOOL bRegister) -{ - TCHAR szToken[MAX_VALUE]; - HRESULT hr = S_OK; - - LPTSTR szReg = NULL; - hr = PreProcessBuffer(szBuffer, &szReg); - if (FAILED(hr)) - return hr; - - ATLTRACE(atlTraceRegistrar, 0, _T("%s\n"), szReg); - - m_pchCur = szReg; - - // Preprocess szReg - - while (NULL != *m_pchCur) - { - if (FAILED(hr = NextToken(szToken))) - break; - HKEY hkBase; - if ((hkBase = HKeyFromString(szToken)) == NULL) - { - ATLTRACE(atlTraceRegistrar, 0, _T("HKeyFromString failed on %s\n"), szToken); - hr = GenerateError(E_ATL_BAD_HKEY); - break; - } - - if (FAILED(hr = NextToken(szToken))) - break; - - if (chLeftBracket != *szToken) - { - ATLTRACE(atlTraceRegistrar, 0, _T("Syntax error, expecting a {, found a %s\n"), szToken); - hr = GenerateError(E_ATL_MISSING_OPENKEY_TOKEN); - break; - } - if (bRegister) - { - LPTSTR szRegAtRegister = m_pchCur; - hr = RegisterSubkeys(szToken, hkBase, bRegister); - if (FAILED(hr)) - { - ATLTRACE(atlTraceRegistrar, 0, _T("Failed to register, cleaning up!\n")); - m_pchCur = szRegAtRegister; - RegisterSubkeys(szToken, hkBase, FALSE); - break; - } - } - else - { - if (FAILED(hr = RegisterSubkeys(szToken, hkBase, bRegister))) - break; - } - - SkipWhiteSpace(); - } - CoTaskMemFree(szReg); - return hr; -} - -inline HRESULT CRegParser::RegisterSubkeys(__out_ecount_z(MAX_VALUE) LPTSTR szToken, __in HKEY hkParent, __in BOOL bRegister, __in BOOL bRecover) -{ - CRegKey keyCur; - LONG lRes; - TCHAR szKey[_MAX_PATH]; - BOOL bDelete = TRUE; - BOOL bInRecovery = bRecover; - HRESULT hr = S_OK; - - ATLTRACE(atlTraceRegistrar, 2, _T("Num Els = %d\n"), cbNeverDelete); - if (FAILED(hr = NextToken(szToken))) - return hr; - - - while (*szToken != chRightBracket) // Continue till we see a } - { - - - bDelete = TRUE; - BOOL bTokenDelete = !lstrcmpi(szToken, szDelete); - - if (!lstrcmpi(szToken, szForceRemove) || bTokenDelete) - { - if (FAILED(hr = NextToken(szToken))) - break; - - if (bRegister) - { - CRegKey rkForceRemove; - - if (StrChr(szToken, chDirSep) != NULL) - return GenerateError(E_ATL_COMPOUND_KEY); - - if (CanForceRemoveKey(szToken)) - { - rkForceRemove.Attach(hkParent); - // Error not returned. We will overwrite the values any way. - rkForceRemove.RecurseDeleteKey(szToken); - rkForceRemove.Detach(); - } - if (bTokenDelete) - { - if (FAILED(hr = NextToken(szToken))) - break; - if (FAILED(hr = SkipAssignment(szToken))) - break; - goto EndCheck; - } - } - - } - - if (!lstrcmpi(szToken, szNoRemove)) - { - bDelete = FALSE; // set even for register - if (FAILED(hr = NextToken(szToken))) - break; - } - - if (!lstrcmpi(szToken, szValToken)) // need to add a value to hkParent - { - TCHAR szValueName[_MAX_PATH]; - - - - if (FAILED(hr = NextToken(szValueName))) - break; - if (FAILED(hr = NextToken(szToken))) - break; - - if (*szToken != chEquals) - return GenerateError(E_ATL_EXPECTING_EQUAL); - - if (bRegister) - { - CRegKey rk; - - rk.Attach(hkParent); - hr = AddValue(rk, szValueName, szToken); - rk.Detach(); - - if (FAILED(hr)) - return hr; - - goto EndCheck; - } - else - { - if (!bRecover && bDelete) - { - ATLTRACE(atlTraceRegistrar, 1, _T("Deleting %s\n"), szValueName); - // We have to open the key for write to be able to delete. - CRegKey rkParent; - lRes = rkParent.Open(hkParent, NULL, KEY_WRITE); - if (lRes == ERROR_SUCCESS) - { - lRes = rkParent.DeleteValue(szValueName); - if (lRes != ERROR_SUCCESS && lRes != ERROR_FILE_NOT_FOUND) - { - // Key not present is not an error - hr = AtlHresultFromWin32(lRes); - break; - } - } - else - { - hr = AtlHresultFromWin32(lRes); - break; - } - } - if (FAILED(hr = SkipAssignment(szToken))) - break; - continue; // can never have a subkey - } - } - - if (StrChr(szToken, chDirSep) != NULL) - return GenerateError(E_ATL_COMPOUND_KEY); - - if (bRegister) - { - lRes = keyCur.Open(hkParent, szToken, KEY_READ | KEY_WRITE); - if (ERROR_SUCCESS != lRes) - { - // Failed all access try read only - lRes = keyCur.Open(hkParent, szToken, KEY_READ); - if (ERROR_SUCCESS != lRes) - { - // Finally try creating it - ATLTRACE(atlTraceRegistrar, 2, _T("Creating key %s\n"), szToken); - lRes = keyCur.Create(hkParent, szToken, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE); - if (lRes != ERROR_SUCCESS) - return AtlHresultFromWin32(lRes); - } - } - - if (FAILED(hr = NextToken(szToken))) - break; - - - if (*szToken == chEquals) - { - if (FAILED(hr = AddValue(keyCur, NULL, szToken))) // NULL == default - break; - } - } - else //Unregister - { - if (!bRecover) - { - lRes = keyCur.Open(hkParent, szToken, KEY_READ); - - } - else - lRes = ERROR_FILE_NOT_FOUND; - - - // Open failed set recovery mode - if (lRes != ERROR_SUCCESS) - bRecover = true; - - // TRACE out Key open status and if in recovery mode -#ifdef _DEBUG - if (!bRecover) - ATLTRACE(atlTraceRegistrar, 1, _T("Opened Key %s\n"), szToken); - else - ATLTRACE(atlTraceRegistrar, 0, _T("Ignoring Open key on %s : In Recovery mode\n"), szToken); -#endif //_DEBUG - - // Remember Subkey - Checked::tcsncpy_s(szKey, _countof(szKey), szToken, _TRUNCATE); - - if (FAILED(hr = NextToken(szToken))) - break; - if (FAILED(hr = SkipAssignment(szToken))) - break; - - if (*szToken == chLeftBracket && lstrlen(szToken) == 1) - { - hr = RegisterSubkeys(szToken, keyCur.m_hKey, bRegister, bRecover); - // In recover mode ignore error - if (FAILED(hr) && !bRecover) - break; - // Skip the } - if (FAILED(hr = NextToken(szToken))) - break; - } - -#ifdef _DEBUG - if (bRecover != bInRecovery) - ATLTRACE(atlTraceRegistrar, 0, _T("Ending Recovery Mode\n")); -#endif - bRecover = bInRecovery; - - if (lRes == ERROR_FILE_NOT_FOUND) - // Key already not present so not an error. - continue; - - if (lRes != ERROR_SUCCESS) - { - // We are recovery mode continue on errors else break - if (bRecover) - continue; - else - { - hr = AtlHresultFromWin32(lRes); - break; - } - } - - // If in recovery mode - if (bRecover && HasSubKeys(keyCur)) - { - // See if the KEY is in the NeverDelete list and if so, don't - if (CanForceRemoveKey(szKey) && bDelete) - { - ATLTRACE(atlTraceRegistrar, 0, _T("Deleting non-empty subkey %s by force\n"), szKey); - // Error not returned since we are in recovery mode. The error that caused recovery mode is returned - keyCur.RecurseDeleteKey(szKey); - } - continue; - } - - BOOL bHasSubKeys=HasSubKeys(keyCur); - lRes = keyCur.Close(); - if (lRes != ERROR_SUCCESS) - return AtlHresultFromWin32(lRes); - - if (bDelete&& !bHasSubKeys) - { - ATLTRACE(atlTraceRegistrar, 0, _T("Deleting Key %s\n"), szKey); - CRegKey rkParent; - rkParent.Attach(hkParent); - lRes = rkParent.DeleteSubKey(szKey); - rkParent.Detach(); - if (lRes != ERROR_SUCCESS) - { - - hr = AtlHresultFromWin32(lRes); - break; - } - } - - - - - } - -EndCheck: - - if (bRegister) - { - if (*szToken == chLeftBracket && lstrlen(szToken) == 1) - { - if (FAILED(hr = RegisterSubkeys(szToken, keyCur.m_hKey, bRegister, FALSE))) - break; - if (FAILED(hr = NextToken(szToken))) - break; - } - } - } - - return hr; -} - -}; //namespace ATL - -#pragma pack(pop) -#pragma warning(pop) - -#endif //__STATREG_H__ diff --git a/prog/3rdPartyLibs/wtl-8.1/lib/vc7_atl/atls.lib b/prog/3rdPartyLibs/wtl-8.1/lib/vc7_atl/atls.lib deleted file mode 100644 index 2428ccac0..000000000 Binary files a/prog/3rdPartyLibs/wtl-8.1/lib/vc7_atl/atls.lib and /dev/null differ diff --git a/prog/3rdPartyLibs/wtl-8.1/lib/vc8_atl/atls.lib b/prog/3rdPartyLibs/wtl-8.1/lib/vc8_atl/atls.lib deleted file mode 100644 index 7c5f42488..000000000 Binary files a/prog/3rdPartyLibs/wtl-8.1/lib/vc8_atl/atls.lib and /dev/null differ diff --git a/prog/_jBuild/_vc/win_sdk.jam b/prog/_jBuild/_vc/win_sdk.jam index 029454a8f..b95420ef6 100644 --- a/prog/_jBuild/_vc/win_sdk.jam +++ b/prog/_jBuild/_vc/win_sdk.jam @@ -22,8 +22,8 @@ if $(_WIN_SDK_TARGET_SUFFIX) { actions together quietly compile_pch_sync { - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 del $(pch) call_filtered $(_CPP_COMPILER) $(pre_opt) $(_CPP_BASE_INCLUDES) $(cpp_opt) /Fp$(pch) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed diff --git a/prog/_jBuild/defaults.jam b/prog/_jBuild/defaults.jam index a3b11d161..6001093dc 100644 --- a/prog/_jBuild/defaults.jam +++ b/prog/_jBuild/defaults.jam @@ -66,8 +66,6 @@ if ! $(__DEFAULTS_INCLUDED) { IncludeSystemDir ?= -I ; IncludeMSVCDir ?= -I ; - DefQtVer = 4.7.3 ; - Config ?= dev ; CoreLinkage ?= static ; DriverLinkage ?= static ; @@ -121,7 +119,7 @@ if ! $(__DEFAULTS_INCLUDED) { OpenSSLVer = 1.1 ; } - if ! $(Platform) in win32 win64 { DisableUsingPCH ?= yes ; } + if ! $(Platform) in win32 win64 xboxOne scarlett { DisableUsingPCH ?= yes ; } if ( $(Platform) in macosx iOS tvOS ) && $(Config) = dbg { DisableFusion ?= yes ; @@ -178,14 +176,6 @@ if ! $(__DEFAULTS_INCLUDED) { FastLink ?= yes ; # this speed-up linking but pdb become dependand on obj output } - if $(Platform) = win32 || $(Platform) = macosx { - if $(QtVer) = def { QtVer = $(DefQtVer) ; } - if $(QtVer) { QtVerStatic ?= no ; } - } else { - QtVer = ; - QtVerStatic = ; - } - switch $(Platform) { case win32 : PhysXSdk ?= 2.8.4 ; case win64 : PhysXSdk ?= 2.8.4 ; @@ -420,8 +410,6 @@ if ! $(__DEFAULTS_INCLUDED) { out = $(out)~v ; } - if $(QtVer) { if $(QtVerStatic) = yes { out = $(out)~qt$(QtVer)s ; } else { out = $(out)~qt$(QtVer) ; } } - if $(DriverLinkage) = dynamic { out = $(out)~krnlimp ; if $(CoreLinkage) = dynamic { out = $(out)~coreimp ; } diff --git a/prog/_jBuild/jBuild.jam b/prog/_jBuild/jBuild.jam index 02632373b..f62ad9cfe 100644 --- a/prog/_jBuild/jBuild.jam +++ b/prog/_jBuild/jBuild.jam @@ -479,7 +479,6 @@ rule ProcessTargetVariables PreAddIncludes = ; AddIncludes = ; UseDirectX = ; - UseWTL = ; if $(TargetType) in exe dll { if $(IsProgArtifact) = yes && $(SignatureID) { @@ -645,7 +644,6 @@ rule ClearTargetVariables PreAddIncludes = ; AddIncludes = ; UseDirectX = ; - UseWTL = ; UseQuirrel = ; AddLibs = ; Resources = ; @@ -1422,15 +1420,6 @@ rule AddDirectXLibs } } -rule AddWtlInclude -{ - if $(UseWTL) = yes { $(1) += -I$(Root)/prog/3rdPartyLibs/wtl-8.1/include/$(2)_atl -I$(Root)/prog/3rdPartyLibs/wtl-8.1/include ; } -} -rule AddWtlLibs -{ - if $(UseWTL) = yes { $(1) += -libpath:$(Root)/prog/3rdPartyLibs/wtl-8.1/lib/$(2)_atl $(3) ; } -} - rule AddForceFastcall { } @@ -2168,6 +2157,11 @@ for t_lev in 0 1 2 3 4 5 6 7 8 { if $(Platform) = android && clean-android-output in $(JAMTARGETS) { __targets = ; __targets_to_clean = ; } if $(Platform) = iOS && clean-ios-output in $(JAMTARGETS) { __targets = ; __targets_to_clean = ; } +VC_SHOW_INCLUDES_FILTER_PREFIX = "Note: including file:[ ]*" ; # matching regexp in en-US locale +VC_START_SHOW_INCLUDES_FILTER = # force en-US locale + set VSLANG=1033 " + set_filter nul" /$(VC_SHOW_INCLUDES_FILTER_PREFIX)$(_DEVTOOL_RE)(.+)/ ; # filter out paths pointing to _DEVTOOL + if $(GLOBAL_BuildDevtool) { NOCARE $(GLOBAL_BuildDevtool) ; diff --git a/prog/_jBuild/msbuild/daEditor.vcxproj b/prog/_jBuild/msbuild/daEditor.vcxproj index facf3045c..2269a2f4e 100644 --- a/prog/_jBuild/msbuild/daEditor.vcxproj +++ b/prog/_jBuild/msbuild/daEditor.vcxproj @@ -61,7 +61,7 @@ - + diff --git a/prog/_jBuild/msbuild/default.props b/prog/_jBuild/msbuild/default.props index 1a0c42a3f..c9ddfff50 100644 --- a/prog/_jBuild/msbuild/default.props +++ b/prog/_jBuild/msbuild/default.props @@ -58,7 +58,7 @@ $(GDEVTOOL)\xbox.gdk.221000\221000\ 850 $(GDEVTOOL)\ps4.sdk.$(PS4SdkVer) - 500 + 700 $(GDEVTOOL)\ps5.sdk.$(PS5SdkVer)\ $(GDEVTOOL)\android-ndk-r23b\ 2.82 diff --git a/prog/_jBuild/msbuild/projects/skyquake_vrt.args.json b/prog/_jBuild/msbuild/projects/skyquake_vrt.args.json index 640d0e972..777412a8f 100644 --- a/prog/_jBuild/msbuild/projects/skyquake_vrt.args.json +++ b/prog/_jBuild/msbuild/projects/skyquake_vrt.args.json @@ -504,6 +504,10 @@ "Id": "72e8a272-77b8-466a-b8af-c39fee270bde", "Command": "-config:xr/useVrMultiview:b=no" }, + { + "Id": "a6bfe40b-083f-42f9-8775-51402c27a63e", + "Command": "-config:xr/useFsr:b=yes" + }, { "Id": "f2b493f7-4443-42be-a834-d1e92b99881d", "Command": "-config:xr/vrMultiviewStereoMode:t=horizontal" diff --git a/prog/_jBuild/removed_code.txt b/prog/_jBuild/removed_code.txt index e9152ffe8..7476f353e 100644 --- a/prog/_jBuild/removed_code.txt +++ b/prog/_jBuild/removed_code.txt @@ -1,3 +1,8 @@ +removed on 2023/10/30: + dagor4/prog/_jBuild/win32/icl15-cpp.jam + dagor4/prog/_jBuild/win*/vc9*-*.jam + dagor4/prog/_jBuild/win*/qt-inc.jam (removed Qt support) + removed on 2023/04/14: dagor4/prog/_jBuild/_jam-2.5-src (refer to https://github.com/GaijinEntertainment/jam-G8 now) dagor4/prog/_jBuild/_codeCheck (not used since .clang-format and clang_format.py used) diff --git a/prog/_jBuild/win32/clang-cpp.jam b/prog/_jBuild/win32/clang-cpp.jam index 983073bd6..cf63cb792 100644 --- a/prog/_jBuild/win32/clang-cpp.jam +++ b/prog/_jBuild/win32/clang-cpp.jam @@ -66,9 +66,6 @@ rule ProcessCompileTarget AddForceFastcall _CPP_OPT ; AddDirectXInclude pre_opt : post_opt ; - AddWtlInclude pre_opt : vc8 ; - - if $(QtVer) { AddQtCompileOpt ; } include $(Root)/prog/_jBuild/_vc/add_fp_fast.jam ; $(Target)__CPP_OPT = -FImemory/dag_memBase.h $(post_opt) $(_CPP_OPT) -TP ; @@ -120,8 +117,8 @@ rule CheckHeaders actions together quietly compile_cpp { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 echo $(2:G=:D=) call_filtered $(_CPP_COMPILER) $(pre_opt) $(_CPP_BASE_INCLUDES) $(cpp_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed @@ -150,8 +147,8 @@ actions together quietly compile_prefast_cpp actions together quietly compile_c { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 echo $(2:G=:D=) call_filtered $(_C_COMPILER) $(pre_opt) $(_C_BASE_INCLUDES) $(c_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed diff --git a/prog/_jBuild/win32/clang-sets.jam b/prog/_jBuild/win32/clang-sets.jam index b2570c2cf..f4a27ebdd 100644 --- a/prog/_jBuild/win32/clang-sets.jam +++ b/prog/_jBuild/win32/clang-sets.jam @@ -67,25 +67,7 @@ if $(SSEVersion) = 4 { _DEF_C_CMDLINE += -msse2 ; } -_DEF_C_CMDLINE += -m32 ; - -if $(QtVer) { - _QT_DIR = $(_DEVTOOL)/Qt-$(QtVer)-vc2008 ; - if ! [ GLOB $(_QT_DIR) : * ] { exit FATAL\: \"$(_QT_DIR)\" not found! Please, update DEVTOOLS ; } - - _DEF_C_CMDLINE += - -DQT_LARGEFILE_SUPPORT -DQT_THREAD_SUPPORT -DQT_GUI_LIB -DQT_CORE_LIB - -D_STD_RTL_MEMORY=1 - /Zc:wchar_t- - ; - if $(QtVerStatic) = yes { _DEF_C_CMDLINE += -DQT_NODLL ; } else { _VC_CRT_TYPE = -MD ; } - - _QT_MOC = $(_QT_DIR)/bin/moc.exe ; - _QT_UIC = $(_QT_DIR)/bin/uic.exe ; - _QT_RCC = $(_QT_DIR)/bin/rcc.exe ; -} else { - _DEF_C_CMDLINE += /Zc:wchar_t ; -} +_DEF_C_CMDLINE += -m32 /Zc:wchar_t ; if $(UseWholeOpt) = yes { UseLLDLink = yes ; @@ -121,14 +103,6 @@ _UCRT_SRC_INC = $(_DEVTOOL)/win.sdk.100/source/10.0.19041.0/ucrt/inc ; _INCLUDE = $(_WIN_SDK_INC) $(_VC_DIR)/include $(_UCRT_INC) ; _LIBPATH = $(_UCRT_LIB) $(_WIN_SDK_LIB) $(_CLANG_DIR)/lib/clang/$(CLangVer)/lib/windows $(_VC_DIR)/lib/x86 $(_UM_LIB) ; -_INCLUDE += - $(_QT_DIR)/include/QtCore - $(_QT_DIR)/include/QtGui - $(_QT_DIR)/include/ActiveQt - $(_QT_DIR)/include - $(_QT_DIR)/mkspecs/win32-msvc2008 -; - # make linker cmd-line ### for lib in $(_LIBPATH) { _LINK += -libpath:$(lib) ; @@ -146,5 +120,3 @@ for inc in $(_INCLUDE) { } _DEF_C_CMDLINE = ; - -if $(QtVer) { include $(Root)/prog/_jBuild/win32/qt-inc.jam ; } diff --git a/prog/_jBuild/win32/icl15-cpp.jam b/prog/_jBuild/win32/icl15-cpp.jam deleted file mode 100644 index 00a6ca3e1..000000000 --- a/prog/_jBuild/win32/icl15-cpp.jam +++ /dev/null @@ -1,256 +0,0 @@ -# to be included in jBuild.jam - -rule ProcessCompileTarget -{ - # basic opts: warning/remark suppressing, additional includes etc. - local _SUPPRESS_OPT = ; - local _CONFIG_OPT = ; - local pre_opt = ; - local post_opt = ; - - if $(StrictCompile) = yes - { - # suppressed warnigs list (marked with x are not suppressed now): - # C4265 'XXX' : class has virtual functions, but destructor is not virtual - # C4127 conditional expression is constant - # x C4100 'XXX' : unreferenced formal parameter - # x 981 operands are evaluated in unspecified order - # x 383 value copied to temporary, reference to temporary used - # x 310 old-style parameter list (anachronism) - # x 174 expression has no effect - # x 111 statement is unreachable - # x 271 trailing comma is nonstandard - # C4514 'XXX' : unreferenced inline function has been removed - # C4061 enumerator 'XXX' in switch of enum 'YYY' is not explicitly handled by a case label - # C4062 enumerator 'XXX' in switch of enum 'YYY' is not handled - # C4820 'XXX' : 'N' bytes padding added after data member 'XXX::YYY' - # C4324 'XXX' : structure was padded due to __declspec(align()) - # C4668 'XXX' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' - # C4619 pragma warning : there is no warning number 'NNN' - # C4365 'XXX' : conversion from 'TYPE1' to 'TYPE2', signed/unsigned mismatch - # C4302 'type cast' : truncation from 'TYPE1' to 'TYPE2' - # C4244 '=' : conversion from 'TYPE1' to 'TYPE2', possible loss of data - # C4242 'argument' : conversion from 'TYPE1' to 'TYPE2', possible loss of data - # C4245 'argument' : conversion from 'TYPE1' to 'TYPE2', signed/unsigned mismatch - # C4101 'XXX' : unreferenced local variable - # C4201 nonstandard extension used : nameless struct/union - # C4625 'XXX' : copy constructor could not be generated because a base class copy constructor is inaccessible - # C4626 'XXX' : assignment operator could not be generated because a base class assignment operator is inaccessible - # C4800 'int' : forcing value to bool 'true' or 'false' (performance warning) - # C4018 '<' : signed/unsigned mismatch - # C4710 'XXX' : function not inlined - # C4291 'void *operator new(size_t,IMemAlloc *)' : no matching operator delete found; memory will not be freed if initialization throws an exception - # C4389 '!=' : signed/unsigned mismatch - # C4200 nonstandard extension used : zero-sized array in struct/union - # C4255 'XXX' : no function prototype given: converting '()' to '(void)' - # C4711 function 'XXX' selected for automatic inline expansion - # C4355 'this' : used in base member initializer list - # C4640 'XXX' : construction of local static object is not thread-safe - # x C4714 function 'XXX' marked as __forceinline not inlined - # C4305 'initializing' : truncation from 'double' to 'real' - # C4511 'XXX' : copy constructor could not be generated - # C4512 'XXX' : assignment operator could not be generated - # C4305 'XXX' : truncation from 'double' to 'float' - # C4738 storing 32-bit float result in memory, possible loss of performance - # C4996 'stricmp' was declared deprecated - # C4740 macro redefinition - # C4702 unreachable code - # C4826: Conversion from 'const void *' to 'void * __ptr64' is sign-extended. This may cause unexpected runtime behavior. - # C4503 decorated name length exceeded, name was truncated - # C4748: /GS can not protect parameters and local variables from local buffer overrun because optimizations are disabled in function - # C4987: nonstandard extension used: 'throw (...)' - # C4574: '_SECURE_SCL' is defined to be '0': did you mean to use '#if _SECURE_SCL'? - # C4554: '>>' : check operator precedence for possible error; use parentheses to clarif - # C4471: 'bar' : a forward declaration of an unscoped enumeration must have an underlying type (int assumed) - # C4350: behavior change: 'std::...' called instead of 'std::...' - # C4316: object allocated on the heap may not be aligned - - _SUPPRESS_OPT = -W3 -WX /wd4514 /wd4061 /wd4820 /wd4668 /wd4619 - /wd4365 /wd4127 /wd4302 /wd4242 /wd4244 /wd4265 - /wd4101 /wd4201 /wd4625 /wd4626 /wd4800 /wd4018 - /wd4710 /wd4245 /wd4291 /wd4389 /wd4200 /wd4255 - /wd4711 /wd4062 /wd4355 /wd4640 /wd4305 /wd4324 - /wd4511 /wd4512 /wd4305 /wd4738 /wd4996 /wd4005 - /wd4740 /wd4702 /wd4826 /wd4503 /wd4748 /wd4987 - /wd4574 /wd4554 /wd4471 /wd4350 /wd4316 - /wd1879 /wd3199 /wd11075 - /wd11074 #remark - /Qdiag-disable:94 /Qdiag-disable:791 - /Qdiag-disable:873 - /Qdiag-disable:161 - /Qdiag-disable:2650 - /Qdiag-disable:864 - /Qdiag-disable:597 - /Qdiag-disable:589 - /Qdiag-disable:47 #should be removed! it is useful! - /Qdiag-disable:177 #should be removed! it is useful! - /Qdiag-disable:810 #should be removed! it is useful! - - #/wd444 /wd279 /wd981 /wd383 /wd310 /wd174 /wd111 /wd271 /wd4714 ; - ; - } - else - { - _SUPPRESS_OPT = -W3 /wd4244 /wd4101 /wd4800 /wd4018 /wd4291 /wd4200 /wd4355 /wd4305 - /wd4996 /wd4005 /wd4740 /wd4748 /wd4324 /wd4503 /wd4574 /wd4554 /wd4316 - /wd1879 /wd3199 /wd11075 - /wd11074 #remark - /Qdiag-disable:94 /Qdiag-disable:791 - /Qdiag-disable:873 - /Qdiag-disable:161 - /Qdiag-disable:2650 - /Qdiag-disable:864 - /Qdiag-disable:597 - /Qdiag-disable:589 - /Qdiag-disable:47 #should be removed! it is useful! - /Qdiag-disable:177 #should be removed! it is useful! - /Qdiag-disable:810 #should be removed! it is useful! - #warning C4263: 'void B::f(int)' : member function does not override any base class virtual member function - #/w14263 - #warning C4264: 'void A::f(void)' : no override available for virtual member function from base 'A'; function is hidden - #/w14264 - ; - } - - switch $(Config) { - case dev : - _CONFIG_OPT = /GF /Gy /Oi /Ot /Qx:SSE2 /Zi /Oy- /O3 /Qprec-div- /fp:fast=2 -DDAGOR_DBGLEVEL=1 ; - case rel : - _CONFIG_OPT = /GF /Gy /Oi /Ot /Qx:SSE2 /Zi /Oy- /O3 /Qprec-div- /fp:fast=2 /Qipo -DDAGOR_DBGLEVEL=0 -DNDEBUG=1 -D_SECURE_SCL=0 ; - case irel : - _CONFIG_OPT = /GF /Gy /Oi /Ot /Qx:SSE2 /Zi /Oy- /O3 /Qprec-div- /fp:fast=2 /Qipo -DDAGOR_DBGLEVEL=-1 -DNDEBUG=1 -D_SECURE_SCL=0 ; - case dbg : - _CONFIG_OPT = /Zi /Od /RTC1 /arch:SSE2 -DDAGOR_DBGLEVEL=2 ; - case analyze : - _CONFIG_OPT = /Ox /GF /Gy /Oi /Ot /arch:SSE2 /Zi -DDAGOR_DBGLEVEL=1 /analyze ; - case prefast : - _CONFIG_OPT = /Ox /GF /Gy /Oi /Ot /arch:SSE2 /Zi -DDAGOR_DBGLEVEL=1 ; - case * : - _CONFIG_OPT = ; - } - - _CONFIG_OPT += /Qvc10 ; - - if $(Exceptions) != yes { - _CONFIG_OPT += -D_HAS_EXCEPTIONS=0 -DEA_COMPILER_NO_NOEXCEPT ; - } else { - if ($CatchSEH) != yes { - _CONFIG_OPT += /EHsc -DDAGOR_EXCEPTIONS_ENABLED=1 ; - } else { - _CONFIG_OPT += /EHac -DDAGOR_EXCEPTIONS_ENABLED=1 ; - } - } - - if $(Rtti) != yes { - _CONFIG_OPT += /GR- ; - } - - if $(Config) != dbg { - _CONFIG_OPT += $(_VC_CRT_TYPE) ; - } else { - _CONFIG_OPT += $(_VC_CRT_TYPE)d ; - } - - if $(DriverLinkage) = static { _CONFIG_OPT += -D_TARGET_STATIC_LIB=1 ; } - if $(StarForce) = yes { _CONFIG_OPT += -DSTARFORCE_PROTECT ; } - if $(UseWholeOpt) = yes { _CONFIG_OPT += /GL ; } - - if $(Analyze) = yes { _CONFIG_OPT += /analyze ; } - - # _CONFIG_OPT += /FS ; # Force Synchronous PDB Writes. - - _CPP_OPT = -I$(AddIncludes) $(_CONFIG_OPT) $(_SUPPRESS_OPT) $(CPPopt) $(GlobalCPPopt) ; - - AddForceFastcall _CPP_OPT ; - AddDirectXInclude pre_opt : post_opt ; - AddWtlInclude pre_opt : vc8 ; - - if $(QtVer) { AddQtCompileOpt ; } - - $(Target)__CPP_OPT = -FImemory/dag_memBase.h $(post_opt) $(_CPP_OPT) -TP /QMD ; - $(Target)__C_OPT = $(post_opt) $(Copt) $(_CPP_OPT) /QMD ; - $(Target)__ASM_OPT = -I$(AddIncludes) $(ASMopt) ; - $(Target)__PRE_OPT = $(pre_opt) ; - include $(Root)/prog/_jBuild/_vc/add_fd_opt.jam ; -} - - -rule DepRule -{ - local changed_dep = ; - - # add $(Root) prefix when needed - for dep in $(>) - { - switch $(dep) - { - case ?:* : changed_dep += $(dep) ; # absolute path with drive - # case \.\\* : changed_dep += asas/$(dep) ; # absolute path with root folder (./) - case \\* : changed_dep += $(dep) ; # absolute path with root folder (\) - case /* : changed_dep += $(dep) ; # absolute path with root folder (/) - # case * : changed_dep += $(Root)/$(dep) ; # relative path, add $(Root) prefix - } - } - Includes $(<) : $(changed_dep) ; - null_action $(changed_dep) ; -} - - -rule CheckHeaders -{ - Depends $(<) : $(>) ; - NoCare $(>) ; # tolerant to .d absence - NOUPDATE $(>) ; # tolerant to .d timestamp - - # scan line for header, skipping any ../ at the beginning [will be prefixed with $(Root)] -# HDRSCAN on $(>) = "^.*: [\.\\\/]*([^\ -# ]*).*$" ; - HDRRULE on $(>) = DepRule ; -} - - -actions together quietly compile_cpp -{ -#async - set PATH=#\($(_VC_DIR)/bin)\# - call $(_CPP_COMPILER) $(pre_opt) $(_CPP_BASE_INCLUDES) $(cpp_opt) #\(-Fo$(1) $(2:G=))\# - if errorlevel 1 goto failed - if not exist $(1) goto failed - goto end - :failed - set ERRORLEVEL=13 - :end - - clr_filters - $(CODE_CHECK) -x $(1) $(2) -} - -actions together quietly compile_prefast_cpp -{ - set PATH=#\($(_VC_DIR)/bin)\# - call $(_PREFAST_COMPILER) $(pre_opt) $(_CPP_BASE_INCLUDES) $(cpp_opt) #\(-Fo$(1) $(2:G=))\# - if errorlevel 1 goto failed - if not exist $(1) goto failed - goto end - :failed - set ERRORLEVEL=13 - :end -} - -actions together quietly compile_c -{ -#async - set PATH=#\($(_VC_DIR)/bin)\# - call $(_CPP_COMPILER) $(pre_opt) $(_C_BASE_INCLUDES) $(c_opt) #\(-Fo$(1) $(2:G=))\# - if errorlevel 1 goto failed - if not exist $(1) goto failed - goto end - :failed - set ERRORLEVEL=13 - :end - - clr_filters - $(CODE_CHECK) -x $(1) $(2) -} - -include $(Root)/prog/_jBuild/_vc/win_rc.jam ; diff --git a/prog/_jBuild/win32/icl15-link.jam b/prog/_jBuild/win32/icl15-link.jam deleted file mode 100644 index 348d949f3..000000000 --- a/prog/_jBuild/win32/icl15-link.jam +++ /dev/null @@ -1,142 +0,0 @@ -# to be included in jBuild.jam - -rule ProcessLinkTarget -{ - BaseAddress ?= 0x00400000 ; - - local _WIN_LIBS = user32.lib ole32.lib kernel32.lib gdi32.lib winmm.lib dbghelp.lib ; - - if $(TargetType) = exe - { - _LINK_OPT = -nologo -filealign:512 -base:$(BaseAddress) -incremental:no /LARGEADDRESSAWARE ; - - AddDirectXLibs _LINK_OPT ; - AddWtlLibs _LINK_OPT : vc8 ; - - if $(ConsoleExe) != yes { - _LINK_OPT += -subsystem:windows ; - } - - if $(_VC_CRT_TYPE) = -MT { - _LINK_OPT += -nodefaultlib:MSVCRT -nodefaultlib:MSVCPRT -nodefaultlib:LIBMMT -nodefaultlib:LIBIRC -nodefaultlib:LIBC ; - if $(Config) != dbg { - _WIN_LIBS += libcmt.lib libcpmt.lib libircmt.lib libmmt.lib ; - _LINK_OPT += -nodefaultlib:LIBCMTD -nodefaultlib:LIBCPMTD ; - } else { - _WIN_LIBS += libcmtd.lib libcpmtd.lib libircmtd.lib libmmtd.lib ; - _LINK_OPT += -nodefaultlib:LIBCMT -nodefaultlib:LIBCPMT ; - } - } else { - _LINK_OPT += -nodefaultlib:LIBMMT -nodefaultlib:LIBIRC -nodefaultlib:LIBC ; - if $(Config) != dbg { - _WIN_LIBS += MSVCRT.lib MSVCPRT.lib libirc.lib libm.lib ; - _LINK_OPT += -nodefaultlib:LIBCMT -nodefaultlib:LIBCPMT ; - } else { - _WIN_LIBS += MSVCRTd.lib MSVCPRTd.lib libircd.lib libmd.lib ; - _LINK_OPT += -nodefaultlib:LIBCMT -nodefaultlib:LIBCPMT ; - } - } - - if $(Config) != dbg { - _LINK_OPT += -opt:ref ; - } - - if $(UseWholeOpt) = yes { - _LINK_OPT += /LTCG ; - } - - $(Target)__LINK = $(_LINK) $(LINKopt) ; - $(Target)__LINK_OPT = $(_LINK_OPT) ; - - LinkExeSetMap $(Target) : ; - LinkExeSetBuildStamp $(Target) ; - LinkAddManifest $(Target) : $(OutDir) ; - } - else if $(TargetType) = lib - { - $(Target)__LINK = $(_LIB) ; - $(Target)__LINK_OPT = -nologo $(LINKopt) ; - - if $(UseWholeOpt) = yes { - $(Target)__LINK_OPT += /LTCG ; - } - } - else if $(TargetType) = dll - { - _LINK_OPT = -nologo -dll -subsystem:windows -base:$(BaseAddress) -incremental:no /LARGEADDRESSAWARE ; - AddDirectXLibs _LINK_OPT ; - if $(Config) != dbg { - _LINK_OPT += -opt:ref ; - } - - if $(UseWholeOpt) = yes { - _LINK_OPT += /LTCG ; - } - - $(Target)__LINK = $(_LINK) ; - $(Target)__LINK_OPT = $(_LINK_OPT) $(LINKopt) ; - - LinkDllSetMapExpLib $(Target) : $(OutDir) : ; - } - - local _ADD_LIBS = " " $(1) ; - - if $(QtVer) { AddQtLinkOpt ; } - - if $(TargetType) = exe { - _ADD_LIBS += $(_WIN_LIBS) ; - } - - $(Target)__LINK_LIBS = $(_ADD_LIBS) ; -} - - -actions together quietly link_target -{ -#async - set PATH=#\($(_VC_DIR)/bin)\# - $(prelink_cmd) - echo linking $(1:B)$(1:S) - del $(1) - $(DEL_)$(pdb_path) - set_filter nul /warning LNK4099/ - call_filtered $(link) $(link_opt) #\( $(link_libs) $(resources) $(DEBUG_PDB_)$(pdb_path) -out:$(1) $(obj_list) )\# - if errorlevel 1 goto after_postlink - $(postlink_cmd) - :after_postlink - echo ---------------------------------------------------------------------- - if errorlevel 1 goto failed - if not exist $(1) goto failed - echo SUCCESSFULLY built $(1:B)$(1:S) $(_PrintedOutput) - goto end - - :failed - echo FAILED to build $(1:B)$(1:S) [Error #%errorlevel%] $(_PrintedOutput) - set ERRORLEVEL=13 - - :end - echo . -} - - -actions together quietly lib_target -{ -#async - set PATH=#\($(_VC_DIR)/bin)\# - echo creating lib $(1:B)$(1:S) - del $(1) - set_filter nul /warning LNK4221/ - call_filtered $(link) $(link_opt) #\( -out:$(1) $(obj_list) $(link_libs) )\# - echo ---------------------------------------------------------------------- - if errorlevel 1 goto failed - if not exist $(1) goto failed - echo SUCCESSFULLY built $(1:B)$(1:S) $(_PrintedOutput) - goto end - - :failed - echo FAILED to build $(1:B)$(1:S) [Error #%errorlevel%] $(_PrintedOutput) - set ERRORLEVEL=13 - - :end - echo . -} diff --git a/prog/_jBuild/win32/icl15-sets.jam b/prog/_jBuild/win32/icl15-sets.jam deleted file mode 100644 index 7ff784768..000000000 --- a/prog/_jBuild/win32/icl15-sets.jam +++ /dev/null @@ -1,85 +0,0 @@ -# Setup for VC 2013 compiler for Win32 (to be included from jBuild.jam) - -_OBJ_SUFFIX = .obj ; - -_ICL_DIR = $(_DEVTOOL)/icpp15 ; -_VC_DIR = $(_DEVTOOL)/vc2010 ; -include $(Root)/prog/_jBuild/_vc/win_sdk.jam ; -_PREFAST_DIR = $(_DEVTOOL)/prefast ; -_VC_CRT_TYPE = -MT ; -C_preopt_DirectXVer = jun2010 ; - -if ! [ GLOB $(_VC_DIR) : * ] { exit FATAL\: \"$(_VC_DIR)\" not found! Please, update DEVTOOLS ; } -if ! [ GLOB $(_WIN_SDK) : * ] { exit FATAL\: \"$(_WIN_SDK)\" not found! Please, update DEVTOOLS ; } - -local _DEF_C_CMDLINE = - -X /D_TARGET_PC=1 -D_TARGET_PC_WIN=1 -D_TARGET_CPU_IA32=1 /D__IA32__=1 /DWIN32 /Dasm=__asm /DWIN32_LEAN_AND_MEAN= - -DNOMINMAX - -D_TARGET_SIMD_SSE=$(SSEVersion) -D_ALLOW_KEYWORD_MACROS= - -Di_strlen=strlen - /c /nologo /Zc:forScope /Zp8 /J /fp:fast=2 -; - -if $(QtVer) { - _QT_DIR = $(_DEVTOOL)/Qt-$(QtVer)-vc2008 ; - if ! [ GLOB $(_QT_DIR) : * ] { exit FATAL\: \"$(_QT_DIR)\" not found! Please, update DEVTOOLS ; } - - _DEF_C_CMDLINE += - -DQT_LARGEFILE_SUPPORT -DQT_THREAD_SUPPORT -DQT_GUI_LIB -DQT_CORE_LIB - -D_STD_RTL_MEMORY=1 - /Zc:wchar_t- - ; - if $(QtVerStatic) = yes { _DEF_C_CMDLINE += -DQT_NODLL ; } else { _VC_CRT_TYPE = -MD ; } - - _QT_MOC = $(_QT_DIR)/bin/moc.exe ; - _QT_UIC = $(_QT_DIR)/bin/uic.exe ; - _QT_RCC = $(_QT_DIR)/bin/rcc.exe ; -} else { - _DEF_C_CMDLINE += /Zc:wchar_t ; -} - -_LINK = $(_ICL_DIR)/ia32/xilink.exe /machine:x86 ; -_LIB = $(_ICL_DIR)/ia32/xilib.exe /machine:x86 ; -_CPP_COMPILER = $(_ICL_DIR)/ia32/icl.exe $(_DEF_C_CMDLINE) ; -_C_COMPILER = $(_ICL_DIR)/ia32/icl.exe $(_DEF_C_CMDLINE) ; -_PREFAST_COMPILER = $(_PREFAST_DIR)/bin/bin/x86/PREfast.exe /NEW_FAILURE=never /StackHogThreshold=512000 /FilterPreset=wspmin /noreset cl $(_DEF_C_CMDLINE) ; -_ASM_COMPILER = $(_DEVTOOL)/nasm/nasmw.exe -f win32 --prefix _ ; -_MASM_COMPILER = $(_VC_DIR)/bin/ml.exe -c -nologo ; - -_DEP_COMPILER = $(Root)/prog/_jBuild/fastdep-g.exe --cVC80 /D_TARGET_PC=1 -D_TARGET_PC_WIN=1 /D__IA32__=1 /DWIN32 ; - -_RC_COMPILER = $(_WIN_SDK_BIN)/rc.exe /x /i$(_WIN_SDK_INC) /i$(_VC_DIR)/Include ; -_MT_UTIL = $(_WIN_SDK_BIN)/mt.exe ; -_CVTRES_EXE = $(_VC_DIR)/bin/cvtres.exe /MACHINE:X86 /NOLOGO ; - -_INCLUDE = $(_ICL_DIR)/compiler/include $(_WIN_SDK_INC) $(_VC_DIR)/include ; -_LIBPATH = $(_ICL_DIR)/compiler/lib/ia32 $(_WIN_SDK_LIB) $(_VC_DIR)/lib ; - -_INCLUDE += - $(_QT_DIR)/include/QtCore - $(_QT_DIR)/include/QtGui - $(_QT_DIR)/include/ActiveQt - $(_QT_DIR)/include - $(_QT_DIR)/mkspecs/win32-msvc2008 -; - - -# make linker cmd-line ### -for lib in $(_LIBPATH) { - _LINK += -libpath:$(lib) ; - _LIB += -libpath:$(lib) ; -} - -# make compiler cmd-line ### -_CPP_BASE_INCLUDES = -I$(MasterPreInclude) -I$(Root)/prog/dagorInclude -I$(Root)/prog/1stPartyLibs -I$(Root)/prog/3rdPartyLibs -I$(Root)/prog/3rdPartyLibs/eastl/include ; -_C_BASE_INCLUDES = -I$(MasterPreInclude) -I$(Root)/prog/dagorInclude -I$(Root)/prog/1stPartyLibs -I$(Root)/prog/3rdPartyLibs ; - -for inc in $(_INCLUDE) { - _CPP_BASE_INCLUDES += -I$(inc) ; - _C_BASE_INCLUDES += -I$(inc) ; - _DEP_COMPILER += --x$(inc) ; -} - -_DEF_C_CMDLINE = ; - -if $(QtVer) { include $(Root)/prog/_jBuild/win32/qt-inc.jam ; } diff --git a/prog/_jBuild/win32/qt-inc.jam b/prog/_jBuild/win32/qt-inc.jam deleted file mode 100644 index 1758827d5..000000000 --- a/prog/_jBuild/win32/qt-inc.jam +++ /dev/null @@ -1,108 +0,0 @@ -rule AddQtCompileOpt -{ - _CPP_OPT = -I$(_QT_DIR)/include/Qt$(UseQtLibs) -I$(_QT_DIR)/include/Qt$(DefQtLibs) - -DQT_$(UseQtLibs:U)_LIB -DQT_$(DefQtLibs:U)_LIB - $(_CPP_OPT) ; - $(Target)__MOC_OPT = -I$(_QT_DIR)/include/Qt$(UseQtLibs) -I$(_QT_DIR)/include/Qt$(DefQtLibs) -DQT_$(UseQtLibs:U)_LIB -DQT_$(DefQtLibs:U)_LIB $(dll_opt) ; -} - -rule AddQtLinkOpt -{ - if $(TargetType) = exe || $(TargetType) = dll { - local qt_libs = $(_QT_DIR)/lib/QtCore $(_QT_DIR)/lib/QtGui $(_QT_DIR)/lib/Qt$(UseQtLibs) $(_QT_DIR)/lib/Qt$(DefQtLibs) ; - if $(Config) = dbg { - _ADD_LIBS += $(qt_libs)d4.lib ; - } else { - _ADD_LIBS += $(qt_libs)4.lib ; - } - } -} - -# rule how to compile QT .ui target -# params: ( target_pathname : sources : target ) -rule CompileUI -{ - local tgt = $($(3)__OutDir)/$(3) ; - local ui_h = $(Root)/$(1) ; - LOCATE on $(2) = $(Root) ; - Depends $(ui_h) : $(2) ; - Depends $(tgt) : $(ui_h) ; - compile_qt_ui $(ui_h) : $(2) ; -} - -# rule how to compile QT .moc target -# params: ( target_pathname : sources : target ) -rule CompileMOC -{ - Depends $(1) : $(Root)/$(2) ; - MakeDirectory $(1) : $(1:D) ; - opt on $(1) = $($(3)__MOC_OPT) ; - compile_qt_moc $(1) : $(Root)/$(2) ; - - local obj = $(1:S=$(_OBJ_SUFFIX)) ; - Depends $(obj) : $(1) ; - MakeDirectory $(obj) : $(obj:D) ; - - cpp_opt on $(obj) = $($(3)__CPP_OPT) ; - pre_opt on $(obj) = $($(3)__PRE_OPT) ; - - compile_cpp $(obj) : $(1) ; -} - -# rule how to compile QT .qrc target -# params: ( target_pathname : sources : target ) -rule CompileQRC -{ - Depends $(1) : $(Root)/$(2) ; - MakeDirectory $(1) : $(1:D) ; - compile_qt_rcc $(1) : $(Root)/$(2) ; - - local obj = $(1:S=$(_OBJ_SUFFIX)) ; - Depends $(obj) : $(1) ; - MakeDirectory $(obj) : $(obj:D) ; - - cpp_opt on $(obj) = $($(3)__CPP_OPT) ; - pre_opt on $(obj) = $($(3)__PRE_OPT) ; - - compile_cpp $(obj) : $(1) ; -} - - -actions quietly compile_qt_ui -{ -#async - echo QT-uic $(2:D=) - call $(_QT_UIC) -o $(1) $(2) - if errorlevel 1 goto failed - if not exist $(1) goto failed - goto end - :failed - set ERRORLEVEL=13 - :end -} - -actions quietly compile_qt_moc -{ -#async - echo QT-moc $(2:D=) - call $(_QT_MOC) $(opt) $(_CPP_BASE_INCLUDES) -o $(1) $(2) - if errorlevel 1 goto failed - if not exist $(1) goto failed - goto end - :failed - set ERRORLEVEL=13 - :end -} - -actions quietly compile_qt_rcc -{ -#async - echo QT-rcc $(2:D=) - call $(_QT_RCC) -o $(1) $(2) - if errorlevel 1 goto failed - if not exist $(1) goto failed - goto end - :failed - set ERRORLEVEL=13 - :end -} diff --git a/prog/_jBuild/win32/vc10-cpp.jam b/prog/_jBuild/win32/vc10-cpp.jam index c4c860bd2..c75cf603b 100644 --- a/prog/_jBuild/win32/vc10-cpp.jam +++ b/prog/_jBuild/win32/vc10-cpp.jam @@ -129,9 +129,6 @@ rule ProcessCompileTarget AddForceFastcall _CPP_OPT ; AddDirectXInclude pre_opt : post_opt ; - AddWtlInclude pre_opt : vc8 ; - - if $(QtVer) { AddQtCompileOpt ; } include $(Root)/prog/_jBuild/_vc/add_fp_fast.jam ; $(Target)__CPP_OPT = -FImemory/dag_memBase.h $(post_opt) $(_CPP_OPT) -TP ; @@ -178,8 +175,8 @@ rule CheckHeaders actions together quietly compile_cpp { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 call_filtered $(_CPP_COMPILER) $(pre_opt) $(_CPP_BASE_INCLUDES) $(cpp_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed if not exist $(1) goto failed @@ -207,8 +204,8 @@ actions together quietly compile_prefast_cpp actions together quietly compile_c { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 call_filtered $(_CPP_COMPILER) $(pre_opt) $(_C_BASE_INCLUDES) $(c_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed if not exist $(1) goto failed diff --git a/prog/_jBuild/win32/vc10-link.jam b/prog/_jBuild/win32/vc10-link.jam index a63807909..7f071cad9 100644 --- a/prog/_jBuild/win32/vc10-link.jam +++ b/prog/_jBuild/win32/vc10-link.jam @@ -11,7 +11,6 @@ rule ProcessLinkTarget _LINK_OPT = -nologo -filealign:512 -base:$(BaseAddress) -incremental:no /LARGEADDRESSAWARE ; AddDirectXLibs _LINK_OPT ; - AddWtlLibs _LINK_OPT : vc8 ; if $(ConsoleExe) != yes { _LINK_OPT += -subsystem:windows ; @@ -81,8 +80,6 @@ rule ProcessLinkTarget local _ADD_LIBS = " " $(1) ; - if $(QtVer) { AddQtLinkOpt ; } - if $(TargetType) = exe { _ADD_LIBS += $(_WIN_LIBS) ; } diff --git a/prog/_jBuild/win32/vc10-sets.jam b/prog/_jBuild/win32/vc10-sets.jam index 2a21d9401..8f9ada6e8 100644 --- a/prog/_jBuild/win32/vc10-sets.jam +++ b/prog/_jBuild/win32/vc10-sets.jam @@ -16,27 +16,9 @@ local _DEF_C_CMDLINE = /DNOMINMAX -D_TARGET_SIMD_SSE=$(SSEVersion) -Di_strlen=strlen - /c /nologo /Zc:forScope /Zp8 /J /bigobj + /c /nologo /Zc:forScope /Zp8 /J /bigobj /Zc:wchar_t ; -if $(QtVer) { - _QT_DIR = $(_DEVTOOL)/Qt-$(QtVer)-vc2008 ; - if ! [ GLOB $(_QT_DIR) : * ] { exit FATAL\: \"$(_QT_DIR)\" not found! Please, update DEVTOOLS ; } - - _DEF_C_CMDLINE += - -DQT_LARGEFILE_SUPPORT -DQT_THREAD_SUPPORT -DQT_GUI_LIB -DQT_CORE_LIB - -D_STD_RTL_MEMORY=1 - /Zc:wchar_t- - ; - if $(QtVerStatic) = yes { _DEF_C_CMDLINE += -DQT_NODLL ; } else { _VC_CRT_TYPE = -MD ; } - - _QT_MOC = $(_QT_DIR)/bin/moc.exe ; - _QT_UIC = $(_QT_DIR)/bin/uic.exe ; - _QT_RCC = $(_QT_DIR)/bin/rcc.exe ; -} else { - _DEF_C_CMDLINE += /Zc:wchar_t ; -} - _LINK = $(_VC_DIR)/bin/link.exe /machine:x86 ; _LIB = $(_VC_DIR)/bin/lib.exe /machine:x86 ; _CPP_COMPILER = $(_VC_DIR)/bin/cl.exe $(_DEF_C_CMDLINE) ; @@ -54,14 +36,6 @@ _CVTRES_EXE = $(_VC_DIR)/bin/cvtres.exe /MACHINE:X86 /NOLOGO ; _INCLUDE = $(_WIN_SDK_INC) $(_VC_DIR)/include ; _LIBPATH = $(_WIN_SDK_LIB) $(_VC_DIR)/lib ; -_INCLUDE += - $(_QT_DIR)/include/QtCore - $(_QT_DIR)/include/QtGui - $(_QT_DIR)/include/ActiveQt - $(_QT_DIR)/include - $(_QT_DIR)/mkspecs/win32-msvc2008 -; - # make linker cmd-line ### for lib in $(_LIBPATH) { @@ -80,5 +54,3 @@ for inc in $(_INCLUDE) { } _DEF_C_CMDLINE = ; - -if $(QtVer) { include $(Root)/prog/_jBuild/win32/qt-inc.jam ; } diff --git a/prog/_jBuild/win32/vc10u-cpp.jam b/prog/_jBuild/win32/vc10u-cpp.jam index 40b97448c..6cd26a8c7 100644 --- a/prog/_jBuild/win32/vc10u-cpp.jam +++ b/prog/_jBuild/win32/vc10u-cpp.jam @@ -180,8 +180,8 @@ rule CheckHeaders actions together quietly compile_cpp { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 call_filtered $(_CPP_COMPILER) $(pre_opt) $(_CPP_BASE_INCLUDES) /fp:fast $(cpp_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed if not exist $(1) goto failed @@ -194,8 +194,8 @@ actions together quietly compile_cpp actions together quietly compile_c { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 call_filtered $(_CPP_COMPILER) $(pre_opt) $(_C_BASE_INCLUDES) /fp:fast $(c_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed if not exist $(1) goto failed diff --git a/prog/_jBuild/win32/vc11-cpp.jam b/prog/_jBuild/win32/vc11-cpp.jam index b061b2cf7..e55051749 100644 --- a/prog/_jBuild/win32/vc11-cpp.jam +++ b/prog/_jBuild/win32/vc11-cpp.jam @@ -133,9 +133,6 @@ rule ProcessCompileTarget AddForceFastcall _CPP_OPT ; AddDirectXInclude pre_opt : post_opt ; - AddWtlInclude pre_opt : vc8 ; - - if $(QtVer) { AddQtCompileOpt ; } include $(Root)/prog/_jBuild/_vc/add_fp_fast.jam ; $(Target)__CPP_OPT = -FImemory/dag_memBase.h $(post_opt) $(_CPP_OPT) -TP ; @@ -182,8 +179,8 @@ rule CheckHeaders actions together quietly compile_cpp { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 call_filtered $(_CPP_COMPILER) $(pre_opt) $(_CPP_BASE_INCLUDES) $(cpp_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed if not exist $(1) goto failed @@ -211,8 +208,8 @@ actions together quietly compile_prefast_cpp actions together quietly compile_c { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 call_filtered $(_CPP_COMPILER) $(pre_opt) $(_C_BASE_INCLUDES) $(c_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed if not exist $(1) goto failed diff --git a/prog/_jBuild/win32/vc11-link.jam b/prog/_jBuild/win32/vc11-link.jam index a63807909..7f071cad9 100644 --- a/prog/_jBuild/win32/vc11-link.jam +++ b/prog/_jBuild/win32/vc11-link.jam @@ -11,7 +11,6 @@ rule ProcessLinkTarget _LINK_OPT = -nologo -filealign:512 -base:$(BaseAddress) -incremental:no /LARGEADDRESSAWARE ; AddDirectXLibs _LINK_OPT ; - AddWtlLibs _LINK_OPT : vc8 ; if $(ConsoleExe) != yes { _LINK_OPT += -subsystem:windows ; @@ -81,8 +80,6 @@ rule ProcessLinkTarget local _ADD_LIBS = " " $(1) ; - if $(QtVer) { AddQtLinkOpt ; } - if $(TargetType) = exe { _ADD_LIBS += $(_WIN_LIBS) ; } diff --git a/prog/_jBuild/win32/vc11-sets.jam b/prog/_jBuild/win32/vc11-sets.jam index ef008f1a7..883be366c 100644 --- a/prog/_jBuild/win32/vc11-sets.jam +++ b/prog/_jBuild/win32/vc11-sets.jam @@ -16,27 +16,9 @@ local _DEF_C_CMDLINE = /DNOMINMAX -D_TARGET_SIMD_SSE=$(SSEVersion) -D_ALLOW_KEYWORD_MACROS= -Di_strlen=strlen - /c /nologo /Zc:forScope /Zp8 /J /bigobj + /c /nologo /Zc:forScope /Zp8 /J /bigobj /Zc:wchar_t ; -if $(QtVer) { - _QT_DIR = $(_DEVTOOL)/Qt-$(QtVer)-vc2008 ; - if ! [ GLOB $(_QT_DIR) : * ] { exit FATAL\: \"$(_QT_DIR)\" not found! Please, update DEVTOOLS ; } - - _DEF_C_CMDLINE += - -DQT_LARGEFILE_SUPPORT -DQT_THREAD_SUPPORT -DQT_GUI_LIB -DQT_CORE_LIB - -D_STD_RTL_MEMORY=1 - /Zc:wchar_t- - ; - if $(QtVerStatic) = yes { _DEF_C_CMDLINE += -DQT_NODLL ; } else { _VC_CRT_TYPE = -MD ; } - - _QT_MOC = $(_QT_DIR)/bin/moc.exe ; - _QT_UIC = $(_QT_DIR)/bin/uic.exe ; - _QT_RCC = $(_QT_DIR)/bin/rcc.exe ; -} else { - _DEF_C_CMDLINE += /Zc:wchar_t ; -} - _LINK = $(_VC_DIR)/bin/link.exe /machine:x86 ; _LIB = $(_VC_DIR)/bin/lib.exe /machine:x86 ; _CPP_COMPILER = $(_VC_DIR)/bin/cl.exe $(_DEF_C_CMDLINE) ; @@ -54,14 +36,6 @@ _CVTRES_EXE = $(_VC_DIR)/bin/cvtres.exe /MACHINE:X86 /NOLOGO ; _INCLUDE = $(_WIN_SDK_INC) $(_VC_DIR)/include ; _LIBPATH = $(_WIN_SDK_LIB) $(_VC_DIR)/lib ; -_INCLUDE += - $(_QT_DIR)/include/QtCore - $(_QT_DIR)/include/QtGui - $(_QT_DIR)/include/ActiveQt - $(_QT_DIR)/include - $(_QT_DIR)/mkspecs/win32-msvc2008 -; - # make linker cmd-line ### for lib in $(_LIBPATH) { @@ -80,5 +54,3 @@ for inc in $(_INCLUDE) { } _DEF_C_CMDLINE = ; - -if $(QtVer) { include $(Root)/prog/_jBuild/win32/qt-inc.jam ; } diff --git a/prog/_jBuild/win32/vc11u-cpp.jam b/prog/_jBuild/win32/vc11u-cpp.jam index 40b97448c..6cd26a8c7 100644 --- a/prog/_jBuild/win32/vc11u-cpp.jam +++ b/prog/_jBuild/win32/vc11u-cpp.jam @@ -180,8 +180,8 @@ rule CheckHeaders actions together quietly compile_cpp { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 call_filtered $(_CPP_COMPILER) $(pre_opt) $(_CPP_BASE_INCLUDES) /fp:fast $(cpp_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed if not exist $(1) goto failed @@ -194,8 +194,8 @@ actions together quietly compile_cpp actions together quietly compile_c { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 call_filtered $(_CPP_COMPILER) $(pre_opt) $(_C_BASE_INCLUDES) /fp:fast $(c_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed if not exist $(1) goto failed diff --git a/prog/_jBuild/win32/vc12-cpp.jam b/prog/_jBuild/win32/vc12-cpp.jam index 66375d0f4..4dba69da1 100644 --- a/prog/_jBuild/win32/vc12-cpp.jam +++ b/prog/_jBuild/win32/vc12-cpp.jam @@ -137,9 +137,6 @@ rule ProcessCompileTarget AddForceFastcall _CPP_OPT ; AddDirectXInclude pre_opt : post_opt ; - AddWtlInclude pre_opt : vc8 ; - - if $(QtVer) { AddQtCompileOpt ; } include $(Root)/prog/_jBuild/_vc/add_fp_fast.jam ; $(Target)__CPP_OPT = -FImemory/dag_memBase.h $(post_opt) $(_CPP_OPT) -TP ; @@ -186,8 +183,8 @@ rule CheckHeaders actions together quietly compile_cpp { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 call_filtered $(_CPP_COMPILER) $(pre_opt) $(_CPP_BASE_INCLUDES) $(cpp_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed if not exist $(1) goto failed @@ -215,8 +212,8 @@ actions together quietly compile_prefast_cpp actions together quietly compile_c { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 call_filtered $(_CPP_COMPILER) $(pre_opt) $(_C_BASE_INCLUDES) $(c_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed if not exist $(1) goto failed diff --git a/prog/_jBuild/win32/vc12-link.jam b/prog/_jBuild/win32/vc12-link.jam index a63807909..7f071cad9 100644 --- a/prog/_jBuild/win32/vc12-link.jam +++ b/prog/_jBuild/win32/vc12-link.jam @@ -11,7 +11,6 @@ rule ProcessLinkTarget _LINK_OPT = -nologo -filealign:512 -base:$(BaseAddress) -incremental:no /LARGEADDRESSAWARE ; AddDirectXLibs _LINK_OPT ; - AddWtlLibs _LINK_OPT : vc8 ; if $(ConsoleExe) != yes { _LINK_OPT += -subsystem:windows ; @@ -81,8 +80,6 @@ rule ProcessLinkTarget local _ADD_LIBS = " " $(1) ; - if $(QtVer) { AddQtLinkOpt ; } - if $(TargetType) = exe { _ADD_LIBS += $(_WIN_LIBS) ; } diff --git a/prog/_jBuild/win32/vc12-sets.jam b/prog/_jBuild/win32/vc12-sets.jam index f889fe422..aa98b8af2 100644 --- a/prog/_jBuild/win32/vc12-sets.jam +++ b/prog/_jBuild/win32/vc12-sets.jam @@ -16,27 +16,9 @@ local _DEF_C_CMDLINE = /DNOMINMAX -D_TARGET_SIMD_SSE=$(SSEVersion) -D_ALLOW_KEYWORD_MACROS= -Di_strlen=strlen - /c /nologo /Zc:forScope /Zp8 /J /bigobj + /c /nologo /Zc:forScope /Zp8 /J /bigobj /Zc:wchar_t ; -if $(QtVer) { - _QT_DIR = $(_DEVTOOL)/Qt-$(QtVer)-vc2008 ; - if ! [ GLOB $(_QT_DIR) : * ] { exit FATAL\: \"$(_QT_DIR)\" not found! Please, update DEVTOOLS ; } - - _DEF_C_CMDLINE += - -DQT_LARGEFILE_SUPPORT -DQT_THREAD_SUPPORT -DQT_GUI_LIB -DQT_CORE_LIB - -D_STD_RTL_MEMORY=1 - /Zc:wchar_t- - ; - if $(QtVerStatic) = yes { _DEF_C_CMDLINE += -DQT_NODLL ; } else { _VC_CRT_TYPE = -MD ; } - - _QT_MOC = $(_QT_DIR)/bin/moc.exe ; - _QT_UIC = $(_QT_DIR)/bin/uic.exe ; - _QT_RCC = $(_QT_DIR)/bin/rcc.exe ; -} else { - _DEF_C_CMDLINE += /Zc:wchar_t ; -} - _LINK = $(_VC_DIR)/bin/link.exe /machine:x86 ; _LIB = $(_VC_DIR)/bin/lib.exe /machine:x86 ; _CPP_COMPILER = $(_VC_DIR)/bin/cl.exe $(_DEF_C_CMDLINE) ; @@ -54,14 +36,6 @@ _CVTRES_EXE = $(_VC_DIR)/bin/cvtres.exe /MACHINE:X86 /NOLOGO ; _INCLUDE = $(_WIN_SDK_INC) $(_VC_DIR)/include ; _LIBPATH = $(_WIN_SDK_LIB) $(_VC_DIR)/lib ; -_INCLUDE += - $(_QT_DIR)/include/QtCore - $(_QT_DIR)/include/QtGui - $(_QT_DIR)/include/ActiveQt - $(_QT_DIR)/include - $(_QT_DIR)/mkspecs/win32-msvc2008 -; - # make linker cmd-line ### for lib in $(_LIBPATH) { @@ -80,5 +54,3 @@ for inc in $(_INCLUDE) { } _DEF_C_CMDLINE = ; - -if $(QtVer) { include $(Root)/prog/_jBuild/win32/qt-inc.jam ; } diff --git a/prog/_jBuild/win32/vc12u-cpp.jam b/prog/_jBuild/win32/vc12u-cpp.jam index 772337f19..4c9eba086 100644 --- a/prog/_jBuild/win32/vc12u-cpp.jam +++ b/prog/_jBuild/win32/vc12u-cpp.jam @@ -185,8 +185,8 @@ rule CheckHeaders actions together quietly compile_cpp { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 call_filtered $(_CPP_COMPILER) $(pre_opt) $(_CPP_BASE_INCLUDES) /fp:fast $(cpp_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed if not exist $(1) goto failed @@ -199,8 +199,8 @@ actions together quietly compile_cpp actions together quietly compile_c { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 call_filtered $(_CPP_COMPILER) $(pre_opt) $(_C_BASE_INCLUDES) /fp:fast $(c_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed if not exist $(1) goto failed diff --git a/prog/_jBuild/win32/vc14-cpp.jam b/prog/_jBuild/win32/vc14-cpp.jam index a7807d197..889cdc357 100644 --- a/prog/_jBuild/win32/vc14-cpp.jam +++ b/prog/_jBuild/win32/vc14-cpp.jam @@ -160,9 +160,6 @@ rule ProcessCompileTarget AddForceFastcall _CPP_OPT ; AddDirectXInclude pre_opt : post_opt ; - AddWtlInclude pre_opt : vc8 ; - - if $(QtVer) { AddQtCompileOpt ; } include $(Root)/prog/_jBuild/_vc/add_fp_fast.jam ; $(Target)__CPP_OPT = -FImemory/dag_memBase.h $(post_opt) $(_CPP_OPT) -TP ; @@ -209,8 +206,8 @@ rule CheckHeaders actions together quietly compile_cpp { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 call_filtered $(_CPP_COMPILER) $(pre_opt) $(_CPP_BASE_INCLUDES) $(cpp_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed if not exist $(1) goto failed @@ -226,8 +223,8 @@ actions together quietly compile_cpp actions together quietly compile_c { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 call_filtered $(_CPP_COMPILER) $(pre_opt) $(_C_BASE_INCLUDES) $(c_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed if not exist $(1) goto failed diff --git a/prog/_jBuild/win32/vc14-link.jam b/prog/_jBuild/win32/vc14-link.jam index ec2c1c142..a677064c3 100644 --- a/prog/_jBuild/win32/vc14-link.jam +++ b/prog/_jBuild/win32/vc14-link.jam @@ -27,7 +27,6 @@ rule ProcessLinkTarget _LINK_OPT = -nologo $(FileAlignLinkOption):512 -base:$(BaseAddress) -incremental:no /LARGEADDRESSAWARE ; AddDirectXLibs _LINK_OPT ; - AddWtlLibs _LINK_OPT : vc8 ; if $(ConsoleExe) = yes { _LINK_OPT += -subsystem:console,\"5.01\" ; @@ -108,8 +107,6 @@ rule ProcessLinkTarget local _ADD_LIBS = " " $(1) ; - if $(QtVer) { AddQtLinkOpt ; } - if $(TargetType) = exe { _ADD_LIBS += $(_WIN_LIBS) ; } diff --git a/prog/_jBuild/win32/vc14-sets.jam b/prog/_jBuild/win32/vc14-sets.jam index 62e27dd5d..f82d6afa5 100644 --- a/prog/_jBuild/win32/vc14-sets.jam +++ b/prog/_jBuild/win32/vc14-sets.jam @@ -23,27 +23,9 @@ local _DEF_C_CMDLINE = /DDELAYIMP_INSECURE_WRITABLE_HOOKS -Di_strlen=strlen /c /nologo /Zc:forScope /Zp8 /J - /Zc:inline /bigobj + /Zc:inline /bigobj /Zc:wchar_t ; -if $(QtVer) { - _QT_DIR = $(_DEVTOOL)/Qt-$(QtVer)-vc2008 ; - if ! [ GLOB $(_QT_DIR) : * ] { exit FATAL\: \"$(_QT_DIR)\" not found! Please, update DEVTOOLS ; } - - _DEF_C_CMDLINE += - -DQT_LARGEFILE_SUPPORT -DQT_THREAD_SUPPORT -DQT_GUI_LIB -DQT_CORE_LIB - -D_STD_RTL_MEMORY=1 - /Zc:wchar_t- - ; - if $(QtVerStatic) = yes { _DEF_C_CMDLINE += -DQT_NODLL ; } else { _VC_CRT_TYPE = -MD ; } - - _QT_MOC = $(_QT_DIR)/bin/moc.exe ; - _QT_UIC = $(_QT_DIR)/bin/uic.exe ; - _QT_RCC = $(_QT_DIR)/bin/rcc.exe ; -} else { - _DEF_C_CMDLINE += /Zc:wchar_t ; -} - if $(UseWholeOpt) = yes { UseLLDLink = no ; } @@ -75,14 +57,6 @@ _UCRT_SRC_INC = $(_DEVTOOL)/win.sdk.100/source/10.0.19041.0/ucrt/inc ; _INCLUDE = $(_WIN_SDK_INC) $(_VC_DIR)/include $(_UCRT_INC) ; _LIBPATH = $(_UCRT_LIB) $(_WIN_SDK_LIB) $(_VC_DIR)/lib/ $(_UM_LIB) ; -_INCLUDE += - $(_QT_DIR)/include/QtCore - $(_QT_DIR)/include/QtGui - $(_QT_DIR)/include/ActiveQt - $(_QT_DIR)/include - $(_QT_DIR)/mkspecs/win32-msvc2008 -; - # make linker cmd-line ### for lib in $(_LIBPATH) { @@ -101,5 +75,3 @@ for inc in $(_INCLUDE) { } _DEF_C_CMDLINE = ; - -if $(QtVer) { include $(Root)/prog/_jBuild/win32/qt-inc.jam ; } diff --git a/prog/_jBuild/win32/vc15-cpp.jam b/prog/_jBuild/win32/vc15-cpp.jam index 45d09a976..2be739f6a 100644 --- a/prog/_jBuild/win32/vc15-cpp.jam +++ b/prog/_jBuild/win32/vc15-cpp.jam @@ -186,9 +186,6 @@ rule ProcessCompileTarget AddForceFastcall _CPP_OPT ; AddDirectXInclude pre_opt : post_opt ; - AddWtlInclude pre_opt : vc8 ; - - if $(QtVer) { AddQtCompileOpt ; } include $(Root)/prog/_jBuild/_vc/add_fp_fast.jam ; $(Target)__CPP_OPT = -FImemory/dag_memBase.h $(post_opt) $(_CPP_OPT) -TP ; @@ -235,8 +232,8 @@ rule CheckHeaders actions together quietly compile_cpp { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 call_filtered $(_CPP_COMPILER) $(pre_opt) $(_CPP_BASE_INCLUDES) $(cpp_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed if not exist $(1) goto failed @@ -252,8 +249,8 @@ actions together quietly compile_cpp actions together quietly compile_c { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 call_filtered $(_C_COMPILER) $(pre_opt) $(_C_BASE_INCLUDES) $(c_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed if not exist $(1) goto failed diff --git a/prog/_jBuild/win32/vc15-link.jam b/prog/_jBuild/win32/vc15-link.jam index ec2c1c142..a677064c3 100644 --- a/prog/_jBuild/win32/vc15-link.jam +++ b/prog/_jBuild/win32/vc15-link.jam @@ -27,7 +27,6 @@ rule ProcessLinkTarget _LINK_OPT = -nologo $(FileAlignLinkOption):512 -base:$(BaseAddress) -incremental:no /LARGEADDRESSAWARE ; AddDirectXLibs _LINK_OPT ; - AddWtlLibs _LINK_OPT : vc8 ; if $(ConsoleExe) = yes { _LINK_OPT += -subsystem:console,\"5.01\" ; @@ -108,8 +107,6 @@ rule ProcessLinkTarget local _ADD_LIBS = " " $(1) ; - if $(QtVer) { AddQtLinkOpt ; } - if $(TargetType) = exe { _ADD_LIBS += $(_WIN_LIBS) ; } diff --git a/prog/_jBuild/win32/vc15-sets.jam b/prog/_jBuild/win32/vc15-sets.jam index 53086ddbe..15efb8730 100644 --- a/prog/_jBuild/win32/vc15-sets.jam +++ b/prog/_jBuild/win32/vc15-sets.jam @@ -20,27 +20,9 @@ local _DEF_C_CMDLINE = /DDELAYIMP_INSECURE_WRITABLE_HOOKS -Di_strlen=strlen /c /nologo /Zc:forScope /Zp8 /J - /Zc:inline /bigobj + /Zc:inline /bigobj /Zc:wchar_t ; -if $(QtVer) { - _QT_DIR = $(_DEVTOOL)/Qt-$(QtVer)-vc2008 ; - if ! [ GLOB $(_QT_DIR) : * ] { exit FATAL\: \"$(_QT_DIR)\" not found! Please, update DEVTOOLS ; } - - _DEF_C_CMDLINE += - -DQT_LARGEFILE_SUPPORT -DQT_THREAD_SUPPORT -DQT_GUI_LIB -DQT_CORE_LIB - -D_STD_RTL_MEMORY=1 - /Zc:wchar_t- - ; - if $(QtVerStatic) = yes { _DEF_C_CMDLINE += -DQT_NODLL ; } else { _VC_CRT_TYPE = -MD ; } - - _QT_MOC = $(_QT_DIR)/bin/moc.exe ; - _QT_UIC = $(_QT_DIR)/bin/uic.exe ; - _QT_RCC = $(_QT_DIR)/bin/rcc.exe ; -} else { - _DEF_C_CMDLINE += /Zc:wchar_t ; -} - _LINK = $(_VC_DIR)/bin/Hostx86/x86/link.exe /machine:x86 ; _LIB = $(_VC_DIR)/bin/Hostx86/x86/lib.exe /machine:x86 ; _CPP_COMPILER = $(_VC_DIR)/bin/Hostx86/x86/cl.exe $(_DEF_C_CMDLINE) ; @@ -61,14 +43,6 @@ _UCRT_SRC_INC = $(_DEVTOOL)/win.sdk.100/source/10.0.19041.0/ucrt/inc ; _INCLUDE = $(_WIN_SDK_INC) $(_VC_DIR)/include $(_UCRT_INC) ; _LIBPATH = $(_UCRT_LIB) $(_WIN_SDK_LIB) $(_VC_DIR)/lib/x86/ $(_UM_LIB) ; -_INCLUDE += - $(_QT_DIR)/include/QtCore - $(_QT_DIR)/include/QtGui - $(_QT_DIR)/include/ActiveQt - $(_QT_DIR)/include - $(_QT_DIR)/mkspecs/win32-msvc2008 -; - # make linker cmd-line ### for lib in $(_LIBPATH) { @@ -87,5 +61,3 @@ for inc in $(_INCLUDE) { } _DEF_C_CMDLINE = ; - -if $(QtVer) { include $(Root)/prog/_jBuild/win32/qt-inc.jam ; } diff --git a/prog/_jBuild/win32/vc16-sets.jam b/prog/_jBuild/win32/vc16-sets.jam index e6d9efa0c..f8b94e5a1 100644 --- a/prog/_jBuild/win32/vc16-sets.jam +++ b/prog/_jBuild/win32/vc16-sets.jam @@ -23,27 +23,9 @@ local _DEF_C_CMDLINE = /DDELAYIMP_INSECURE_WRITABLE_HOOKS -Di_strlen=strlen /c /nologo /Zc:forScope /Zp8 /J - /Zc:inline /bigobj + /Zc:inline /bigobj /Zc:wchar_t ; -if $(QtVer) { - _QT_DIR = $(_DEVTOOL)/Qt-$(QtVer)-vc2008 ; - if ! [ GLOB $(_QT_DIR) : * ] { exit FATAL\: \"$(_QT_DIR)\" not found! Please, update DEVTOOLS ; } - - _DEF_C_CMDLINE += - -DQT_LARGEFILE_SUPPORT -DQT_THREAD_SUPPORT -DQT_GUI_LIB -DQT_CORE_LIB - -D_STD_RTL_MEMORY=1 - /Zc:wchar_t- - ; - if $(QtVerStatic) = yes { _DEF_C_CMDLINE += -DQT_NODLL ; } else { _VC_CRT_TYPE = -MD ; } - - _QT_MOC = $(_QT_DIR)/bin/moc.exe ; - _QT_UIC = $(_QT_DIR)/bin/uic.exe ; - _QT_RCC = $(_QT_DIR)/bin/rcc.exe ; -} else { - _DEF_C_CMDLINE += /Zc:wchar_t ; -} - if $(UseWholeOpt) = yes { UseLLDLink = no ; } @@ -79,14 +61,6 @@ if ! $(_UM_LIB:L) in $(_LIBPATH:L) { _LIBPATH += $(_UM_LIB) ; } -_INCLUDE += - $(_QT_DIR)/include/QtCore - $(_QT_DIR)/include/QtGui - $(_QT_DIR)/include/ActiveQt - $(_QT_DIR)/include - $(_QT_DIR)/mkspecs/win32-msvc2008 -; - # make linker cmd-line ### for lib in $(_LIBPATH) { @@ -105,5 +79,3 @@ for inc in $(_INCLUDE) { } _DEF_C_CMDLINE = ; - -if $(QtVer) { include $(Root)/prog/_jBuild/win32/qt-inc.jam ; } diff --git a/prog/_jBuild/win32/vc17-sets.jam b/prog/_jBuild/win32/vc17-sets.jam index 2592fbd09..e6e5625d8 100644 --- a/prog/_jBuild/win32/vc17-sets.jam +++ b/prog/_jBuild/win32/vc17-sets.jam @@ -23,27 +23,9 @@ local _DEF_C_CMDLINE = /DDELAYIMP_INSECURE_WRITABLE_HOOKS -Di_strlen=strlen /c /nologo /Zc:forScope /Zp8 /J - /Zc:inline /bigobj + /Zc:inline /bigobj /Zc:wchar_t ; -if $(QtVer) { - _QT_DIR = $(_DEVTOOL)/Qt-$(QtVer)-vc2008 ; - if ! [ GLOB $(_QT_DIR) : * ] { exit FATAL\: \"$(_QT_DIR)\" not found! Please, update DEVTOOLS ; } - - _DEF_C_CMDLINE += - -DQT_LARGEFILE_SUPPORT -DQT_THREAD_SUPPORT -DQT_GUI_LIB -DQT_CORE_LIB - -D_STD_RTL_MEMORY=1 - /Zc:wchar_t- - ; - if $(QtVerStatic) = yes { _DEF_C_CMDLINE += -DQT_NODLL ; } else { _VC_CRT_TYPE = -MD ; } - - _QT_MOC = $(_QT_DIR)/bin/moc.exe ; - _QT_UIC = $(_QT_DIR)/bin/uic.exe ; - _QT_RCC = $(_QT_DIR)/bin/rcc.exe ; -} else { - _DEF_C_CMDLINE += /Zc:wchar_t ; -} - if $(UseWholeOpt) = yes { UseLLDLink = no ; } @@ -79,14 +61,6 @@ if ! $(_UM_LIB:L) in $(_LIBPATH:L) { _LIBPATH += $(_UM_LIB) ; } -_INCLUDE += - $(_QT_DIR)/include/QtCore - $(_QT_DIR)/include/QtGui - $(_QT_DIR)/include/ActiveQt - $(_QT_DIR)/include - $(_QT_DIR)/mkspecs/win32-msvc2008 -; - # make linker cmd-line ### for lib in $(_LIBPATH) { @@ -105,5 +79,3 @@ for inc in $(_INCLUDE) { } _DEF_C_CMDLINE = ; - -if $(QtVer) { include $(Root)/prog/_jBuild/win32/qt-inc.jam ; } diff --git a/prog/_jBuild/win32/vc9-cpp.jam b/prog/_jBuild/win32/vc9-cpp.jam deleted file mode 100644 index 04ae05a65..000000000 --- a/prog/_jBuild/win32/vc9-cpp.jam +++ /dev/null @@ -1,218 +0,0 @@ -# to be included in jBuild.jam - -rule ProcessCompileTarget -{ - # basic opts: warning/remark suppressing, additional includes etc. - local _SUPPRESS_OPT = ; - local _CONFIG_OPT = ; - local pre_opt = ; - local post_opt = ; - - if $(StrictCompile) = yes - { - # suppressed warnigs list (marked with x are not suppressed now): - # C4265 'XXX' : class has virtual functions, but destructor is not virtual - # C4127 conditional expression is constant - # x C4100 'XXX' : unreferenced formal parameter - # x 981 operands are evaluated in unspecified order - # x 383 value copied to temporary, reference to temporary used - # x 310 old-style parameter list (anachronism) - # x 174 expression has no effect - # x 111 statement is unreachable - # x 271 trailing comma is nonstandard - # C4514 'XXX' : unreferenced inline function has been removed - # C4061 enumerator 'XXX' in switch of enum 'YYY' is not explicitly handled by a case label - # C4062 enumerator 'XXX' in switch of enum 'YYY' is not handled - # C4820 'XXX' : 'N' bytes padding added after data member 'XXX::YYY' - # C4324 'XXX' : structure was padded due to __declspec(align()) - # C4668 'XXX' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' - # C4619 pragma warning : there is no warning number 'NNN' - # C4365 'XXX' : conversion from 'TYPE1' to 'TYPE2', signed/unsigned mismatch - # C4302 'type cast' : truncation from 'TYPE1' to 'TYPE2' - # C4244 '=' : conversion from 'TYPE1' to 'TYPE2', possible loss of data - # C4242 'argument' : conversion from 'TYPE1' to 'TYPE2', possible loss of data - # C4245 'argument' : conversion from 'TYPE1' to 'TYPE2', signed/unsigned mismatch - # C4101 'XXX' : unreferenced local variable - # C4201 nonstandard extension used : nameless struct/union - # C4625 'XXX' : copy constructor could not be generated because a base class copy constructor is inaccessible - # C4626 'XXX' : assignment operator could not be generated because a base class assignment operator is inaccessible - # C4800 'int' : forcing value to bool 'true' or 'false' (performance warning) - # C4018 '<' : signed/unsigned mismatch - # C4710 'XXX' : function not inlined - # C4291 'void *operator new(size_t,IMemAlloc *)' : no matching operator delete found; memory will not be freed if initialization throws an exception - # C4389 '!=' : signed/unsigned mismatch - # C4200 nonstandard extension used : zero-sized array in struct/union - # C4255 'XXX' : no function prototype given: converting '()' to '(void)' - # C4711 function 'XXX' selected for automatic inline expansion - # C4355 'this' : used in base member initializer list - # C4640 'XXX' : construction of local static object is not thread-safe - # x C4714 function 'XXX' marked as __forceinline not inlined - # C4305 'initializing' : truncation from 'double' to 'real' - # C4511 'XXX' : copy constructor could not be generated - # C4512 'XXX' : assignment operator could not be generated - # C4305 'XXX' : truncation from 'double' to 'float' - # C4738 storing 32-bit float result in memory, possible loss of performance - # C4996 'stricmp' was declared deprecated - # C4740 macro redefinition - # C4702 unreachable code - # C4826: Conversion from 'const void *' to 'void * __ptr64' is sign-extended. This may cause unexpected runtime behavior. - # C4503 decorated name length exceeded, name was truncated - _SUPPRESS_OPT = -Wall -WX /wd4514 /wd4061 /wd4820 /wd4668 /wd4619 - /wd4365 /wd4127 /wd4302 /wd4242 /wd4244 /wd4265 - /wd4101 /wd4201 /wd4625 /wd4626 /wd4800 /wd4018 - /wd4710 /wd4245 /wd4291 /wd4389 /wd4200 /wd4255 - /wd4711 /wd4062 /wd4355 /wd4640 /wd4305 /wd4324 - /wd4511 /wd4512 /wd4305 /wd4738 /wd4996 /wd4005 - /wd4740 /wd4702 /wd4826 /wd4503 - #/wd444 /wd279 /wd981 /wd383 /wd310 /wd174 /wd111 /wd271 /wd4714 ; - ; - } - else - { - _SUPPRESS_OPT = -W3 /wd4244 /wd4101 /wd4800 /wd4018 /wd4291 /wd4200 /wd4355 /wd4305 - /wd4996 /wd4005 /wd4740 /wd4324 /wd4503 - #/w14263 #warning C4263: 'void B::f(int)' : member function does not override any base class virtual member function - #/w14264 #warning C4264: 'void A::f(void)' : no override available for virtual member function from base 'A'; function is hidden - ; - } - - - switch $(Config) { - case dev : - _CONFIG_OPT = /Ox /GF /Gy /Oi /Ot /arch:SSE2 /Zi /Oy- -DDAGOR_DBGLEVEL=1 ; - case rel : - _CONFIG_OPT = /Ox /GF /Gy /Oi /Ot /arch:SSE2 /Zi /Oy- -DDAGOR_DBGLEVEL=0 -DNDEBUG=1 -D_SECURE_SCL=0 ; - case irel : - _CONFIG_OPT = /Ox /GF /Gy /Oi /Ot /arch:SSE2 /Zi /Oy- -DDAGOR_DBGLEVEL=-1 -DNDEBUG=1 -D_SECURE_SCL=0 ; - case dbg : - _CONFIG_OPT = /Zi /Od /RTC1 /arch:SSE2 -DDAGOR_DBGLEVEL=2 ; - case analyze : - _CONFIG_OPT = /Ox /GF /Gy /Oi /Ot /arch:SSE2 /Zi -DDAGOR_DBGLEVEL=1 /analyze ; - case prefast : - _CONFIG_OPT = /Ox /GF /Gy /Oi /Ot /arch:SSE2 /Zi -DDAGOR_DBGLEVEL=1 ; - case * : - _CONFIG_OPT = ; - } - - if $(Exceptions) != yes { - _CONFIG_OPT += -D_HAS_EXCEPTIONS=0 -DEA_COMPILER_NO_NOEXCEPT ; - } else { - if ($CatchSEH) != yes { - _CONFIG_OPT += /EHsc -DDAGOR_EXCEPTIONS_ENABLED=1 ; - } else { - _CONFIG_OPT += /EHac -DDAGOR_EXCEPTIONS_ENABLED=1 ; - } - } - - if $(Rtti) != yes { - _CONFIG_OPT += /GR- ; - } - - if $(Config) != dbg { - _CONFIG_OPT += $(_VC_CRT_TYPE) ; - } else { - _CONFIG_OPT += $(_VC_CRT_TYPE)d ; - } - - if $(DriverLinkage) = static { _CONFIG_OPT += -D_TARGET_STATIC_LIB=1 ; } - if $(StarForce) = yes { _CONFIG_OPT += -DSTARFORCE_PROTECT ; } - if $(UseWholeOpt) = yes { _CONFIG_OPT += /GL ; } - if $(Analyze) = yes { _CONFIG_OPT += /analyze ; } - - _CPP_OPT = -I$(AddIncludes) $(_CONFIG_OPT) $(_SUPPRESS_OPT) $(CPPopt) $(GlobalCPPopt) ; - - AddForceFastcall _CPP_OPT ; - AddDirectXInclude pre_opt : post_opt ; - AddWtlInclude pre_opt : vc8 ; - - if $(QtVer) { AddQtCompileOpt ; } - - include $(Root)/prog/_jBuild/_vc/add_fp_fast.jam ; - $(Target)__CPP_OPT = -FImemory/dag_memBase.h $(post_opt) $(_CPP_OPT) -TP ; - $(Target)__C_OPT = $(post_opt) $(Copt) $(_CPP_OPT) ; - $(Target)__ASM_OPT = -I$(AddIncludes) $(ASMopt) ; - $(Target)__PRE_OPT = $(pre_opt) ; - include $(Root)/prog/_jBuild/_vc/add_fd_opt.jam ; -} - - -rule DepRule -{ - local changed_dep = ; - - # add $(Root) prefix when needed - for dep in $(>) - { - switch $(dep) - { - case ?:* : changed_dep += $(dep) ; # absolute path with drive - case \\* : changed_dep += $(dep) ; # absolute path with root foolder (\) - case /* : changed_dep += $(dep) ; # absolute path with root foolder (/) - case * : changed_dep += $(Root)/$(dep) ; # relative path, add $(Root) prefix - } - } - Includes $(<) : $(changed_dep) ; - null_action $(changed_dep) ; -} - - -rule CheckHeaders -{ - Depends $(<) : $(>) ; - NoCare $(>) ; # tolerant to .d absence - NOUPDATE $(>) ; # tolerant to .d timestamp - - # scan line for header, skipping any ../ at the beginning [will be prefixed with $(Root)] - HDRSCAN on $(>) = "^.*: [\.\\\/]*([^\ -]*).*$" ; - HDRRULE on $(>) = DepRule ; -} - - -actions together quietly compile_cpp -{ -#async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 - call_filtered $(_CPP_COMPILER) $(pre_opt) $(_CPP_BASE_INCLUDES) $(cpp_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# - if errorlevel 1 goto failed - if not exist $(1) goto failed - goto end - :failed - set ERRORLEVEL=13 - :end - - clr_filters - $(CODE_CHECK) -x $(1) $(2) -} - -actions together quietly compile_prefast_cpp -{ - set PATH=#\($(_VC_DIR)/bin)\# - call $(_PREFAST_COMPILER) $(pre_opt) $(_CPP_BASE_INCLUDES) $(cpp_opt) #\(-Fo$(1) $(2:G=))\# - if errorlevel 1 goto failed - if not exist $(1) goto failed - goto end - :failed - set ERRORLEVEL=13 - :end -} - -actions together quietly compile_c -{ -#async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 - call_filtered $(_CPP_COMPILER) $(pre_opt) $(_C_BASE_INCLUDES) $(c_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# - if errorlevel 1 goto failed - if not exist $(1) goto failed - goto end - :failed - set ERRORLEVEL=13 - :end - - clr_filters - $(CODE_CHECK) -x $(1) $(2) -} - -include $(Root)/prog/_jBuild/_vc/win_rc.jam ; diff --git a/prog/_jBuild/win32/vc9-link.jam b/prog/_jBuild/win32/vc9-link.jam deleted file mode 100644 index 1e0c711c1..000000000 --- a/prog/_jBuild/win32/vc9-link.jam +++ /dev/null @@ -1,140 +0,0 @@ -# to be included in jBuild.jam - -rule ProcessLinkTarget -{ - BaseAddress ?= 0x00400000 ; - - local _WIN_LIBS = user32.lib ole32.lib kernel32.lib gdi32.lib winmm.lib dbghelp.lib ; - - if $(TargetType) = exe - { - _LINK_OPT = -nologo -filealign:512 -base:$(BaseAddress) -incremental:no /LARGEADDRESSAWARE ; - - AddDirectXLibs _LINK_OPT ; - AddWtlLibs _LINK_OPT : vc8 ; - - if $(ConsoleExe) != yes { - _LINK_OPT += -subsystem:windows ; - } - - if $(_VC_CRT_TYPE) = -MT { - _LINK_OPT += -nodefaultlib:MSVCRT -nodefaultlib:MSVCPRT -nodefaultlib:LIBMMT -nodefaultlib:LIBIRC -nodefaultlib:LIBC ; - if $(Config) != dbg { - _WIN_LIBS += libcmt.lib libcpmt.lib ; - _LINK_OPT += -nodefaultlib:LIBCMTD -nodefaultlib:LIBCPMTD ; - } else { - _WIN_LIBS += libcmtd.lib libcpmtd.lib ; - _LINK_OPT += -nodefaultlib:LIBCMT -nodefaultlib:LIBCPMT ; - } - } else { - _LINK_OPT += -nodefaultlib:LIBMMT -nodefaultlib:LIBIRC -nodefaultlib:LIBC ; - if $(Config) != dbg { - _WIN_LIBS += MSVCRT.lib MSVCPRT.lib ; - _LINK_OPT += -nodefaultlib:LIBCMT -nodefaultlib:LIBCPMT ; - } else { - _WIN_LIBS += MSVCRTd.lib MSVCPRTd.lib ; - _LINK_OPT += -nodefaultlib:LIBCMT -nodefaultlib:LIBCPMT ; - } - } - - if $(Config) != dbg { - _LINK_OPT += -opt:ref ; - } - - if $(UseWholeOpt) = yes { - _LINK_OPT += /LTCG ; - } - - $(Target)__LINK = $(_LINK) $(LINKopt) ; - $(Target)__LINK_OPT = $(_LINK_OPT) ; - - LinkExeSetMap $(Target) : ; - LinkExeSetBuildStamp $(Target) ; - LinkAddManifest $(Target) : $(OutDir) ; - } - else if $(TargetType) = lib - { - $(Target)__LINK = $(_LIB) ; - $(Target)__LINK_OPT = -nologo $(LINKopt) ; - - if $(UseWholeOpt) = yes { - $(Target)__LINK_OPT += /LTCG ; - } - } - else if $(TargetType) = dll - { - _LINK_OPT = -nologo -dll -subsystem:windows -base:$(BaseAddress) -incremental:no /LARGEADDRESSAWARE ; - AddDirectXLibs _LINK_OPT ; - if $(Config) != dbg { - _LINK_OPT += -opt:ref ; - } - - if $(UseWholeOpt) = yes { - _LINK_OPT += /LTCG ; - } - - $(Target)__LINK = $(_LINK) ; - $(Target)__LINK_OPT = $(_LINK_OPT) $(LINKopt) ; - - LinkDllSetMapExpLib $(Target) : $(OutDir) : ; - } - - local _ADD_LIBS = " " $(1) ; - - if $(QtVer) { AddQtLinkOpt ; } - - if $(TargetType) = exe { - _ADD_LIBS += $(_WIN_LIBS) ; - } - - $(Target)__LINK_LIBS = $(_ADD_LIBS) ; -} - - -actions together quietly link_target -{ -#async - $(prelink_cmd) - echo linking $(1:B)$(1:S) - del $(1) - $(DEL_)$(pdb_path) - set_filter nul /warning LNK4099/ - call_filtered $(link) $(link_opt) #\( $(link_libs) $(resources) $(DEBUG_PDB_)$(pdb_path) -out:$(1) $(obj_list) )\# - if errorlevel 1 goto after_postlink - $(postlink_cmd) - :after_postlink - echo ---------------------------------------------------------------------- - if errorlevel 1 goto failed - if not exist $(1) goto failed - echo SUCCESSFULLY built $(1:B)$(1:S) $(_PrintedOutput) - goto end - - :failed - echo FAILED to build $(1:B)$(1:S) [Error #%errorlevel%] $(_PrintedOutput) - set ERRORLEVEL=13 - - :end - echo . -} - - -actions together quietly lib_target -{ -#async - echo creating lib $(1:B)$(1:S) - del $(1) - set_filter nul /warning LNK4221/ - call_filtered $(link) $(link_opt) #\( -out:$(1) $(obj_list) $(link_libs) )\# - echo ---------------------------------------------------------------------- - if errorlevel 1 goto failed - if not exist $(1) goto failed - echo SUCCESSFULLY built $(1:B)$(1:S) $(_PrintedOutput) - goto end - - :failed - echo FAILED to build $(1:B)$(1:S) [Error #%errorlevel%] $(_PrintedOutput) - set ERRORLEVEL=13 - - :end - echo . -} diff --git a/prog/_jBuild/win32/vc9-sets.jam b/prog/_jBuild/win32/vc9-sets.jam deleted file mode 100644 index 1aa539741..000000000 --- a/prog/_jBuild/win32/vc9-sets.jam +++ /dev/null @@ -1,84 +0,0 @@ -# Setup for Intel C++ compiler for Win32 (to be included from jBuild.jam) - -_OBJ_SUFFIX = .obj ; - -_VC_DIR = $(_DEVTOOL)/vc2008 ; -include $(Root)/prog/_jBuild/_vc/win_sdk.jam ; -_PREFAST_DIR = $(_DEVTOOL)/prefast ; -_VC_CRT_TYPE = -MT ; -C_preopt_DirectXVer = jun2010 ; - -if ! [ GLOB $(_VC_DIR) : * ] { exit FATAL\: \"$(_VC_DIR)\" not found! Please, update DEVTOOLS ; } -if ! [ GLOB $(_WIN_SDK) : * ] { exit FATAL\: \"$(_WIN_SDK)\" not found! Please, update DEVTOOLS ; } - -local _DEF_C_CMDLINE = - -X /D_TARGET_PC=1 -D_TARGET_PC_WIN=1 -D_TARGET_CPU_IA32=1 /D__IA32__=1 /DWIN32 /Dasm=__asm /DWIN32_LEAN_AND_MEAN= - /DNOMINMAX - -D_TARGET_SIMD_SSE=$(SSEVersion) - -Di_strlen=strlen - /c /nologo /Zc:forScope /Zp8 /J /bigobj -; - -if $(QtVer) { - _QT_DIR = $(_DEVTOOL)/Qt-$(QtVer)-vc2008 ; - if ! [ GLOB $(_QT_DIR) : * ] { exit FATAL\: \"$(_QT_DIR)\" not found! Please, update DEVTOOLS ; } - - _DEF_C_CMDLINE += - -DQT_LARGEFILE_SUPPORT -DQT_THREAD_SUPPORT -DQT_GUI_LIB -DQT_CORE_LIB - -D_STD_RTL_MEMORY=1 - /Zc:wchar_t- - ; - if $(QtVerStatic) = yes { _DEF_C_CMDLINE += -DQT_NODLL ; } else { _VC_CRT_TYPE = -MD ; } - - _QT_MOC = $(_QT_DIR)/bin/moc.exe ; - _QT_UIC = $(_QT_DIR)/bin/uic.exe ; - _QT_RCC = $(_QT_DIR)/bin/rcc.exe ; -} else { - _DEF_C_CMDLINE += /Zc:wchar_t ; -} - -_LINK = $(_VC_DIR)/bin/link.exe /machine:x86 ; -_LIB = $(_VC_DIR)/bin/lib.exe /machine:x86 ; -_CPP_COMPILER = $(_VC_DIR)/bin/cl.exe $(_DEF_C_CMDLINE) ; -_C_COMPILER = $(_VC_DIR)/bin/cl.exe $(_DEF_C_CMDLINE) ; -_PREFAST_COMPILER = $(_PREFAST_DIR)/bin/bin/x86/PREfast.exe /NEW_FAILURE=never /StackHogThreshold=512000 /FilterPreset=wspmin /noreset cl $(_DEF_C_CMDLINE) ; -_ASM_COMPILER = $(_DEVTOOL)/nasm/nasmw.exe -f win32 --prefix _ ; -_MASM_COMPILER = $(_VC_DIR)/bin/ml.exe -c -nologo ; - -_DEP_COMPILER = $(Root)/prog/_jBuild/fastdep-g.exe --cVC80 /D_TARGET_PC=1 -D_TARGET_PC_WIN=1 /D__IA32__=1 /DWIN32 ; - -_RC_COMPILER = $(_WIN_SDK_BIN)/rc.exe /x /i$(_WIN_SDK_INC) /i$(_VC_DIR)/Include ; -_MT_UTIL = $(_WIN_SDK_BIN)/mt.exe ; -_CVTRES_EXE = $(_VC_DIR)/bin/cvtres.exe /MACHINE:X86 /NOLOGO ; - -_INCLUDE = $(_WIN_SDK_INC) $(_VC_DIR)/include ; -_LIBPATH = $(_WIN_SDK_LIB) $(_VC_DIR)/lib ; - -_INCLUDE += - $(_QT_DIR)/include/QtCore - $(_QT_DIR)/include/QtGui - $(_QT_DIR)/include/ActiveQt - $(_QT_DIR)/include - $(_QT_DIR)/mkspecs/win32-msvc2008 -; - - -# make linker cmd-line ### -for lib in $(_LIBPATH) { - _LINK += -libpath:$(lib) ; - _LIB += -libpath:$(lib) ; -} - -# make compiler cmd-line ### -_CPP_BASE_INCLUDES = -I$(MasterPreInclude) -I$(Root)/prog/dagorInclude -I$(Root)/prog/1stPartyLibs -I$(Root)/prog/3rdPartyLibs -I$(Root)/prog/3rdPartyLibs/eastl/include ; -_C_BASE_INCLUDES = -I$(MasterPreInclude) -I$(Root)/prog/dagorInclude -I$(Root)/prog/1stPartyLibs -I$(Root)/prog/3rdPartyLibs ; - -for inc in $(_INCLUDE) { - _CPP_BASE_INCLUDES += -I$(inc) ; - _C_BASE_INCLUDES += -I$(inc) ; - _DEP_COMPILER += --x$(inc) ; -} - -_DEF_C_CMDLINE = ; - -if $(QtVer) { include $(Root)/prog/_jBuild/win32/qt-inc.jam ; } diff --git a/prog/_jBuild/win32/vc9u-cpp.jam b/prog/_jBuild/win32/vc9u-cpp.jam deleted file mode 100644 index 40b97448c..000000000 --- a/prog/_jBuild/win32/vc9u-cpp.jam +++ /dev/null @@ -1,208 +0,0 @@ -# to be included in jBuild.jam - -rule ProcessCompileTarget -{ - # basic opts: warning/remark suppressing, additional includes etc. - local _SUPPRESS_OPT = ; - local _CONFIG_OPT = ; - local pre_opt = ; - local post_opt = ; - - if $(StrictCompile) = yes - { - # suppressed warnigs list (marked with x are not suppressed now): - # C4265 'XXX' : class has virtual functions, but destructor is not virtual - # C4127 conditional expression is constant - # x C4100 'XXX' : unreferenced formal parameter - # x 981 operands are evaluated in unspecified order - # x 383 value copied to temporary, reference to temporary used - # x 310 old-style parameter list (anachronism) - # x 174 expression has no effect - # x 111 statement is unreachable - # x 271 trailing comma is nonstandard - # C4514 'XXX' : unreferenced inline function has been removed - # C4061 enumerator 'XXX' in switch of enum 'YYY' is not explicitly handled by a case label - # C4062 enumerator 'XXX' in switch of enum 'YYY' is not handled - # C4820 'XXX' : 'N' bytes padding added after data member 'XXX::YYY' - # C4668 'XXX' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' - # C4619 pragma warning : there is no warning number 'NNN' - # C4365 'XXX' : conversion from 'TYPE1' to 'TYPE2', signed/unsigned mismatch - # C4302 'type cast' : truncation from 'TYPE1' to 'TYPE2' - # C4244 '=' : conversion from 'TYPE1' to 'TYPE2', possible loss of data - # C4242 'argument' : conversion from 'TYPE1' to 'TYPE2', possible loss of data - # C4245 'argument' : conversion from 'TYPE1' to 'TYPE2', signed/unsigned mismatch - # C4101 'XXX' : unreferenced local variable - # C4201 nonstandard extension used : nameless struct/union - # C4625 'XXX' : copy constructor could not be generated because a base class copy constructor is inaccessible - # C4626 'XXX' : assignment operator could not be generated because a base class assignment operator is inaccessible - # C4800 'int' : forcing value to bool 'true' or 'false' (performance warning) - # C4018 '<' : signed/unsigned mismatch - # C4710 'XXX' : function not inlined - # C4291 'void *operator new(size_t,IMemAlloc *)' : no matching operator delete found; memory will not be freed if initialization throws an exception - # C4389 '!=' : signed/unsigned mismatch - # C4200 nonstandard extension used : zero-sized array in struct/union - # C4255 'XXX' : no function prototype given: converting '()' to '(void)' - # C4711 function 'XXX' selected for automatic inline expansion - # C4355 'this' : used in base member initializer list - # C4640 'XXX' : construction of local static object is not thread-safe - # x C4714 function 'XXX' marked as __forceinline not inlined - # C4305 'initializing' : truncation from 'double' to 'real' - # C4511 'XXX' : copy constructor could not be generated - # C4512 'XXX' : assignment operator could not be generated - # C4305 'XXX' : truncation from 'double' to 'float' - # C4738 storing 32-bit float result in memory, possible loss of performance - # C4996 'stricmp' was declared deprecated - # C4740 macro redefinition - # C4702 unreachable code - _SUPPRESS_OPT = -Wall -WX /wd4514 /wd4061 /wd4820 /wd4668 /wd4619 - /wd4365 /wd4127 /wd4302 /wd4242 /wd4244 /wd4265 - /wd4101 /wd4201 /wd4625 /wd4626 /wd4800 /wd4018 - /wd4710 /wd4245 /wd4291 /wd4389 /wd4200 /wd4255 - /wd4711 /wd4062 /wd4355 /wd4640 /wd4305 - /wd4511 /wd4512 /wd4305 /wd4738 /wd4996 /wd4005 - /wd4740 /wd4702 - #/wd444 /wd279 /wd981 /wd383 /wd310 /wd174 /wd111 /wd271 /wd4714 ; - ; - } - else - { - _SUPPRESS_OPT = -W3 /wd4244 /wd4101 /wd4800 /wd4018 /wd4291 /wd4200 /wd4355 /wd4305 - /wd4996 /wd4005 /wd4740 /wd4265 ; - } - - local _DEF_CPP_OPT = /c /nologo /Zc:wchar_t /Zp8 /J /DWIN32 ; - - if $(Exceptions) != yes { - _DEF_CPP_OPT += -D_HAS_EXCEPTIONS=0 -DEA_COMPILER_NO_NOEXCEPT ; - } else { - if ($CatchSEH) != yes { - _DEF_CPP_OPT += /EHsc -DDAGOR_EXCEPTIONS_ENABLED=1 ; - } else { - _DEF_CPP_OPT += /EHac -DDAGOR_EXCEPTIONS_ENABLED=1 ; - } - } - - if $(Rtti) != yes { - _DEF_CPP_OPT += /GR- ; - } - - if $(_GlobCopt_ForScope) { - _DEF_CPP_OPT += $(_GlobCopt_ForScope) ; - } else { - _DEF_CPP_OPT += /Zc:forScope ; - } - - local _DEF_ASM_OPT = ; - - switch $(Config) { - case dev : - _CONFIG_OPT = /GF /Gy /arch:SSE /Zi /Oy- -DDAGOR_DBGLEVEL=1 ; - case *rel : - _CONFIG_OPT = /GF /Gy /arch:SSE /Zi /Oy- -DDAGOR_DBGLEVEL=0 ; - case dbg : - _CONFIG_OPT = /Zi /RTC1 -DDAGOR_DBGLEVEL=2 ; - case * : - _CONFIG_OPT = ; - } - - if $(_GlobCopt_Optimize) { - _CONFIG_OPT += $(_GlobCopt_Optimize) ; - } else { - if $(Config) != dbg { - _CONFIG_OPT += /Ox /Oi /Ot ; - } else { - _CONFIG_OPT += /Od ; - } - } - - if $(_GlobCopt_CRT) { - _CONFIG_OPT += $(_GlobCopt_CRT) ; - } else { - if $(Config) != dbg { - _CONFIG_OPT += -MT ; - } else { - _CONFIG_OPT += -MTd ; - } - } - - for inc in $(AddIncludes) - { - _DEF_CPP_OPT += -I$(inc) ; - _DEF_ASM_OPT += -I$(inc) ; - } - - _CPP_OPT = $(_DEF_CPP_OPT) $(_CONFIG_OPT) $(_SUPPRESS_OPT) $(CPPopt) $(GlobalCPPopt) ; - - AddDirectXInclude pre_opt : post_opt ; - - - $(Target)__CPP_OPT = $(post_opt) $(_CPP_OPT) -TP ; - $(Target)__C_OPT = $(post_opt) $(Copt) $(_CPP_OPT) ; - $(Target)__ASM_OPT = $(_DEF_ASM_OPT) $(ASMopt) ; - $(Target)__PRE_OPT = -I$(PreAddIncludes) $(pre_opt) ; - include $(Root)/prog/_jBuild/_vc/add_fd_opt.jam ; -} - - -rule DepRule -{ - local changed_dep = ; - - # add $(Root) prefix when needed - for dep in $(>) - { - switch $(dep) - { - case ?:* : changed_dep += $(dep) ; # absolute path with drive - case \\* : changed_dep += $(dep) ; # absolute path with root foolder (\) - case /* : changed_dep += $(dep) ; # absolute path with root foolder (/) - case * : changed_dep += $(Root)/$(dep) ; # relative path, add $(Root) prefix - } - } - Includes $(<) : $(changed_dep) ; - null_action $(changed_dep) ; -} - - -rule CheckHeaders -{ - Depends $(<) : $(>) ; - NoCare $(>) ; # tolerant to .d absence - NOUPDATE $(>) ; # tolerant to .d timestamp - - # scan line for header, skipping any ../ at the beginning [will be prefixed with $(Root)] - HDRSCAN on $(>) = "^.*: [\.\\\/]*([^\ -]*).*$" ; - HDRRULE on $(>) = DepRule ; -} - - -actions together quietly compile_cpp -{ -#async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 - call_filtered $(_CPP_COMPILER) $(pre_opt) $(_CPP_BASE_INCLUDES) /fp:fast $(cpp_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# - if errorlevel 1 goto failed - if not exist $(1) goto failed - goto end - :failed - set ERRORLEVEL=13 - :end -} - -actions together quietly compile_c -{ -#async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 - call_filtered $(_CPP_COMPILER) $(pre_opt) $(_C_BASE_INCLUDES) /fp:fast $(c_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# - if errorlevel 1 goto failed - if not exist $(1) goto failed - goto end - :failed - set ERRORLEVEL=13 - :end -} - -include $(Root)/prog/_jBuild/_vc/win_rc.jam ; diff --git a/prog/_jBuild/win32/vc9u-link.jam b/prog/_jBuild/win32/vc9u-link.jam deleted file mode 100644 index 120f06c63..000000000 --- a/prog/_jBuild/win32/vc9u-link.jam +++ /dev/null @@ -1,113 +0,0 @@ -# to be included in jBuild.jam - -rule ProcessLinkTarget -{ - BaseAddress ?= 0x00400000 ; - - local _WIN_LIBS = user32.lib ole32.lib kernel32.lib gdi32.lib winmm.lib dbghelp.lib ; - - if $(TargetType) = exe - { - _LINK_OPT = -nologo -filealign:512 -base:$(BaseAddress) -incremental:no /LARGEADDRESSAWARE ; - AddDirectXLibs _LINK_OPT ; - - if $(ConsoleExe) != yes { - _LINK_OPT += -subsystem:windows ; - } - - _LINK_OPT += -nodefaultlib:MSVCRT -nodefaultlib:MSVCPRT ; - if $(Config) != dbg { - _WIN_LIBS += libcmt.lib libcpmt.lib ; - _LINK_OPT += -nodefaultlib:LIBCMTD -nodefaultlib:LIBCPMTD ; - } else { - _WIN_LIBS += libcmtd.lib libcpmtd.lib ; - _LINK_OPT += -nodefaultlib:LIBCMT -nodefaultlib:LIBCPMT ; - } - - if $(Config) != dbg { - _LINK_OPT += -opt:ref ; - } - - $(Target)__LINK = $(_LINK) ; - $(Target)__LINK_OPT = $(_LINK_OPT) $(LINKopt) ; - - LinkExeSetMap $(Target) : ; - LinkExeSetBuildStamp $(Target) ; - LinkAddManifest $(Target) : $(OutDir) ; - } - else if $(TargetType) = lib - { - $(Target)__LINK = $(_LIB) ; - $(Target)__LINK_OPT = -nologo $(LINKopt) ; - } - else if $(TargetType) = dll - { - _LINK_OPT = -nologo -dll -subsystem:windows -base:$(BaseAddress) -incremental:no /LARGEADDRESSAWARE ; - AddDirectXLibs _LINK_OPT ; - if $(Config) != dbg { - _LINK_OPT += -opt:ref ; - } - - $(Target)__LINK = $(_LINK) ; - $(Target)__LINK_OPT = $(_LINK_OPT) $(LINKopt) ; - - LinkDllSetMapExpLib $(Target) : $(OutDir) : ; - } - - local _ADD_LIBS = " " $(1) ; - - if $(TargetType) = exe { - _ADD_LIBS += $(_WIN_LIBS) ; - } - - $(Target)__LINK_LIBS = $(_ADD_LIBS) ; -} - - -actions together quietly link_target -{ -#async - $(prelink_cmd) - echo linking $(1:B)$(1:S) - del $(1) - $(DEL_)$(pdb_path) - set_filter nul /warning LNK4099/ - call_filtered $(link) $(link_opt) #\( $(link_libs) $(resources) $(DEBUG_PDB_)$(pdb_path) -out:$(1) $(obj_list) )\# - if errorlevel 1 goto after_postlink - $(postlink_cmd) - :after_postlink - echo ---------------------------------------------------------------------- - if errorlevel 1 goto failed - if not exist $(1) goto failed - echo SUCCESSFULLY built $(1:B)$(1:S) $(_PrintedOutput) - goto end - - :failed - echo FAILED to build $(1:B)$(1:S) [Error #%errorlevel%] $(_PrintedOutput) - set ERRORLEVEL=13 - - :end - echo . -} - - -actions together quietly lib_target -{ -#async - echo creating lib $(1:B)$(1:S) - del $(1) - set_filter nul /warning LNK4221/ - call_filtered $(link) $(link_opt) #\( -out:$(1) $(obj_list) $(link_libs) )\# - echo ---------------------------------------------------------------------- - if errorlevel 1 goto failed - if not exist $(1) goto failed - echo SUCCESSFULLY built $(1:B)$(1:S) $(_PrintedOutput) - goto end - - :failed - echo FAILED to build $(1:B)$(1:S) [Error #%errorlevel%] $(_PrintedOutput) - set ERRORLEVEL=13 - - :end - echo . -} diff --git a/prog/_jBuild/win32/vc9u-sets.jam b/prog/_jBuild/win32/vc9u-sets.jam deleted file mode 100644 index 592e511e9..000000000 --- a/prog/_jBuild/win32/vc9u-sets.jam +++ /dev/null @@ -1,41 +0,0 @@ -# Setup for MS Visual C++ 8 compiler for Win32 (to be included from jBuild.jam) - -_OBJ_SUFFIX = .obj ; - -_VC_DIR = $(_DEVTOOL)/vc2008 ; -include $(Root)/prog/_jBuild/_vc/win_sdk.jam ; -C_preopt_DirectXVer = jun2010 ; - -if ! [ GLOB $(_VC_DIR) : * ] { exit FATAL\: \"$(_VC_DIR)\" not found! Please, update DEVTOOLS ; } -if ! [ GLOB $(_WIN_SDK) : * ] { exit FATAL\: \"$(_WIN_SDK)\" not found! Please, update DEVTOOLS ; } - -_LINK = $(_VC_DIR)/bin/link.exe /machine:x86 ; -_LIB = $(_VC_DIR)/bin/lib.exe /machine:x86 ; -_CPP_COMPILER = $(_VC_DIR)/bin/cl.exe ; -_C_COMPILER = $(_VC_DIR)/bin/cl.exe ; -_ASM_COMPILER = $(_DEVTOOL)/nasm/nasmw.exe -f win32 --prefix _ ; -_MASM_COMPILER = $(_VC_DIR)/bin/ml.exe -c -nologo ; - -_DEP_COMPILER = $(Root)/prog/_jBuild/fastdep-g.exe --cVC80 ; - -_RC_COMPILER = $(_WIN_SDK_BIN)/rc.exe /x /i$(_WIN_SDK_INC) /i$(_VC_DIR)/Include ; -_MT_UTIL = $(_WIN_SDK_BIN)/mt.exe ; -_CVTRES_EXE = $(_VC_DIR)/bin/cvtres.exe /MACHINE:X86 /NOLOGO ; - -_INCLUDE = $(_WIN_SDK_INC) $(_VC_DIR)/include ; -_LIBPATH = $(_VC_DIR)/lib $(_WIN_SDK_LIB) ; - -# make linker cmd-line ### -for lib in $(_LIBPATH) { - _LINK += -libpath:$(lib) ; -} - -# make compiler cmd-line ### -_CPP_BASE_INCLUDES = -X -I$(MasterPreInclude) ; -_C_BASE_INCLUDES = -X -I$(MasterPreInclude) ; - -for inc in $(_INCLUDE) { - _CPP_BASE_INCLUDES += -I$(inc) ; - _C_BASE_INCLUDES += -I$(inc) ; - _DEP_COMPILER += --x$(inc) ; -} diff --git a/prog/_jBuild/win64/clang-cpp.jam b/prog/_jBuild/win64/clang-cpp.jam index 3b091b8f1..1934469d1 100644 --- a/prog/_jBuild/win64/clang-cpp.jam +++ b/prog/_jBuild/win64/clang-cpp.jam @@ -67,9 +67,6 @@ rule ProcessCompileTarget AddForceFastcall _CPP_OPT ; AddDirectXInclude pre_opt : post_opt ; - AddWtlInclude pre_opt : vc8 ; - - if $(QtVer) { AddQtCompileOpt ; } include $(Root)/prog/_jBuild/_vc/add_fp_fast.jam ; $(Target)__CPP_OPT = -FImemory/dag_memBase.h $(post_opt) $(_CPP_OPT) -TP ; @@ -121,8 +118,8 @@ rule CheckHeaders actions together quietly compile_cpp { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 echo $(2:G=:D=) call_filtered $(_CPP_COMPILER) $(pre_opt) $(_CPP_BASE_INCLUDES) $(cpp_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed @@ -151,8 +148,8 @@ actions together quietly compile_prefast_cpp actions together quietly compile_c { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 echo $(2:G=:D=) call_filtered $(_C_COMPILER) $(pre_opt) $(_C_BASE_INCLUDES) $(c_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed diff --git a/prog/_jBuild/win64/clang-sets.jam b/prog/_jBuild/win64/clang-sets.jam index c2abfb089..cbab3a50f 100644 --- a/prog/_jBuild/win64/clang-sets.jam +++ b/prog/_jBuild/win64/clang-sets.jam @@ -68,23 +68,7 @@ if $(SSEVersion) = 4 { _DEF_C_CMDLINE += -msse2 ; } -if $(QtVer) { - _QT_DIR = $(_DEVTOOL)/Qt-$(QtVer)-vc2008 ; - if ! [ GLOB $(_QT_DIR) : * ] { exit FATAL\: \"$(_QT_DIR)\" not found! Please, update DEVTOOLS ; } - - _DEF_C_CMDLINE += - -DQT_LARGEFILE_SUPPORT -DQT_THREAD_SUPPORT -DQT_GUI_LIB -DQT_CORE_LIB - -D_STD_RTL_MEMORY=1 - /Zc:wchar_t- - ; - if $(QtVerStatic) = yes { _DEF_C_CMDLINE += -DQT_NODLL ; } else { _VC_CRT_TYPE = -MD ; } - - _QT_MOC = $(_QT_DIR)/bin/moc.exe ; - _QT_UIC = $(_QT_DIR)/bin/uic.exe ; - _QT_RCC = $(_QT_DIR)/bin/rcc.exe ; -} else { - _DEF_C_CMDLINE += /Zc:wchar_t ; -} +_DEF_C_CMDLINE += /Zc:wchar_t ; if $(UseWholeOpt) = yes { UseLLDLink = yes ; @@ -120,14 +104,6 @@ _UCRT_INC = $(_DEVTOOL)/win.sdk.100/Include/10.0.19041.0/ucrt ; _INCLUDE = $(_UCRT_INC) $(_WIN_SDK_INC) $(_VC_DIR)/include ; _LIBPATH = $(_UCRT_LIB) $(_WIN_SDK_LIB) $(_CLANG_DIR)/lib/clang/$(CLangVer)/lib/windows $(_VC_DIR)/lib/x64 $(_UM_LIB) ; -_INCLUDE += - $(_QT_DIR)/include/QtCore - $(_QT_DIR)/include/QtGui - $(_QT_DIR)/include/ActiveQt - $(_QT_DIR)/include - $(_QT_DIR)/mkspecs/win64-msvc2008 -; - # make linker cmd-line ### for lib in $(_LIBPATH) { _LINK += -libpath:$(lib) ; @@ -145,5 +121,3 @@ for inc in $(_INCLUDE) { } _DEF_C_CMDLINE = ; - -if $(QtVer) { include $(Root)/prog/_jBuild/win64/qt-inc.jam ; } diff --git a/prog/_jBuild/win64/qt-inc.jam b/prog/_jBuild/win64/qt-inc.jam deleted file mode 100644 index 1758827d5..000000000 --- a/prog/_jBuild/win64/qt-inc.jam +++ /dev/null @@ -1,108 +0,0 @@ -rule AddQtCompileOpt -{ - _CPP_OPT = -I$(_QT_DIR)/include/Qt$(UseQtLibs) -I$(_QT_DIR)/include/Qt$(DefQtLibs) - -DQT_$(UseQtLibs:U)_LIB -DQT_$(DefQtLibs:U)_LIB - $(_CPP_OPT) ; - $(Target)__MOC_OPT = -I$(_QT_DIR)/include/Qt$(UseQtLibs) -I$(_QT_DIR)/include/Qt$(DefQtLibs) -DQT_$(UseQtLibs:U)_LIB -DQT_$(DefQtLibs:U)_LIB $(dll_opt) ; -} - -rule AddQtLinkOpt -{ - if $(TargetType) = exe || $(TargetType) = dll { - local qt_libs = $(_QT_DIR)/lib/QtCore $(_QT_DIR)/lib/QtGui $(_QT_DIR)/lib/Qt$(UseQtLibs) $(_QT_DIR)/lib/Qt$(DefQtLibs) ; - if $(Config) = dbg { - _ADD_LIBS += $(qt_libs)d4.lib ; - } else { - _ADD_LIBS += $(qt_libs)4.lib ; - } - } -} - -# rule how to compile QT .ui target -# params: ( target_pathname : sources : target ) -rule CompileUI -{ - local tgt = $($(3)__OutDir)/$(3) ; - local ui_h = $(Root)/$(1) ; - LOCATE on $(2) = $(Root) ; - Depends $(ui_h) : $(2) ; - Depends $(tgt) : $(ui_h) ; - compile_qt_ui $(ui_h) : $(2) ; -} - -# rule how to compile QT .moc target -# params: ( target_pathname : sources : target ) -rule CompileMOC -{ - Depends $(1) : $(Root)/$(2) ; - MakeDirectory $(1) : $(1:D) ; - opt on $(1) = $($(3)__MOC_OPT) ; - compile_qt_moc $(1) : $(Root)/$(2) ; - - local obj = $(1:S=$(_OBJ_SUFFIX)) ; - Depends $(obj) : $(1) ; - MakeDirectory $(obj) : $(obj:D) ; - - cpp_opt on $(obj) = $($(3)__CPP_OPT) ; - pre_opt on $(obj) = $($(3)__PRE_OPT) ; - - compile_cpp $(obj) : $(1) ; -} - -# rule how to compile QT .qrc target -# params: ( target_pathname : sources : target ) -rule CompileQRC -{ - Depends $(1) : $(Root)/$(2) ; - MakeDirectory $(1) : $(1:D) ; - compile_qt_rcc $(1) : $(Root)/$(2) ; - - local obj = $(1:S=$(_OBJ_SUFFIX)) ; - Depends $(obj) : $(1) ; - MakeDirectory $(obj) : $(obj:D) ; - - cpp_opt on $(obj) = $($(3)__CPP_OPT) ; - pre_opt on $(obj) = $($(3)__PRE_OPT) ; - - compile_cpp $(obj) : $(1) ; -} - - -actions quietly compile_qt_ui -{ -#async - echo QT-uic $(2:D=) - call $(_QT_UIC) -o $(1) $(2) - if errorlevel 1 goto failed - if not exist $(1) goto failed - goto end - :failed - set ERRORLEVEL=13 - :end -} - -actions quietly compile_qt_moc -{ -#async - echo QT-moc $(2:D=) - call $(_QT_MOC) $(opt) $(_CPP_BASE_INCLUDES) -o $(1) $(2) - if errorlevel 1 goto failed - if not exist $(1) goto failed - goto end - :failed - set ERRORLEVEL=13 - :end -} - -actions quietly compile_qt_rcc -{ -#async - echo QT-rcc $(2:D=) - call $(_QT_RCC) -o $(1) $(2) - if errorlevel 1 goto failed - if not exist $(1) goto failed - goto end - :failed - set ERRORLEVEL=13 - :end -} diff --git a/prog/_jBuild/win64/vc10-cpp.jam b/prog/_jBuild/win64/vc10-cpp.jam index d9106c4ed..49bc3f324 100644 --- a/prog/_jBuild/win64/vc10-cpp.jam +++ b/prog/_jBuild/win64/vc10-cpp.jam @@ -131,9 +131,6 @@ rule ProcessCompileTarget AddForceFastcall _CPP_OPT ; AddDirectXInclude pre_opt : post_opt ; - AddWtlInclude pre_opt : vc8 ; - - if $(QtVer) { AddQtCompileOpt ; } include $(Root)/prog/_jBuild/_vc/add_fp_fast.jam ; $(Target)__CPP_OPT = -FImemory/dag_memBase.h $(post_opt) $(_CPP_OPT) -TP ; @@ -180,8 +177,8 @@ rule CheckHeaders actions together quietly compile_cpp { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 call_filtered $(_CPP_COMPILER) $(pre_opt) $(_CPP_BASE_INCLUDES) $(cpp_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed if not exist $(1) goto failed @@ -209,8 +206,8 @@ actions together quietly compile_prefast_cpp actions together quietly compile_c { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 call_filtered $(_CPP_COMPILER) $(pre_opt) $(_C_BASE_INCLUDES) $(c_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed if not exist $(1) goto failed diff --git a/prog/_jBuild/win64/vc10-link.jam b/prog/_jBuild/win64/vc10-link.jam index 3d3cae6e1..c613dd4dc 100644 --- a/prog/_jBuild/win64/vc10-link.jam +++ b/prog/_jBuild/win64/vc10-link.jam @@ -11,7 +11,6 @@ rule ProcessLinkTarget _LINK_OPT = -nologo -filealign:512 -base:$(BaseAddress) -incremental:no ; AddDirectXLibs _LINK_OPT ; - AddWtlLibs _LINK_OPT : vc8 ; if $(ConsoleExe) != yes { _LINK_OPT += -subsystem:windows ; @@ -81,8 +80,6 @@ rule ProcessLinkTarget local _ADD_LIBS = " " $(1) ; - if $(QtVer) { AddQtLinkOpt ; } - if $(TargetType) = exe { _ADD_LIBS += $(_WIN_LIBS) ; } diff --git a/prog/_jBuild/win64/vc10-sets.jam b/prog/_jBuild/win64/vc10-sets.jam index 186b76c4d..e91c4b046 100644 --- a/prog/_jBuild/win64/vc10-sets.jam +++ b/prog/_jBuild/win64/vc10-sets.jam @@ -17,27 +17,9 @@ local _DEF_C_CMDLINE = /DNOMINMAX -D_TARGET_SIMD_SSE=$(SSEVersion) -D_TARGET_64BIT=1 -Di_strlen=(int)strlen - /c /nologo /Zc:forScope /Zp8 /J /bigobj + /c /nologo /Zc:forScope /Zp8 /J /bigobj /Zc:wchar_t ; -if $(QtVer) { - _QT_DIR = $(_DEVTOOL)/Qt-$(QtVer)-vc2008 ; - if ! [ GLOB $(_QT_DIR) : * ] { exit FATAL\: \"$(_QT_DIR)\" not found! Please, update DEVTOOLS ; } - - _DEF_C_CMDLINE += - -DQT_LARGEFILE_SUPPORT -DQT_THREAD_SUPPORT -DQT_GUI_LIB -DQT_CORE_LIB - -D_STD_RTL_MEMORY=1 - /Zc:wchar_t- - ; - if $(QtVerStatic) = yes { _DEF_C_CMDLINE += -DQT_NODLL ; } else { _VC_CRT_TYPE = -MD ; } - - _QT_MOC = $(_QT_DIR)/bin/moc.exe ; - _QT_UIC = $(_QT_DIR)/bin/uic.exe ; - _QT_RCC = $(_QT_DIR)/bin/rcc.exe ; -} else { - _DEF_C_CMDLINE += /Zc:wchar_t ; -} - _LINK = $(_VC_DIR)/bin/amd64/link.exe /machine:x64 ; _LIB = $(_VC_DIR)/bin/amd64/lib.exe /machine:x64 ; _CPP_COMPILER = $(_VC_DIR)/bin/amd64/cl.exe $(_DEF_C_CMDLINE) ; @@ -55,14 +37,6 @@ _CVTRES_EXE = $(_VC_DIR)/bin/amd64/cvtres.exe /MACHINE:x64 /NOLOGO ; _INCLUDE = $(_WIN_SDK_INC) $(_VC_DIR)/include ; _LIBPATH = $(_WIN_SDK_LIB) $(_VC_DIR)/lib/amd64 ; -_INCLUDE += - $(_QT_DIR)/include/QtCore - $(_QT_DIR)/include/QtGui - $(_QT_DIR)/include/ActiveQt - $(_QT_DIR)/include - $(_QT_DIR)/mkspecs/win64-msvc2008 -; - # make linker cmd-line ### for lib in $(_LIBPATH) { @@ -81,5 +55,3 @@ for inc in $(_INCLUDE) { } _DEF_C_CMDLINE = ; - -if $(QtVer) { include $(Root)/prog/_jBuild/win64/qt-inc.jam ; } diff --git a/prog/_jBuild/win64/vc10u-cpp.jam b/prog/_jBuild/win64/vc10u-cpp.jam index acbcd2538..3e0fb2e22 100644 --- a/prog/_jBuild/win64/vc10u-cpp.jam +++ b/prog/_jBuild/win64/vc10u-cpp.jam @@ -182,8 +182,8 @@ rule CheckHeaders actions together quietly compile_cpp { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 call_filtered $(_CPP_COMPILER) $(pre_opt) $(_CPP_BASE_INCLUDES) $(cpp_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed if not exist $(1) goto failed @@ -198,8 +198,8 @@ actions together quietly compile_cpp actions together quietly compile_c { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 call_filtered $(_CPP_COMPILER) $(pre_opt) $(_C_BASE_INCLUDES) $(c_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed if not exist $(1) goto failed diff --git a/prog/_jBuild/win64/vc10u-link.jam b/prog/_jBuild/win64/vc10u-link.jam index 1cad8b16a..476c5720b 100644 --- a/prog/_jBuild/win64/vc10u-link.jam +++ b/prog/_jBuild/win64/vc10u-link.jam @@ -9,7 +9,6 @@ rule ProcessLinkTarget _LINK_OPT = -nologo -filealign:512 -base:$(BaseAddress) -incremental:no ; AddDirectXLibs _LINK_OPT ; - AddWtlLibs _LINK_OPT : vc8 ; if $(ConsoleExe) != yes { _LINK_OPT += -subsystem:windows ; diff --git a/prog/_jBuild/win64/vc11-cpp.jam b/prog/_jBuild/win64/vc11-cpp.jam index 411430f4f..a969e73e4 100644 --- a/prog/_jBuild/win64/vc11-cpp.jam +++ b/prog/_jBuild/win64/vc11-cpp.jam @@ -135,9 +135,6 @@ rule ProcessCompileTarget AddForceFastcall _CPP_OPT ; AddDirectXInclude pre_opt : post_opt ; - AddWtlInclude pre_opt : vc8 ; - - if $(QtVer) { AddQtCompileOpt ; } include $(Root)/prog/_jBuild/_vc/add_fp_fast.jam ; $(Target)__CPP_OPT = -FImemory/dag_memBase.h $(post_opt) $(_CPP_OPT) -TP ; @@ -184,8 +181,8 @@ rule CheckHeaders actions together quietly compile_cpp { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 call_filtered $(_CPP_COMPILER) $(pre_opt) $(_CPP_BASE_INCLUDES) $(cpp_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed if not exist $(1) goto failed @@ -213,8 +210,8 @@ actions together quietly compile_prefast_cpp actions together quietly compile_c { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 call_filtered $(_CPP_COMPILER) $(pre_opt) $(_C_BASE_INCLUDES) $(c_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed if not exist $(1) goto failed diff --git a/prog/_jBuild/win64/vc11-link.jam b/prog/_jBuild/win64/vc11-link.jam index 3d3cae6e1..c613dd4dc 100644 --- a/prog/_jBuild/win64/vc11-link.jam +++ b/prog/_jBuild/win64/vc11-link.jam @@ -11,7 +11,6 @@ rule ProcessLinkTarget _LINK_OPT = -nologo -filealign:512 -base:$(BaseAddress) -incremental:no ; AddDirectXLibs _LINK_OPT ; - AddWtlLibs _LINK_OPT : vc8 ; if $(ConsoleExe) != yes { _LINK_OPT += -subsystem:windows ; @@ -81,8 +80,6 @@ rule ProcessLinkTarget local _ADD_LIBS = " " $(1) ; - if $(QtVer) { AddQtLinkOpt ; } - if $(TargetType) = exe { _ADD_LIBS += $(_WIN_LIBS) ; } diff --git a/prog/_jBuild/win64/vc11-sets.jam b/prog/_jBuild/win64/vc11-sets.jam index bc9df1ae4..c3d1af21f 100644 --- a/prog/_jBuild/win64/vc11-sets.jam +++ b/prog/_jBuild/win64/vc11-sets.jam @@ -17,27 +17,9 @@ local _DEF_C_CMDLINE = /DNOMINMAX -D_TARGET_SIMD_SSE=$(SSEVersion) -D_TARGET_64BIT=1 -D_ALLOW_KEYWORD_MACROS= -Di_strlen=(int)strlen - /c /nologo /Zc:forScope /Zp8 /J /bigobj + /c /nologo /Zc:forScope /Zp8 /J /bigobj /Zc:wchar_t ; -if $(QtVer) { - _QT_DIR = $(_DEVTOOL)/Qt-$(QtVer)-vc2008 ; - if ! [ GLOB $(_QT_DIR) : * ] { exit FATAL\: \"$(_QT_DIR)\" not found! Please, update DEVTOOLS ; } - - _DEF_C_CMDLINE += - -DQT_LARGEFILE_SUPPORT -DQT_THREAD_SUPPORT -DQT_GUI_LIB -DQT_CORE_LIB - -D_STD_RTL_MEMORY=1 - /Zc:wchar_t- - ; - if $(QtVerStatic) = yes { _DEF_C_CMDLINE += -DQT_NODLL ; } else { _VC_CRT_TYPE = -MD ; } - - _QT_MOC = $(_QT_DIR)/bin/moc.exe ; - _QT_UIC = $(_QT_DIR)/bin/uic.exe ; - _QT_RCC = $(_QT_DIR)/bin/rcc.exe ; -} else { - _DEF_C_CMDLINE += /Zc:wchar_t ; -} - _LINK = $(_VC_DIR)/bin/x86_amd64/link.exe /machine:x64 ; _LIB = $(_VC_DIR)/bin/x86_amd64/lib.exe /machine:x64 ; _CPP_COMPILER = $(_VC_DIR)/bin/x86_amd64/cl.exe $(_DEF_C_CMDLINE) ; @@ -55,14 +37,6 @@ _CVTRES_EXE = $(_VC_DIR)/bin/x86_amd64/cvtres.exe /MACHINE:x64 /NOLOGO ; _INCLUDE = $(_WIN_SDK_INC) $(_VC_DIR)/include ; _LIBPATH = $(_WIN_SDK_LIB) $(_VC_DIR)/lib/amd64 ; -_INCLUDE += - $(_QT_DIR)/include/QtCore - $(_QT_DIR)/include/QtGui - $(_QT_DIR)/include/ActiveQt - $(_QT_DIR)/include - $(_QT_DIR)/mkspecs/win64-msvc2008 -; - # make linker cmd-line ### for lib in $(_LIBPATH) { @@ -81,5 +55,3 @@ for inc in $(_INCLUDE) { } _DEF_C_CMDLINE = ; - -if $(QtVer) { include $(Root)/prog/_jBuild/win64/qt-inc.jam ; } diff --git a/prog/_jBuild/win64/vc12-cpp.jam b/prog/_jBuild/win64/vc12-cpp.jam index c866e5931..c4d2b73ad 100644 --- a/prog/_jBuild/win64/vc12-cpp.jam +++ b/prog/_jBuild/win64/vc12-cpp.jam @@ -141,9 +141,6 @@ rule ProcessCompileTarget AddForceFastcall _CPP_OPT ; AddDirectXInclude pre_opt : post_opt ; - AddWtlInclude pre_opt : vc8 ; - - if $(QtVer) { AddQtCompileOpt ; } include $(Root)/prog/_jBuild/_vc/add_fp_fast.jam ; $(Target)__CPP_OPT = -FImemory/dag_memBase.h $(post_opt) $(_CPP_OPT) -TP ; @@ -190,8 +187,8 @@ rule CheckHeaders actions together quietly compile_cpp { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 call_filtered $(_CPP_COMPILER) $(pre_opt) $(_CPP_BASE_INCLUDES) $(cpp_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed if not exist $(1) goto failed @@ -219,8 +216,8 @@ actions together quietly compile_prefast_cpp actions together quietly compile_c { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 call_filtered $(_CPP_COMPILER) $(pre_opt) $(_C_BASE_INCLUDES) $(c_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed if not exist $(1) goto failed diff --git a/prog/_jBuild/win64/vc12-link.jam b/prog/_jBuild/win64/vc12-link.jam index 3d3cae6e1..c613dd4dc 100644 --- a/prog/_jBuild/win64/vc12-link.jam +++ b/prog/_jBuild/win64/vc12-link.jam @@ -11,7 +11,6 @@ rule ProcessLinkTarget _LINK_OPT = -nologo -filealign:512 -base:$(BaseAddress) -incremental:no ; AddDirectXLibs _LINK_OPT ; - AddWtlLibs _LINK_OPT : vc8 ; if $(ConsoleExe) != yes { _LINK_OPT += -subsystem:windows ; @@ -81,8 +80,6 @@ rule ProcessLinkTarget local _ADD_LIBS = " " $(1) ; - if $(QtVer) { AddQtLinkOpt ; } - if $(TargetType) = exe { _ADD_LIBS += $(_WIN_LIBS) ; } diff --git a/prog/_jBuild/win64/vc12-sets.jam b/prog/_jBuild/win64/vc12-sets.jam index c196c8d91..33e399caa 100644 --- a/prog/_jBuild/win64/vc12-sets.jam +++ b/prog/_jBuild/win64/vc12-sets.jam @@ -17,27 +17,9 @@ local _DEF_C_CMDLINE = /DNOMINMAX -D_TARGET_SIMD_SSE=$(SSEVersion) -D_TARGET_64BIT=1 -D_ALLOW_KEYWORD_MACROS= -Di_strlen=(int)strlen - /c /nologo /Zc:forScope /Zp8 /J /bigobj + /c /nologo /Zc:forScope /Zp8 /J /bigobj /Zc:wchar_t ; -if $(QtVer) { - _QT_DIR = $(_DEVTOOL)/Qt-$(QtVer)-vc2008 ; - if ! [ GLOB $(_QT_DIR) : * ] { exit FATAL\: \"$(_QT_DIR)\" not found! Please, update DEVTOOLS ; } - - _DEF_C_CMDLINE += - -DQT_LARGEFILE_SUPPORT -DQT_THREAD_SUPPORT -DQT_GUI_LIB -DQT_CORE_LIB - -D_STD_RTL_MEMORY=1 - /Zc:wchar_t- - ; - if $(QtVerStatic) = yes { _DEF_C_CMDLINE += -DQT_NODLL ; } else { _VC_CRT_TYPE = -MD ; } - - _QT_MOC = $(_QT_DIR)/bin/moc.exe ; - _QT_UIC = $(_QT_DIR)/bin/uic.exe ; - _QT_RCC = $(_QT_DIR)/bin/rcc.exe ; -} else { - _DEF_C_CMDLINE += /Zc:wchar_t ; -} - _LINK = $(_VC_DIR)/bin/x86_amd64/link.exe /machine:x64 ; _LIB = $(_VC_DIR)/bin/x86_amd64/lib.exe /machine:x64 ; _CPP_COMPILER = $(_VC_DIR)/bin/x86_amd64/cl.exe $(_DEF_C_CMDLINE) ; @@ -55,14 +37,6 @@ _CVTRES_EXE = $(_VC_DIR)/bin/cvtres.exe /MACHINE:x64 /NOLOGO ; _INCLUDE = $(_WIN_SDK_INC) $(_VC_DIR)/include ; _LIBPATH = $(_WIN_SDK_LIB) $(_VC_DIR)/lib/amd64 ; -_INCLUDE += - $(_QT_DIR)/include/QtCore - $(_QT_DIR)/include/QtGui - $(_QT_DIR)/include/ActiveQt - $(_QT_DIR)/include - $(_QT_DIR)/mkspecs/win64-msvc2008 -; - # make linker cmd-line ### for lib in $(_LIBPATH) { @@ -81,5 +55,3 @@ for inc in $(_INCLUDE) { } _DEF_C_CMDLINE = ; - -if $(QtVer) { include $(Root)/prog/_jBuild/win64/qt-inc.jam ; } diff --git a/prog/_jBuild/win64/vc14-cpp.jam b/prog/_jBuild/win64/vc14-cpp.jam index ca312cc16..7a680ce20 100644 --- a/prog/_jBuild/win64/vc14-cpp.jam +++ b/prog/_jBuild/win64/vc14-cpp.jam @@ -160,9 +160,6 @@ rule ProcessCompileTarget AddForceFastcall _CPP_OPT ; AddDirectXInclude pre_opt : post_opt ; - AddWtlInclude pre_opt : vc8 ; - - if $(QtVer) { AddQtCompileOpt ; } include $(Root)/prog/_jBuild/_vc/add_fp_fast.jam ; $(Target)__CPP_OPT = -FImemory/dag_memBase.h $(post_opt) $(_CPP_OPT) -TP ; @@ -209,8 +206,8 @@ rule CheckHeaders actions together quietly compile_cpp { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 call_filtered $(_CPP_COMPILER) $(pre_opt) $(_CPP_BASE_INCLUDES) $(cpp_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed if not exist $(1) goto failed @@ -238,8 +235,8 @@ actions together quietly compile_prefast_cpp actions together quietly compile_c { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 call_filtered $(_CPP_COMPILER) $(pre_opt) $(_C_BASE_INCLUDES) $(c_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed if not exist $(1) goto failed diff --git a/prog/_jBuild/win64/vc14-link.jam b/prog/_jBuild/win64/vc14-link.jam index 48b30eeff..a14afda9a 100644 --- a/prog/_jBuild/win64/vc14-link.jam +++ b/prog/_jBuild/win64/vc14-link.jam @@ -25,7 +25,6 @@ rule ProcessLinkTarget if $(Sanitize) != disabled { _LINK_OPT += /FUNCTIONPADMIN ; } AddDirectXLibs _LINK_OPT ; - AddWtlLibs _LINK_OPT : vc8 ; if $(ConsoleExe) = yes { _LINK_OPT += -subsystem:console,\"5.02\" ; @@ -105,8 +104,6 @@ rule ProcessLinkTarget local _ADD_LIBS = " " $(1) ; - if $(QtVer) { AddQtLinkOpt ; } - if $(TargetType) = exe { _ADD_LIBS += $(_WIN_LIBS) ; } diff --git a/prog/_jBuild/win64/vc14-sets.jam b/prog/_jBuild/win64/vc14-sets.jam index 63e477a74..4a8b322bb 100644 --- a/prog/_jBuild/win64/vc14-sets.jam +++ b/prog/_jBuild/win64/vc14-sets.jam @@ -25,27 +25,9 @@ local _DEF_C_CMDLINE = /DDELAYIMP_INSECURE_WRITABLE_HOOKS # -D_STD_RTL_MEMORY=1 /c /nologo /Zc:forScope /Zp8 /J - /Zc:inline /bigobj + /Zc:inline /bigobj /Zc:wchar_t ; -if $(QtVer) { - _QT_DIR = $(_DEVTOOL)/Qt-$(QtVer)-vc2008 ; - if ! [ GLOB $(_QT_DIR) : * ] { exit FATAL\: \"$(_QT_DIR)\" not found! Please, update DEVTOOLS ; } - - _DEF_C_CMDLINE += - -DQT_LARGEFILE_SUPPORT -DQT_THREAD_SUPPORT -DQT_GUI_LIB -DQT_CORE_LIB - -D_STD_RTL_MEMORY=1 - /Zc:wchar_t- - ; - if $(QtVerStatic) = yes { _DEF_C_CMDLINE += -DQT_NODLL ; } else { _VC_CRT_TYPE = -MD ; } - - _QT_MOC = $(_QT_DIR)/bin/moc.exe ; - _QT_UIC = $(_QT_DIR)/bin/uic.exe ; - _QT_RCC = $(_QT_DIR)/bin/rcc.exe ; -} else { - _DEF_C_CMDLINE += /Zc:wchar_t ; -} - if $(UseWholeOpt) = yes { UseLLDLink = no ; } @@ -77,14 +59,6 @@ _UCRT_INC = $(_DEVTOOL)/win.sdk.100/Include/10.0.19041.0/ucrt ; _INCLUDE = $(_WIN_SDK_INC) $(_VC_DIR)/include $(_UCRT_INC) ; _LIBPATH = $(_UCRT_LIB) $(_WIN_SDK_LIB) $(_VC_DIR)/lib/amd64 $(_UM_LIB) ; -_INCLUDE += - $(_QT_DIR)/include/QtCore - $(_QT_DIR)/include/QtGui - $(_QT_DIR)/include/ActiveQt - $(_QT_DIR)/include - $(_QT_DIR)/mkspecs/win64-msvc2008 -; - # make linker cmd-line ### for lib in $(_LIBPATH) { @@ -103,5 +77,3 @@ for inc in $(_INCLUDE) { } _DEF_C_CMDLINE = ; - -if $(QtVer) { include $(Root)/prog/_jBuild/win64/qt-inc.jam ; } diff --git a/prog/_jBuild/win64/vc15-cpp.jam b/prog/_jBuild/win64/vc15-cpp.jam index 345b3ad03..426e1e8d9 100644 --- a/prog/_jBuild/win64/vc15-cpp.jam +++ b/prog/_jBuild/win64/vc15-cpp.jam @@ -183,9 +183,6 @@ rule ProcessCompileTarget AddForceFastcall _CPP_OPT ; AddDirectXInclude pre_opt : post_opt ; - AddWtlInclude pre_opt : vc8 ; - - if $(QtVer) { AddQtCompileOpt ; } include $(Root)/prog/_jBuild/_vc/add_fp_fast.jam ; $(Target)__CPP_OPT = -FImemory/dag_memBase.h $(post_opt) $(_CPP_OPT) -TP ; @@ -232,8 +229,8 @@ rule CheckHeaders actions together quietly compile_cpp { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 call_filtered $(_CPP_COMPILER) $(pre_opt) $(_CPP_BASE_INCLUDES) $(cpp_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed if not exist $(1) goto failed @@ -261,8 +258,8 @@ actions together quietly compile_prefast_cpp actions together quietly compile_c { #async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 + $(VC_START_SHOW_INCLUDES_FILTER) + set_filter $(1:S=.d) /$(VC_SHOW_INCLUDES_FILTER_PREFIX)(.+)/d1 $(1:G=:D=): $1 call_filtered $(_C_COMPILER) $(pre_opt) $(_C_BASE_INCLUDES) $(c_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# if errorlevel 1 goto failed if not exist $(1) goto failed diff --git a/prog/_jBuild/win64/vc15-link.jam b/prog/_jBuild/win64/vc15-link.jam index e0293dd24..144837ac7 100644 --- a/prog/_jBuild/win64/vc15-link.jam +++ b/prog/_jBuild/win64/vc15-link.jam @@ -26,7 +26,6 @@ rule ProcessLinkTarget if $(Sanitize) != disabled { _LINK_OPT += /FUNCTIONPADMIN ; } AddDirectXLibs _LINK_OPT ; - AddWtlLibs _LINK_OPT : vc8 ; if $(ConsoleExe) = yes { _LINK_OPT += -subsystem:console,\"5.02\" ; @@ -114,8 +113,6 @@ rule ProcessLinkTarget local _ADD_LIBS = " " $(1) ; - if $(QtVer) { AddQtLinkOpt ; } - if $(TargetType) = exe { _ADD_LIBS += $(_WIN_LIBS) ; } diff --git a/prog/_jBuild/win64/vc15-sets.jam b/prog/_jBuild/win64/vc15-sets.jam index 72034b19e..1d558ae2f 100644 --- a/prog/_jBuild/win64/vc15-sets.jam +++ b/prog/_jBuild/win64/vc15-sets.jam @@ -23,27 +23,9 @@ local _DEF_C_CMDLINE = /DDELAYIMP_INSECURE_WRITABLE_HOOKS # -D_STD_RTL_MEMORY=1 /c /nologo /Zc:forScope /Zp8 /J - /Zc:inline /bigobj + /Zc:inline /bigobj /Zc:wchar_t ; -if $(QtVer) { - _QT_DIR = $(_DEVTOOL)/Qt-$(QtVer)-vc2008 ; - if ! [ GLOB $(_QT_DIR) : * ] { exit FATAL\: \"$(_QT_DIR)\" not found! Please, update DEVTOOLS ; } - - _DEF_C_CMDLINE += - -DQT_LARGEFILE_SUPPORT -DQT_THREAD_SUPPORT -DQT_GUI_LIB -DQT_CORE_LIB - -D_STD_RTL_MEMORY=1 - /Zc:wchar_t- - ; - if $(QtVerStatic) = yes { _DEF_C_CMDLINE += -DQT_NODLL ; } else { _VC_CRT_TYPE = -MD ; } - - _QT_MOC = $(_QT_DIR)/bin/moc.exe ; - _QT_UIC = $(_QT_DIR)/bin/uic.exe ; - _QT_RCC = $(_QT_DIR)/bin/rcc.exe ; -} else { - _DEF_C_CMDLINE += /Zc:wchar_t ; -} - _LINK = $(_VC_DIR)/bin/Hostx64/x64/link.exe /machine:x64 ; _LIB = $(_VC_DIR)/bin/Hostx64/x64/lib.exe /machine:x64 ; _CPP_COMPILER = $(_VC_DIR)/bin/Hostx64/x64/cl.exe $(_DEF_C_CMDLINE) ; @@ -64,14 +46,6 @@ _UCRT_INC = $(_DEVTOOL)/win.sdk.100/Include/10.0.19041.0/ucrt ; _INCLUDE = $(_WIN_SDK_INC) $(_VC_DIR)/include $(_UCRT_INC) ; _LIBPATH = $(_UCRT_LIB) $(_WIN_SDK_LIB) $(_VC_DIR)/lib/x64 $(_UM_LIB) ; -_INCLUDE += - $(_QT_DIR)/include/QtCore - $(_QT_DIR)/include/QtGui - $(_QT_DIR)/include/ActiveQt - $(_QT_DIR)/include - $(_QT_DIR)/mkspecs/win64-msvc2008 -; - # make linker cmd-line ### for lib in $(_LIBPATH) { @@ -90,5 +64,3 @@ for inc in $(_INCLUDE) { } _DEF_C_CMDLINE = ; - -if $(QtVer) { include $(Root)/prog/_jBuild/win64/qt-inc.jam ; } diff --git a/prog/_jBuild/win64/vc16-sets.jam b/prog/_jBuild/win64/vc16-sets.jam index 563ff75ed..69cb4880a 100644 --- a/prog/_jBuild/win64/vc16-sets.jam +++ b/prog/_jBuild/win64/vc16-sets.jam @@ -24,27 +24,9 @@ local _DEF_C_CMDLINE = /DDELAYIMP_INSECURE_WRITABLE_HOOKS # -D_STD_RTL_MEMORY=1 /c /nologo /Zc:forScope /Zp8 /J - /Zc:inline /bigobj + /Zc:inline /bigobj /Zc:wchar_t ; -if $(QtVer) { - _QT_DIR = $(_DEVTOOL)/Qt-$(QtVer)-vc2008 ; - if ! [ GLOB $(_QT_DIR) : * ] { exit FATAL\: \"$(_QT_DIR)\" not found! Please, update DEVTOOLS ; } - - _DEF_C_CMDLINE += - -DQT_LARGEFILE_SUPPORT -DQT_THREAD_SUPPORT -DQT_GUI_LIB -DQT_CORE_LIB - -D_STD_RTL_MEMORY=1 - /Zc:wchar_t- - ; - if $(QtVerStatic) = yes { _DEF_C_CMDLINE += -DQT_NODLL ; } else { _VC_CRT_TYPE = -MD ; } - - _QT_MOC = $(_QT_DIR)/bin/moc.exe ; - _QT_UIC = $(_QT_DIR)/bin/uic.exe ; - _QT_RCC = $(_QT_DIR)/bin/rcc.exe ; -} else { - _DEF_C_CMDLINE += /Zc:wchar_t ; -} - if $(UseWholeOpt) = yes { UseLLDLink = no ; } @@ -79,14 +61,6 @@ if ! $(_UM_LIB:L) in $(_LIBPATH:L) { _LIBPATH += $(_UM_LIB) ; } -_INCLUDE += - $(_QT_DIR)/include/QtCore - $(_QT_DIR)/include/QtGui - $(_QT_DIR)/include/ActiveQt - $(_QT_DIR)/include - $(_QT_DIR)/mkspecs/win64-msvc2008 -; - # make linker cmd-line ### for lib in $(_LIBPATH) { @@ -105,5 +79,3 @@ for inc in $(_INCLUDE) { } _DEF_C_CMDLINE = ; - -if $(QtVer) { include $(Root)/prog/_jBuild/win64/qt-inc.jam ; } diff --git a/prog/_jBuild/win64/vc17-sets.jam b/prog/_jBuild/win64/vc17-sets.jam index 079027706..8e4d51667 100644 --- a/prog/_jBuild/win64/vc17-sets.jam +++ b/prog/_jBuild/win64/vc17-sets.jam @@ -24,27 +24,9 @@ local _DEF_C_CMDLINE = /DDELAYIMP_INSECURE_WRITABLE_HOOKS # -D_STD_RTL_MEMORY=1 /c /nologo /Zc:forScope /Zp8 /J - /Zc:inline /bigobj + /Zc:inline /bigobj /Zc:wchar_t ; -if $(QtVer) { - _QT_DIR = $(_DEVTOOL)/Qt-$(QtVer)-vc2008 ; - if ! [ GLOB $(_QT_DIR) : * ] { exit FATAL\: \"$(_QT_DIR)\" not found! Please, update DEVTOOLS ; } - - _DEF_C_CMDLINE += - -DQT_LARGEFILE_SUPPORT -DQT_THREAD_SUPPORT -DQT_GUI_LIB -DQT_CORE_LIB - -D_STD_RTL_MEMORY=1 - /Zc:wchar_t- - ; - if $(QtVerStatic) = yes { _DEF_C_CMDLINE += -DQT_NODLL ; } else { _VC_CRT_TYPE = -MD ; } - - _QT_MOC = $(_QT_DIR)/bin/moc.exe ; - _QT_UIC = $(_QT_DIR)/bin/uic.exe ; - _QT_RCC = $(_QT_DIR)/bin/rcc.exe ; -} else { - _DEF_C_CMDLINE += /Zc:wchar_t ; -} - if $(UseWholeOpt) = yes { UseLLDLink = no ; } @@ -79,14 +61,6 @@ if ! $(_UM_LIB:L) in $(_LIBPATH:L) { _LIBPATH += $(_UM_LIB) ; } -_INCLUDE += - $(_QT_DIR)/include/QtCore - $(_QT_DIR)/include/QtGui - $(_QT_DIR)/include/ActiveQt - $(_QT_DIR)/include - $(_QT_DIR)/mkspecs/win64-msvc2008 -; - # make linker cmd-line ### for lib in $(_LIBPATH) { @@ -105,5 +79,3 @@ for inc in $(_INCLUDE) { } _DEF_C_CMDLINE = ; - -if $(QtVer) { include $(Root)/prog/_jBuild/win64/qt-inc.jam ; } diff --git a/prog/_jBuild/win64/vc9-cpp.jam b/prog/_jBuild/win64/vc9-cpp.jam deleted file mode 100644 index 8e0eb591e..000000000 --- a/prog/_jBuild/win64/vc9-cpp.jam +++ /dev/null @@ -1,218 +0,0 @@ -# to be included in jBuild.jam - -rule ProcessCompileTarget -{ - # basic opts: warning/remark suppressing, additional includes etc. - local _SUPPRESS_OPT = ; - local _CONFIG_OPT = ; - local pre_opt = ; - local post_opt = ; - - if $(StrictCompile) = yes - { - # suppressed warnigs list (marked with x are not suppressed now): - # C4265 'XXX' : class has virtual functions, but destructor is not virtual - # C4127 conditional expression is constant - # x C4100 'XXX' : unreferenced formal parameter - # x 981 operands are evaluated in unspecified order - # x 383 value copied to temporary, reference to temporary used - # x 310 old-style parameter list (anachronism) - # x 174 expression has no effect - # x 111 statement is unreachable - # x 271 trailing comma is nonstandard - # C4514 'XXX' : unreferenced inline function has been removed - # C4061 enumerator 'XXX' in switch of enum 'YYY' is not explicitly handled by a case label - # C4062 enumerator 'XXX' in switch of enum 'YYY' is not handled - # C4820 'XXX' : 'N' bytes padding added after data member 'XXX::YYY' - # C4324 'XXX' : structure was padded due to __declspec(align()) - # C4668 'XXX' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' - # C4619 pragma warning : there is no warning number 'NNN' - # C4365 'XXX' : conversion from 'TYPE1' to 'TYPE2', signed/unsigned mismatch - # C4302 'type cast' : truncation from 'TYPE1' to 'TYPE2' - # C4244 '=' : conversion from 'TYPE1' to 'TYPE2', possible loss of data - # C4242 'argument' : conversion from 'TYPE1' to 'TYPE2', possible loss of data - # C4245 'argument' : conversion from 'TYPE1' to 'TYPE2', signed/unsigned mismatch - # C4101 'XXX' : unreferenced local variable - # C4201 nonstandard extension used : nameless struct/union - # C4625 'XXX' : copy constructor could not be generated because a base class copy constructor is inaccessible - # C4626 'XXX' : assignment operator could not be generated because a base class assignment operator is inaccessible - # C4800 'int' : forcing value to bool 'true' or 'false' (performance warning) - # C4018 '<' : signed/unsigned mismatch - # C4710 'XXX' : function not inlined - # C4291 'void *operator new(size_t,IMemAlloc *)' : no matching operator delete found; memory will not be freed if initialization throws an exception - # C4389 '!=' : signed/unsigned mismatch - # C4200 nonstandard extension used : zero-sized array in struct/union - # C4255 'XXX' : no function prototype given: converting '()' to '(void)' - # C4711 function 'XXX' selected for automatic inline expansion - # C4355 'this' : used in base member initializer list - # C4640 'XXX' : construction of local static object is not thread-safe - # x C4714 function 'XXX' marked as __forceinline not inlined - # C4305 'initializing' : truncation from 'double' to 'real' - # C4511 'XXX' : copy constructor could not be generated - # C4512 'XXX' : assignment operator could not be generated - # C4305 'XXX' : truncation from 'double' to 'float' - # C4738 storing 32-bit float result in memory, possible loss of performance - # C4996 'stricmp' was declared deprecated - # C4740 macro redefinition - # C4702 unreachable code - # C4826: Conversion from 'const void *' to 'void * __ptr64' is sign-extended. This may cause unexpected runtime behavior. - # C4503 decorated name length exceeded, name was truncated - _SUPPRESS_OPT = -Wall -WX /wd4514 /wd4061 /wd4820 /wd4668 /wd4619 - /wd4365 /wd4127 /wd4302 /wd4242 /wd4244 /wd4265 - /wd4101 /wd4201 /wd4625 /wd4626 /wd4800 /wd4018 - /wd4710 /wd4245 /wd4291 /wd4389 /wd4200 /wd4255 - /wd4711 /wd4062 /wd4355 /wd4640 /wd4305 /wd4324 - /wd4511 /wd4512 /wd4305 /wd4738 /wd4996 /wd4005 - /wd4740 /wd4702 /wd4826 /wd4503 - #/wd444 /wd279 /wd981 /wd383 /wd310 /wd174 /wd111 /wd271 /wd4714 ; - ; - } - else - { - _SUPPRESS_OPT = -W3 /wd4244 /wd4101 /wd4800 /wd4018 /wd4291 /wd4200 /wd4355 /wd4305 - /wd4996 /wd4005 /wd4740 /wd4324 /wd4503 - #/w14263 #warning C4263: 'void B::f(int)' : member function does not override any base class virtual member function - #/w14264 #warning C4264: 'void A::f(void)' : no override available for virtual member function from base 'A'; function is hidden - ; - } - - - switch $(Config) { - case dev : - _CONFIG_OPT = /Ox /GF /Gy /Oi /Ot /Zi /Oy- -DDAGOR_DBGLEVEL=1 ; - case rel : - _CONFIG_OPT = /Ox /GF /Gy /Oi /Ot /Zi /Oy- -DDAGOR_DBGLEVEL=0 -DNDEBUG=1 -D_SECURE_SCL=0 ; - case irel : - _CONFIG_OPT = /Ox /GF /Gy /Oi /Ot /Zi /Oy- -DDAGOR_DBGLEVEL=-1 -DNDEBUG=1 -D_SECURE_SCL=0 ; - case dbg : - _CONFIG_OPT = /Zi /Od /RTC1 -DDAGOR_DBGLEVEL=2 ; - case analyze : - _CONFIG_OPT = /Ox /GF /Gy /Oi /Ot /Zi -DDAGOR_DBGLEVEL=1 /analyze ; - case prefast : - _CONFIG_OPT = /Ox /GF /Gy /Oi /Ot /Zi -DDAGOR_DBGLEVEL=1 ; - case * : - _CONFIG_OPT = ; - } - - if $(Exceptions) != yes { - _CONFIG_OPT += -D_HAS_EXCEPTIONS=0 -DEA_COMPILER_NO_NOEXCEPT ; - } else { - if ($CatchSEH) != yes { - _CONFIG_OPT += /EHsc -DDAGOR_EXCEPTIONS_ENABLED=1 ; - } else { - _CONFIG_OPT += /EHac -DDAGOR_EXCEPTIONS_ENABLED=1 ; - } - } - - if $(Rtti) != yes { - _CONFIG_OPT += /GR- ; - } - - if $(Config) != dbg { - _CONFIG_OPT += $(_VC_CRT_TYPE) ; - } else { - _CONFIG_OPT += $(_VC_CRT_TYPE)d ; - } - - if $(DriverLinkage) = static { _CONFIG_OPT += -D_TARGET_STATIC_LIB=1 ; } - if $(StarForce) = yes { _CONFIG_OPT += -DSTARFORCE_PROTECT ; } - if $(UseWholeOpt) = yes { _CONFIG_OPT += /GL ; } - if $(Analyze) = yes { _CONFIG_OPT += /analyze ; } - - _CPP_OPT = -I$(AddIncludes) $(_CONFIG_OPT) $(_SUPPRESS_OPT) $(CPPopt) $(GlobalCPPopt) ; - - AddForceFastcall _CPP_OPT ; - AddDirectXInclude pre_opt : post_opt ; - AddWtlInclude pre_opt : vc8 ; - - if $(QtVer) { AddQtCompileOpt ; } - - include $(Root)/prog/_jBuild/_vc/add_fp_fast.jam ; - $(Target)__CPP_OPT = -FImemory/dag_memBase.h $(post_opt) $(_CPP_OPT) -TP ; - $(Target)__C_OPT = $(post_opt) $(Copt) $(_CPP_OPT) ; - $(Target)__ASM_OPT = -I$(AddIncludes) $(ASMopt) ; - $(Target)__PRE_OPT = $(pre_opt) ; - include $(Root)/prog/_jBuild/_vc/add_fd_opt.jam ; -} - - -rule DepRule -{ - local changed_dep = ; - - # add $(Root) prefix when needed - for dep in $(>) - { - switch $(dep) - { - case ?:* : changed_dep += $(dep) ; # absolute path with drive - case \\* : changed_dep += $(dep) ; # absolute path with root foolder (\) - case /* : changed_dep += $(dep) ; # absolute path with root foolder (/) - case * : changed_dep += $(Root)/$(dep) ; # relative path, add $(Root) prefix - } - } - Includes $(<) : $(changed_dep) ; - null_action $(changed_dep) ; -} - - -rule CheckHeaders -{ - Depends $(<) : $(>) ; - NoCare $(>) ; # tolerant to .d absence - NOUPDATE $(>) ; # tolerant to .d timestamp - - # scan line for header, skipping any ../ at the beginning [will be prefixed with $(Root)] - HDRSCAN on $(>) = "^.*: [\.\\\/]*([^\ -]*).*$" ; - HDRRULE on $(>) = DepRule ; -} - - -actions together quietly compile_cpp -{ -#async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 - call_filtered $(_CPP_COMPILER) $(pre_opt) $(_CPP_BASE_INCLUDES) $(cpp_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# - if errorlevel 1 goto failed - if not exist $(1) goto failed - goto end - :failed - set ERRORLEVEL=13 - :end - - clr_filters - $(CODE_CHECK) -x $(1) $(2) -} - -actions together quietly compile_prefast_cpp -{ - set PATH=#\($(_VC_DIR)/bin)\# - call $(_PREFAST_COMPILER) $(pre_opt) $(_CPP_BASE_INCLUDES) $(cpp_opt) #\(-Fo$(1) $(2:G=))\# - if errorlevel 1 goto failed - if not exist $(1) goto failed - goto end - :failed - set ERRORLEVEL=13 - :end -} - -actions together quietly compile_c -{ -#async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 - call_filtered $(_CPP_COMPILER) $(pre_opt) $(_C_BASE_INCLUDES) $(c_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# - if errorlevel 1 goto failed - if not exist $(1) goto failed - goto end - :failed - set ERRORLEVEL=13 - :end - - clr_filters - $(CODE_CHECK) -x $(1) $(2) -} - -include $(Root)/prog/_jBuild/_vc/win_rc.jam ; diff --git a/prog/_jBuild/win64/vc9-link.jam b/prog/_jBuild/win64/vc9-link.jam deleted file mode 100644 index e7b7c93f7..000000000 --- a/prog/_jBuild/win64/vc9-link.jam +++ /dev/null @@ -1,140 +0,0 @@ -# to be included in jBuild.jam - -rule ProcessLinkTarget -{ - BaseAddress ?= 0x00400000 ; - - local _WIN_LIBS = user32.lib ole32.lib kernel32.lib gdi32.lib winmm.lib dbghelp.lib ; - - if $(TargetType) = exe - { - _LINK_OPT = -nologo -filealign:512 -base:$(BaseAddress) -incremental:no ; - - AddDirectXLibs _LINK_OPT ; - AddWtlLibs _LINK_OPT : vc8 ; - - if $(ConsoleExe) != yes { - _LINK_OPT += -subsystem:windows ; - } - - if $(_VC_CRT_TYPE) = -MT { - _LINK_OPT += -nodefaultlib:MSVCRT -nodefaultlib:MSVCPRT -nodefaultlib:LIBMMT -nodefaultlib:LIBIRC -nodefaultlib:LIBC ; - if $(Config) != dbg { - _WIN_LIBS += libcmt.lib libcpmt.lib ; - _LINK_OPT += -nodefaultlib:LIBCMTD -nodefaultlib:LIBCPMTD ; - } else { - _WIN_LIBS += libcmtd.lib libcpmtd.lib ; - _LINK_OPT += -nodefaultlib:LIBCMT -nodefaultlib:LIBCPMT ; - } - } else { - _LINK_OPT += -nodefaultlib:LIBMMT -nodefaultlib:LIBIRC -nodefaultlib:LIBC ; - if $(Config) != dbg { - _WIN_LIBS += MSVCRT.lib MSVCPRT.lib ; - _LINK_OPT += -nodefaultlib:LIBCMT -nodefaultlib:LIBCPMT ; - } else { - _WIN_LIBS += MSVCRTd.lib MSVCPRTd.lib ; - _LINK_OPT += -nodefaultlib:LIBCMT -nodefaultlib:LIBCPMT ; - } - } - - if $(Config) != dbg { - _LINK_OPT += -opt:ref ; - } - - if $(UseWholeOpt) = yes { - _LINK_OPT += /LTCG ; - } - - $(Target)__LINK = $(_LINK) $(LINKopt) ; - $(Target)__LINK_OPT = $(_LINK_OPT) ; - - LinkExeSetMap $(Target) : ; - LinkExeSetBuildStamp $(Target) ; - LinkAddManifest $(Target) : $(OutDir) ; - } - else if $(TargetType) = lib - { - $(Target)__LINK = $(_LIB) ; - $(Target)__LINK_OPT = -nologo $(LINKopt) ; - - if $(UseWholeOpt) = yes { - $(Target)__LINK_OPT += /LTCG ; - } - } - else if $(TargetType) = dll - { - _LINK_OPT = -nologo -dll -subsystem:windows -base:$(BaseAddress) -incremental:no ; - AddDirectXLibs _LINK_OPT ; - if $(Config) != dbg { - _LINK_OPT += -opt:ref ; - } - - if $(UseWholeOpt) = yes { - _LINK_OPT += /LTCG ; - } - - $(Target)__LINK = $(_LINK) ; - $(Target)__LINK_OPT = $(_LINK_OPT) $(LINKopt) ; - - LinkDllSetMapExpLib $(Target) : $(OutDir) : ; - } - - local _ADD_LIBS = " " $(1) ; - - if $(QtVer) { AddQtLinkOpt ; } - - if $(TargetType) = exe { - _ADD_LIBS += $(_WIN_LIBS) ; - } - - $(Target)__LINK_LIBS = $(_ADD_LIBS) ; -} - - -actions together quietly link_target -{ -#async - $(prelink_cmd) - echo linking $(1:B)$(1:S) - del $(1) - $(DEL_)$(pdb_path) - set_filter nul /warning LNK4099/ - call_filtered $(link) $(link_opt) #\( $(link_libs) $(resources) $(DEBUG_PDB_)$(pdb_path) -out:$(1) $(obj_list) )\# - if errorlevel 1 goto after_postlink - $(postlink_cmd) - :after_postlink - echo ---------------------------------------------------------------------- - if errorlevel 1 goto failed - if not exist $(1) goto failed - echo SUCCESSFULLY built $(1:B)$(1:S) $(_PrintedOutput) - goto end - - :failed - echo FAILED to build $(1:B)$(1:S) [Error #%errorlevel%] $(_PrintedOutput) - set ERRORLEVEL=13 - - :end - echo . -} - - -actions together quietly lib_target -{ -#async - echo creating lib $(1:B)$(1:S) - del $(1) - set_filter nul /warning LNK4221/ - call_filtered $(link) $(link_opt) #\( -out:$(1) $(obj_list) $(link_libs) )\# - echo ---------------------------------------------------------------------- - if errorlevel 1 goto failed - if not exist $(1) goto failed - echo SUCCESSFULLY built $(1:B)$(1:S) $(_PrintedOutput) - goto end - - :failed - echo FAILED to build $(1:B)$(1:S) [Error #%errorlevel%] $(_PrintedOutput) - set ERRORLEVEL=13 - - :end - echo . -} diff --git a/prog/_jBuild/win64/vc9-sets.jam b/prog/_jBuild/win64/vc9-sets.jam deleted file mode 100644 index 67623f5bb..000000000 --- a/prog/_jBuild/win64/vc9-sets.jam +++ /dev/null @@ -1,83 +0,0 @@ -# Setup for Intel C++ compiler for Win32 (to be included from jBuild.jam) - -_OBJ_SUFFIX = .obj ; - -_VC_DIR = $(_DEVTOOL)/vc2008 ; -_VC_CRT_TYPE = -MT ; -C_preopt_DirectXVer = jun2010 ; -_WIN_SDK_TARGET_SUFFIX = x64 ; -include $(Root)/prog/_jBuild/_vc/win_sdk.jam ; - -if ! [ GLOB $(_VC_DIR) : * ] { exit FATAL\: \"$(_VC_DIR)\" not found! Please, update DEVTOOLS ; } -if ! [ GLOB $(_WIN_SDK) : * ] { exit FATAL\: \"$(_WIN_SDK)\" not found! Please, update DEVTOOLS ; } - -local _DEF_C_CMDLINE = - -X /D_TARGET_PC=1 -D_TARGET_PC_WIN=1 /DWIN64 /Dasm=__asm /DWIN32_LEAN_AND_MEAN= - /DNOMINMAX - -D_TARGET_SIMD_SSE=$(SSEVersion) -D_TARGET_64BIT=1 - -Di_strlen=(int)strlen - /c /nologo /Zc:forScope /Zp8 /J /bigobj -; - -if $(QtVer) { - _QT_DIR = $(_DEVTOOL)/Qt-$(QtVer)-vc2008 ; - if ! [ GLOB $(_QT_DIR) : * ] { exit FATAL\: \"$(_QT_DIR)\" not found! Please, update DEVTOOLS ; } - - _DEF_C_CMDLINE += - -DQT_LARGEFILE_SUPPORT -DQT_THREAD_SUPPORT -DQT_GUI_LIB -DQT_CORE_LIB - -D_STD_RTL_MEMORY=1 - /Zc:wchar_t- - ; - if $(QtVerStatic) = yes { _DEF_C_CMDLINE += -DQT_NODLL ; } else { _VC_CRT_TYPE = -MD ; } - - _QT_MOC = $(_QT_DIR)/bin/amd64/moc.exe ; - _QT_UIC = $(_QT_DIR)/bin/amd64/uic.exe ; - _QT_RCC = $(_QT_DIR)/bin/amd64/rcc.exe ; -} else { - _DEF_C_CMDLINE += /Zc:wchar_t ; -} - -_LINK = $(_VC_DIR)/bin/amd64/link.exe /machine:x64 ; -_LIB = $(_VC_DIR)/bin/amd64/lib.exe /machine:x64 ; -_CPP_COMPILER = $(_VC_DIR)/bin/amd64/cl.exe $(_DEF_C_CMDLINE) ; -_C_COMPILER = $(_VC_DIR)/bin/amd64/cl.exe $(_DEF_C_CMDLINE) ; -_ASM_COMPILER = $(_DEVTOOL)/nasm/nasmw.exe -f win64 --prefix _ ; -_MASM_COMPILER = $(_VC_DIR)/bin/amd64/ml64.exe -c -nologo ; - -_DEP_COMPILER = $(Root)/prog/_jBuild/fastdep-g.exe --cVC80 /D_TARGET_PC=1 -D_TARGET_PC_WIN=1 /DWIN64 ; - -_RC_COMPILER = $(_WIN_SDK_BIN)/rc.exe /x /i$(_WIN_SDK_INC) /i$(_VC_DIR)/Include ; -_MT_UTIL = $(_WIN_SDK_BIN)/mt.exe ; -_CVTRES_EXE = $(_VC_DIR)/bin/amd64/cvtres.exe /MACHINE:x64 /NOLOGO ; - -_INCLUDE = $(_WIN_SDK_INC) $(_VC_DIR)/include ; -_LIBPATH = $(_WIN_SDK_LIB) $(_VC_DIR)/lib/amd64 ; - -_INCLUDE += - $(_QT_DIR)/include/QtCore - $(_QT_DIR)/include/QtGui - $(_QT_DIR)/include/ActiveQt - $(_QT_DIR)/include - $(_QT_DIR)/mkspecs/win64-msvc2008 -; - - -# make linker cmd-line ### -for lib in $(_LIBPATH) { - _LINK += -libpath:$(lib) ; - _LIB += -libpath:$(lib) ; -} - -# make compiler cmd-line ### -_CPP_BASE_INCLUDES = -I$(MasterPreInclude) -I$(Root)/prog/dagorInclude -I$(Root)/prog/1stPartyLibs -I$(Root)/prog/3rdPartyLibs -I$(Root)/prog/3rdPartyLibs/eastl/include ; -_C_BASE_INCLUDES = -I$(MasterPreInclude) -I$(Root)/prog/dagorInclude -I$(Root)/prog/1stPartyLibs -I$(Root)/prog/3rdPartyLibs ; - -for inc in $(_INCLUDE) { - _CPP_BASE_INCLUDES += -I$(inc) ; - _C_BASE_INCLUDES += -I$(inc) ; - _DEP_COMPILER += --x$(inc) ; -} - -_DEF_C_CMDLINE = ; - -if $(QtVer) { include $(Root)/prog/_jBuild/win64/qt-inc.jam ; } diff --git a/prog/_jBuild/win64/vc9u-cpp.jam b/prog/_jBuild/win64/vc9u-cpp.jam deleted file mode 100644 index 3b5e98b91..000000000 --- a/prog/_jBuild/win64/vc9u-cpp.jam +++ /dev/null @@ -1,207 +0,0 @@ -# to be included in jBuild.jam - -rule ProcessCompileTarget -{ - # basic opts: warning/remark suppressing, additional includes etc. - local _SUPPRESS_OPT = ; - local _CONFIG_OPT = ; - local pre_opt = ; - local post_opt = ; - - if $(StrictCompile) = yes - { - # suppressed warnigs list (marked with x are not suppressed now): - # C4265 'XXX' : class has virtual functions, but destructor is not virtual - # C4127 conditional expression is constant - # x C4100 'XXX' : unreferenced formal parameter - # x 981 operands are evaluated in unspecified order - # x 383 value copied to temporary, reference to temporary used - # x 310 old-style parameter list (anachronism) - # x 174 expression has no effect - # x 111 statement is unreachable - # x 271 trailing comma is nonstandard - # C4514 'XXX' : unreferenced inline function has been removed - # C4061 enumerator 'XXX' in switch of enum 'YYY' is not explicitly handled by a case label - # C4062 enumerator 'XXX' in switch of enum 'YYY' is not handled - # C4820 'XXX' : 'N' bytes padding added after data member 'XXX::YYY' - # C4668 'XXX' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' - # C4619 pragma warning : there is no warning number 'NNN' - # C4365 'XXX' : conversion from 'TYPE1' to 'TYPE2', signed/unsigned mismatch - # C4302 'type cast' : truncation from 'TYPE1' to 'TYPE2' - # C4244 '=' : conversion from 'TYPE1' to 'TYPE2', possible loss of data - # C4242 'argument' : conversion from 'TYPE1' to 'TYPE2', possible loss of data - # C4245 'argument' : conversion from 'TYPE1' to 'TYPE2', signed/unsigned mismatch - # C4101 'XXX' : unreferenced local variable - # C4201 nonstandard extension used : nameless struct/union - # C4625 'XXX' : copy constructor could not be generated because a base class copy constructor is inaccessible - # C4626 'XXX' : assignment operator could not be generated because a base class assignment operator is inaccessible - # C4800 'int' : forcing value to bool 'true' or 'false' (performance warning) - # C4018 '<' : signed/unsigned mismatch - # C4710 'XXX' : function not inlined - # C4291 'void *operator new(size_t,IMemAlloc *)' : no matching operator delete found; memory will not be freed if initialization throws an exception - # C4389 '!=' : signed/unsigned mismatch - # C4200 nonstandard extension used : zero-sized array in struct/union - # C4255 'XXX' : no function prototype given: converting '()' to '(void)' - # C4711 function 'XXX' selected for automatic inline expansion - # C4355 'this' : used in base member initializer list - # C4640 'XXX' : construction of local static object is not thread-safe - # x C4714 function 'XXX' marked as __forceinline not inlined - # C4305 'initializing' : truncation from 'double' to 'real' - # C4511 'XXX' : copy constructor could not be generated - # C4512 'XXX' : assignment operator could not be generated - # C4305 'XXX' : truncation from 'double' to 'float' - # C4738 storing 32-bit float result in memory, possible loss of performance - # C4996 'stricmp' was declared deprecated - # C4740 macro redefinition - # C4702 unreachable code - _SUPPRESS_OPT = -Wall -WX /wd4514 /wd4061 /wd4820 /wd4668 /wd4619 - /wd4365 /wd4127 /wd4302 /wd4242 /wd4244 /wd4265 - /wd4101 /wd4201 /wd4625 /wd4626 /wd4800 /wd4018 - /wd4710 /wd4245 /wd4291 /wd4389 /wd4200 /wd4255 - /wd4711 /wd4062 /wd4355 /wd4640 /wd4305 - /wd4511 /wd4512 /wd4305 /wd4738 /wd4996 /wd4005 - /wd4740 /wd4702 - #/wd444 /wd279 /wd981 /wd383 /wd310 /wd174 /wd111 /wd271 /wd4714 ; - ; - } - else - { - _SUPPRESS_OPT = -W3 /wd4244 /wd4101 /wd4800 /wd4018 /wd4291 /wd4200 /wd4355 /wd4305 - /wd4996 /wd4005 /wd4740 /wd4265 ; - } - - local _DEF_CPP_OPT = /c /nologo /Zc:wchar_t /Zp8 /J /DWIN32 ; - - if $(Exceptions) != yes { - _DEF_CPP_OPT += -D_HAS_EXCEPTIONS=0 -DEA_COMPILER_NO_NOEXCEPT ; - } else { - if ($CatchSEH) != yes { - _DEF_CPP_OPT += /EHsc -DDAGOR_EXCEPTIONS_ENABLED=1 ; - } else { - _DEF_CPP_OPT += /EHac -DDAGOR_EXCEPTIONS_ENABLED=1 ; - } - } - - if $(Rtti) != yes { - _DEF_CPP_OPT += /GR- ; - } - - if $(_GlobCopt_ForScope) { - _DEF_CPP_OPT += $(_GlobCopt_ForScope) ; - } else { - _DEF_CPP_OPT += /Zc:forScope ; - } - - local _DEF_ASM_OPT = ; - - switch $(Config) { - case dev : - _CONFIG_OPT = /GF /Gy /Zi /Oy- -DDAGOR_DBGLEVEL=1 ; - case *rel : - _CONFIG_OPT = /GF /Gy /Zi /Oy- -DDAGOR_DBGLEVEL=0 ; - case dbg : - _CONFIG_OPT = /Zi /RTC1 -DDAGOR_DBGLEVEL=2 ; - case * : - _CONFIG_OPT = ; - } - - if $(_GlobCopt_Optimize) { - _CONFIG_OPT += $(_GlobCopt_Optimize) ; - } else { - if $(Config) != dbg { - _CONFIG_OPT += /Ox /Oi /Ot ; - } else { - _CONFIG_OPT += /Od ; - } - } - - if $(_GlobCopt_CRT) { - _CONFIG_OPT += $(_GlobCopt_CRT) ; - } else { - if $(Config) != dbg { - _CONFIG_OPT += -MT ; - } else { - _CONFIG_OPT += -MTd ; - } - } - - for inc in $(AddIncludes) - { - _DEF_CPP_OPT += -I$(inc) ; - _DEF_ASM_OPT += -I$(inc) ; - } - - _CPP_OPT = $(_DEF_CPP_OPT) $(_CONFIG_OPT) $(_SUPPRESS_OPT) $(CPPopt) $(GlobalCPPopt) ; - - AddDirectXInclude pre_opt : post_opt ; - - - $(Target)__CPP_OPT = $(post_opt) $(_CPP_OPT) -TP ; - $(Target)__C_OPT = $(post_opt) $(Copt) $(_CPP_OPT) ; - $(Target)__ASM_OPT = $(_DEF_ASM_OPT) $(ASMopt) ; - $(Target)__PRE_OPT = -I$(PreAddIncludes) $(pre_opt) ; -} - - -rule DepRule -{ - local changed_dep = ; - - # add $(Root) prefix when needed - for dep in $(>) - { - switch $(dep) - { - case ?:* : changed_dep += $(dep) ; # absolute path with drive - case \\* : changed_dep += $(dep) ; # absolute path with root foolder (\) - case /* : changed_dep += $(dep) ; # absolute path with root foolder (/) - case * : changed_dep += $(Root)/$(dep) ; # relative path, add $(Root) prefix - } - } - Includes $(<) : $(changed_dep) ; - null_action $(changed_dep) ; -} - - -rule CheckHeaders -{ - Depends $(<) : $(>) ; - NoCare $(>) ; # tolerant to .d absence - NOUPDATE $(>) ; # tolerant to .d timestamp - - # scan line for header, skipping any ../ at the beginning [will be prefixed with $(Root)] - HDRSCAN on $(>) = "^.*: [\.\\\/]*([^\ -]*).*$" ; - HDRRULE on $(>) = DepRule ; -} - - -actions together quietly compile_cpp -{ -#async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 - call_filtered $(_CPP_COMPILER) $(pre_opt) $(_CPP_BASE_INCLUDES) /fp:fast $(cpp_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# - if errorlevel 1 goto failed - if not exist $(1) goto failed - goto end - :failed - set ERRORLEVEL=13 - :end -} - -actions together quietly compile_c -{ -#async - set_filter nul /Note\: including file\:[ ]*$(_DEVTOOL_RE)(.+)/ - set_filter $(1:S=.d) /Note\: including file\:[ ]*(.+)/d1 $(1:G=:D=): $1 - call_filtered $(_CPP_COMPILER) $(pre_opt) $(_C_BASE_INCLUDES) /fp:fast $(c_opt) -showIncludes #\(-Fo$(1) $(2:G=))\# - if errorlevel 1 goto failed - if not exist $(1) goto failed - goto end - :failed - set ERRORLEVEL=13 - :end -} - -include $(Root)/prog/_jBuild/_vc/win_rc.jam ; diff --git a/prog/_jBuild/win64/vc9u-link.jam b/prog/_jBuild/win64/vc9u-link.jam deleted file mode 100644 index 1fcc2a909..000000000 --- a/prog/_jBuild/win64/vc9u-link.jam +++ /dev/null @@ -1,113 +0,0 @@ -# to be included in jBuild.jam - -rule ProcessLinkTarget -{ - BaseAddress ?= 0x00400000 ; - - local _WIN_LIBS = user32.lib ole32.lib kernel32.lib gdi32.lib winmm.lib dbghelp.lib ; - - if $(TargetType) = exe - { - _LINK_OPT = -nologo -filealign:512 -base:$(BaseAddress) -incremental:no ; - AddDirectXLibs _LINK_OPT ; - - if $(ConsoleExe) != yes { - _LINK_OPT += -subsystem:windows ; - } - - _LINK_OPT += -nodefaultlib:MSVCRT -nodefaultlib:MSVCPRT ; - if $(Config) != dbg { - _WIN_LIBS += libcmt.lib libcpmt.lib ; - _LINK_OPT += -nodefaultlib:LIBCMTD -nodefaultlib:LIBCPMTD ; - } else { - _WIN_LIBS += libcmtd.lib libcpmtd.lib ; - _LINK_OPT += -nodefaultlib:LIBCMT -nodefaultlib:LIBCPMT ; - } - - if $(Config) != dbg { - _LINK_OPT += -opt:ref ; - } - - $(Target)__LINK = $(_LINK) ; - $(Target)__LINK_OPT = $(_LINK_OPT) $(LINKopt) ; - - LinkExeSetMap $(Target) : ; - LinkExeSetBuildStamp $(Target) ; - LinkAddManifest $(Target) : $(OutDir) ; - } - else if $(TargetType) = lib - { - $(Target)__LINK = $(_LIB) ; - $(Target)__LINK_OPT = -nologo $(LINKopt) ; - } - else if $(TargetType) = dll - { - _LINK_OPT = -nologo -dll -subsystem:windows -base:$(BaseAddress) -incremental:no ; - AddDirectXLibs _LINK_OPT ; - if $(Config) != dbg { - _LINK_OPT += -opt:ref ; - } - - $(Target)__LINK = $(_LINK) ; - $(Target)__LINK_OPT = $(_LINK_OPT) $(LINKopt) ; - - LinkDllSetMapExpLib $(Target) : $(OutDir) : ; - } - - local _ADD_LIBS = " " $(1) ; - - if $(TargetType) = exe { - _ADD_LIBS += $(_WIN_LIBS) ; - } - - $(Target)__LINK_LIBS = $(_ADD_LIBS) ; -} - - -actions together quietly link_target -{ -#async - $(prelink_cmd) - echo linking $(1:B)$(1:S) - del $(1) - $(DEL_)$(pdb_path) - set_filter nul /warning LNK4099/ - call_filtered $(link) $(link_opt) #\( $(link_libs) $(resources) $(DEBUG_PDB_)$(pdb_path) -out:$(1) $(obj_list) )\# - if errorlevel 1 goto after_postlink - $(postlink_cmd) - :after_postlink - echo ---------------------------------------------------------------------- - if errorlevel 1 goto failed - if not exist $(1) goto failed - echo SUCCESSFULLY built $(1:B)$(1:S) $(_PrintedOutput) - goto end - - :failed - echo FAILED to build $(1:B)$(1:S) [Error #%errorlevel%] $(_PrintedOutput) - set ERRORLEVEL=13 - - :end - echo . -} - - -actions together quietly lib_target -{ -#async - echo creating lib $(1:B)$(1:S) - del $(1) - set_filter nul /warning LNK4221/ - call_filtered $(link) $(link_opt) #\( -out:$(1) $(obj_list) $(link_libs) )\# - echo ---------------------------------------------------------------------- - if errorlevel 1 goto failed - if not exist $(1) goto failed - echo SUCCESSFULLY built $(1:B)$(1:S) $(_PrintedOutput) - goto end - - :failed - echo FAILED to build $(1:B)$(1:S) [Error #%errorlevel%] $(_PrintedOutput) - set ERRORLEVEL=13 - - :end - echo . -} diff --git a/prog/_jBuild/win64/vc9u-sets.jam b/prog/_jBuild/win64/vc9u-sets.jam deleted file mode 100644 index 750bd7547..000000000 --- a/prog/_jBuild/win64/vc9u-sets.jam +++ /dev/null @@ -1,42 +0,0 @@ -# Setup for MS Visual C++ 8 compiler for Win32 (to be included from jBuild.jam) - -_OBJ_SUFFIX = .obj ; - -_VC_DIR = $(_DEVTOOL)/vc2008 ; -C_preopt_DirectXVer = jun2010 ; -_WIN_SDK_TARGET_SUFFIX = x64 ; -include $(Root)/prog/_jBuild/_vc/win_sdk.jam ; - -if ! [ GLOB $(_VC_DIR) : * ] { exit FATAL\: \"$(_VC_DIR)\" not found! Please, update DEVTOOLS ; } -if ! [ GLOB $(_WIN_SDK) : * ] { exit FATAL\: \"$(_WIN_SDK)\" not found! Please, update DEVTOOLS ; } - -_LINK = $(_VC_DIR)/bin/amd64/link.exe /machine:x64 ; -_LIB = $(_VC_DIR)/bin/amd64/lib.exe /machine:x64 ; -_CPP_COMPILER = $(_VC_DIR)/bin/amd64/cl.exe ; -_C_COMPILER = $(_VC_DIR)/bin/amd64/cl.exe ; -_ASM_COMPILER = $(_DEVTOOL)/nasm/nasmw.exe -f win32 --prefix _ ; -_MASM_COMPILER = $(_VC_DIR)/bin/amd64/ml.exe -c -nologo ; - -_DEP_COMPILER = $(Root)/prog/_jBuild/fastdep-g.exe --cVC80 ; - -_RC_COMPILER = $(_WIN_SDK_BIN)/rc.exe /x /i$(_WIN_SDK_INC) /i$(_VC_DIR)/Include ; -_MT_UTIL = $(_WIN_SDK_BIN)/mt.exe ; -_CVTRES_EXE = $(_VC_DIR)/bin/amd64/cvtres.exe /MACHINE:x64 /NOLOGO ; - -_INCLUDE = $(_WIN_SDK_INC) $(_VC_DIR)/include ; -_LIBPATH = $(_VC_DIR)/lib/amd64 $(_WIN_SDK_LIB) ; - -# make linker cmd-line ### -for lib in $(_LIBPATH) { - _LINK += -libpath:$(lib) ; -} - -# make compiler cmd-line ### -_CPP_BASE_INCLUDES = -X -I$(MasterPreInclude) ; -_C_BASE_INCLUDES = -X -I$(MasterPreInclude) ; - -for inc in $(_INCLUDE) { - _CPP_BASE_INCLUDES += -I$(inc) ; - _C_BASE_INCLUDES += -I$(inc) ; - _DEP_COMPILER += --x$(inc) ; -} diff --git a/prog/commonFx/commonFxGame/dafxCompound.cpp b/prog/commonFx/commonFxGame/dafxCompound.cpp index 6bd4b40f8..1afa0bca7 100644 --- a/prog/commonFx/commonFxGame/dafxCompound.cpp +++ b/prog/commonFx/commonFxGame/dafxCompound.cpp @@ -24,6 +24,16 @@ enum HUID_ACES_IS_ACTIVE = 0xD6872FCEu }; +enum +{ + RGROUP_DEFAULT = 0, + RGROUP_LOWRES = 1, + RGROUP_HIGHRES = 2, + RGROUP_DISTORTION = 3, + RGROUP_WATER_PROJ = 4, + RGROUP_UNDERWATER = 5, +}; + #define MODFX_RFLAG_USE_ETM_AS_WTM 0 #define MODFX_RFLAG_OMNI_LIGHT_ENABLED 7 @@ -296,15 +306,28 @@ struct DafxCompound : BaseParticleEffect } } - if (par.render_group != 0) + if (par.render_group != RGROUP_DEFAULT) { for (auto &i : ddesc->renderDescs) { - if (strcmp(i.tag.c_str(), dafx_ex::renderTags[dafx_ex::RTAG_LOWRES]) == 0 || - strcmp(i.tag.c_str(), dafx_ex::renderTags[dafx_ex::RTAG_HIGHRES]) == 0) + if (strcmp(i.tag.c_str(), dafx_ex::renderTags[dafx_ex::RTAG_LOWRES]) != 0 && + strcmp(i.tag.c_str(), dafx_ex::renderTags[dafx_ex::RTAG_HIGHRES]) != 0 && + // strcmp(i.tag.c_str(), dafx_ex::renderTags[dafx_ex::RTAG_DISTORTION]) != 0 && + strcmp(i.tag.c_str(), dafx_ex::renderTags[dafx_ex::RTAG_WATER_PROJ]) != 0 && + strcmp(i.tag.c_str(), dafx_ex::renderTags[dafx_ex::RTAG_UNDERWATER]) != 0) + continue; + + int t = dafx_ex::RTAG_LOWRES; + switch (par.render_group) { - i.tag = dafx_ex::renderTags[par.render_group == 1 ? dafx_ex::RTAG_LOWRES : dafx_ex::RTAG_HIGHRES]; + case RGROUP_LOWRES: t = dafx_ex::RTAG_LOWRES; break; + case RGROUP_HIGHRES: t = dafx_ex::RTAG_HIGHRES; break; + case RGROUP_DISTORTION: t = dafx_ex::RTAG_DISTORTION; break; + case RGROUP_WATER_PROJ: t = dafx_ex::RTAG_WATER_PROJ; break; + case RGROUP_UNDERWATER: t = dafx_ex::RTAG_UNDERWATER; break; + default: G_ASSERT(false); } + i.tag = dafx_ex::renderTags[t]; } } diff --git a/prog/commonFx/commonFxGame/dafxCompound.gen.nut b/prog/commonFx/commonFxGame/dafxCompound.gen.nut index a904d119b..1cc3837e1 100644 --- a/prog/commonFx/commonFxGame/dafxCompound.gen.nut +++ b/prog/commonFx/commonFxGame/dafxCompound.gen.nut @@ -35,7 +35,7 @@ declare_struct("ModFxQuality", 1, { name="high_quality", type="bool", defVal=1 }, ]); -declare_struct("ModfxParams", 8, +declare_struct("ModfxParams", 9, [ { name="ref_slot", type="int", defVal=0 }, { name="offset", type="Point3", defVal=Point3(0,0,0) }, @@ -60,7 +60,7 @@ declare_struct("ModfxParams", 8, { name="global_life_time_min", type="real", defVal=0 }, { name="global_life_time_max", type="real", defVal=0 }, { name="transform_type", type="list", list=["default", "world_space", "local_space"] }, - { name="render_group", type="list", list=["default", "lowres", "highres"] }, + { name="render_group", type="list", list=["default", "lowres", "highres", "distortion", "water_proj", "underwater"] }, { name="quality", type="ModFxQuality" }, ]); diff --git a/prog/commonFx/commonFxGame/dafxCompound_decl.h b/prog/commonFx/commonFxGame/dafxCompound_decl.h index f9e86b9bd..73ff65076 100644 --- a/prog/commonFx/commonFxGame/dafxCompound_decl.h +++ b/prog/commonFx/commonFxGame/dafxCompound_decl.h @@ -127,7 +127,7 @@ class ModfxParams void load(const char *&ptr, int &len, BaseParamScriptLoadCB *load_cb) { G_UNREFERENCED(load_cb); - CHECK_FX_VERSION(ptr, len, 8); + CHECK_FX_VERSION(ptr, len, 9); ref_slot = readType(ptr, len); offset = readType(ptr, len); diff --git a/prog/commonFx/commonFxGame/dafxSparks.cpp b/prog/commonFx/commonFxGame/dafxSparks.cpp index 86bfebebc..aba8df2ea 100644 --- a/prog/commonFx/commonFxGame/dafxSparks.cpp +++ b/prog/commonFx/commonFxGame/dafxSparks.cpp @@ -30,6 +30,13 @@ enum HUID_ACES_IS_ACTIVE = 0xD6872FCEu }; // +enum +{ + RGROUP_HIGHRES = 0, + RGROUP_LOWRES = 1, + RGROUP_UNDERWATER = 2, +}; + static dafx::ContextId g_dafx_ctx; struct DafxSparks : BaseParticleEffect @@ -53,7 +60,7 @@ struct DafxSparks : BaseParticleEffect void loadParamsData(const char *ptr, int len, BaseParamScriptLoadCB *load_cb) override { - CHECK_FX_VERSION(ptr, len, 3); + CHECK_FX_VERSION(ptr, len, 4); if (!g_dafx_ctx) { @@ -71,12 +78,14 @@ struct DafxSparks : BaseParticleEffect DafxSparksRenParams renParams = {}; DafxSparksGlobalParams parGlobals = {}; DafxSparksQuality parQuality = {}; + DafxRenderGroup parRenderGroup = {}; if (len) { simParams.load(ptr, len, load_cb); renParams.load(ptr, len, load_cb); parGlobals.load(ptr, len, load_cb); parQuality.load(ptr, len, load_cb); + parRenderGroup.load(ptr, len, load_cb); } sinfo.maxInstances = parGlobals.max_instances; @@ -124,7 +133,15 @@ struct DafxSparks : BaseParticleEffect #undef GDATA - desc.renderDescs.push_back({"highres", "sparks_ps"}); // sparks is always high res (and there is no forced low res) + int rtag = 0; + if (parRenderGroup.type == RGROUP_LOWRES) + rtag = dafx_ex::RTAG_LOWRES; + else if (parRenderGroup.type == RGROUP_HIGHRES) + rtag = dafx_ex::RTAG_HIGHRES; + else if (parRenderGroup.type == RGROUP_UNDERWATER) + rtag = dafx_ex::RTAG_UNDERWATER; + + desc.renderDescs.push_back({dafx_ex::renderTags[rtag], "sparks_ps"}); desc.renderDescs.push_back({dafx_ex::renderTags[dafx_ex::RTAG_THERMAL], "sparks_thermal"}); parentDesc.qualityFlags = fx_apply_quality_bits(parQuality, 0xffffffff); diff --git a/prog/commonFx/commonFxGame/dafxSparks.gen.nut b/prog/commonFx/commonFxGame/dafxSparks.gen.nut index 65506b7d1..793fd9637 100644 --- a/prog/commonFx/commonFxGame/dafxSparks.gen.nut +++ b/prog/commonFx/commonFxGame/dafxSparks.gen.nut @@ -93,10 +93,16 @@ declare_struct("DafxSparksQuality", 1, { name="high_quality", type="bool", defVal=1 }, ]); -end_declare_params("dafx_sparks", 3, [ +declare_struct("DafxRenderGroup", 1, +[ + { name="type", type="list", list=["highres", "lowres", "underwater"]}, +]); + +end_declare_params("dafx_sparks", 4, [ {struct="DafxEmitterParams"}, {struct="DafxSparksSimParams"}, {struct="DafxSparksRenParams"}, {struct="DafxSparksGlobalParams"}, - {struct="DafxSparksQuality"} + {struct="DafxSparksQuality"}, + {struct="DafxRenderGroup"} ]); diff --git a/prog/commonFx/commonFxGame/dafxSparks_decl.h b/prog/commonFx/commonFxGame/dafxSparks_decl.h index 896b44f66..3be52f587 100644 --- a/prog/commonFx/commonFxGame/dafxSparks_decl.h +++ b/prog/commonFx/commonFxGame/dafxSparks_decl.h @@ -252,3 +252,20 @@ class DafxSparksQuality high_quality = readType(ptr, len); } }; + +class DafxRenderGroup +{ +public: + int type; + + + static ScriptHelpers::TunedElement *createTunedElement(const char *name); + + void load(const char *&ptr, int &len, BaseParamScriptLoadCB *load_cb) + { + G_UNREFERENCED(load_cb); + CHECK_FX_VERSION(ptr, len, 1); + + type = readType(ptr, len); + } +}; diff --git a/prog/commonFx/commonFxGame/dafx_sparks.sh b/prog/commonFx/commonFxGame/dafx_sparks.sh index 2a05bdb48..94d613977 100644 --- a/prog/commonFx/commonFxGame/dafx_sparks.sh +++ b/prog/commonFx/commonFxGame/dafx_sparks.sh @@ -48,8 +48,8 @@ shader sparks_ps, sparks_thermal INIT_SIMPLE_AMBIENT(vs) DAFXEX_USE_FOG() - blend_src = one; blend_dst = sa; - blend_asrc = zero; blend_adst = one; + blend_src = one; blend_dst = isa; + blend_asrc = zero; blend_adst = isa; z_write = false; z_test = true; @@ -105,12 +105,11 @@ shader sparks_ps, sparks_thermal if (IS_ABLEND) { res.rgb *= input.lighting * res.a; - res.a = 1.0 - res.a; } else { res.rgb *= res.a; - res.a = 1; + res.a = 0; } ##endif ##if shader == sparks_thermal diff --git a/prog/commonFx/commonFxGame/modfx/modfx_bboard_render.hlsl b/prog/commonFx/commonFxGame/modfx/modfx_bboard_render.hlsl index be2e8348b..8e43acd73 100644 --- a/prog/commonFx/commonFxGame/modfx/modfx_bboard_render.hlsl +++ b/prog/commonFx/commonFxGame/modfx/modfx_bboard_render.hlsl @@ -881,6 +881,10 @@ input.pos.w = rcp(input.pos.w); #endif +#if !MODFX_SHADER_RIBBON && defined(FSR_DISTORTION) + input.tc.xy = getTexcoord(GET_SCREEN_POS(input.pos).xy); +#endif + GlobalData gdata = global_data_load(); DafxRenderData ren_info; dafx_get_render_info( 0, ren_info ); @@ -1265,7 +1269,10 @@ float3 lighting = ndl * gdata.sun_color * shadow + nda * ambient + input.lighting.rgb; - lighting_part *= lighting; +#if MODFX_WATER_PROJ_IGNORES_LIGHTING + if (!dafx_is_water_proj) +#endif + lighting_part *= lighting; #endif lighting_part += specular * gdata.sun_color * alpha; } diff --git a/prog/commonFx/commonFxGame/modfx_bboard_render.sh b/prog/commonFx/commonFxGame/modfx_bboard_render.sh index 17253a98c..86856acf4 100644 --- a/prog/commonFx/commonFxGame/modfx_bboard_render.sh +++ b/prog/commonFx/commonFxGame/modfx_bboard_render.sh @@ -4,6 +4,7 @@ include "dafx_helpers.sh" include "fom_shadows.sh" include "clustered/lights_cb.sh" include "dynamic_lights_count.sh" +include "flexible_scale_rasterization.sh" int modfx_debug_render = 0; interval modfx_debug_render : off < 1, on; @@ -55,7 +56,9 @@ shader dafx_modfx_bboard_render, dafx_modfx_bboard_render_atest, dafx_modfx_bboa hlsl { ##if hardware.metal - #define MODFX_USE_INVERTED_POS_W 1 + #if !SHADER_COMPILER_DXC + #define MODFX_USE_INVERTED_POS_W 1 + #endif ##endif #if !MOBILE_DEVICE #define MODFX_USE_LIGHTING 1 @@ -364,6 +367,7 @@ shader dafx_modfx_bboard_render, dafx_modfx_bboard_render_atest, dafx_modfx_bboa DAFXEX_USE_DEPTH_MASK(ps) DAFXEX_USE_HDR() DAFXEX_USE_FOG() + USE_FSR(ps) hlsl(vs) { diff --git a/prog/commonFx/commonFxGame/validateScripts.py b/prog/commonFx/commonFxGame/validateScripts.py new file mode 100644 index 000000000..d06005d07 --- /dev/null +++ b/prog/commonFx/commonFxGame/validateScripts.py @@ -0,0 +1,21 @@ +import sys, os, subprocess + +dagor_cdk_path = os.path.abspath(os.path.join(__file__, "../../../../tools/dagor3_cdk")) +if sys.platform == "win32" : + csq = os.path.join(dagor_cdk_path, "util", "csq-dev.exe") +elif sys.platform == "linux" : + csq = os.path.join(dagor_cdk_path, "util-linux64", "csq-dev") + +def check(cmd): + print(cmd) + return subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, errors='ignore', timeout=70) #encoding='utf-8', +# return (r.returncode==0, cmd, r.stdout) +# except subprocess.TimeoutExpired as e: +# return (False, cmd, f"{type(e).__name__}: {str(e)}") + +def main(): + files = [f for f in os.listdir() if f.endswith(".nut")] + for f in files: + check([csq, "--static-analysis", f]) +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/prog/commonFx/commonFxTools/dafxCompound_tools.cpp b/prog/commonFx/commonFxTools/dafxCompound_tools.cpp index 6c6f7211e..9a0400b1d 100644 --- a/prog/commonFx/commonFxTools/dafxCompound_tools.cpp +++ b/prog/commonFx/commonFxTools/dafxCompound_tools.cpp @@ -93,7 +93,7 @@ ScriptHelpers::TunedElement *ModfxParams::createTunedElement(const char *name) } { Tab enumEntries(tmpmem); - enumEntries.resize(3); + enumEntries.resize(6); enumEntries[0].name = "default"; enumEntries[0].value = 0; @@ -101,12 +101,18 @@ ScriptHelpers::TunedElement *ModfxParams::createTunedElement(const char *name) enumEntries[1].value = 1; enumEntries[2].name = "highres"; enumEntries[2].value = 2; + enumEntries[3].name = "distortion"; + enumEntries[3].value = 3; + enumEntries[4].name = "water_proj"; + enumEntries[4].value = 4; + enumEntries[5].name = "underwater"; + enumEntries[5].value = 5; elems.push_back(ScriptHelpers::create_tuned_enum_param("render_group", enumEntries)); } elems.push_back(ModFxQuality::createTunedElement("quality")); - return ScriptHelpers::create_tuned_struct(name, 8, elems); + return ScriptHelpers::create_tuned_struct(name, 9, elems); } diff --git a/prog/commonFx/commonFxTools/dafxSparks_tools.cpp b/prog/commonFx/commonFxTools/dafxSparks_tools.cpp index 00f2f7621..a2f6b5179 100644 --- a/prog/commonFx/commonFxTools/dafxSparks_tools.cpp +++ b/prog/commonFx/commonFxTools/dafxSparks_tools.cpp @@ -159,6 +159,29 @@ ScriptHelpers::TunedElement *DafxSparksQuality::createTunedElement(const char *n } +ScriptHelpers::TunedElement *DafxRenderGroup::createTunedElement(const char *name) +{ + Tab elems(tmpmem); + elems.reserve(1); + + { + Tab enumEntries(tmpmem); + enumEntries.resize(3); + + enumEntries[0].name = "highres"; + enumEntries[0].value = 0; + enumEntries[1].name = "lowres"; + enumEntries[1].value = 1; + enumEntries[2].name = "underwater"; + enumEntries[2].value = 2; + + elems.push_back(ScriptHelpers::create_tuned_enum_param("type", enumEntries)); + } + + return ScriptHelpers::create_tuned_struct(name, 1, elems); +} + + class DafxSparksEffectTools : public IEffectClassTools { public: @@ -167,15 +190,16 @@ class DafxSparksEffectTools : public IEffectClassTools virtual ScriptHelpers::TunedElement *createTunedElement() { Tab elems(tmpmem); - elems.reserve(5); + elems.reserve(6); elems.push_back(DafxEmitterParams::createTunedElement("DafxEmitterParams_data")); elems.push_back(DafxSparksSimParams::createTunedElement("DafxSparksSimParams_data")); elems.push_back(DafxSparksRenParams::createTunedElement("DafxSparksRenParams_data")); elems.push_back(DafxSparksGlobalParams::createTunedElement("DafxSparksGlobalParams_data")); elems.push_back(DafxSparksQuality::createTunedElement("DafxSparksQuality_data")); + elems.push_back(DafxRenderGroup::createTunedElement("DafxRenderGroup_data")); - return ScriptHelpers::create_tuned_group("params", 3, elems); + return ScriptHelpers::create_tuned_group("params", 4, elems); } }; diff --git a/prog/dagorInclude/3d/dag_drv3dCmd.h b/prog/dagorInclude/3d/dag_drv3dCmd.h index dc692dc59..e47da8438 100644 --- a/prog/dagorInclude/3d/dag_drv3dCmd.h +++ b/prog/dagorInclude/3d/dag_drv3dCmd.h @@ -5,6 +5,8 @@ // #pragma once +class DataBlock; + struct FrameEvents { virtual ~FrameEvents() = default; @@ -367,6 +369,9 @@ enum // The PS5 swapchain needs to be recreated when switcing between VR and flatscreen. DRV3D_COMMAND_RESET_PS5_SWAPCHAIN_VR_MODE, + // Sets to the PS5 driver which eye is rendered in VR and get back the distortion resolve LUT's ID + DRV3D_COMMAND_SET_PS5_FSR_VIEW, + // It tells Swappy on android, what is the target frame rate. // par1: int* frame rate DRV3D_COMMAND_SWAPPY_SET_TARGET_FRAME_RATE, @@ -385,6 +390,9 @@ enum // Removes a string previously added with DRV3D_COMMAND_ADD_DEBUG_BREAK_STRING_SEARCH DRV3D_COMMAND_REMOVE_DEBUG_BREAK_STRING_SEARCH, + // par1: CompilePipelineSet* + DRV3D_COMMAND_COMPILE_PIPELINE_SET, + DRV3D_COMMAND_USER = 1000, }; @@ -411,6 +419,31 @@ struct Drv3dTimings long long frontendWaitForSwapchainDuration; }; +// All values are optional, but graphics and mesh pipelines can not be created without output and render state sets. +struct CompilePipelineSet +{ + // When not specified, the driver assumes its driver specific format (if supported) and otherwise engine. + const char *defaultFormat; + // A block with a set of feature sets referenced by pipelines in the pipeline sets to indicate required features. + const DataBlock *featureSet; + // A block with a set of blocks describing input layouts. + const DataBlock *inputLayoutSet; + // A block with a set of blocks describing render states. + // The driver will ignore render states that are incompatible with the system. + const DataBlock *renderStateSet; + // A block with a set of blocks describing output format states. + // The driver will ignore output format states that are incompatible wit the system. + const DataBlock *outputFormatSet; + // A block with a set of blocks describing graphics pipelines. + // The driver will ignore pipelines using unsupported input layouts, render states or output formats. + const DataBlock *graphicsPipelineSet; + // A block with a set of blocks describing mesh pipelines. + // The driver will ignore pipelines using unsupported render states or output formats. + const DataBlock *meshPipelineSet; + // A block with a set of blocks describing compute pipelines. + const DataBlock *computePipelineSet; +}; + enum ResourceBarrier : int; struct Drv3dMakeTextureParams diff --git a/prog/dagorInclude/3d/dag_drv3dConsts.h b/prog/dagorInclude/3d/dag_drv3dConsts.h index 930487880..61d31ba28 100644 --- a/prog/dagorInclude/3d/dag_drv3dConsts.h +++ b/prog/dagorInclude/3d/dag_drv3dConsts.h @@ -640,6 +640,12 @@ struct DeviceDriverCapabilitiesBase * \platformtable{hasCompareSampler,c,c,c,c,r,r,c,c,c,c,c} */ bool hasCompareSampler : 1; + /** + * \capbrief supports 16-bit floating-point types in shaders for arithmetic operations. + * \someNYI + * \platformtable{"hasShaderFloat16Support",c,a,c,a,c,c,r,r,c,r,r} + */ + bool hasShaderFloat16Support : 1; /* !!!!! TO ADD NEW VALUES, FOLOW THE STEPS DESCRIBED AT THE REMARK SECTION, KEEP THIS AT THE END OF THIS STRUCT !!!!! */ }; /** @@ -756,6 +762,8 @@ struct DeviceDriverCapabilitiesXboxOne : DeviceDriverCapabilitiesBase static constexpr bool hasIndirectSupport = true; //! \briefconstcap{true, DeviceDriverCapabilitiesBase::hasCompareSampler} static constexpr bool hasCompareSampler = true; + //! \briefconstcap{false, DeviceDriverCapabilitiesBase::hasShaderFloat16Support} + static constexpr bool hasShaderFloat16Support = false; }; /** * \brief Optimized capabilities structure, hiding bitfield entries with static const values of known platform features for \scarlett @@ -788,6 +796,8 @@ struct DeviceDriverCapabilitiesScarlett : DeviceDriverCapabilitiesXboxOne //! \warning Documentation is contradicting it self about proper support of indirect dispatch with pipelines that use amplification //! shaders. static constexpr bool hasMeshShader = true; + //! \briefconstcap{false, DeviceDriverCapabilitiesBase::hasShaderFloat16Support} + static constexpr bool hasShaderFloat16Support = false; }; /** * \brief Optimized capabilities structure, hiding bitfield entries with static const values of known platform features for @@ -858,9 +868,6 @@ struct DeviceDriverCapabilitiesPS4 : DeviceDriverCapabilitiesBase static constexpr bool hasVariableRateShadingBy4 = false; //! \briefconstcap{true, DeviceDriverCapabilitiesBase::hasAliasedTextures} static constexpr bool hasAliasedTextures = true; - //! \briefconstcap{false, DeviceDriverCapabilitiesBase::hasResourceHeaps} - //! \NYI - static constexpr bool hasResourceHeaps = true; //! \briefconstcap{false, DeviceDriverCapabilitiesBase::hasBufferOverlapCopy} static constexpr bool hasBufferOverlapCopy = false; //! \briefconstcap{false, DeviceDriverCapabilitiesBase::hasBufferOverlapRegionsCopy} @@ -905,6 +912,8 @@ struct DeviceDriverCapabilitiesPS4 : DeviceDriverCapabilitiesBase static constexpr bool hasIndirectSupport = true; //! \briefconstcap{true, DeviceDriverCapabilitiesBase::hasCompareSampler} static constexpr bool hasCompareSampler = true; + //! \briefconstcap{false, DeviceDriverCapabilitiesBase::hasShaderFloat16Support} + static constexpr bool hasShaderFloat16Support = false; }; /** * \brief Optimized capabilities structure, hiding bitfield entries with static const values of known platform features for @@ -1027,6 +1036,8 @@ struct DeviceDriverCapabilitiesIOS : DeviceDriverCapabilitiesBase static constexpr bool hasTileBasedArchitecture = true; //! \briefconstcap{false, DeviceDriverCapabilitiesBase::hasLazyMemory} static constexpr bool hasLazyMemory = false; + //! \briefconstcap{true, DeviceDriverCapabilitiesBase::hasShaderFloat16Support} + static constexpr bool hasShaderFloat16Support = true; }; /** * \brief Optimized capabilities structure, hiding bitfield entries with static const values of known platform features for @@ -1137,6 +1148,8 @@ struct DeviceDriverCapabilitiesTVOS : DeviceDriverCapabilitiesBase static constexpr bool hasTileBasedArchitecture = true; //! \briefconstcap{false, DeviceDriverCapabilitiesBase::hasLazyMemory} static constexpr bool hasLazyMemory = false; + //! \briefconstcap{true, DeviceDriverCapabilitiesBase::hasShaderFloat16Support} + static constexpr bool hasShaderFloat16Support = true; }; /** * \brief Optimized capabilities structure, hiding bitfield entries with static const values of known platform features for @@ -1454,6 +1467,9 @@ struct DeviceDriverCapabilitiesMacOSX : DeviceDriverCapabilitiesBase static constexpr bool hasIndirectSupport = true; //! \briefconstcap{true, DeviceDriverCapabilitiesBase::hasCompareSampler} static constexpr bool hasCompareSampler = true; + //! \briefconstcap{false, DeviceDriverCapabilitiesBase::hasShaderFloat16Support} + //! \NYI + static constexpr bool hasShaderFloat16Support = false; }; /** * \brief Optimized capabilities structure, hiding bitfield entries with static const values of known platform features for diff --git a/prog/dagorInclude/3d/dag_occlusionSystem.h b/prog/dagorInclude/3d/dag_occlusionSystem.h index b777fde46..ec1380ad0 100644 --- a/prog/dagorInclude/3d/dag_occlusionSystem.h +++ b/prog/dagorInclude/3d/dag_occlusionSystem.h @@ -8,6 +8,7 @@ #include #include #include <3d/dag_stereoIndex.h> +#include <3d/dag_textureIDHolder.h> class BaseTexture; typedef BaseTexture Texture; @@ -46,7 +47,7 @@ class OcclusionSystem : protected OcclusionTest // Inh virtual void buildMips() = 0; virtual void prepareDebug() = 0; virtual void prepareNextFrame(vec3f viewPos, mat44f_cref view, mat44f_cref proj, mat44f_cref viewProj, float zn, float zf, - Texture *mipped_depth, Texture *depth = 0, StereoIndex stereo_index = StereoIndex::Mono) = 0; + TextureIDPair mipped_depth, Texture *depth = 0, StereoIndex stereo_index = StereoIndex::Mono) = 0; virtual void setReprojectionUseCameraTranslatedSpace(bool enabled) = 0; virtual bool getReprojectionUseCameraTranslatedSpace() const = 0; diff --git a/prog/dagorInclude/3d/dag_ringCPUQueryLock.h b/prog/dagorInclude/3d/dag_ringCPUQueryLock.h index 228e78cd1..6e8e6f3cd 100644 --- a/prog/dagorInclude/3d/dag_ringCPUQueryLock.h +++ b/prog/dagorInclude/3d/dag_ringCPUQueryLock.h @@ -14,14 +14,18 @@ class D3dEventQuery; class RingCPUBufferLock { public: - D3dResource *getNewTarget(uint32_t &frame); - inline D3dResource *getNewTarget(int &frame) + D3dResource *getNewTargetAndId(uint32_t &frame, D3DRESID &id); + D3dResource *getNewTarget(uint32_t &frame) { - uint32_t f = (uint32_t)frame; - auto r = getNewTarget(f); - frame = (int)f; - return r; + D3DRESID id; + return getNewTargetAndId(frame, id); } + D3dResource *getNewTarget(int &frame) + { + D3DRESID id; + return getNewTargetAndId((uint32_t &)frame, id); + } + D3dResource *getNewTargetAndId(int &frame, D3DRESID &id) { return getNewTargetAndId((uint32_t &)frame, id); } void startCPUCopy(); // Texture *getCurrentTarget(); RingCPUBufferLock() {} @@ -48,6 +52,7 @@ class RingCPUBufferLock struct FencedGPUResource { D3dResource *gpu = 0; + D3DRESID id = BAD_D3DRESID; D3dEventQuery *event = 0; }; StaticTab buffers; // diff --git a/prog/dagorInclude/3d/dag_ringCPUTextureLock.h b/prog/dagorInclude/3d/dag_ringCPUTextureLock.h index 6fdebe0af..0da1d9594 100644 --- a/prog/dagorInclude/3d/dag_ringCPUTextureLock.h +++ b/prog/dagorInclude/3d/dag_ringCPUTextureLock.h @@ -13,7 +13,16 @@ typedef BaseTexture Texture; class RingCPUTextureLock : public RingCPUBufferLock { public: - Texture *getNewTarget(int &frame) { return (Texture *)RingCPUBufferLock::getNewTarget(frame); } + template + Texture *getNewTarget(T &frame) + { + return (Texture *)RingCPUBufferLock::getNewTarget(frame); + } + template + Texture *getNewTargetAndId(T &frame, D3DRESID &id) + { + return (Texture *)RingCPUBufferLock::getNewTargetAndId(frame, id); + } void init(uint32_t w, uint32_t h, int max_buffers_count, const char *name, uint32_t fmt) { RingCPUBufferLock::init(w, h, max_buffers_count, name, 0, fmt, true); diff --git a/prog/dagorInclude/anim/dag_animPostBlendCtrl.h b/prog/dagorInclude/anim/dag_animPostBlendCtrl.h index 2c9605f39..2546e2157 100644 --- a/prog/dagorInclude/anim/dag_animPostBlendCtrl.h +++ b/prog/dagorInclude/anim/dag_animPostBlendCtrl.h @@ -1119,7 +1119,7 @@ class AnimPostBlendCompoundRotateShift : public AnimPostBlendCtrl { struct LocalData { - dag::Index16 targetNode, alignAsNode; + dag::Index16 targetNode, alignAsNode, moveAlongNode; }; struct VarId { @@ -1130,7 +1130,7 @@ class AnimPostBlendCompoundRotateShift : public AnimPostBlendCtrl float yaw = 1, pitch = 1, lean = 1, ofsX = 1, ofsY = 1, ofsZ = 1; } scale; int localVarId = -1; - SimpleString targetNode, alignAsNode; + SimpleString targetNode, alignAsNode, moveAlongNode; mat33f tmRot[2]; public: diff --git a/prog/dagorInclude/gameRes/dag_gameResSystem.h b/prog/dagorInclude/gameRes/dag_gameResSystem.h index 5183919c5..eb9509ab7 100644 --- a/prog/dagorInclude/gameRes/dag_gameResSystem.h +++ b/prog/dagorInclude/gameRes/dag_gameResSystem.h @@ -120,7 +120,8 @@ void set_gameres_scan_recorder(DataBlock *rootBlk, const char *grp_pref, const c // Scan for game resource packs in specified location. // Path must end with slash. -void scan_for_game_resources(const char *path, bool scan_subdirs, bool scan_dxp = false, bool allow_override = false); +void scan_for_game_resources(const char *path, bool scan_subdirs, bool scan_dxp = false, bool allow_override = false, + bool scan_vromfs = false); // Load pack list BLK from specified filename and load respacks according to list // when res_base_dir==NULL, base directory is extracted from pack_list_blk_fname path diff --git a/prog/dagorInclude/osApiWrappers/dag_basePath.h b/prog/dagorInclude/osApiWrappers/dag_basePath.h index 693091092..2e58c1efc 100644 --- a/prog/dagorInclude/osApiWrappers/dag_basePath.h +++ b/prog/dagorInclude/osApiWrappers/dag_basePath.h @@ -39,6 +39,11 @@ extern "C" //! returns path assigned for named mount (when mount exists) or nullptr (when mount_name not known) KRNLIMP const char *dd_get_named_mount_path(const char *mount_name, int mount_name_len = -1); + //! return first mount name without % associated with fpath otherwise nulls + //! this code return raw pointer in internal structure, that mean this code is not safty if you remove mount + //! if you want keep mount name for a long time, make a copy of returned string + KRNLIMP const char *dd_get_named_mount_by_path(const char *fpath); + //! dumps list of named mounts (with assigned pathes) to output KRNLIMP void dd_dump_named_mounts(); diff --git a/prog/dagorInclude/phys/dag_physCollision.h b/prog/dagorInclude/phys/dag_physCollision.h index 11892c677..b293805ce 100644 --- a/prog/dagorInclude/phys/dag_physCollision.h +++ b/prog/dagorInclude/phys/dag_physCollision.h @@ -184,6 +184,7 @@ class PhysHeightfieldCollision : public PhysCollision class PhysTriMeshCollision : public PhysCollision { const void *vdata, *idata; + const char *debugName = nullptr; Point3 scale = Point3(1, 1, 1); unsigned vstride, vnum, istride, inum; bool vtypeShort, revNorm; @@ -202,6 +203,7 @@ class PhysTriMeshCollision : public PhysCollision if (scl) scale = Point3(scl[0], scl[1], scl[2]); } + void setDebugName(const char *dbgn) { debugName = dbgn; } friend class PhysBody; }; diff --git a/prog/dagorInclude/scene/dag_occlusion.h b/prog/dagorInclude/scene/dag_occlusion.h index 4c86afd70..ba7192352 100644 --- a/prog/dagorInclude/scene/dag_occlusion.h +++ b/prog/dagorInclude/scene/dag_occlusion.h @@ -7,6 +7,7 @@ #include #include <3d/dag_occlusionSystem.h> +#include <3d/dag_textureIDHolder.h> #include #pragma warning(push) @@ -113,7 +114,8 @@ class Occlusion } bool hasGPUFrame() const { return occ->hasGPUFrame(); } - void prepareNextFrame(float zn, float zf, Texture *mipped_depth, Texture *depth = 0, StereoIndex stereo_index = StereoIndex::Mono) + void prepareNextFrame(float zn, float zf, TextureIDPair mipped_depth, Texture *depth = 0, + StereoIndex stereo_index = StereoIndex::Mono) { occ->prepareNextFrame(curViewPos, curView, curProj, curViewProj, zn, zf, mipped_depth, depth, stereo_index); } diff --git a/prog/dagorInclude/shaders/dag_shaderHash.h b/prog/dagorInclude/shaders/dag_shaderHash.h index e8b8229d9..fff12865e 100644 --- a/prog/dagorInclude/shaders/dag_shaderHash.h +++ b/prog/dagorInclude/shaders/dag_shaderHash.h @@ -40,6 +40,13 @@ struct ShaderHashValue return value; } + static ShaderHashValue fromString(const char *str, int len = -1) + { + ShaderHashValue value; + str_hex_to_data_buf(value.value, sizeof(value.value), str, nullptr, len); + return value; + } + void convertToString(char *buffer, size_t size) const { G_ASSERT(size > (sizeof(ShaderHashValue) * 2)); diff --git a/prog/dagorInclude/shaders/dag_shaderResUnitedData.h b/prog/dagorInclude/shaders/dag_shaderResUnitedData.h index b7c842e83..245f58cfa 100644 --- a/prog/dagorInclude/shaders/dag_shaderResUnitedData.h +++ b/prog/dagorInclude/shaders/dag_shaderResUnitedData.h @@ -154,7 +154,7 @@ class ShaderResUnitedVdata void buildStatusStr(String &out_str, bool full_res_list, bool (*resolve_res_name)(String &nm, RES *r) = nullptr); void dumpMemBlocks(String *out_str_summary = nullptr); - int getPendingReloadResCount() const { return pendingVdataReloadResCount; } + int getPendingReloadResCount() const { return interlocked_acquire_load(pendingVdataReloadResCount); } int getFailedReloadResCount() const { return failedVdataReloadResList.size(); } void setHints(const DataBlock &hints_blk); @@ -176,7 +176,7 @@ class ShaderResUnitedVdata volatile int vbSizeToFree = 0, ibSizeToFree = 0; int uselessDiscardAttempts = 0; Tab failedVdataReloadResList; - int pendingVdataReloadResCount = 0; + volatile int pendingVdataReloadResCount = 0; unitedvdata::BufConfig hints; mutable std::mutex hintsMutex; @@ -211,7 +211,7 @@ class ShaderResUnitedVdata inline void releaseUpdateJob(UpdateModelCtx &ctx); inline void ceaseUpdateJob(UpdateModelCtx &ctx) { - pendingVdataReloadResCount--; + interlocked_decrement(pendingVdataReloadResCount); ctx.res->setResLoadingFlag(false); ctx.res = nullptr; } diff --git a/prog/dagorInclude/startup/dag_androidMain.inc.cpp b/prog/dagorInclude/startup/dag_androidMain.inc.cpp index eefc01614..0dd9d1ca8 100644 --- a/prog/dagorInclude/startup/dag_androidMain.inc.cpp +++ b/prog/dagorInclude/startup/dag_androidMain.inc.cpp @@ -666,8 +666,7 @@ void read_argv_from_file(const char *file, int &argc, char **argv) cmdBuffer[lSize] = 0; if (df_read(cmdFile, cmdBuffer, lSize) == lSize) { - const char *delimeter = " "; - int i = 0; + const char *delimeter = " \n"; char *token = strtok(cmdBuffer, delimeter); while ((argc < MAX_ARGS_COUNT) && (token != NULL)) { diff --git a/prog/gameLibs/publicInclude/comPtr/comPtr.h b/prog/dagorInclude/supp/dag_comPtr.h similarity index 99% rename from prog/gameLibs/publicInclude/comPtr/comPtr.h rename to prog/dagorInclude/supp/dag_comPtr.h index 153bdbbeb..6e19a2a5a 100644 --- a/prog/gameLibs/publicInclude/comPtr/comPtr.h +++ b/prog/dagorInclude/supp/dag_comPtr.h @@ -1,5 +1,5 @@ // -// Dagor Engine 6.5 - Game Libraries +// Dagor Engine 6.5 // Copyright (C) 2023 Gaijin Games KFT. All rights reserved // (for conditions of use see prog/license.txt) // diff --git a/prog/dagorInclude/util/dag_simpleString.h b/prog/dagorInclude/util/dag_simpleString.h index c18aed5ee..aeb78e9c5 100644 --- a/prog/dagorInclude/util/dag_simpleString.h +++ b/prog/dagorInclude/util/dag_simpleString.h @@ -92,7 +92,9 @@ class SimpleString // comparison operators bool operator==(const char *s) const { return strcmp(str(), s ? s : "") == 0; } + friend bool operator==(const char *a, const SimpleString &s) { return strcmp(a ? a : "", s.str()) == 0; } bool operator!=(const char *s) const { return strcmp(str(), s ? s : "") != 0; } + friend bool operator!=(const char *a, const SimpleString &s) { return strcmp(a ? a : "", s.str()) != 0; } bool operator>(const char *s) const { return strcmp(str(), s ? s : "") > 0; } bool operator<(const char *s) const { return strcmp(str(), s ? s : "") < 0; } bool operator>=(const char *s) const { return strcmp(str(), s ? s : "") >= 0; } diff --git a/prog/dagorInclude/util/dag_string.h b/prog/dagorInclude/util/dag_string.h index 130469f22..b1a9fde96 100644 --- a/prog/dagorInclude/util/dag_string.h +++ b/prog/dagorInclude/util/dag_string.h @@ -272,8 +272,10 @@ class String : public Tab /// comparison operators bool operator==(const char *a) const { return strcmp(str(), a) == 0; } bool operator==(const String &s) const { return strcmp(str(), s.str()) == 0; } + friend bool operator==(const char *a, const String &s) { return strcmp(a, s.str()) == 0; } bool operator!=(const char *a) const { return strcmp(str(), a) != 0; } bool operator!=(const String &s) const { return strcmp(str(), s.str()) != 0; } + friend bool operator!=(const char *a, const String &s) { return strcmp(a, s.str()) != 0; } KRNLIMP String &toUpper(); KRNLIMP String &toLower(); @@ -337,9 +339,6 @@ class String : public Tab } }; -inline bool operator==(const char *a, const String &s) { return strcmp(a, s.str()) == 0; } -inline bool operator!=(const char *a, const String &s) { return strcmp(a, s.str()) != 0; } - inline String operator+(const char *p, const String &s) { if (!p || !p[0]) diff --git a/prog/engine/anim/animGraph.cpp b/prog/engine/anim/animGraph.cpp index ae88bd65d..e9d8ab763 100644 --- a/prog/engine/anim/animGraph.cpp +++ b/prog/engine/anim/animGraph.cpp @@ -2285,14 +2285,14 @@ void AnimBlendCtrl_ParametricSwitcher::createNode(AnimationGraph &graph, const D { // if recursionCount will become more than then blockCount, so we are in deadlock int recursionCount = 0; - String parentEnumBlockName(enumBlock->getStr("_extends", "")); + String parentEnumBlockName(enumBlock->getStr("_use", "")); while (!parentEnumBlockName.empty() && recursionCount < je) { recursionCount++; if (const DataBlock *parentBlock = init_st->getBlockByName(parentEnumBlockName.c_str())) { nm = parentBlock->getStr(name, ""); - parentEnumBlockName = nm.empty() ? parentBlock->getStr("_extends", "") : ""; + parentEnumBlockName = nm.empty() ? parentBlock->getStr("_use", "") : ""; } else parentEnumBlockName.clear(); // break cycle @@ -2300,7 +2300,7 @@ void AnimBlendCtrl_ParametricSwitcher::createNode(AnimationGraph &graph, const D if (recursionCount == je) { - ANIM_ERR("enum <%s> has cycle in _extends!", enum_nm); + ANIM_ERR("enum <%s> has cycle in _use!", enum_nm); continue; } diff --git a/prog/engine/anim/animIKCtrl.cpp b/prog/engine/anim/animIKCtrl.cpp index 4efe0b8ad..44cbc6c54 100644 --- a/prog/engine/anim/animIKCtrl.cpp +++ b/prog/engine/anim/animIKCtrl.cpp @@ -66,10 +66,13 @@ void AnimV20::LegsIKCtrl::process(IPureAnimStateHolder &st, real wt, GeomNodeTre Point3_vec4 footNewPos(0.f, 0.f, 0.f); bool move_foot = false; const mat44f &animcharTm = tree.getRootWtmRel(); - Point3_vec4 up = Point3_vec4(0, 1, 0); + vec4f vup = V_C_UNIT_0100; + bool up_is_world_up = true; if (rec[i].useAnimcharUpDir) - up = as_point3(&animcharTm.col1); - bool up_is_world_up = up.y > 0.999f; + { + vup = animcharTm.col1; + up_is_world_up = v_extract_y(vup) > 0.999f; + } if (isCrawl) { @@ -116,28 +119,28 @@ void AnimV20::LegsIKCtrl::process(IPureAnimStateHolder &st, real wt, GeomNodeTre float foot_len = as_point4(&rec[i].vFootFwd).w; float trace_h1 = 0, trace_h2 = 0; - float leg_height = as_point3(&leg_wtm.col3) * up; - float foot_height = as_point3(&foot_wtm.col3) * up; - if (leg_height > foot_height) + float leg_diff = v_extract_x(v_sub_x(v_dot3_x(leg_wtm.col3, vup), v_dot3_x(foot_wtm.col3, vup))); + if (leg_diff > 0.f) { float maxDist = rec[i].maxFootUp + 0.15; - float footUpOfs = min(rec[i].maxFootUp, (leg_height - foot_height - 0.15f) * 0.9f); + float footUpOfs = min(rec[i].maxFootUp, (leg_diff - 0.15f) * 0.9f); + + Point3_vec4 dir; + v_st(&dir, v_neg(vup)); Point3_vec4 pt; - Point3_vec4 dir = -up; - v_st(&pt, v_add(v_mat44_mul_vec3p(animcharTm, v_and(foot_p1, v_cast_vec4f(V_CI_MASK1010))), wofs)); - pt += footUpOfs * up; + v_st(&pt, + v_madd(vup, v_splats(footUpOfs), v_add(v_mat44_mul_vec3p(animcharTm, v_and(foot_p1, v_cast_vec4f(V_CI_MASK1010))), wofs))); trace_h1 = maxDist; if (ctx.irq(up_is_world_up ? GIRQT_TraceFootStepDown : GIRQT_TraceFootStepDir, (intptr_t)(void *)&pt, - (intptr_t)(up_is_world_up ? (void *)&maxDist : (void *)&dir), (intptr_t)(void *)&trace_h1) == GIRQR_TraceOK) + (intptr_t)(up_is_world_up ? (void *)&trace_h1 : (void *)&dir), (intptr_t)(void *)&trace_h1) == GIRQR_TraceOK) trace_h1 -= footUpOfs; - v_st(&pt, v_add(v_mat44_mul_vec3p(animcharTm, v_and(foot_p2, v_cast_vec4f(V_CI_MASK1010))), wofs)); - pt += footUpOfs * up; - + v_st(&pt, + v_madd(vup, v_splats(footUpOfs), v_add(v_mat44_mul_vec3p(animcharTm, v_and(foot_p2, v_cast_vec4f(V_CI_MASK1010))), wofs))); trace_h2 = maxDist; if (ctx.irq(up_is_world_up ? GIRQT_TraceFootStepDown : GIRQT_TraceFootStepDir, (intptr_t)(void *)&pt, - (intptr_t)(up_is_world_up ? (void *)&maxDist : (void *)&dir), (intptr_t)(void *)&trace_h2) == GIRQR_TraceOK) + (intptr_t)(up_is_world_up ? (void *)&trace_h2 : (void *)&dir), (intptr_t)(void *)&trace_h2) == GIRQR_TraceOK) trace_h2 -= footUpOfs; else trace_h2 = trace_h1; @@ -184,11 +187,7 @@ void AnimV20::LegsIKCtrl::process(IPureAnimStateHolder &st, real wt, GeomNodeTre if (isCrawl) as_point3(&foot_wtm.col3) = footNewPos; else - { - if (move_foot) - foot_wtm.col3 = foot_p1; - as_point3(&foot_wtm.col3) += nodes[i].dy * up; - } + foot_wtm.col3 = v_perm_xyzd(v_madd(vup, v_splats(nodes[i].dy), move_foot ? foot_p1 : foot_wtm.col3), V_C_UNIT_0001); solve_2bones_ik(leg_wtm, knee_wtm, foot_wtm, foot_wtm, len0, len1, as_point3(&knee_wtm.col1)); if (ctx.acScale) { diff --git a/prog/engine/anim/animPostBlendCtrl.cpp b/prog/engine/anim/animPostBlendCtrl.cpp index 1d9f09c42..61539712a 100644 --- a/prog/engine/anim/animPostBlendCtrl.cpp +++ b/prog/engine/anim/animPostBlendCtrl.cpp @@ -3187,6 +3187,7 @@ void AnimPostBlendCompoundRotateShift::init(IPureAnimStateHolder &st, const Geom LocalData &ldata = *(LocalData *)st.getInlinePtr(localVarId); ldata.targetNode = resolve_node_by_name(tree, targetNode); ldata.alignAsNode = resolve_node_by_name(tree, alignAsNode); + ldata.moveAlongNode = resolve_node_by_name(tree, moveAlongNode); } void AnimPostBlendCompoundRotateShift::process(IPureAnimStateHolder &st, real wt, GeomNodeTree &tree, AnimPostBlendCtrl::Context &) { @@ -3250,12 +3251,25 @@ void AnimPostBlendCompoundRotateShift::process(IPureAnimStateHolder &st, real wt v_mat33_mul(m, m2, tmRot[1]); vec3f pos = dn_wtm.col3; + + if (ldata.moveAlongNode) + { + mat44f &moveAlong_wtm = tree.getNodeWtmRel(ldata.moveAlongNode); + tree.partialCalcWtm(ldata.alignAsNode); + + m2.col0 = moveAlong_wtm.col0; + m2.col1 = moveAlong_wtm.col1; + m2.col2 = moveAlong_wtm.col2; + } + + mat33f &moveAlong = ldata.moveAlongNode ? m2 : m; + if (varId.ofsX >= 0) - pos = v_madd(m.col0, v_splats(scale.ofsX * st.getParam(varId.ofsX)), pos); + pos = v_madd(moveAlong.col0, v_splats(scale.ofsX * st.getParam(varId.ofsX)), pos); if (varId.ofsY >= 0) - pos = v_madd(m.col1, v_splats(scale.ofsY * st.getParam(varId.ofsY)), pos); + pos = v_madd(moveAlong.col1, v_splats(scale.ofsY * st.getParam(varId.ofsY)), pos); if (varId.ofsZ >= 0) - pos = v_madd(m.col2, v_splats(scale.ofsZ * st.getParam(varId.ofsZ)), pos); + pos = v_madd(moveAlong.col2, v_splats(scale.ofsZ * st.getParam(varId.ofsZ)), pos); dn_wtm.col0 = m.col0; dn_wtm.col1 = m.col1; @@ -3278,6 +3292,7 @@ void AnimPostBlendCompoundRotateShift::createNode(AnimationGraph &graph, const D node->targetNode = blk.getStr("targetNode", NULL); node->alignAsNode = blk.getStr("alignAsNode", NULL); + node->moveAlongNode = blk.getStr("moveAlongNode", NULL); #define SETUP_PARAM(NM) \ if (const char *pname = blk.getStr(#NM, NULL)) \ node->varId.NM = graph.addParamId(pname, IPureAnimStateHolder::PT_ScalarParam), node->scale.NM = blk.getReal(#NM "_mul", 1.0f) diff --git a/prog/engine/animChar/animCharBase.cpp b/prog/engine/animChar/animCharBase.cpp index 30b3788e8..c8a457b2b 100644 --- a/prog/engine/animChar/animCharBase.cpp +++ b/prog/engine/animChar/animCharBase.cpp @@ -897,7 +897,7 @@ intptr_t AnimcharBaseComponent::irq(int type, intptr_t p1, intptr_t p2, intptr_t if (!AnimCharV20::trace_static_ray_dir) return GIRQR_NoResponse; Point3_vec4 &pt = *(Point3_vec4 *)(void *)p1; - Point3_vec4 dir = *(Point3_vec4 *)(void *)p2; + const Point3_vec4 &dir = *(Point3_vec4 *)(void *)p2; float *res = (float *)(void *)p3; float max_trace_dist = *res; if (AnimCharV20::trace_static_ray_dir(pt, dir, max_trace_dist, *res, ac->traceContext)) diff --git a/prog/engine/baseUtil/watchdog.cpp b/prog/engine/baseUtil/watchdog.cpp index a9648e688..5a6e083a5 100644 --- a/prog/engine/baseUtil/watchdog.cpp +++ b/prog/engine/baseUtil/watchdog.cpp @@ -37,8 +37,10 @@ #define WATCHDOG_FREEZE_THRESHOLD (7000) #define WATCHDOG_DUMP_CALLSTACK_THRESHOLD (WATCHDOG_FREEZE_THRESHOLD / 2) #endif -#define WATCHDOG_SLEEP_TIME_MS (500) -#define ACTIVE_SWAP_THRESHOLD (1000) +#define WATCHDOG_SLEEP_TIME_MS (500) +#define WATCHDOG_ACTIVE_SWAP_THRESHOLD (1000) +// Assume that OS is resumed from sleep/hibernation if more then this time passed +#define WATCHDOG_OS_RESUMED_THRESHOLD (10 * 60 * 1000) static inline unsigned get_cur_time_ms() { @@ -119,10 +121,11 @@ class WatchDogThread : public DaThread // freezes detector goto keep_sleeping; #endif unsigned curTime = get_cur_time_ms(), lastTime = lastUpdateTimeMs.load(std::memory_order_relaxed); - if (curTime < lastTime) // wrap-around? + unsigned e_time = curTime - lastTime; + if (curTime < lastTime || // timeGetTime wraps around happens each ~49.71 days since system start + e_time > WATCHDOG_OS_RESUMED_THRESHOLD) goto keep_sleeping; - int e_time = curTime - lastTime; bool freeze = e_time >= triggering_threshold_ms + (cfg.flags & WATCHDOG_SWAP_HANDICAP ? activeSwapHandicapMs : 0); if (e_time > interlocked_acquire_load(cfg.dump_threads_threshold_ms)) { @@ -163,7 +166,7 @@ class WatchDogThread : public DaThread // freezes detector lastPageFaultCount = memc.PageFaultCount; pageFaultCountResetAt = curTime; } - else if (memc.PageFaultCount - lastPageFaultCount > ACTIVE_SWAP_THRESHOLD * (curTime - pageFaultCountResetAt) / 1000) + else if (memc.PageFaultCount - lastPageFaultCount > WATCHDOG_ACTIVE_SWAP_THRESHOLD * (curTime - pageFaultCountResetAt) / 1000) activeSwapHandicapMs += cfg.dump_threads_threshold_ms * 2 / 3; #endif } diff --git a/prog/engine/consoleProc/consoleProcessor.cpp b/prog/engine/consoleProc/consoleProcessor.cpp index b72ca08ab..a552a98ca 100644 --- a/prog/engine/consoleProc/consoleProcessor.cpp +++ b/prog/engine/consoleProc/consoleProcessor.cpp @@ -55,6 +55,8 @@ static class FuncCommandProcessor final : public console::ICommandProcessor //************************************************************************ static eastl::vector console_listeners; +static String cached_prefix; +static console::CommandList cached_commands; void register_console_listener(const ConsoleOutputCallback &listener_func) { console_listeners.push_back(listener_func); } @@ -222,6 +224,9 @@ bool command(const char *cmd) if (!res) console::warning("unknown command: '%s'", arg[0]); + cached_prefix.clear(); + cached_commands.clear(); + memfree(s, tmpa); return res; } @@ -282,10 +287,6 @@ bool process_file(const char *filename) } -static String cached_prefix; -static console::CommandList cached_commands; - - // open console on screen void show() { diff --git a/prog/engine/drv/drv3d_DX11/driver.h b/prog/engine/drv/drv3d_DX11/driver.h index 0cf780a39..deda389dd 100644 --- a/prog/engine/drv/drv3d_DX11/driver.h +++ b/prog/engine/drv/drv3d_DX11/driver.h @@ -37,7 +37,7 @@ struct RENDERDOC_API_1_5_0; #include #include #include -#include +#include #include <3d/dag_drv3dReset.h> /* diff --git a/prog/engine/drv/drv3d_DX11/init.cpp b/prog/engine/drv/drv3d_DX11/init.cpp index b41d6905a..b472a6bfd 100644 --- a/prog/engine/drv/drv3d_DX11/init.cpp +++ b/prog/engine/drv/drv3d_DX11/init.cpp @@ -1245,6 +1245,7 @@ bool init_device(Driver3dInitCallback *cb, HWND window_hwnd, int screen_wdt, int g_device_desc.caps.hasOptimizedViewInstancing = false; g_device_desc.caps.hasAcceleratedViewInstancing = false; g_device_desc.caps.hasRenderPassDepthResolve = false; + g_device_desc.caps.hasShaderFloat16Support = false; if (init_ngx(get_log_directory())) { diff --git a/prog/engine/drv/drv3d_DX11/jamfile b/prog/engine/drv/drv3d_DX11/jamfile index 78a0e14e8..6bef3f092 100644 --- a/prog/engine/drv/drv3d_DX11/jamfile +++ b/prog/engine/drv/drv3d_DX11/jamfile @@ -23,7 +23,6 @@ Sources = AddIncludes = - $(Root)/prog/gameLibs/publicInclude $(Root)/prog/engine/sharedInclude $(Root)/prog/engine/drv/drv3d_commonCode $(Root)/prog/3rdPartyLibs/nvapi diff --git a/prog/engine/drv/drv3d_DX11/texture.cpp b/prog/engine/drv/drv3d_DX11/texture.cpp index 73fb203bf..0098cf162 100644 --- a/prog/engine/drv/drv3d_DX11/texture.cpp +++ b/prog/engine/drv/drv3d_DX11/texture.cpp @@ -27,7 +27,7 @@ #include #include "driver.h" -#include +#include #include #if HAS_NVAPI && NVAPI_SLI_SYNC #include diff --git a/prog/engine/drv/drv3d_DX12/debug/device_state_pc.cpp b/prog/engine/drv/drv3d_DX12/debug/device_state_pc.cpp index 45b3094ea..7d88f1819 100644 --- a/prog/engine/drv/drv3d_DX12/debug/device_state_pc.cpp +++ b/prog/engine/drv/drv3d_DX12/debug/device_state_pc.cpp @@ -1,5 +1,6 @@ #include "device.h" +#if USE_PIX #if _TARGET_64BIT // PROFILE_BUILD will enable USE_PIX in pix3.h if architecture is supported #define PROFILE_BUILD @@ -11,6 +12,7 @@ #include "WinPixEventRuntime/pix3.h" #endif #endif +#endif #include #include diff --git a/prog/engine/drv/drv3d_DX12/debug/gpu_capture.cpp b/prog/engine/drv/drv3d_DX12/debug/gpu_capture.cpp index 966fad466..d6386e621 100644 --- a/prog/engine/drv/drv3d_DX12/debug/gpu_capture.cpp +++ b/prog/engine/drv/drv3d_DX12/debug/gpu_capture.cpp @@ -1,5 +1,6 @@ #include "device.h" +#if USE_PIX // PROFILE_BUILD will enable USE_PIX in pix3.h if architecture is supported #define PROFILE_BUILD #if !defined(__d3d12_h__) @@ -9,6 +10,8 @@ #else #include "WinPixEventRuntime/pix3.h" #endif +#endif + #include using namespace drv3d_dx12; @@ -144,6 +147,7 @@ LibPointer debug::gpu_capture::PIX::try_connect_capture_interface() return {}; } +#if USE_PIX LibPointer debug::gpu_capture::PIX::try_load_capture_interface() { return {PIXLoadLatestWinPixGpuCapturerLibrary(), {}}; } void debug::gpu_capture::PIX::configure() { PIXSetHUDOptions(PIXHUDOptions::PIX_HUD_SHOW_ON_NO_WINDOWS); } @@ -202,6 +206,17 @@ void debug::gpu_capture::PIX::marker(ID3D12GraphicsCommandList *cmd, eastl::span cmd->SetMarker(PIX_EVENT_ANSI_VERSION, text.data(), text.size()); } } +#else +LibPointer debug::gpu_capture::PIX::try_load_capture_interface() { return {}; } +void debug::gpu_capture::PIX::configure() {} +void debug::gpu_capture::PIX::beginCapture() {} +void debug::gpu_capture::PIX::endCapture() {} +void debug::gpu_capture::PIX::onPresent() {} +void debug::gpu_capture::PIX::captureFrames(const wchar_t *, int) {} +void debug::gpu_capture::PIX::beginEvent(ID3D12GraphicsCommandList *, eastl::span) {} +void debug::gpu_capture::PIX::endEvent(ID3D12GraphicsCommandList *) {} +void debug::gpu_capture::PIX::marker(ID3D12GraphicsCommandList *, eastl::span) {} +#endif bool debug::gpu_capture::nvidia::NSight::try_connect_interface() { diff --git a/prog/engine/drv/drv3d_DX12/device.cpp b/prog/engine/drv/drv3d_DX12/device.cpp index 1a429aad3..afaa68796 100644 --- a/prog/engine/drv/drv3d_DX12/device.cpp +++ b/prog/engine/drv/drv3d_DX12/device.cpp @@ -295,7 +295,7 @@ D3D12_CPU_DESCRIPTOR_HANDLE Device::getNonRecentImageViews(Image *img, ImageView return img->getRecentView().handle; } -Device::~Device() { shutdown(); } +Device::~Device() { shutdown({}); } void Device::setupNullViews() { @@ -486,7 +486,7 @@ bool Device::init(DXGIFactory *factory, AdapterInfo &&adapterInfo, D3D_FEATURE_L { return SUCCEEDED(d3d_env.D3D12CreateDevice(this->adapter.Get(), feature_level, uuid, ptr)); })) { debug("DX12: Failed..."); - shutdown(); + shutdown({}); return false; } @@ -526,7 +526,7 @@ bool Device::init(DXGIFactory *factory, AdapterInfo &&adapterInfo, D3D_FEATURE_L #if DAGOR_DBGLEVEL > 0 debug("DX12: Debug build, allowing target without DXIL support"); #else - shutdown(); + shutdown({}); return false; #endif } @@ -535,7 +535,7 @@ bool Device::init(DXGIFactory *factory, AdapterInfo &&adapterInfo, D3D_FEATURE_L if (!queues.init(device.get(), shouldNameObjects())) { debug("DX12: Failed..."); - shutdown(); + shutdown({}); return false; } @@ -544,7 +544,7 @@ bool Device::init(DXGIFactory *factory, AdapterInfo &&adapterInfo, D3D_FEATURE_L eastl::move(swapchain_create_info))) { debug("DX12: Failed..."); - shutdown(); + shutdown({}); return false; } @@ -625,8 +625,6 @@ bool Device::init(DXGIFactory *factory, AdapterInfo &&adapterInfo, D3D_FEATURE_L pipeMan.init(pipelineManagerSetup); - renderStateSystem.loadFromCache(pipelineCache, pipeMan); - #if !FIXED_EXECUTION_MODE DeviceContext::ExecutionMode execMode = DeviceContext::ExecutionMode::IMMEDIATE; if (config.features.test(DeviceFeaturesConfig::USE_THREADED_COMMAND_EXECUTION)) @@ -656,7 +654,7 @@ bool Device::init(DXGIFactory *factory, AdapterInfo &&adapterInfo, D3D_FEATURE_L bool Device::isInitialized() const { return nullptr != device.get(); } -void Device::shutdown() +void Device::shutdown(const DeviceCapsAndShaderModel &features) { if (!isInitialized()) return; @@ -692,8 +690,23 @@ void Device::shutdown() #if DX12_ENABLE_CONST_BUFFER_DESCRIPTORS pipelineCacheSetup.rootSignaturesUsesCBVDescriptorRanges = rootSignaturesUsesCBVDescriptorRanges(); #endif + auto dxBlock = dgs_get_settings()->getBlockByNameEx("dx12"); + pipelineCacheSetup.features = features; + // smNone is a indicator for default constructed, eg on error case + if (features.shaderModel != d3d::smNone) + { + pipelineCacheSetup.generateBlks = dxBlock->getBool("generateCacheBlks", false); + pipelineCacheSetup.alwaysGenerateBlks = dxBlock->getBool("alwaysGenerateCacheBlks", false); + } + else + { + pipelineCacheSetup.generateBlks = false; + pipelineCacheSetup.alwaysGenerateBlks = false; + } pipelineCache.shutdown(pipelineCacheSetup); +#else + G_UNUSED(features); #endif resources.shutdown(getDXGIAdapter(), &bindlessManager); @@ -749,6 +762,7 @@ void Device::adjustCaps(Driver3dDesc &capabilities) capabilities.caps.hasNativeRenderPassSubPasses = false; capabilities.caps.hasDrawID = true; capabilities.caps.hasRenderPassDepthResolve = false; + capabilities.caps.hasShaderFloat16Support = false; #if HAS_NVAPI // This is a bloody workaround for broken terrain tessellation. diff --git a/prog/engine/drv/drv3d_DX12/device.h b/prog/engine/drv/drv3d_DX12/device.h index 1eb4ccda1..9c1b1997f 100644 --- a/prog/engine/drv/drv3d_DX12/device.h +++ b/prog/engine/drv/drv3d_DX12/device.h @@ -15,6 +15,7 @@ #include "bindless.h" #include "device_context.h" #include "query_manager.h" +#include "pipeline/blk_cache.h" #include #include @@ -562,7 +563,7 @@ class Device : public DeviceErrroState, public DeviceErrorObserver, prot bool init(SwapchainCreateInfo swapchain_create_info, const Config &cfg); #endif bool isInitialized() const; - void shutdown(); + void shutdown(const DeviceCapsAndShaderModel &deatures); void adjustCaps(Driver3dDesc &); #if D3D_HAS_RAY_TRACING bool hasRaytraceSupport() const { return caps.test(Caps::RAY_TRACING); } @@ -1497,30 +1498,35 @@ inline bool PipelineStageStateBase::URegister::is(D3D_SHADER_INPUT_TYPE type, D3 #undef CHECK_BUFFER #undef CHECK_IMAGE_TYPE -inline StaticRenderStateID RenderStateSystem::registerStaticState(DeviceContext &ctx, const shaders::RenderState &def) +inline DynamicArray RenderStateSystem::loadStaticStatesFromBlk(DeviceContext &ctx, const Driver3dDesc &desc, + const DataBlock *blk, const char *default_format) { - auto staticRenderState = StaticState::fromRenderState(def); - auto ref = eastl::find(begin(staticStateTable), end(staticStateTable), staticRenderState); - if (ref == end(staticStateTable)) + DynamicArray renderStateIdTable{blk->blockCount()}; + pipeline::DataBlockDecodeEnumarator decoder{*blk, 0, default_format}; + for (; !decoder.completed(); decoder.next()) { - ref = staticStateTable.insert(end(staticStateTable), staticRenderState); - ctx.registerStaticRenderState(StaticRenderStateID{static_cast(ref - begin(staticStateTable))}, *ref); + auto rsi = decoder.index(); + renderStateIdTable[rsi] = StaticRenderStateID::Null(); + decoder.invoke([rsi, this, &desc, &renderStateIdTable, &ctx](auto &state) { + if (this->is_compatible(desc, state)) + { + renderStateIdTable[rsi] = this->registerStaticState(ctx, state); + } + return true; + }); } - return StaticRenderStateID{static_cast(ref - begin(staticStateTable))}; + return renderStateIdTable; } -inline void RenderStateSystem::loadFromCache(PipelineCache &cache, PipelineManager &pipe_man) +inline StaticRenderStateID RenderStateSystem::registerStaticState(DeviceContext &ctx, const StaticState &def) { - cache.enumerateStaticRenderStates([this, &pipe_man](auto &&state) // - { - auto ref = eastl::find(begin(staticStateTable), end(staticStateTable), state); - if (ref == end(staticStateTable)) - { - ref = staticStateTable.insert(end(staticStateTable), state); - StaticRenderStateID ident{static_cast(ref - begin(staticStateTable))}; - pipe_man.registerStaticRenderState(ident, state); - } - }); + auto ref = eastl::find(begin(staticStateTable), end(staticStateTable), def); + if (ref == end(staticStateTable)) + { + ref = staticStateTable.insert(end(staticStateTable), def); + ctx.registerStaticRenderState(StaticRenderStateID{static_cast(ref - begin(staticStateTable))}, *ref); + } + return StaticRenderStateID{static_cast(ref - begin(staticStateTable))}; } inline BufferInterfaceConfigCommon::BufferType PlatformBufferInterfaceConfig::createBuffer(uint32_t size, uint32_t structure_size, diff --git a/prog/engine/drv/drv3d_DX12/device_context.cpp b/prog/engine/drv/drv3d_DX12/device_context.cpp index 2e97fe744..7c23879b7 100644 --- a/prog/engine/drv/drv3d_DX12/device_context.cpp +++ b/prog/engine/drv/drv3d_DX12/device_context.cpp @@ -418,6 +418,102 @@ void DeviceContext::loadComputeShaderFromDump(ProgramID program) immediateModeExecute(); } +void DeviceContext::compilePipelineSet(const DataBlock *feature_sets, DynamicArray &&input_layouts, + DynamicArray &&static_render_states, const DataBlock *output_formats_set, + const DataBlock *graphics_pipeline_set, const DataBlock *mesh_pipeline_set, const DataBlock *compute_pipeline_set, + const char *default_format) +{ + // resolve if any feature set is supported by this device + DynamicArray featureSetSupported; + if (feature_sets && feature_sets->blockCount() > 0) + { + auto blockCount = feature_sets->blockCount(); + featureSetSupported.resize(blockCount); + pipeline::DataBlockDecodeEnumarator resolver{*feature_sets, 0, d3d::get_driver_desc()}; + for (; !resolver.completed(); resolver.next()) + { + resolver.decode(featureSetSupported[resolver.index()]); + } + } + + DynamicArray framebufferLayouts; + if (output_formats_set && output_formats_set->blockCount() > 0) + { + auto blockCount = output_formats_set->blockCount(); + framebufferLayouts.resize(blockCount); + pipeline::DataBlockDecodeEnumarator decoder{*output_formats_set, 0, default_format}; + for (; !decoder.completed(); decoder.next()) + { + auto fi = decoder.index(); + framebufferLayouts[fi] = {}; + decoder.invoke([&framebufferLayouts, fi](auto &info) { + framebufferLayouts[fi] = info; + return true; + }); + } + } + + DynamicArray graphicsPiplines; + if (graphics_pipeline_set && graphics_pipeline_set->blockCount() > 0) + { + auto blockCount = graphics_pipeline_set->blockCount(); + graphicsPiplines.resize(blockCount); + uint32_t decodedCount = 0; + pipeline::DataBlockDecodeEnumarator decoder{ + *graphics_pipeline_set, 0, featureSetSupported.data(), featureSetSupported.size()}; + for (; !decoder.completed(); decoder.next()) + { + if (decoder.decode(graphicsPiplines[decodedCount].base, graphicsPiplines[decodedCount].variants)) + { + ++decodedCount; + } + } + graphicsPiplines.resize(decodedCount); + } + + DynamicArray meshPipelines; + if (mesh_pipeline_set && mesh_pipeline_set->blockCount() > 0) + { + auto blockCount = mesh_pipeline_set->blockCount(); + meshPipelines.resize(blockCount); + uint32_t decodedCount = 0; + pipeline::DataBlockDecodeEnumarator decoder{ + *mesh_pipeline_set, 0, featureSetSupported.data(), featureSetSupported.size()}; + for (; !decoder.completed(); decoder.next()) + { + if (decoder.decode(meshPipelines[decodedCount].base, meshPipelines[decodedCount].variants)) + { + ++decodedCount; + } + } + meshPipelines.resize(decodedCount); + } + + DynamicArray computePipelines; + if (compute_pipeline_set && compute_pipeline_set->blockCount() > 0) + { + auto blockCount = compute_pipeline_set->blockCount(); + computePipelines.resize(blockCount); + uint32_t decodedCount = 0; + pipeline::DataBlockDecodeEnumarator decoder{ + *compute_pipeline_set, 0, featureSetSupported.data(), featureSetSupported.size()}; + for (; !decoder.completed(); decoder.next()) + { + if (decoder.decode(computePipelines[decodedCount].base)) + { + ++decodedCount; + } + } + meshPipelines.resize(decodedCount); + } + + DX12_LOCK_FRONT(); + commandStream.pushBack(make_command(input_layouts.releaseAsSpan(), static_render_states.releaseAsSpan(), + framebufferLayouts.releaseAsSpan(), graphicsPiplines.releaseAsSpan(), meshPipelines.releaseAsSpan(), + computePipelines.releaseAsSpan())); + immediateModeExecute(); +} + void DeviceContext::resizeSwapchain(Extent2D size) { front.swapchain.prepareForShutdown(device); @@ -6061,3 +6157,17 @@ void DeviceContext::ExecutionContext::loadComputeShaderFromDump(ProgramID progra device.config.features.test(DeviceFeaturesConfig::ASSERT_ON_PIPELINE_COMPILATION_ERROR)), device.shouldNameObjects()); } + +void DeviceContext::ExecutionContext::compilePipelineSet(DynamicArray &&input_layouts, + DynamicArray &&static_render_states, DynamicArray &&framebuffer_layouts, + DynamicArray &&graphics_pipelines, DynamicArray &&mesh_pipelines, + DynamicArray &&compute_pipelines) +{ + device.pipeMan.compilePipelineSet(device.getDevice(), device.pipelineCache, contextState.framebufferLayouts, + eastl::forward>(input_layouts), + eastl::forward>(static_render_states), + eastl::forward>(framebuffer_layouts), + eastl::forward>(graphics_pipelines), + eastl::forward>(mesh_pipelines), + eastl::forward>(compute_pipelines)); +} diff --git a/prog/engine/drv/drv3d_DX12/device_context.h b/prog/engine/drv/drv3d_DX12/device_context.h index 8444f37c4..498549b69 100644 --- a/prog/engine/drv/drv3d_DX12/device_context.h +++ b/prog/engine/drv/drv3d_DX12/device_context.h @@ -1443,6 +1443,9 @@ class DeviceContext : protected ResourceUsageHistoryDataSetDebugger, public debu void addShaderGroup(uint32_t group, ScriptedShadersBinDumpOwner *dump, ShaderID null_pixel_shader); void removeShaderGroup(uint32_t group); void loadComputeShaderFromDump(ProgramID program); + void compilePipelineSet(DynamicArray &&input_layouts, DynamicArray &&static_render_states, + DynamicArray &&framebuffer_layouts, DynamicArray &&graphics_pipelines, + DynamicArray &&mesh_pipelines, DynamicArray &&compute_pipelines); }; #if DAGOR_DBGLEVEL > 0 @@ -2008,6 +2011,10 @@ class DeviceContext : protected ResourceUsageHistoryDataSetDebugger, public debu void addShaderGroup(uint32_t group, ScriptedShadersBinDumpOwner *dump, ShaderID null_pixel_shader); void removeShaderGroup(uint32_t group); void loadComputeShaderFromDump(ProgramID program); + void compilePipelineSet(const DataBlock *feature_sets, DynamicArray &&input_layouts, + DynamicArray &&static_render_states, const DataBlock *output_formats_set, + const DataBlock *graphics_pipeline_set, const DataBlock *mesh_pipeline_set, const DataBlock *compute_pipeline_set, + const char *default_format); }; class ScopedCommitLock diff --git a/prog/engine/drv/drv3d_DX12/device_context_cmd.h b/prog/engine/drv/drv3d_DX12/device_context_cmd.h index e7b0b7ec7..db07c3b11 100644 --- a/prog/engine/drv/drv3d_DX12/device_context_cmd.h +++ b/prog/engine/drv/drv3d_DX12/device_context_cmd.h @@ -1345,3 +1345,20 @@ DX12_BEGIN_CONTEXT_COMMAND(LoadComputeShaderFromDump) ctx.loadComputeShaderFromDump(program); #endif DX12_END_CONTEXT_COMMAND + +DX12_BEGIN_CONTEXT_COMMAND(CompilePipelineSet) + DX12_CONTEXT_COMMAND_PARAM(eastl::span, inputLayouts) + DX12_CONTEXT_COMMAND_PARAM(eastl::span, staticRenderStates) + DX12_CONTEXT_COMMAND_PARAM(eastl::span, framebufferLayouts) + DX12_CONTEXT_COMMAND_PARAM(eastl::span, graphicsPipelines) + DX12_CONTEXT_COMMAND_PARAM(eastl::span, meshPipelines) + DX12_CONTEXT_COMMAND_PARAM(eastl::span, computePipelines) + +#if DX12_CONTEXT_COMMAND_IMPLEMENTATION + ctx.compilePipelineSet(DynamicArray::fromSpan(inputLayouts), + DynamicArray::fromSpan(staticRenderStates), DynamicArray::fromSpan(framebufferLayouts), + DynamicArray::fromSpan(graphicsPipelines), + DynamicArray::fromSpan(meshPipelines), + DynamicArray::fromSpan(computePipelines)); +#endif +DX12_END_CONTEXT_COMMAND diff --git a/prog/engine/drv/drv3d_DX12/driver.h b/prog/engine/drv/drv3d_DX12/driver.h index 288782806..d558ec68a 100644 --- a/prog/engine/drv/drv3d_DX12/driver.h +++ b/prog/engine/drv/drv3d_DX12/driver.h @@ -29,7 +29,7 @@ #include "drvCommonConsts.h" -#include +#include #include "constants.h" @@ -2959,4 +2959,244 @@ inline uint32_t spread_color_chanel_mask_to_render_target_color_channel_mask(uin const uint32_t b1 = b | (b << 1) | (b >> 1) | (b >> 2); const uint32_t a1 = a | (a >> 1) | (a >> 2) | (a >> 3); return r1 | g1 | b1 | a1; -} \ No newline at end of file +} + +// used for de and encoding into blk's +#define DX12_D3D_CAP_SET \ + DX12_D3D_CAP(hasAnisotropicFilter); \ + DX12_D3D_CAP(hasDepthReadOnly); \ + DX12_D3D_CAP(hasStructuredBuffers); \ + DX12_D3D_CAP(hasNoOverwriteOnShaderResourceBuffers); \ + DX12_D3D_CAP(hasForcedSamplerCount); \ + DX12_D3D_CAP(hasVolMipMap); \ + DX12_D3D_CAP(hasAsyncCompute); \ + DX12_D3D_CAP(hasOcclusionQuery); \ + DX12_D3D_CAP(hasConstBufferOffset); \ + DX12_D3D_CAP(hasDepthBoundsTest); \ + DX12_D3D_CAP(hasConditionalRender); \ + DX12_D3D_CAP(hasResourceCopyConversion); \ + DX12_D3D_CAP(hasAsyncCopy); \ + DX12_D3D_CAP(hasReadMultisampledDepth); \ + DX12_D3D_CAP(hasInstanceID); \ + DX12_D3D_CAP(hasConservativeRassterization); \ + DX12_D3D_CAP(hasQuadTessellation); \ + DX12_D3D_CAP(hasGather4); \ + DX12_D3D_CAP(hasAlphaCoverage); \ + DX12_D3D_CAP(hasWellSupportedIndirect); \ + DX12_D3D_CAP(hasRaytracing); \ + DX12_D3D_CAP(hasRaytracingT11); \ + DX12_D3D_CAP(hasBindless); \ + DX12_D3D_CAP(hasNVApi); \ + DX12_D3D_CAP(hasATIApi); \ + DX12_D3D_CAP(hasVariableRateShading); \ + DX12_D3D_CAP(hasVariableRateShadingTexture); \ + DX12_D3D_CAP(hasVariableRateShadingShaderOutput); \ + DX12_D3D_CAP(hasVariableRateShadingCombiners); \ + DX12_D3D_CAP(hasVariableRateShadingBy4); \ + DX12_D3D_CAP(hasAliasedTextures); \ + DX12_D3D_CAP(hasResourceHeaps); \ + DX12_D3D_CAP(hasBufferOverlapCopy); \ + DX12_D3D_CAP(hasBufferOverlapRegionsCopy); \ + DX12_D3D_CAP(hasUAVOnlyForcedSampleCount); \ + DX12_D3D_CAP(hasShader64BitIntegerResources); \ + DX12_D3D_CAP(hasNativeRenderPassSubPasses); \ + DX12_D3D_CAP(hasTiled2DResources); \ + DX12_D3D_CAP(hasTiled3DResources); \ + DX12_D3D_CAP(hasTiledSafeResourcesAccess); \ + DX12_D3D_CAP(hasTiledMemoryAliasing); \ + DX12_D3D_CAP(hasDLSS); \ + DX12_D3D_CAP(hasXESS); \ + DX12_D3D_CAP(hasDrawID); \ + DX12_D3D_CAP(hasMeshShader); \ + DX12_D3D_CAP(hasBasicViewInstancing); \ + DX12_D3D_CAP(hasOptimizedViewInstancing); \ + DX12_D3D_CAP(hasAcceleratedViewInstancing); \ + DX12_D3D_CAP(hasRenderPassDepthResolve); \ + DX12_D3D_CAP(hasStereoExpansion); \ + DX12_D3D_CAP(hasTileBasedArchitecture); \ + DX12_D3D_CAP(hasLazyMemory); \ + DX12_D3D_CAP(hasIndirectSupport); \ + DX12_D3D_CAP(hasCompareSampler); + +template +class DynamicArray +{ + eastl::unique_ptr ptr; + size_t count = 0; + +public: + DynamicArray() = default; + DynamicArray(const DynamicArray &) = delete; + DynamicArray(DynamicArray &&) = default; + DynamicArray(T *p, size_t sz) : ptr{p}, count{sz} {} + DynamicArray(eastl::unique_ptr &&p, size_t sz) : ptr{eastl::forward>(p)}, count{sz} {} + explicit DynamicArray(size_t sz) : DynamicArray{eastl::make_unique(sz), sz} {} + DynamicArray &operator=(const DynamicArray &) = delete; + DynamicArray &operator=(DynamicArray &&other) + { + eastl::swap(ptr, other.ptr); + eastl::swap(count, other.count); + return *this; + } + + void adopt(T *new_ptr, size_t new_sz) + { + eastl::unique_ptr newPtr{new_ptr}; + eastl::swap(ptr, newPtr); + count = new_sz; + } + + T *release() + { + count = 0; + return ptr.release(); + } + + bool resize(size_t new_size) + { + if (count == new_size) + { + return false; + } + + if (0 == new_size) + { + ptr.reset(); + count = 0; + return true; + } + + auto newBlock = eastl::make_unique(new_size); + if (!newBlock) + { + return false; + } + + for (uint32_t i = 0; i < count; ++i) + { + newBlock[i] = eastl::move(ptr[i]); + } + eastl::swap(ptr, newBlock); + count = new_size; + return true; + } + + T &operator[](size_t i) { return ptr[i]; } + const T &operator[](size_t i) const { return ptr[i]; } + size_t size() const { return count; } + bool empty() const { return !ptr || 0 == count; } + T *data() { return ptr.get(); } + const T *data() const { return ptr.get(); } + eastl::span asSpan() { return {data(), size()}; } + eastl::span asSpan() const { return {data(), size()}; } + eastl::span releaseAsSpan() + { + auto retValue = asSpan(); + release(); + return retValue; + } + static DynamicArray fromSpan(eastl::span span) { return {span.data(), span.size()}; } + T *begin() { return ptr.get(); } + const T *begin() const { return ptr.get(); } + const T *cbegin() const { return begin(); } + T *end() { return begin() + size(); } + const T *end() const { return begin() + size(); } + const T *cend() const { return end(); } +}; + +template +class DerivedSpan +{ + using BytePointerType = typename eastl::conditional::value, const uint8_t *, uint8_t *>::type; + BytePointerType uBase = nullptr; + size_t uSize = 0; + size_t uCount = 0; + BytePointerType atIndex(size_t i) const { return &uBase[i * uSize]; } + +public: + DerivedSpan() = default; + DerivedSpan(const DerivedSpan &) = default; + template + DerivedSpan(U *u_base, size_t u_count) : uBase{reinterpret_cast(u_base)}, uSize{sizeof(U)}, uCount{u_count} + { + static_assert(eastl::is_base_of::value, "U is invalid type"); + } + template + DerivedSpan(const eastl::vector &u_base) : DerivedSpan{u_base.data(), u_base.size()} + {} + class Iterator + { + BytePointerType uBase = nullptr; + size_t uSize = 0; + + public: + Iterator() = default; + Iterator(const Iterator &) = default; + Iterator(BytePointerType u_base, size_t u_size) : uBase{u_base}, uSize{u_size} {} + + friend bool operator==(const Iterator &l, const Iterator &r) { return l.uBase == r.uBase; } + friend bool operator!=(const Iterator &l, const Iterator &r) { return !(l == r); } + + Iterator &operator++() + { + uBase += uSize; + return *this; + } + Iterator operator++(int) const + { + auto other = *this; + ++other; + return other; + } + + Iterator &operator--() + { + uBase -= uSize; + return *this; + } + Iterator operator--(int) const + { + auto other = *this; + --other; + return other; + } + T &operator*() const { return *reinterpret_cast(uBase); } + }; + + Iterator begin() const { return {uBase, uSize}; } + Iterator cbegin() const { return begin(); } + Iterator end() const { return {atIndex(uCount), uSize}; } + Iterator cend() const { return end(); } + size_t size() const { return uCount; } + T *data() const { return reinterpret_cast(uBase); } +}; + +struct DeviceCapsAndShaderModel +{ + // deliberately using base to allow to load all cap values + DeviceDriverCapabilitiesBase caps; + d3d::shadermodel::Version shaderModel; + + bool isCompatibleTo(d3d::shadermodel::Version shader_model) const { return shader_model <= shaderModel; } + bool isCompatibleTo(const DeviceDriverCapabilities &other) const + { + // This is a very simple approach, when a feature of other is requested but not indicated by caps, we are not compatible. +#define DX12_D3D_CAP(name) \ + if (other.name && !caps.name) \ + return false; + DX12_D3D_CAP_SET +#undef DX12_D3D_CAP + return true; + } + bool isCompatibleTo(const Driver3dDesc &desc) const { return isCompatibleTo(desc.shaderModel) && isCompatibleTo(desc.caps); } + static DeviceCapsAndShaderModel fromDriverDesc(const Driver3dDesc &desc) + { + DeviceCapsAndShaderModel result; + result.shaderModel = desc.shaderModel; + // need to do a copy this way to properly copy constants into variables. +#define DX12_D3D_CAP(name) result.caps.name = desc.caps.name; + DX12_D3D_CAP_SET +#undef DX12_D3D_CAP + return result; + } +}; diff --git a/prog/engine/drv/drv3d_DX12/dx12.cpp b/prog/engine/drv/drv3d_DX12/dx12.cpp index 081ad386e..14e63ec71 100644 --- a/prog/engine/drv/drv3d_DX12/dx12.cpp +++ b/prog/engine/drv/drv3d_DX12/dx12.cpp @@ -37,7 +37,6 @@ #include #endif - #if _TARGET_PC_WIN extern "C" { @@ -385,7 +384,7 @@ struct ApiState shaderProgramDatabase.shutdown(ctx); ctx.finish(); - device.shutdown(); + device.shutdown(DeviceCapsAndShaderModel::fromDriverDesc(driverDesc)); deviceName.clear(); @@ -1213,11 +1212,40 @@ static IPoint2 handleAutoResolution(const IPoint2 &target) } #endif +namespace +{ +int on_driver_command_compile_pipeline_set(void *par1) +{ + if (!par1) + { + return 1; + } + auto sets = static_cast(par1); + const char *defaultFormat = sets->defaultFormat ? sets->defaultFormat : "dx12"; + DynamicArray inputLayouts; + if (sets->inputLayoutSet) + { + inputLayouts = + api_state.shaderProgramDatabase.loadInputLayoutFromBlk(api_state.device.getContext(), sets->inputLayoutSet, defaultFormat); + } + DynamicArray renderStates; + if (sets->renderStateSet) + { + renderStates = api_state.device.getRenderStateSystem().loadStaticStatesFromBlk(api_state.device.getContext(), api_state.driverDesc, + sets->renderStateSet, defaultFormat); + } + api_state.device.getContext().compilePipelineSet(sets->featureSet, eastl::move(inputLayouts), eastl::move(renderStates), + sets->outputFormatSet, sets->graphicsPipelineSet, sets->meshPipelineSet, sets->computePipelineSet, defaultFormat); + return 1; +} +} // namespace + int d3d::driver_command(int command, void *par1, void *par2, void *par3) { STORE_RETURN_ADDRESS(); switch (command) { + case DRV3D_COMMAND_COMPILE_PIPELINE_SET: return on_driver_command_compile_pipeline_set(par1); case DRV3D_COMMAND_REMOVE_DEBUG_BREAK_STRING_SEARCH: api_state.device.getContext().removeDebugBreakString({static_cast(par1)}); return 1; diff --git a/prog/engine/drv/drv3d_DX12/jamfile b/prog/engine/drv/drv3d_DX12/jamfile index de78a2c75..61cc38b07 100644 --- a/prog/engine/drv/drv3d_DX12/jamfile +++ b/prog/engine/drv/drv3d_DX12/jamfile @@ -27,6 +27,7 @@ Sources = resource_memory_heap_heap_components.cpp resource_update_buffer.cpp resource_usage_debugger.cpp + pipeline/blk_cache.cpp ; CPPopt = -DINSIDE_DRIVER ; @@ -67,12 +68,6 @@ if $(Platform) in win32 win64 xboxOne scarlett { CPPopt += -FId3d_config.h ; } -if $(Platform) in win64 { - CPPopt += -DUSE_PIX=1 ; - AddLibs += $(Root)/prog/3rdPartyLibs/winpixeventruntime/bin/x64/WinPixEventRuntime.lib ; - AddLibs += delayimp.lib -delayload:WinPixEventRuntime.dll ; -} - if ( $(Platform) in win32 win64 xboxOne scarlett ) { CPPopt += -DUSE_RESOURCE_HEAPS=1 ; } @@ -97,10 +92,16 @@ AddIncludes = $(Root)/prog/gameLibs/publicInclude $(Root)/prog/3rdPartyLibs/d3dx12 $(Root)/prog/3rdPartyLibs/aftermath/2022.2.0.22145/include - $(Root)/prog/3rdPartyLibs/winpixeventruntime/Include $(Root)/prog/3rdPartyLibs/imgui ; +if $(Platform) in win64 && [ GLOB $(Root)/prog/3rdPartyLibs/winpixeventruntime : * ] { + CPPopt += -DUSE_PIX=1 ; + AddLibs += $(Root)/prog/3rdPartyLibs/winpixeventruntime/bin/x64/WinPixEventRuntime.lib ; + AddLibs += delayimp.lib -delayload:WinPixEventRuntime.dll ; + AddIncludes += $(Root)/prog/3rdPartyLibs/winpixeventruntime/Include ; +} + if $(DlssEnabled) = yes && $(Platform) = win64 { Target = $(Target:B) ~dlss ; Target = $(Target:J="") ; diff --git a/prog/engine/drv/drv3d_DX12/pipeline.cpp b/prog/engine/drv/drv3d_DX12/pipeline.cpp index 1c93d7624..cc1d09936 100644 --- a/prog/engine/drv/drv3d_DX12/pipeline.cpp +++ b/prog/engine/drv/drv3d_DX12/pipeline.cpp @@ -1840,7 +1840,8 @@ eastl::unique_ptr PipelineManager::createGraphics(ID3D12Device2 *d return nullptr; } return eastl::make_unique(device, *signature, cache, static_cast(*this), - static_cast(*this), staticRenderStateTable, fbs, vertexShader, pixelShader, on_error, give_name); + static_cast(*this), static_cast(*this), fbs, vertexShader, + pixelShader, on_error, give_name); } void PipelineManager::unloadAll() diff --git a/prog/engine/drv/drv3d_DX12/pipeline.h b/prog/engine/drv/drv3d_DX12/pipeline.h index 56e6cf259..902efb391 100644 --- a/prog/engine/drv/drv3d_DX12/pipeline.h +++ b/prog/engine/drv/drv3d_DX12/pipeline.h @@ -725,6 +725,30 @@ class FramebufferLayoutManager const FramebufferLayout &getLayout(FramebufferLayoutID id) const { return table[id.get()]; } }; +namespace backend +{ +class StaticRenderStateManager +{ +protected: + eastl::vector staticRenderStateTable; + +public: + const RenderStateSystem::StaticState &getStaticRenderState(StaticRenderStateID ident) const + { + return staticRenderStateTable[ident.get()]; + } + StaticRenderStateID findOrAddStaticRenderState(const RenderStateSystem::StaticState &state) + { + auto ref = eastl::find(begin(staticRenderStateTable), end(staticRenderStateTable), state); + if (end(staticRenderStateTable) == ref) + { + ref = staticRenderStateTable.insert(ref, state); + } + return StaticRenderStateID::make(ref - begin(staticRenderStateTable)); + } +}; +} // namespace backend + class BasePipeline { friend class PipelineVariant; @@ -757,6 +781,26 @@ class BasePipeline staticRenderState = srs.get(); } + void moveStaticRenderStateID(StaticRenderStateID from, StaticRenderStateID to) + { + if (from.get() == staticRenderState) + { + setStaticRenderState(to); + } + } + + void swapStaticRenderStateID(StaticRenderStateID a, StaticRenderStateID b) + { + if (a.get() == staticRenderState) + { + setStaticRenderState(b); + } + else if (b.get() == staticRenderState) + { + setStaticRenderState(a); + } + } + void setFrambufferLayout(FramebufferLayoutID fbl) { G_ASSERT(fbl.get() < 0x80000); @@ -827,7 +871,7 @@ class BasePipeline public: BasePipeline(ID3D12Device2 *device, GraphicsPipelineSignature &s, PipelineCache &cache, backend::ShaderModuleManager &shader_bytecodes, backend::InputLayoutManager &input_layouts, - const eastl::vector &static_state_list, FramebufferLayoutManager &framebuffer_layouts, + backend::StaticRenderStateManager &static_states, FramebufferLayoutManager &framebuffer_layouts, backend::VertexShaderModuleRefStore vsm, backend::PixelShaderModuleRefStore psm, RecoverablePipelineCompileBehavior on_error, bool give_name) : program(GraphicsProgramID::Null()), signature(s), vsModule(vsm), psModule(psm) @@ -881,26 +925,13 @@ class BasePipeline RenderStateSystem::StaticState staticState = {}; FramebufferLayout framebufferLayout = {}; auto top = cache.getGraphicsPipelineVariantDesc(cacheId, i, inputLayout, isWireFrame, staticState, framebufferLayout); - auto staticStateListEntry = eastl::find(begin(static_state_list), end(static_state_list), staticState); - if (staticStateListEntry == end(static_state_list)) - { - logerr("DX12: Graphics pipeline cache contains entry with static state that is not in " - "the runtime static state list, removing from cache and skipping"); - debug("DX12: Was looking for %s", staticState.toString()); - for (auto &&e : static_state_list) - { - debug("DX12: %s", e.toString()); - } - cnt = cache.removeGraphicsPipelineVariant(cacheId, i); - continue; - } + auto staticRenderStateID = static_states.findOrAddStaticRenderState(staticState); if (!weAreMesh) { auto layoutID = input_layouts.addInternalLayout(inputLayout); - auto &variant = getVariantFromConfiguration(layoutID, - StaticRenderStateID{static_cast(staticStateListEntry - begin(static_state_list))}, + auto &variant = getVariantFromConfiguration(layoutID, staticRenderStateID, framebuffer_layouts.getLayoutID(framebufferLayout), top, isWireFrame); if (!variant.load(device, shader_bytecodes, *this, cache, inputLayout, isWireFrame, staticState, framebufferLayout, top, on_error, give_name)) @@ -912,8 +943,7 @@ class BasePipeline else { auto &variant = - getMeshVariantFromConfiguration(StaticRenderStateID{static_cast(staticStateListEntry - begin(static_state_list))}, - framebuffer_layouts.getLayoutID(framebufferLayout), isWireFrame); + getMeshVariantFromConfiguration(staticRenderStateID, framebuffer_layouts.getLayoutID(framebufferLayout), isWireFrame); if (!variant.loadMesh(device, shader_bytecodes, *this, cache, isWireFrame, staticState, framebufferLayout, on_error, give_name)) { @@ -994,6 +1024,26 @@ class BasePipeline G_ASSERT(!isMesh()); return vsModule.header.header.inOutSemanticMask; } + bool matches(const backend::VertexShaderModuleRefStore &vs, const backend::PixelShaderModuleRefStore &ps) const + { + return vsModule.header.hash == vs.header.hash && psModule.header.hash == ps.header.hash; + } + + void moveStaticRenderStateID(StaticRenderStateID from, StaticRenderStateID to) + { + for (auto &variant : variants) + { + variant.moveStaticRenderStateID(from, to); + } + } + + void swapStaticRenderStateID(StaticRenderStateID a, StaticRenderStateID b) + { + for (auto &variant : variants) + { + variant.swapStaticRenderStateID(a, b); + } + } }; class ComputePipeline @@ -1159,10 +1209,28 @@ class RaytracePipeline }; #endif -class PipelineManager : public backend::ShaderModuleManager, protected backend::InputLayoutManager +struct GraphicsPipelinePreloadInfo +{ + BasePipelineIdentifier base; + DynamicArray variants; +}; + +struct MeshPipelinePreloadInfo +{ + BasePipelineIdentifier base; + DynamicArray variants; +}; + +struct ComputePipelinePreloadInfo +{ + ComputePipelineIdentifier base; +}; + +class PipelineManager : public backend::ShaderModuleManager, + protected backend::InputLayoutManager, + public backend::StaticRenderStateManager { eastl::vector> graphicsPipelines[max_scripted_shaders_bin_groups]; - eastl::vector staticRenderStateTable; eastl::vector> computePipelines[max_scripted_shaders_bin_groups]; eastl::vector> graphicsSignatures; #if !_TARGET_XBOXONE @@ -1280,21 +1348,67 @@ class PipelineManager : public backend::ShaderModuleManager, protected backend:: void preRecovery(); + // TODO this needs to be here for now to allow access to pipelines to patch the ids. void registerStaticRenderState(StaticRenderStateID ident, const RenderStateSystem::StaticState &state) { if (ident.get() == staticRenderStateTable.size()) { staticRenderStateTable.push_back(state); } - else + else if (ident.get() > staticRenderStateTable.size()) { fatal("DX12: registerStaticRenderState was called with ident of %u but table has %u entries", ident.get(), staticRenderStateTable.size()); } + else if (staticRenderStateTable[ident.get()] != state) + { + debug("DX12: need to patch render state %u", ident.get()); + auto ref = eastl::find(begin(staticRenderStateTable) + ident.get() + 1, end(staticRenderStateTable), state); + if (end(staticRenderStateTable) == ref) + { + auto moveID = StaticRenderStateID::make(staticRenderStateTable.size()); + debug("DX12: moving existing render state to %u", moveID.get()); + staticRenderStateTable.push_back(staticRenderStateTable[ident.get()]); + staticRenderStateTable[ident.get()] = state; + for (auto &group : graphicsPipelines) + { + for (auto &pipeline : group) + { + if (pipeline) + { + pipeline->moveStaticRenderStateID(ident, moveID); + } + } + } + for (auto &pipeline : preloadedGraphicsPipelines) + { + pipeline.pipeline->moveStaticRenderStateID(ident, moveID); + } + } + else + { + auto swapID = StaticRenderStateID::make(ref - begin(staticRenderStateTable)); + debug("DX12: swapping existing render state with %u", swapID.get()); + staticRenderStateTable[swapID.get()] = staticRenderStateTable[ident.get()]; + staticRenderStateTable[ident.get()] = state; + for (auto &group : graphicsPipelines) + { + for (auto &pipeline : group) + { + if (pipeline) + { + pipeline->swapStaticRenderStateID(ident, swapID); + } + } + } + for (auto &pipeline : preloadedGraphicsPipelines) + { + pipeline.pipeline->swapStaticRenderStateID(ident, swapID); + } + } + } } - const RenderStateSystem::StaticState &getStaticRenderState(StaticRenderStateID ident) { return staticRenderStateTable[ident.get()]; } - using backend::InputLayoutManager::getInputLayout; using backend::InputLayoutManager::registerInputLayout; using backend::InputLayoutManager::remapInputLayout; @@ -1313,13 +1427,13 @@ class PipelineManager : public backend::ShaderModuleManager, protected backend:: uint16_t compressionIndex; }; eastl::vector computeProgramIndexToDumpShaderIndex[max_scripted_shaders_bin_groups]; + eastl::vector> pixelShaderComputeProgramIDMap[max_scripted_shaders_bin_groups]; struct ScriptedShaderBinDumpInspector { uint32_t group = 0; ShaderID nullPixelShader; PipelineManager *target = nullptr; ScriptedShadersBinDumpOwner *owner = nullptr; - eastl::vector> pixelShaderComputeProgramIDMap; uint32_t pixelShaderCount = 0; uint32_t computeShaderCount = 0; ID3D12Device2 *device = nullptr; @@ -1337,7 +1451,7 @@ class PipelineManager : public backend::ShaderModuleManager, protected backend:: target->setVertexShaderCompressionGroup(group, i, hash, map.groupId, map.indexInGroup); } } - void pixelOrComputeShaderCount(uint32_t count) { pixelShaderComputeProgramIDMap.resize(count); }; + void pixelOrComputeShaderCount(uint32_t count) { target->pixelShaderComputeProgramIDMap[group].resize(count); }; void preloadGraphicsPipeline(ShaderID vsID, ShaderID psID) { @@ -1366,7 +1480,7 @@ class PipelineManager : public backend::ShaderModuleManager, protected backend:: void addGraphicsProgram(uint16_t vs_index, uint16_t ps_index) { ShaderID psID; - if (auto shader = eastl::get_if(&pixelShaderComputeProgramIDMap[ps_index])) + if (auto shader = eastl::get_if(&target->pixelShaderComputeProgramIDMap[group][ps_index])) { psID = *shader; } @@ -1379,7 +1493,7 @@ class PipelineManager : public backend::ShaderModuleManager, protected backend:: auto id = pixelShaderCount++; target->setPixelShaderCompressionGroup(group, id, hash, map.groupId, map.indexInGroup); psID = ShaderID::make(group, id); - pixelShaderComputeProgramIDMap[ps_index] = psID; + target->pixelShaderComputeProgramIDMap[group][ps_index] = psID; } auto vsID = ShaderID::make(group, vs_index); preloadGraphicsPipeline(vsID, psID); @@ -1392,12 +1506,12 @@ class PipelineManager : public backend::ShaderModuleManager, protected backend:: } void addComputeProgram(uint32_t shader_index) { - if (eastl::holds_alternative(pixelShaderComputeProgramIDMap[shader_index])) + if (eastl::holds_alternative(target->pixelShaderComputeProgramIDMap[group][shader_index])) { return; } auto id = ProgramID::asComputeProgram(group, target->computeProgramIndexToDumpShaderIndex[group].size()); - pixelShaderComputeProgramIDMap[shader_index] = id; + target->pixelShaderComputeProgramIDMap[group][shader_index] = id; auto dump = owner->getDump(); auto &map = dump->shGroupsMapping[dump->vprId.size() + shader_index]; ShaderCompressionIndex compressionIndex; @@ -1474,6 +1588,266 @@ class PipelineManager : public backend::ShaderModuleManager, protected backend:: addCompute(device, cache, program, eastl::move(basicModule), on_error, give_name); } + + BasePipeline *findLoadedPipeline(const backend::VertexShaderModuleRefStore &vs, const backend::PixelShaderModuleRefStore &ps) + { + for (auto &group : graphicsPipelines) + { + for (auto &pipeline : group) + { + if (!pipeline) + { + continue; + } + if (pipeline->matches(vs, ps)) + { + return pipeline.get(); + } + } + } + return nullptr; + } + + void compileGraphicsPipelineSet(ID3D12Device2 *device, PipelineCache &pipeline_cache, FramebufferLayoutManager &fbs, + const DynamicArray &input_layouts, const DynamicArray &static_render_states, + const DynamicArray &framebuffer_layouts, const DynamicArray &graphics_pipelines) + { + for (auto &pipeline : graphics_pipelines) + { + debug("DX12: precomiling graphics pipeline..."); + + char hashString[1 + 2 * sizeof(dxil::HashValue)]; + pipeline.base.vs.convertToString(hashString, array_size(hashString)); + debug("DX12: Looking for VS %s...", hashString); + auto vsID = findVertexShader(pipeline.base.vs); + if (ShaderID::Null() == vsID) + { + debug("DX12: ...shader not found"); + continue; + } + pipeline.base.ps.convertToString(hashString, array_size(hashString)); + debug("DX12: Looking for PS %s...", hashString); + auto psID = findPixelShader(pipeline.base.ps); + if (ShaderID::Null() == psID) + { + debug("DX12: ...shader not found"); + continue; + } + debug("DX12: looking for existing pipeline..."); + BasePipeline *pipelineBase = nullptr; + for (auto &preloadInfo : preloadedGraphicsPipelines) + { + if ((vsID != preloadInfo.vsID) || (psID != preloadInfo.psID)) + { + continue; + } + debug("DX12: ...found in preloadedGraphicsPipelines"); + pipelineBase = preloadInfo.pipeline.get(); + break; + } + if (!pipelineBase) + { + auto vs = getVertexShader(vsID); + auto ps = getPixelShader(psID); + pipelineBase = findLoadedPipeline(vs, ps); + + if (!pipelineBase) + { + auto &preloadedPipeline = preloadedGraphicsPipelines.emplace_back(); + preloadedPipeline.vsID = vsID; + preloadedPipeline.psID = psID; + preloadedPipeline.pipeline = + createGraphics(device, pipeline_cache, fbs, vs, ps, RecoverablePipelineCompileBehavior::REPORT_ERROR, true); + pipelineBase = preloadedPipeline.pipeline.get(); + debug("DX12: ...none found, creating new..."); + } + else + { + debug("DX12: ...found loaded pipeline"); + } + } + if (!pipelineBase) + { + debug("DX12: ...failed"); + continue; + } + debug("DX12: ...loading variants..."); + for (auto &variant : pipeline.variants) + { + if ((variant.inputLayoutIndex >= input_layouts.size()) || (variant.framebufferLayoutIndex >= framebuffer_layouts.size()) || + (variant.staticRenderStateIndex >= static_render_states.size())) + { + debug("DX12: ...invalid state index, ignoring pipeline variant..."); + continue; + } + if (StaticRenderStateID::Null() == static_render_states[variant.staticRenderStateIndex]) + { + debug("DX12: ...unsupported render state, ignoring pipeline variant..."); + continue; + } + debug("DX12: ...resolving input layout and output layout..."); + auto inputLayout = remapInputLayout(input_layouts[variant.inputLayoutIndex], pipelineBase->getVertexShaderInputMask()); + debug("DX12: ...resolving frame buffer layout..."); + auto fbLayout = fbs.getLayoutID(framebuffer_layouts[variant.framebufferLayoutIndex]); + debug("DX12: ...compiling variant..."); + pipelineBase->getVariantFromConfiguration(inputLayout, static_render_states[variant.staticRenderStateIndex], fbLayout, + variant.topology, 0 != variant.isWireFrame); + } + debug("DX12: ...completed"); + } + } + + void compileMeshPipelineSet(ID3D12Device2 *device, PipelineCache &pipeline_cache, FramebufferLayoutManager &fbs, + const DynamicArray &static_render_states, const DynamicArray &framebuffer_layouts, + const DynamicArray &mesh_pipelines) + { + for (auto &pipeline : mesh_pipelines) + { + debug("DX12: precomiling mesh pipeline..."); + + char hashString[1 + 2 * sizeof(dxil::HashValue)]; + pipeline.base.vs.convertToString(hashString, array_size(hashString)); + debug("DX12: Looking for VS %s...", hashString); + auto vsID = findVertexShader(pipeline.base.vs); + if (ShaderID::Null() == vsID) + { + debug("DX12: ...shader not found"); + continue; + } + pipeline.base.ps.convertToString(hashString, array_size(hashString)); + debug("DX12: Looking for PS %s...", hashString); + auto psID = findPixelShader(pipeline.base.ps); + if (ShaderID::Null() == psID) + { + debug("DX12: ...shader not found"); + continue; + } + debug("DX12: looking for existing pipeline..."); + BasePipeline *pipelineBase = nullptr; + for (auto &preloadInfo : preloadedGraphicsPipelines) + { + if ((vsID != preloadInfo.vsID) || (psID != preloadInfo.psID)) + { + continue; + } + debug("DX12: ...found in preloadedGraphicsPipelines"); + pipelineBase = preloadInfo.pipeline.get(); + break; + } + if (!pipelineBase) + { + auto vs = getVertexShader(vsID); + auto ps = getPixelShader(psID); + pipelineBase = findLoadedPipeline(vs, ps); + + if (!pipelineBase) + { + auto &preloadedPipeline = preloadedGraphicsPipelines.emplace_back(); + preloadedPipeline.vsID = vsID; + preloadedPipeline.psID = psID; + preloadedPipeline.pipeline = + createGraphics(device, pipeline_cache, fbs, vs, ps, RecoverablePipelineCompileBehavior::REPORT_ERROR, true); + pipelineBase = preloadedPipeline.pipeline.get(); + debug("DX12: ...none found, creating new..."); + } + else + { + debug("DX12: ...found loaded pipeline"); + } + } + if (!pipelineBase) + { + debug("DX12: ...failed"); + continue; + } + debug("DX12: ...loading variants..."); + for (auto &variant : pipeline.variants) + { + if ((variant.framebufferLayoutIndex >= framebuffer_layouts.size()) || + (variant.staticRenderStateIndex >= static_render_states.size())) + { + debug("DX12: ...invalid state index, ignoring pipeline variant..."); + continue; + } + if (StaticRenderStateID::Null() == static_render_states[variant.staticRenderStateIndex]) + { + debug("DX12: ...unsupported render state, ignoring pipeline variant..."); + continue; + } + debug("DX12: ...resolving frame buffer layout..."); + auto fbLayout = fbs.getLayoutID(framebuffer_layouts[variant.framebufferLayoutIndex]); + debug("DX12: ...compiling variant..."); + pipelineBase->getMeshVariantFromConfiguration(static_render_states[variant.staticRenderStateIndex], fbLayout, + 0 != variant.isWireFrame); + } + debug("DX12: ...completed"); + } + } + + void compileComputePipelineSet(ID3D12Device2 *device, PipelineCache &pipeline_cache, + const DynamicArray &compute_pipelines) + { + for (auto &pipeline : compute_pipelines) + { + debug("DX12: precomiling compute pipeline..."); + char hashString[1 + 2 * sizeof(dxil::HashValue)]; + pipeline.base.hash.convertToString(hashString, array_size(hashString)); + debug("DX12: Looking for CS %s...", hashString); + bool found = false; + enumerateShaderFromHash(pipeline.base.hash, [device, &pipeline_cache, &found, this](auto gi, auto si, auto vs_count) { + // has collision with a vs?! + if (si < vs_count) + { + return true; + } + auto &mapping = pixelShaderComputeProgramIDMap[gi]; + auto shaderIndex = si - vs_count; + // mapping table incomplete?! + if (shaderIndex >= mapping.size()) + { + return true; + } + // has collision with a ps?! + auto program = eastl::get_if(&mapping[shaderIndex]); + if (!program) + { + return true; + } + auto progId = *program; + auto &progGroup = computePipelines[progId.getGroup()]; + if (progId.getIndex() < progGroup.size() && progGroup[progId.getIndex()]) + { + debug("DX12: ...already loaded..."); + // already loaded, so we are done + found = true; + return false; + } + debug("DX12: ...loading..."); + loadComputeShaderFromDump(device, pipeline_cache, progId, RecoverablePipelineCompileBehavior::REPORT_ERROR, true); + found = true; + return false; + }); + if (found) + { + debug("DX12: ...completed"); + } + else + { + debug("DX12: ...not found"); + } + } + } + + void compilePipelineSet(ID3D12Device2 *device, PipelineCache &pipeline_cache, FramebufferLayoutManager &fbs, + DynamicArray &&input_layouts, DynamicArray &&static_render_states, + DynamicArray &&framebuffer_layouts, DynamicArray &&graphics_pipelines, + DynamicArray &&mesh_pipelines, DynamicArray &&compute_pipelines) + { + compileGraphicsPipelineSet(device, pipeline_cache, fbs, input_layouts, static_render_states, framebuffer_layouts, + graphics_pipelines); + compileMeshPipelineSet(device, pipeline_cache, fbs, static_render_states, framebuffer_layouts, mesh_pipelines); + compileComputePipelineSet(device, pipeline_cache, compute_pipelines); + } }; diff --git a/prog/engine/drv/drv3d_DX12/pipeline/blk_cache.cpp b/prog/engine/drv/drv3d_DX12/pipeline/blk_cache.cpp new file mode 100644 index 000000000..bef58e5ca --- /dev/null +++ b/prog/engine/drv/drv3d_DX12/pipeline/blk_cache.cpp @@ -0,0 +1,514 @@ +#include "device.h" + +using namespace drv3d_dx12; + +bool drv3d_dx12::pipeline::InputLayoutDeEncoder::decodeDX12(const DataBlock &blk, InputLayout &target) const +{ + if (auto vertexAttributeSetBlk = blk.getBlockByName("vertexAttributeSet")) + { + target.vertexAttributeSet.locationMask = vertexAttributeSetBlk->getInt("locationMask", 0); + target.vertexAttributeSet.locationSourceStream = vertexAttributeSetBlk->getInt64("locationSourceStream", 0); + auto count = min(MAX_SEMANTIC_INDEX, vertexAttributeSetBlk->blockCount()); + for (uint32_t locationIndex = 0, locationBlockIndex = 0; locationIndex < MAX_SEMANTIC_INDEX && locationBlockIndex < count; + ++locationIndex) + { + if (0 == (target.vertexAttributeSet.locationMask & (1u << locationIndex))) + { + continue; + } + + auto compactedFormatAndOffset = vertexAttributeSetBlk->getBlock(locationBlockIndex++); + if (compactedFormatAndOffset->paramExists("compactedFormatAndOffset")) + { + target.vertexAttributeSet.compactedFormatAndOffset[locationIndex] = + compactedFormatAndOffset->getInt("compactedFormatAndOffset", 0); + } + else + { + if (compactedFormatAndOffset->paramExists("offset")) + { + target.vertexAttributeSet.setLocationStreamOffset(locationIndex, compactedFormatAndOffset->getInt("offset", 0)); + } + if (compactedFormatAndOffset->paramExists("formatIndex")) + { + target.vertexAttributeSet.setLocationFormatIndex(locationIndex, compactedFormatAndOffset->getInt("formatIndex", 0)); + } + } + } + } + if (auto imputStreamSetBlk = blk.getBlockByName("inputStreamSet")) + { + target.inputStreamSet.usageMask = imputStreamSetBlk->getInt("usageMask", 0); + target.inputStreamSet.stepRateMask = imputStreamSetBlk->getInt("stepRateMask", 0); + } + return true; +} + +bool drv3d_dx12::pipeline::InputLayoutDeEncoder::decodeEngine(const DataBlock &blk, InputLayout &target) const +{ + InputLayout::DecodeContext ctx; + uint32_t pc = blk.paramCount(); + for (uint32_t i = 0; i < pc; ++i) + { + if (!target.fromVdecl(ctx, blk.getInt(i))) + { + break; + } + } + return true; +} + +bool drv3d_dx12::pipeline::InputLayoutDeEncoder::decode(const DataBlock &blk, InputLayout &target) const +{ + if (0 == strcmp("dx12", blk.getStr("fmt", defaultFormat))) + { + return decodeDX12(blk, target); + } + return decodeEngine(blk, target); +} + +bool drv3d_dx12::pipeline::InputLayoutDeEncoder::encode(DataBlock &blk, const InputLayout &source) const +{ + constexpr bool use_combined_format = false; + auto vertexAttributeSetBlk = blk.addNewBlock("vertexAttributeSet"); + auto imputStreamSetBlk = blk.addNewBlock("inputStreamSet"); + if (!vertexAttributeSetBlk || !imputStreamSetBlk) + { + return false; + } + vertexAttributeSetBlk->setInt("locationMask", source.vertexAttributeSet.locationMask); + vertexAttributeSetBlk->setInt64("locationSourceStream", source.vertexAttributeSet.locationSourceStream); + for (uint32_t locationIndex = 0; locationIndex < MAX_SEMANTIC_INDEX; ++locationIndex) + { + if (0 == (source.vertexAttributeSet.locationMask & (1u << locationIndex))) + { + continue; + } + + char blockName[32]; + sprintf_s(blockName, "l_%x", (1u << locationIndex)); + auto compactedFormatAndOffset = vertexAttributeSetBlk->addNewBlock(blockName); + if (!compactedFormatAndOffset) + { + return false; + } + if (use_combined_format) + { + compactedFormatAndOffset->setInt("compactedFormatAndOffset", source.vertexAttributeSet.compactedFormatAndOffset[locationIndex]); + } + else + { + compactedFormatAndOffset->setInt("offset", source.vertexAttributeSet.getLocationStreamOffset(locationIndex)); + compactedFormatAndOffset->setInt("formatIndex", source.vertexAttributeSet.getLocationFormatIndex(locationIndex)); + } + } + imputStreamSetBlk->setInt("usageMask", source.inputStreamSet.usageMask); + imputStreamSetBlk->setInt("stepRateMask", source.inputStreamSet.stepRateMask); + return true; +} + +bool drv3d_dx12::pipeline::RenderStateDeEncoder::decodeDX12(const DataBlock &blk, RenderStateSystem::StaticState &target) const +{ + target.enableDepthTest = blk.getBool("enableDepthTest", target.enableDepthTest); + target.enableDepthWrite = blk.getBool("enableDepthWrite", target.enableDepthWrite); + target.enableDepthClip = blk.getBool("enableDepthClip", target.enableDepthClip); + target.enableDepthBounds = blk.getBool("enableDepthBounds", target.enableDepthBounds); + target.enableStencil = blk.getBool("enableStencil", target.enableStencil); + target.enableIndependentBlend = blk.getBool("enableIndependentBlend", target.enableIndependentBlend); + target.enableAlphaToCoverage = blk.getBool("enableAlphaToCoverage", target.enableAlphaToCoverage); + target.depthFunc = blk.getInt("depthFunc", target.depthFunc); + target.forcedSampleCountShift = blk.getInt("forcedSampleCountShift", target.forcedSampleCountShift); + target.enableConservativeRaster = blk.getBool("enableConservativeRaster", target.enableConservativeRaster); + target.viewInstanceCount = blk.getInt("viewInstanceCount", target.viewInstanceCount); + target.cullMode = blk.getInt("cullMode", target.cullMode); + target.stencilReadMask = blk.getInt("stencilReadMask", target.stencilReadMask); + target.stencilWriteMask = blk.getInt("stencilWriteMask", target.stencilWriteMask); + target.stencilFunction = blk.getInt("stencilFunction", target.stencilFunction); + target.stencilOnFail = blk.getInt("stencilOnFail", target.stencilOnFail); + target.stencilOnDepthFail = blk.getInt("stencilOnDepthFail", target.stencilOnDepthFail); + target.stencilOnPass = blk.getInt("stencilOnPass", target.stencilOnPass); + target.colorWriteMask = blk.getInt("colorWriteMask", target.colorWriteMask); + target.depthBias = blk.getReal("depthBias", target.depthBias); + target.depthBiasSloped = blk.getReal("depthBiasSloped", target.depthBiasSloped); + if (auto blendParamsBlk = blk.getBlockByName("blendParams")) + { + auto blendParamsBlkCount = min(blendParamsBlk->blockCount(), shaders::RenderState::NumIndependentBlendParameters); + for (uint32_t bbi = 0; bbi < blendParamsBlkCount; ++bbi) + { + auto blendBlk = blendParamsBlk->getBlock(bbi); + if (!blendBlk) + { + continue; + } + auto ¶m = target.blendParams[bbi]; + + param.blendFactors.Source = blendBlk->getInt("blendFactorsSource", param.blendFactors.Source); + param.blendFactors.Destination = blendBlk->getInt("blendFactorsDestination", param.blendFactors.Destination); + + param.blendAlphaFactors.Source = blendBlk->getInt("blendAlphaFactorsSource", param.blendAlphaFactors.Source); + param.blendAlphaFactors.Destination = blendBlk->getInt("blendAlphaFactorsDestination", param.blendAlphaFactors.Destination); + + param.blendFunction = blendBlk->getInt("blendFunction", param.blendFunction); + param.blendAlphaFunction = blendBlk->getInt("blendAlphaFunction", param.blendAlphaFunction); + param.enableBlending = blendBlk->getBool("enableBlending", param.enableBlending); + } + } + return true; +} + +bool drv3d_dx12::pipeline::RenderStateDeEncoder::decodeEngine(const DataBlock &blk, shaders::RenderState &target) const +{ + target.zwrite = blk.getBool("zwrite", target.zwrite); + target.ztest = blk.getBool("ztest", target.ztest); + target.zFunc = blk.getInt("zFunc", target.zFunc); + target.stencilRef = blk.getInt("stencilRef", target.stencilRef); + target.cull = blk.getInt("cull", target.cull); + // optional + target.depthBoundsEnable = blk.getBool("depthBoundsEnable", target.depthBoundsEnable); + target.forcedSampleCount = blk.getInt("forcedSampleCount", target.forcedSampleCount); + // optional + target.conservativeRaster = blk.getBool("conservativeRaster", target.conservativeRaster); + target.zClip = blk.getBool("zClip", target.zClip); + target.scissorEnabled = blk.getBool("scissorEnabled", target.scissorEnabled); + target.independentBlendEnabled = blk.getBool("independentBlendEnabled", target.independentBlendEnabled); + target.alphaToCoverage = blk.getBool("alphaToCoverage", target.alphaToCoverage); + target.viewInstanceCount = blk.getInt("viewInstanceCount", target.viewInstanceCount); + target.colorWr = blk.getInt("colorWr", target.colorWr); + target.zBias = blk.getReal("zBias", target.zBias); + target.slopeZBias = blk.getReal("slopeZBias", target.slopeZBias); + if (auto stencilBlk = blk.getBlockByName("stencil")) + { + target.stencil.func = stencilBlk->getInt("func", target.stencil.func); + target.stencil.fail = stencilBlk->getInt("fail", target.stencil.fail); + target.stencil.zFail = stencilBlk->getInt("zFail", target.stencil.zFail); + target.stencil.pass = stencilBlk->getInt("pass", target.stencil.pass); + target.stencil.readMask = stencilBlk->getInt("readMask", target.stencil.readMask); + target.stencil.writeMask = stencilBlk->getInt("writeMask", target.stencil.writeMask); + } + if (auto blendParamsBlk = blk.getBlockByName("blendParams")) + { + auto blendParamsBlkCount = min(blendParamsBlk->blockCount(), shaders::RenderState::NumIndependentBlendParameters); + for (uint32_t bbi = 0; bbi < blendParamsBlkCount; ++bbi) + { + auto blendBlk = blendParamsBlk->getBlock(bbi); + if (!blendBlk) + { + continue; + } + auto ¶m = target.blendParams[bbi]; + + param.ablendFactors.src = blendBlk->getInt("ablendFactorsSrc", param.ablendFactors.src); + param.ablendFactors.dst = blendBlk->getInt("ablendFactorsDst", param.ablendFactors.dst); + + param.sepablendFactors.src = blendBlk->getInt("sepablendFactorsSrc", param.sepablendFactors.src); + param.sepablendFactors.dst = blendBlk->getInt("sepablendFactorsDst", param.sepablendFactors.dst); + + param.blendOp = blendBlk->getInt("blendOp", param.blendOp); + param.sepablendOp = blendBlk->getInt("sepablendOp", param.sepablendOp); + param.ablend = blendBlk->getBool("ablend", param.ablend); + param.sepablend = blendBlk->getBool("sepablend", param.sepablend); + } + } + return true; +} + +bool drv3d_dx12::pipeline::RenderStateDeEncoder::decode(const DataBlock &blk, RenderStateSystem::StaticState &target) const +{ + if (0 == strcmp("dx12", blk.getStr("fmt", defaultFormat))) + { + return decodeDX12(blk, target); + } + + shaders::RenderState engineValue; + if (!decodeEngine(blk, engineValue)) + { + return false; + } + target = RenderStateSystem::StaticState::fromRenderState(engineValue); + return true; +} + +bool drv3d_dx12::pipeline::RenderStateDeEncoder::encode(DataBlock &blk, const RenderStateSystem::StaticState &source) const +{ + auto blendParamsBlk = blk.addNewBlock("blendParams"); + if (!blendParamsBlk) + { + return false; + } + blk.setBool("enableDepthTest", source.enableDepthTest); + blk.setBool("enableDepthWrite", source.enableDepthWrite); + blk.setBool("enableDepthClip", source.enableDepthClip); + blk.setBool("enableDepthBounds", source.enableDepthBounds); + blk.setBool("enableStencil", source.enableStencil); + blk.setBool("enableIndependentBlend", source.enableIndependentBlend); + blk.setBool("enableAlphaToCoverage", source.enableAlphaToCoverage); + blk.setInt("depthFunc", source.depthFunc); + blk.setInt("forcedSampleCountShift", source.forcedSampleCountShift); + blk.setBool("enableConservativeRaster", source.enableConservativeRaster); + blk.setInt("viewInstanceCount", source.viewInstanceCount); + blk.setInt("cullMode", source.cullMode); + blk.setInt("stencilReadMask", source.stencilReadMask); + blk.setInt("stencilWriteMask", source.stencilWriteMask); + blk.setInt("stencilFunction", source.stencilFunction); + blk.setInt("stencilOnFail", source.stencilOnFail); + blk.setInt("stencilOnDepthFail", source.stencilOnDepthFail); + blk.setInt("stencilOnPass", source.stencilOnPass); + blk.setInt("colorWriteMask", source.colorWriteMask); + blk.setReal("depthBias", source.depthBias); + blk.setReal("depthBiasSloped", source.depthBiasSloped); + + auto hasIndipendentBlend = source.enableIndependentBlend; + auto blendCount = hasIndipendentBlend ? shaders::RenderState::NumIndependentBlendParameters : 1; + char buf[32]; + for (uint32_t bbi = 0; bbi < blendCount; ++bbi) + { + sprintf_s(buf, "bp_%u", bbi); + auto blendBlk = blendParamsBlk->addNewBlock(buf); + if (!blendBlk) + { + return false; + } + auto ¶m = source.blendParams[bbi]; + + blendBlk->setInt("blendFactorsSource", param.blendFactors.Source); + blendBlk->setInt("blendFactorsDestination", param.blendFactors.Destination); + + blendBlk->setInt("blendAlphaFactorsSource", param.blendAlphaFactors.Source); + blendBlk->setInt("blendAlphaFactorsDestination", param.blendAlphaFactors.Destination); + + blendBlk->setInt("blendFunction", param.blendFunction); + blendBlk->setInt("blendAlphaFunction", param.blendAlphaFunction); + blendBlk->setBool("enableBlending", param.enableBlending); + } + return true; +} + +bool drv3d_dx12::pipeline::FramebufferLayoutDeEncoder::decodeDX12(const DataBlock &blk, FramebufferLayout &target) const +{ + auto formatNameId = blk.getNameId("colorFormats"); + if ((-1 != formatNameId) && blk.paramExists(formatNameId)) + { + uint8_t targetMask = blk.getInt("colorTargetMask", 0xFF); + int lastParamIndex = blk.findParam(formatNameId); + while (lastParamIndex != -1) + { + FormatStore fmt(blk.getInt(lastParamIndex)); + for (uint32_t i = 0; i < Driver3dRenderTarget::MAX_SIMRT; ++i) + { + auto bit = 1u << i; + if (0 == (bit & targetMask)) + { + continue; + } + target.colorTargetMask |= bit; + targetMask ^= bit; + target.colorFormats[i] = fmt; + } + + lastParamIndex = blk.findParam(formatNameId, lastParamIndex); + } + } + if (blk.paramExists("depthStencilFormat")) + { + target.hasDepth = 1; + target.depthStencilFormat = FormatStore(blk.getInt("depthStencilFormat", 0)); + } + return true; +} + +bool drv3d_dx12::pipeline::FramebufferLayoutDeEncoder::decodeEngine(const DataBlock &blk, FramebufferLayout &target) const +{ + auto formatNameId = blk.getNameId("colorFormats"); + if ((-1 != formatNameId) && blk.paramExists(formatNameId)) + { + uint8_t targetMask = blk.getInt("colorTargetMask", 0xFF); + int lastParamIndex = blk.findParam(formatNameId); + while (lastParamIndex != -1) + { + auto fmt = FormatStore::fromCreateFlags(blk.getInt(lastParamIndex)); + for (uint32_t i = 0; i < Driver3dRenderTarget::MAX_SIMRT; ++i) + { + auto bit = 1u << i; + if (0 == (bit & targetMask)) + { + continue; + } + target.colorTargetMask |= bit; + targetMask ^= bit; + target.colorFormats[i] = fmt; + } + + lastParamIndex = blk.findParam(formatNameId, lastParamIndex); + } + } + if (blk.paramExists("depthStencilFormat")) + { + target.hasDepth = 1; + target.depthStencilFormat = FormatStore::fromCreateFlags(blk.getInt("depthStencilFormat", 0)); + } + return true; +} + +bool drv3d_dx12::pipeline::FramebufferLayoutDeEncoder::decode(const DataBlock &blk, FramebufferLayout &target) const +{ + if (0 == strcmp("dx12", blk.getStr("fmt", defaultFormat))) + { + return decodeDX12(blk, target); + } + return decodeEngine(blk, target); +} + +bool drv3d_dx12::pipeline::FramebufferLayoutDeEncoder::encode(DataBlock &blk, const FramebufferLayout &source) const +{ + if (source.colorTargetMask) + { + // TODO only needed when there are holes in the mask + blk.setInt("colorTargetMask", source.colorTargetMask); + for (uint32_t i = 0; i < Driver3dRenderTarget::MAX_SIMRT; ++i) + { + if (0 == (source.colorTargetMask & (1u << i))) + { + continue; + } + blk.addInt("colorFormats", source.colorFormats[i].wrapper.value); + } + } + if (source.hasDepth) + { + blk.setInt("depthStencilFormat", source.depthStencilFormat.wrapper.value); + } + return true; +} + +bool drv3d_dx12::pipeline::DeviceCapsAndShaderModelDeEncoder::decode(const DataBlock &blk, DeviceCapsAndShaderModel &target) const +{ + target.shaderModel.major = blk.getInt("shaderModelMajor", target.shaderModel.major); + target.shaderModel.major = blk.getInt("shaderModelMinor", target.shaderModel.minor); +#define DX12_D3D_CAP(name) target.caps.name = blk.getBool(#name, target.caps.name); + DX12_D3D_CAP_SET +#undef DX12_D3D_CAP + return true; +} + +bool drv3d_dx12::pipeline::DeviceCapsAndShaderModelDeEncoder::encode(DataBlock &blk, const DeviceCapsAndShaderModel &source) const +{ + blk.setInt("shaderModelMajor", source.shaderModel.major); + blk.setInt("shaderModelMinor", source.shaderModel.minor); +#define DX12_D3D_CAP(name) blk.setBool(#name, source.caps.name); + DX12_D3D_CAP_SET +#undef DX12_D3D_CAP + return true; +} + +bool drv3d_dx12::pipeline::FeatureSupportResolver::decode(const DataBlock &blk, bool &target) const +{ + DeviceCapsAndShaderModel compare{}; + if (!this->DeviceCapsAndShaderModelDeEncoder::decode(blk, compare)) + { + return false; + } + target = compare.isCompatibleTo(features); + return true; +} + +bool drv3d_dx12::pipeline::GraphicsPipelineVariantDeEncoder::decode(const DataBlock &blk, GraphicsPipelineVariantState &target) const +{ + if (blk.paramExists("featureSet") && featureSet) + { + auto fi = blk.getInt("featureSet", 0); + // when index is out of range, we assume unsupported + if (fi > featureSetCount) + { + return false; + } + if (!featureSet[fi]) + { + return false; + } + } + if (!blk.paramExists("renderState") || !blk.paramExists("outputFormat") || !blk.paramExists("inputLayout") || + !blk.paramExists("primitiveTopology")) + { + return false; + } + target.staticRenderStateIndex = blk.getInt("renderState", 0); + target.framebufferLayoutIndex = blk.getInt("outputFormat", 0); + target.inputLayoutIndex = blk.getInt("inputLayout", 0); + target.isWireFrame = blk.getBool("wireFrame", false); + target.topology = static_cast(blk.getInt("primitiveTopology", 0)); + return true; +} + +bool drv3d_dx12::pipeline::GraphicsPipelineVariantDeEncoder::encode(DataBlock &blk, const GraphicsPipelineVariantState &source) const +{ + blk.setInt("renderState", source.staticRenderStateIndex); + blk.setInt("outputFormat", source.framebufferLayoutIndex); + blk.setInt("inputLayout", source.inputLayoutIndex); + blk.setBool("wireFrame", 0 != source.isWireFrame); + blk.setInt("primitiveTopology", static_cast(source.topology)); + return true; +} + +bool drv3d_dx12::pipeline::MeshPipelineVariantDeEncoder::decode(const DataBlock &blk, MeshPipelineVariantState &target) const +{ + if (blk.paramExists("featureSet") && featureSet) + { + auto fi = blk.getInt("featureSet", 0); + // when index is out of range, we assume unsupported + if (fi > featureSetCount) + { + return false; + } + if (!featureSet[fi]) + { + return false; + } + } + if (!blk.paramExists("renderState") || !blk.paramExists("outputFormat")) + { + return false; + } + target.staticRenderStateIndex = blk.getInt("renderState", 0); + target.framebufferLayoutIndex = blk.getInt("outputFormat", 0); + target.isWireFrame = blk.getBool("wireFrame", false); + return true; +} + +bool drv3d_dx12::pipeline::MeshPipelineVariantDeEncoder::encode(DataBlock &blk, const MeshPipelineVariantState &source) const +{ + blk.setInt("renderState", source.staticRenderStateIndex); + blk.setInt("outputFormat", source.framebufferLayoutIndex); + blk.setBool("wireFrame", 0 != source.isWireFrame); + return true; +} + +bool drv3d_dx12::pipeline::ComputePipelineDeEncoder::decode(const DataBlock &blk, ComputePipelineIdentifier &target) const +{ + if (blk.paramExists("featureSet") && featureSet) + { + auto fi = blk.getInt("featureSet", 0); + // when index is out of range, we assume unsupported + if (fi > featureSetCount) + { + return false; + } + if (!featureSet[fi]) + { + return false; + } + } + auto hash = blk.getStr("hash", nullptr); + if (!hash) + { + return false; + } + target.hash = dxil::HashValue::fromString(hash); + return true; +} + +bool drv3d_dx12::pipeline::ComputePipelineDeEncoder::encode(DataBlock &blk, const ComputePipelineIdentifier &source) const +{ + ComputePipelineIdentifierHashSet set = source; + blk.setStr("hash", set.hash); + return true; +} diff --git a/prog/engine/drv/drv3d_DX12/pipeline/blk_cache.h b/prog/engine/drv/drv3d_DX12/pipeline/blk_cache.h new file mode 100644 index 000000000..5d7610d53 --- /dev/null +++ b/prog/engine/drv/drv3d_DX12/pipeline/blk_cache.h @@ -0,0 +1,420 @@ +#pragma once + +namespace drv3d_dx12 +{ +struct GraphicsPipelineVariantSet +{ + const BasePipelineIdentifier &ident; + DerivedSpan variants; +}; + +struct MeshPipelineVariantSet +{ + const BasePipelineIdentifier &ident; + DerivedSpan variants; +}; + +namespace pipeline +{ +template +class DataBlockDecodeEnumarator : private Decoder +{ + const DataBlock █ + uint32_t blockIndex = 0; + +public: + DataBlockDecodeEnumarator(const DataBlock &blk, uint32_t start) : block{blk}, blockIndex{start} {} + template + DataBlockDecodeEnumarator(const DataBlock &blk, uint32_t start, Ts &&...ts) : + block{blk}, blockIndex{start}, Decoder{eastl::forward(ts)...} + {} + + template + bool invoke(T &&target) const + { + if (completed()) + { + return false; + } + auto blk = block.getBlock(blockIndex); + if (!blk) + { + return false; + } + return this->Decoder::invoke(*blk, eastl::forward(target)); + } + template + bool decode(Ts &...targets) const + { + if (completed()) + { + return false; + } + auto blk = block.getBlock(blockIndex); + if (!blk) + { + return false; + } + return this->Decoder::decode(*blk, targets...); + } + + bool next() + { + if (!completed()) + { + ++blockIndex; + } + return completed(); + } + + bool completed() const { return blockIndex >= block.blockCount(); } + uint32_t index() const { return blockIndex; } + uint32_t remaining() const { return block.blockCount() - blockIndex; } +}; + +template +class DataBlockEncodeVisitor : Encoder +{ + using BlockNameType = typename Encoder::BlockNameType; + DataBlock █ + +public: + template + DataBlockEncodeVisitor(DataBlock &blk, Ts &&...ts) : block{blk}, Encoder{eastl::forward(ts)...} + {} + template + bool encode(Ts &&...ts) + { + BlockNameType blockName; + this->Encoder::formatBlockName(blockName, block.blockCount()); + DataBlock *newBlock = block.addNewBlock(blockName); + if (!newBlock) + { + return false; + } + if (!this->Encoder::encode(*newBlock, eastl::forward(ts)...)) + { + block.removeBlock(block.blockCount() - 1); + return true; + } + + return true; + } + uint32_t count() const { return block.blockCount(); } +}; + +template +class DefaltInvokeDecoder +{ +public: + template + bool invoke(const DataBlock &blk, T target) const + { + R out; + if (!static_cast(this)->decode(blk, out)) + { + return false; + } + return target(out); + } +}; + +class FormatedDecoder +{ +protected: + const char *defaultFormat = "dx12"; + +public: + FormatedDecoder() = default; + FormatedDecoder(const char *fmt) : defaultFormat{fmt} {} + FormatedDecoder(const FormatedDecoder &) = default; +}; + +template +struct EncoderBlockNameStore +{ + using BlockNameType = char[N]; + + void formatBlockName(BlockNameType &target, uint32_t index) { sprintf_s(target, D::blockFormat, index); } +}; + +class InputLayoutDeEncoder : FormatedDecoder, + public DefaltInvokeDecoder, + public EncoderBlockNameStore +{ + bool decodeDX12(const DataBlock &blk, InputLayout &target) const; + bool decodeEngine(const DataBlock &blk, InputLayout &target) const; + +public: + static inline const char *blockFormat = "il_%u"; + + using FormatedDecoder::FormatedDecoder; + + bool decode(const DataBlock &blk, InputLayout &target) const; + bool encode(DataBlock &blk, const InputLayout &source) const; +}; + +using InputLayoutDecoder = InputLayoutDeEncoder; +using InputLayoutEncoder = InputLayoutDeEncoder; + +class RenderStateDeEncoder : FormatedDecoder, + public DefaltInvokeDecoder, + public EncoderBlockNameStore +{ + bool decodeDX12(const DataBlock &blk, RenderStateSystem::StaticState &target) const; + bool decodeEngine(const DataBlock &blk, shaders::RenderState &target) const; + +public: + static inline const char *blockFormat = "rs_%u"; + + using FormatedDecoder::FormatedDecoder; + + bool decode(const DataBlock &blk, RenderStateSystem::StaticState &target) const; + bool encode(DataBlock &blk, const RenderStateSystem::StaticState &source) const; +}; + +using RenderStateDecoder = RenderStateDeEncoder; +using RenderStateEncoder = RenderStateDeEncoder; + +class FramebufferLayoutDeEncoder : FormatedDecoder, + public DefaltInvokeDecoder, + public EncoderBlockNameStore +{ + bool decodeDX12(const DataBlock &blk, FramebufferLayout &target) const; + bool decodeEngine(const DataBlock &blk, FramebufferLayout &target) const; + +public: + static inline const char *blockFormat = "fb_%u"; + + using FormatedDecoder::FormatedDecoder; + + bool decode(const DataBlock &blk, FramebufferLayout &target) const; + bool encode(DataBlock &blk, const FramebufferLayout &source) const; +}; + +using FramebufferLayoutDecoder = FramebufferLayoutDeEncoder; +using FramebufferLayoutEncoder = FramebufferLayoutDeEncoder; + +class DeviceCapsAndShaderModelDeEncoder : public DefaltInvokeDecoder, + public EncoderBlockNameStore +{ +public: + static inline const char *blockFormat = "fc_%u"; + + bool decode(const DataBlock &blk, DeviceCapsAndShaderModel &target) const; + bool encode(DataBlock &blk, const DeviceCapsAndShaderModel &source) const; +}; + +using DeviceCapsAndShaderModelDecoder = DeviceCapsAndShaderModelDeEncoder; +using DeviceCapsAndShaderModelEncoder = DeviceCapsAndShaderModelDeEncoder; + +// Checks if the decoded features and shader model are supported by the stored features and shader model. +class FeatureSupportResolver : private DeviceCapsAndShaderModelDecoder, public DefaltInvokeDecoder +{ + const Driver3dDesc &features; + +public: + FeatureSupportResolver(const Driver3dDesc &f) : features{f} {} + + bool decode(const DataBlock &blk, bool &target) const; +}; + +using DeviceCapsAndShaderModelDecoder = DeviceCapsAndShaderModelDeEncoder; +using DeviceCapsAndShaderModelEncoder = DeviceCapsAndShaderModelDeEncoder; + +class GraphicsPipelineVariantDeEncoder : public EncoderBlockNameStore +{ + bool *featureSet = nullptr; + uint32_t featureSetCount = 0; + +public: + static inline const char *blockFormat = "v_%u"; + + GraphicsPipelineVariantDeEncoder(bool *feature_set, uint32_t feature_set_count) : + featureSet{feature_set}, featureSetCount{feature_set_count} + {} + template + bool invoke(const DataBlock &blk, T target) const + { + GraphicsPipelineVariantState out; + if (!decode(blk, out)) + { + return false; + } + return target(out); + } + bool decode(const DataBlock &blk, GraphicsPipelineVariantState &target) const; + bool encode(DataBlock &blk, const GraphicsPipelineVariantState &source) const; +}; + +using GraphicsPipelineVariantDecoder = GraphicsPipelineVariantDeEncoder; +using GraphicsPipelineVariantEncoder = GraphicsPipelineVariantDeEncoder; + +class GraphicsPipelineDeEncoder : public EncoderBlockNameStore +{ + bool *featureSet = nullptr; + uint32_t featureSetCount = 0; + +public: + static inline const char *blockFormat = "gp_%u"; + + GraphicsPipelineDeEncoder(bool *feature_set, uint32_t feature_set_count) : + featureSet{feature_set}, featureSetCount{feature_set_count} + {} + template + bool invoke(const DataBlock &blk, T target) const + { + BasePipelineIdentifier base; + DynamicArray vars; + if (!decode(blk, base, vars)) + { + return false; + } + return target(base, vars); + } + template + bool decode(const DataBlock &blk, BasePipelineIdentifier &base, VC &variants) const + { + auto vertexHash = blk.getStr("vertexHash", nullptr); + auto pixelHash = blk.getStr("pixelHash", nullptr); + if (!vertexHash || !pixelHash) + { + return false; + } + + base.vs = dxil::HashValue::fromString(vertexHash); + base.ps = dxil::HashValue::fromString(pixelHash); + + DataBlockDecodeEnumarator enumerator{blk, 0, featureSet, featureSetCount}; + variants.resize(enumerator.remaining()); + uint32_t enumerated = 0; + for (; !enumerator.completed(); enumerator.next()) + { + if (enumerator.decode(variants[enumerated])) + { + ++enumerated; + } + } + variants.resize(enumerated); + return enumerated > 0; + } + template + bool encode(DataBlock &blk, const BasePipelineIdentifier &base, const VC &variants) const + { + BasePipelineIdentifierHashSet hashSet = base; + blk.setStr("vertexHash", hashSet.vsHash); + blk.setStr("pixelHash", hashSet.psHash); + DataBlockEncodeVisitor visitor{blk, featureSet, featureSetCount}; + for (auto &variant : variants) + { + visitor.encode(variant); + } + return true; + } +}; + +using GraphicsPipelineDecoder = GraphicsPipelineDeEncoder; +using GraphicsPipelineEncoder = GraphicsPipelineDeEncoder; + +class MeshPipelineVariantDeEncoder : public DefaltInvokeDecoder, + public EncoderBlockNameStore +{ + bool *featureSet = nullptr; + uint32_t featureSetCount = 0; + +public: + static inline const char *blockFormat = "v_%u"; + + MeshPipelineVariantDeEncoder() = default; + MeshPipelineVariantDeEncoder(bool *feature_set, uint32_t feature_set_count) : + featureSet{feature_set}, featureSetCount{feature_set_count} + {} + bool decode(const DataBlock &blk, MeshPipelineVariantState &target) const; + bool encode(DataBlock &blk, const MeshPipelineVariantState &source) const; +}; + +using MeshPipelineVariantDecoder = MeshPipelineVariantDeEncoder; +using MeshPipelineVariantEncoder = MeshPipelineVariantDeEncoder; + +class MeshPipelineDeEncoder : public EncoderBlockNameStore +{ + bool *featureSet = nullptr; + uint32_t featureSetCount = 0; + +public: + static inline const char *blockFormat = "mp_%u"; + + MeshPipelineDeEncoder(bool *feature_set, uint32_t feature_set_count) : featureSet{feature_set}, featureSetCount{feature_set_count} {} + template + bool invoke(const DataBlock &blk, T target) const + { + BasePipelineIdentifier base; + DynamicArray vars; + if (!decode(blk, base, vars)) + { + return false; + } + return target(base, vars); + } + template + bool decode(const DataBlock &blk, BasePipelineIdentifier &base, VC &variants) const + { + auto meshHash = blk.getStr("meshHash", nullptr); + auto pixelHash = blk.getStr("pixelHash", nullptr); + if (!meshHash || !pixelHash) + { + return false; + } + + base.vs = dxil::HashValue::fromString(meshHash); + base.ps = dxil::HashValue::fromString(pixelHash); + + DataBlockDecodeEnumarator enumerator{blk, 0, featureSet, featureSetCount}; + variants.resize(enumerator.remaining()); + uint32_t enumerated = 0; + for (; !enumerator.completed(); enumerator.next()) + { + if (enumerator.decode(variants[enumerated])) + { + ++enumerated; + } + } + variants.resize(enumerated); + return enumerated > 0; + } + template + bool encode(DataBlock &blk, const BasePipelineIdentifier &base, const VC &variants) const + { + BasePipelineIdentifierHashSet hashSet = base; + blk.setStr("meshHash", hashSet.vsHash); + blk.setStr("pixelHash", hashSet.psHash); + DataBlockEncodeVisitor visitor{blk, featureSet, featureSetCount}; + for (auto &variant : variants) + { + visitor.encode(variant); + } + return true; + } +}; + +using MeshPipelineDecoder = MeshPipelineDeEncoder; +using MeshPipelineEncoder = MeshPipelineDeEncoder; + +class ComputePipelineDeEncoder : public DefaltInvokeDecoder, + public EncoderBlockNameStore +{ + bool *featureSet = nullptr; + uint32_t featureSetCount = 0; + +public: + static inline const char *blockFormat = "cp_%u"; + ComputePipelineDeEncoder(bool *feature_set, uint32_t feature_set_count) : featureSet{feature_set}, featureSetCount{feature_set_count} + {} + bool decode(const DataBlock &blk, ComputePipelineIdentifier &target) const; + bool encode(DataBlock &blk, const ComputePipelineIdentifier &target) const; +}; + +using ComputePipelineDecoder = ComputePipelineDeEncoder; +using ComputePipelineEncoder = ComputePipelineDeEncoder; +} // namespace pipeline +} // namespace drv3d_dx12 \ No newline at end of file diff --git a/prog/engine/drv/drv3d_DX12/pipeline_cache.cpp b/prog/engine/drv/drv3d_DX12/pipeline_cache.cpp index 6be30461e..d7c80b827 100644 --- a/prog/engine/drv/drv3d_DX12/pipeline_cache.cpp +++ b/prog/engine/drv/drv3d_DX12/pipeline_cache.cpp @@ -50,7 +50,7 @@ enum CacheFileFlags }; constexpr uint32_t CACHE_FILE_MAGIC = _MAKE4C('CX12'); -constexpr uint32_t CACHE_FILE_VERSION = 21; +constexpr uint32_t CACHE_FILE_VERSION = 22; constexpr uint32_t EXPECTED_POINTER_SIZE = static_cast(sizeof(void *)); // Version history: // 1 - initial @@ -76,6 +76,7 @@ constexpr uint32_t EXPECTED_POINTER_SIZE = static_cast(sizeof(void *)) // 20 - independent blending support // 21 - BasePipelineIdentifier only has hashes for vs and ps. Dropped hashes for gs, hs and ds as its no longer used. // Also changes pipeline library names. +// 22 - GraphicsPipeline::VariantCacheEntry changed } // namespace void PipelineCache::init(const SetupParameters ¶ms) @@ -128,6 +129,88 @@ void PipelineCache::shutdown(const ShutdownParameters ¶ms) graphicsMeshSignatures.clear(); }); + if ((hasChanged || params.alwaysGenerateBlks) && params.generateBlks) + { + DataBlock cacheOutBlock; + if (auto inputLayoutOutBlock = cacheOutBlock.addNewBlock("input_layouts")) + { + pipeline::DataBlockEncodeVisitor visitor{*inputLayoutOutBlock}; + for (auto &layout : inputLayouts) + { + visitor.encode(layout); + } + } + + if (auto renderStateOutBlock = cacheOutBlock.addNewBlock("render_states")) + { + pipeline::DataBlockEncodeVisitor visitor{*renderStateOutBlock}; + for (auto &state : staticRenderStates) + { + visitor.encode(state); + } + } + + if (auto framebufferLayoutOutBlock = cacheOutBlock.addNewBlock("framebuffer_layouts")) + { + pipeline::DataBlockEncodeVisitor visitor{*framebufferLayoutOutBlock}; + for (auto &layout : framebufferLayouts) + { + visitor.encode(layout); + } + } + + if (auto graphicsPipelinesOutBlock = cacheOutBlock.addNewBlock("graphics_pipelines")) + { + pipeline::DataBlockEncodeVisitor visitor{*graphicsPipelinesOutBlock, nullptr, 0}; + for (auto &pipeline : graphicsCache) + { + if (pipeline.variantCache.empty()) + { + continue; + } + if (D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED == pipeline.variantCache.front().topology) + { + continue; + } + visitor.encode(pipeline.ident, pipeline.variantCache); + } + } + + if (auto meshPipelinesOutBlock = cacheOutBlock.addNewBlock("mesh_pipelines")) + { + pipeline::DataBlockEncodeVisitor visitor{*meshPipelinesOutBlock, nullptr, 0}; + for (auto &pipeline : graphicsCache) + { + if (pipeline.variantCache.empty()) + { + continue; + } + if (D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED != pipeline.variantCache.front().topology) + { + continue; + } + visitor.encode(pipeline.ident, pipeline.variantCache); + } + } + + if (auto computePipelinesOutBlock = cacheOutBlock.addNewBlock("compute_pipelines")) + { + pipeline::DataBlockEncodeVisitor visitor{*computePipelinesOutBlock, nullptr, 0}; + for (auto &pipeline : computeBlobs) + { + visitor.encode(pipeline); + } + } + + if (auto feeaturesOutBlock = cacheOutBlock.addNewBlock("features")) + { + pipeline::DataBlockEncodeVisitor visitor{*feeaturesOutBlock}; + visitor.encode(params.features); + } + + cacheOutBlock.saveToTextFile("cache/dx12_cache.blk"); + } + if (!hasChanged) return; diff --git a/prog/engine/drv/drv3d_DX12/pipeline_cache.h b/prog/engine/drv/drv3d_DX12/pipeline_cache.h index 4a03991fa..ae4a27c0e 100644 --- a/prog/engine/drv/drv3d_DX12/pipeline_cache.h +++ b/prog/engine/drv/drv3d_DX12/pipeline_cache.h @@ -47,6 +47,60 @@ inline bool operator==(const FramebufferLayout &l, const FramebufferLayout &r) inline bool operator!=(const FramebufferLayout &l, const FramebufferLayout &r) { return !(l == r); } +struct BasePipelineIdentifierHashSet +{ + char vsHash[1 + 2 * sizeof(dxil::HashValue)]{}; + char psHash[1 + 2 * sizeof(dxil::HashValue)]{}; +}; + +struct BasePipelineIdentifier +{ + dxil::HashValue vs; + dxil::HashValue ps; + + operator BasePipelineIdentifierHashSet() const + { + BasePipelineIdentifierHashSet set; + vs.convertToString(set.vsHash, sizeof(set.vsHash)); + ps.convertToString(set.psHash, sizeof(set.psHash)); + return set; + } +}; + +inline bool operator==(const BasePipelineIdentifier &l, const BasePipelineIdentifier &r) { return l.vs == r.vs && l.ps == r.ps; } +inline bool operator!=(const BasePipelineIdentifier &l, const BasePipelineIdentifier &r) { return !(l == r); } + +struct MeshPipelineVariantState +{ + uint32_t framebufferLayoutIndex; + uint32_t staticRenderStateIndex; + // using u32 for predictable size and the option to turn this into a flag field + uint32_t isWireFrame; +}; + +struct GraphicsPipelineVariantState : MeshPipelineVariantState +{ + D3D12_PRIMITIVE_TOPOLOGY_TYPE topology; + uint32_t inputLayoutIndex; +}; + +struct ComputePipelineIdentifierHashSet +{ + char hash[1 + 2 * sizeof(dxil::HashValue)]{}; +}; + +struct ComputePipelineIdentifier +{ + dxil::HashValue hash; + + operator ComputePipelineIdentifierHashSet() const + { + ComputePipelineIdentifierHashSet set; + hash.convertToString(set.hash, sizeof(set.hash)); + return set; + } +}; + struct RootSignatureStageLayout { uint8_t rootConstantsParamIndex = 0; @@ -518,14 +572,7 @@ typedef TaggedHandle GraphicsPipe class PipelineCache { public: - struct BasePipelineIdentifier - { - dxil::HashValue vs; - dxil::HashValue ps; - - bool operator==(const BasePipelineIdentifier &o) const { return o.vs == vs && o.ps == ps; } - bool operator!=(const BasePipelineIdentifier &o) const { return !(*this == o); } - }; + using BasePipelineIdentifier = ::drv3d_dx12::BasePipelineIdentifier; struct ShutdownParameters { @@ -540,6 +587,9 @@ class PipelineCache #else static constexpr bool rootSignaturesUsesCBVDescriptorRanges = false; #endif + bool generateBlks; + bool alwaysGenerateBlks; + DeviceCapsAndShaderModel features; }; struct SetupParameters : ShutdownParameters @@ -702,14 +752,8 @@ class PipelineCache struct GraphicsPipeline { BasePipelineIdentifier ident; - struct VariantCacheEntry - { - D3D12_PRIMITIVE_TOPOLOGY_TYPE topology; - uint32_t framebufferLayoutIndex; - uint32_t staticRenderStateIndex; - uint32_t inputLayoutIndex; - // using u32 for predictable size and the option to turn this into a flag field - uint32_t isWireFrame; + struct VariantCacheEntry : GraphicsPipelineVariantState + { eastl::vector blob; }; eastl::vector variantCache; @@ -777,9 +821,8 @@ class PipelineCache } }; - struct ComputeBlob + struct ComputeBlob : ComputePipelineIdentifier { - dxil::HashValue hash; eastl::vector blob; }; diff --git a/prog/engine/drv/drv3d_DX12/render_state.h b/prog/engine/drv/drv3d_DX12/render_state.h index a6ef71625..cf50b7cfa 100644 --- a/prog/engine/drv/drv3d_DX12/render_state.h +++ b/prog/engine/drv/drv3d_DX12/render_state.h @@ -1,5 +1,7 @@ #pragma once +#include + #define MINIMUM_REPRESENTABLE_D32 3e-10 #define MINIMUM_REPRESENTABLE_D24 33e-8 #define MINIMUM_REPRESENTABLE_D16 2e-5 @@ -28,6 +30,11 @@ class PipelineManager; class RenderStateSystem { public: + struct DynamicState + { + uint32_t stencilRef : 8; + uint32_t enableScissor : 1; + }; struct StaticStateBits { // first 32 bits @@ -138,6 +145,7 @@ class RenderStateSystem 0 == memcmp(l.blendParams, r.blendParams, blendBytesToCompare) && l.depthBias == r.depthBias && l.depthBiasSloped == r.depthBiasSloped; } + friend bool operator!=(const StaticState &l, const StaticState &r) { return !(l == r); } static StaticState fromRenderState(const shaders::RenderState &def) { StaticState result = {}; @@ -261,6 +269,15 @@ class RenderStateSystem return result; } + shaders::RenderState toRenderState(const DynamicState &dynamic_state) const + { + shaders::RenderState result; + // TODO + result.stencilRef = dynamic_state.stencilRef; + result.scissorEnabled = dynamic_state.enableScissor ? 1 : 0; + return result; + } + static bool has_uniform_color_mask(uint32_t mask) { // checks if all sets of 4 bits are equal @@ -418,11 +435,6 @@ class RenderStateSystem return mask; } }; - struct DynamicState - { - uint32_t stencilRef : 8; - uint32_t enableScissor : 1; - }; void reset() { @@ -430,7 +442,6 @@ class RenderStateSystem publicStateTable.clear(); staticStateTable.clear(); } - void loadFromCache(PipelineCache &cache, PipelineManager &pipe_man); struct PublicStateBasicInfo { @@ -461,6 +472,22 @@ class RenderStateSystem return e.second; } + static bool is_compatible(const Driver3dDesc &desc, const StaticState &state) + { + if (state.enableDepthBounds) + { + return desc.caps.hasDepthBoundsTest; + } + if (state.enableConservativeRaster) + { + return desc.caps.hasConservativeRassterization; + } + return true; + } + + DynamicArray loadStaticStatesFromBlk(DeviceContext &ctx, const Driver3dDesc &desc, const DataBlock *blk, + const char *default_format); + private: // 'smart' compare of two RenderStates, it skips modes for functionality that is turned off static bool renderStateCompare(const shaders::RenderState &l, const shaders::RenderState &r) @@ -534,7 +561,11 @@ class RenderStateSystem return result; } - StaticRenderStateID registerStaticState(DeviceContext &ctx, const shaders::RenderState &def); + StaticRenderStateID registerStaticState(DeviceContext &ctx, const StaticState &def); + StaticRenderStateID registerStaticState(DeviceContext &ctx, const shaders::RenderState &def) + { + return registerStaticState(ctx, StaticState::fromRenderState(def)); + } OSSpinlock mutex; eastl::vector staticStateTable; eastl::vector> publicStateTable; diff --git a/prog/engine/drv/drv3d_DX12/shader.cpp b/prog/engine/drv/drv3d_DX12/shader.cpp index bdf494cee..362f99721 100644 --- a/prog/engine/drv/drv3d_DX12/shader.cpp +++ b/prog/engine/drv/drv3d_DX12/shader.cpp @@ -33,80 +33,85 @@ using namespace drv3d_dx12; #endif #undef g_main -void InputLayout::fromVdecl(const VSDTYPE *decl) +bool InputLayout::fromVdecl(DecodeContext &context, const VSDTYPE &decl) { - const VSDTYPE *__restrict vt = decl; - inputStreamSet = VertexStreamsDesc{}; - vertexAttributeSet = VertexAttributesDesc{}; - uint32_t ofs = 0; - uint32_t streamIndex = 0; + if (VSD_END == decl) + { + return false; + } - for (; *vt != VSD_END; ++vt) + const auto op = decl & VSDOP_MASK; + if (op == VSDOP_INPUT) { - if ((*vt & VSDOP_MASK) == VSDOP_INPUT) + if (decl & VSD_SKIPFLG) { - if (*vt & VSD_SKIPFLG) - { - ofs += GET_VSDSKIP(*vt) * 4; - continue; - } + context.ofs += GET_VSDSKIP(decl) * 4; + return true; + } - uint32_t locationIndex = GET_VSDREG(*vt); - vertexAttributeSet.useLocation(locationIndex); - vertexAttributeSet.setLocationStreamSource(locationIndex, streamIndex); - vertexAttributeSet.setLocationStreamOffset(locationIndex, ofs); - vertexAttributeSet.setLocationFormatIndex(locationIndex, *vt & VSDT_MASK); + const auto data = decl & VSDT_MASK; - uint32_t sz = 0; // size of entry - //-V::1037 - switch (*vt & VSDT_MASK) - { - case VSDT_FLOAT1: sz = 32; break; - case VSDT_FLOAT2: sz = 32 + 32; break; - case VSDT_FLOAT3: sz = 32 + 32 + 32; break; - case VSDT_FLOAT4: sz = 32 + 32 + 32 + 32; break; - case VSDT_INT1: sz = 32; break; - case VSDT_INT2: sz = 32 + 32; break; - case VSDT_INT3: sz = 32 + 32 + 32; break; - case VSDT_INT4: sz = 32 + 32 + 32 + 32; break; - case VSDT_UINT1: sz = 32; break; - case VSDT_UINT2: sz = 32 + 32; break; - case VSDT_UINT3: sz = 32 + 32 + 32; break; - case VSDT_UINT4: sz = 32 + 32 + 32 + 32; break; - case VSDT_HALF2: sz = 16 + 16; break; - case VSDT_SHORT2N: sz = 16 + 16; break; - case VSDT_SHORT2: sz = 16 + 16; break; - case VSDT_USHORT2N: sz = 16 + 16; break; - - case VSDT_HALF4: sz = 16 + 16 + 16 + 16; break; - case VSDT_SHORT4N: sz = 16 + 16 + 16 + 16; break; - case VSDT_SHORT4: sz = 16 + 16 + 16 + 16; break; - case VSDT_USHORT4N: sz = 16 + 16 + 16 + 16; break; - - case VSDT_UDEC3: sz = 10 + 10 + 10 + 2; break; - case VSDT_DEC3N: sz = 10 + 10 + 10 + 2; break; - - case VSDT_E3DCOLOR: sz = 8 + 8 + 8 + 8; break; - case VSDT_UBYTE4: sz = 8 + 8 + 8 + 8; break; - default: G_ASSERTF(false, "invalid vertex declaration type"); break; - } - ofs += sz / 8; + uint32_t locationIndex = GET_VSDREG(decl); + vertexAttributeSet.useLocation(locationIndex); + vertexAttributeSet.setLocationStreamSource(locationIndex, context.streamIndex); + vertexAttributeSet.setLocationStreamOffset(locationIndex, context.ofs); + vertexAttributeSet.setLocationFormatIndex(locationIndex, data); + + uint32_t sz = 0; // size of entry + //-V::1037 + switch (data) + { + case VSDT_FLOAT1: sz = 32; break; + case VSDT_FLOAT2: sz = 32 + 32; break; + case VSDT_FLOAT3: sz = 32 + 32 + 32; break; + case VSDT_FLOAT4: sz = 32 + 32 + 32 + 32; break; + case VSDT_INT1: sz = 32; break; + case VSDT_INT2: sz = 32 + 32; break; + case VSDT_INT3: sz = 32 + 32 + 32; break; + case VSDT_INT4: sz = 32 + 32 + 32 + 32; break; + case VSDT_UINT1: sz = 32; break; + case VSDT_UINT2: sz = 32 + 32; break; + case VSDT_UINT3: sz = 32 + 32 + 32; break; + case VSDT_UINT4: sz = 32 + 32 + 32 + 32; break; + case VSDT_HALF2: sz = 16 + 16; break; + case VSDT_SHORT2N: sz = 16 + 16; break; + case VSDT_SHORT2: sz = 16 + 16; break; + case VSDT_USHORT2N: sz = 16 + 16; break; + + case VSDT_HALF4: sz = 16 + 16 + 16 + 16; break; + case VSDT_SHORT4N: sz = 16 + 16 + 16 + 16; break; + case VSDT_SHORT4: sz = 16 + 16 + 16 + 16; break; + case VSDT_USHORT4N: sz = 16 + 16 + 16 + 16; break; + + case VSDT_UDEC3: sz = 10 + 10 + 10 + 2; break; + case VSDT_DEC3N: sz = 10 + 10 + 10 + 2; break; + + case VSDT_E3DCOLOR: sz = 8 + 8 + 8 + 8; break; + case VSDT_UBYTE4: sz = 8 + 8 + 8 + 8; break; + default: G_ASSERTF_RETURN(false, false, "invalid vertex declaration type 0x%08X", data); break; } - else if ((*vt & VSDOP_MASK) == VSDOP_STREAM) + context.ofs += sz / 8; + } + else if (op == VSDOP_STREAM) + { + context.streamIndex = GET_VSDSTREAM(decl); + context.ofs = 0; + inputStreamSet.useStream(context.streamIndex); + if (decl & VSDS_PER_INSTANCE_DATA) { - streamIndex = GET_VSDSTREAM(*vt); - ofs = 0; - inputStreamSet.useStream(streamIndex); - if (*vt & VSDS_PER_INSTANCE_DATA) - inputStreamSet.setStreamStepRate(streamIndex, D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA); - else - inputStreamSet.setStreamStepRate(streamIndex, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA); + inputStreamSet.setStreamStepRate(context.streamIndex, D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA); } else { - G_ASSERTF(0, "Invalid vsd opcode 0x%08X", *vt); + inputStreamSet.setStreamStepRate(context.streamIndex, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA); } } + else + { + G_ASSERTF_RETURN(0, false, "Invalid vsd opcode 0x%08X", decl); + } + + return true; } StageShaderModule drv3d_dx12::shader_layout_to_module(const bindump::Mapper *layout) @@ -842,6 +847,25 @@ void ShaderProgramDatabase::getBindumpShader(DeviceContext &ctx, uint32_t index, } } +DynamicArray ShaderProgramDatabase::loadInputLayoutFromBlk(DeviceContext &ctx, const DataBlock *blk, + const char *default_format) +{ + DynamicArray result{blk->blockCount()}; + pipeline::DataBlockDecodeEnumarator decoder{*blk, 0, default_format}; + for (; !decoder.completed(); decoder.next()) + { + auto bi = decoder.index(); + if (!decoder.invoke([bi, &result, this, &ctx](auto &layout) { + result[bi] = this->registerInputLayout(ctx, layout); + return true; + })) + { + result[bi] = InputLayoutID::Null(); + } + } + return result; +} + void backend::ShaderModuleManager::addVertexShader(ShaderID id, VertexShaderModule *module) { eastl::unique_ptr modulePtr{module}; diff --git a/prog/engine/drv/drv3d_DX12/shader.h b/prog/engine/drv/drv3d_DX12/shader.h index b6a7dab04..4a59352e6 100644 --- a/prog/engine/drv/drv3d_DX12/shader.h +++ b/prog/engine/drv/drv3d_DX12/shader.h @@ -204,7 +204,22 @@ struct InputLayout VertexAttributesDesc vertexAttributeSet; VertexStreamsDesc inputStreamSet; - void fromVdecl(const VSDTYPE *decl); + struct DecodeContext + { + uint32_t ofs = 0; + uint32_t streamIndex = 0; + }; + + void fromVdecl(const VSDTYPE *decl) + { + inputStreamSet = VertexStreamsDesc{}; + vertexAttributeSet = VertexAttributesDesc{}; + DecodeContext context{}; + + while (fromVdecl(context, *decl++)) + ; + } + bool fromVdecl(DecodeContext &context, const VSDTYPE &decl); }; inline bool operator==(const InputLayout::VertexAttributesDesc &l, const InputLayout::VertexAttributesDesc &r) @@ -560,6 +575,8 @@ class ShaderProgramGroup pixelShaderComputeProgramIDMap.clear(); graphicsProgramTemplates.clear(); vertexShaderCount = 0; + pixelShaderCount = 0; + computeShaderCount = 0; } void setup(const ShaderProgramGroup *base, ScriptedShadersBinDumpOwner *d, ShaderID null_pixel_shader) @@ -1092,7 +1109,20 @@ class ShaderProgramGroups { groups[index - 1].setup(groups.data(), dump, null_pixel_shader); } - void dropGroup(uint32_t index) { groups[index - 1].clear(); } + void dropGroup(uint32_t index) + { + groups[index - 1].clear(); + for (auto &inst : graphicsProgramInstances) + { + if (inst.internalProgram.getGroup() == index) + { + inst.deleteAllReferences(); + removeInstanceFromHashmap(&inst - begin(graphicsProgramInstances)); + } + } + // tidy up the hash map + removeAllDeads(); + } dxil::ShaderStage shaderFromIndex(uint32_t group_index, uint32_t shader_index, ShaderCodeType type, void *ident) { return groups[group_index - 1].shaderFromIndex(groups.data(), shader_index, type, ident); @@ -1278,6 +1308,7 @@ class ShaderProgramDatabase #endif void registerShaderBinDump(DeviceContext &ctx, ScriptedShadersBinDumpOwner *dump); void getBindumpShader(DeviceContext &ctx, uint32_t index, ShaderCodeType type, void *ident); + DynamicArray loadInputLayoutFromBlk(DeviceContext &ctx, const DataBlock *blk, const char *default_format); }; namespace backend @@ -1350,6 +1381,34 @@ class ScriptedShadersBinDumpManager ScriptedShadersBinDumpState dumps[max_scripted_shaders_bin_groups]{}; public: + template + void enumerateShaderFromHash(const dxil::HashValue &hash, T reciever) const + { + for (uint32_t gi = 0; gi < array_size(dumps); ++gi) + { + auto &group = dumps[gi]; + if (!group.owner) + { + continue; + } + auto v2 = group.owner->getDumpV2(); + if (!v2) + { + continue; + } + for (uint32_t si = 0; si < v2->shaderHashes.size(); ++si) + { + if (hash != v2->shaderHashes[si]) + { + continue; + } + if (!reciever(gi, si, v2->vprId.size())) + { + break; + } + } + } + } void setDumpOfGroup(uint32_t shaderGroup, ScriptedShadersBinDumpOwner *dump) { dumps[shaderGroup].owner = dump; @@ -1673,6 +1732,62 @@ class ShaderModuleManager : public ScriptedShadersBinDumpManager uint32_t compression_index); void setPixelShaderCompressionGroup(uint32_t group_index, uint32_t index, const dxil::HashValue &hash, uint32_t compression_group, uint32_t compression_index); + ShaderID findVertexShader(const dxil::HashValue &hash) const + { + for (uint32_t si = 0; si < shaderGroupZero.vertex.size(); ++si) + { + auto &vs = shaderGroupZero.vertex[si]; + if (!vs) + { + continue; + } + if (vs->header.hash == hash) + { + return ShaderID::make(0, si); + } + } + for (uint32_t gi = 0; gi < array_size(shaderGroup); ++gi) + { + auto &group = shaderGroup[gi].vertex; + for (uint32_t si = 0; si < group.size(); ++si) + { + auto &vs = group[si]; + if (vs->header.hash == hash) + { + return ShaderID::make(gi + 1, si); + } + } + } + return ShaderID::Null(); + } + ShaderID findPixelShader(const dxil::HashValue &hash) const + { + for (uint32_t si = 0; si < shaderGroupZero.pixel.size(); ++si) + { + auto &ps = shaderGroupZero.pixel[si]; + if (!ps) + { + continue; + } + if (ps->header.hash == hash) + { + return ShaderID::make(0, si); + } + } + for (uint32_t gi = 0; gi < array_size(shaderGroup); ++gi) + { + auto &group = shaderGroup[gi].pixel; + for (uint32_t si = 0; si < group.size(); ++si) + { + auto &ps = group[si]; + if (ps->header.hash == hash) + { + return ShaderID::make(gi + 1, si); + } + } + } + return ShaderID::Null(); + } }; -}; // namespace backend +} // namespace backend } // namespace drv3d_dx12 diff --git a/prog/engine/drv/drv3d_Metal/render_command_buffer.h b/prog/engine/drv/drv3d_Metal/render_command_buffer.h index 474e05993..24562ac10 100644 --- a/prog/engine/drv/drv3d_Metal/render_command_buffer.h +++ b/prog/engine/drv/drv3d_Metal/render_command_buffer.h @@ -1181,7 +1181,7 @@ struct CommandBuffer template __forceinline T *push(Params... params) { - if (is_main_thread() && g_ios_pause_rendering) + if (g_ios_pause_rendering && is_main_thread()) return nullptr; #if CMD_USE_ATOMICS uint32_t current = __atomic_add_fetch(&offset, sizeof(T), __ATOMIC_SEQ_CST) - sizeof(T); diff --git a/prog/engine/drv/drv3d_Metal/shadersPreCache.mm b/prog/engine/drv/drv3d_Metal/shadersPreCache.mm index 2cd65f571..c74d4fca4 100644 --- a/prog/engine/drv/drv3d_Metal/shadersPreCache.mm +++ b/prog/engine/drv/drv3d_Metal/shadersPreCache.mm @@ -12,7 +12,7 @@ namespace drv3d_metal { - static const uint32_t PRECACHE_VERSION = _MAKE4C('2.0'); + static const uint32_t PRECACHE_VERSION = _MAKE4C('2.1'); std::thread g_saver; std::thread g_compiler; diff --git a/prog/engine/drv/drv3d_commonCode/drv_utils.cpp b/prog/engine/drv/drv3d_commonCode/drv_utils.cpp index 3644cfd34..434c1a724 100644 --- a/prog/engine/drv/drv3d_commonCode/drv_utils.cpp +++ b/prog/engine/drv/drv3d_commonCode/drv_utils.cpp @@ -19,6 +19,7 @@ #include #include +#include bool get_settings_resolution(int &width, int &height, bool &is_retina, int def_width, int def_height, bool &out_is_auto) @@ -32,9 +33,11 @@ bool get_settings_resolution(int &width, int &height, bool &is_retina, int def_w if (res_str && res_str[0] == 'x') { float scale = atof(res_str + 1); - int maxScaledWidth = blk_video.getInt("maxScaledWidth", -1); - if (maxScaledWidth > 0 && scale * def_width > maxScaledWidth) - scale = (float)maxScaledWidth / def_width; + const int maxDimension = blk_video.getInt("maxLowerDimension", -1); + const int smallerDimension = eastl::min(def_width, def_height); + + if (maxDimension > 0 && smallerDimension > maxDimension) + scale = ((float)maxDimension * scale) / smallerDimension; width = (int)(scale * def_width); height = (int)(scale * def_height); width -= width % 16; // Grant a 4 pixel alignment for quarter-res targets. diff --git a/prog/engine/drv/drv3d_commonCode/dxgi_utils.h b/prog/engine/drv/drv3d_commonCode/dxgi_utils.h index c0f0c7024..89689ee89 100644 --- a/prog/engine/drv/drv3d_commonCode/dxgi_utils.h +++ b/prog/engine/drv/drv3d_commonCode/dxgi_utils.h @@ -2,7 +2,7 @@ #if _TARGET_PC_WIN -#include +#include #include #include diff --git a/prog/engine/drv/drv3d_commonCode/jamfile b/prog/engine/drv/drv3d_commonCode/jamfile index 7dd9fd16b..fabc60054 100644 --- a/prog/engine/drv/drv3d_commonCode/jamfile +++ b/prog/engine/drv/drv3d_commonCode/jamfile @@ -60,11 +60,11 @@ else { if ! $(Platform) in xboxOne scarlett { AddIncludes += $(Root)/prog/3rdPartyLibs/nvapi - $(Root)/prog/3rdPartyLibs/reflexStats $(Root)/prog/3rdPartyLibs/adl_sdk $(Root)/prog/3rdPartyLibs/ags_sdk/include ; } +if [ GLOB $(Root)/prog/3rdPartyLibs/reflexStats : * ] { AddIncludes += $(Root)/prog/3rdPartyLibs/reflexStats ; } if $(Platform) in ps4 ps5 { Sources += @@ -102,7 +102,6 @@ if $(DlssEnabled) = yes && $(Platform) = win64 && -DHAS_NVSDK_NGX in $(CPPopt) { AddIncludes += $(Root)/prog/3rdPartyLibs/nvsdk_ngx/Include ; AddIncludes += - $(Root)/prog/gameLibs/publicInclude $(Root)/prog/engine/sharedInclude $(Root)/prog/engine/drv/drv3d_commonCode $(Root)/prog/engine/drv/drv3d_commonCode/sony diff --git a/prog/engine/drv/drv3d_commonCode/renderPassGeneric.cpp b/prog/engine/drv/drv3d_commonCode/renderPassGeneric.cpp index 26f439d41..606bb1708 100644 --- a/prog/engine/drv/drv3d_commonCode/renderPassGeneric.cpp +++ b/prog/engine/drv/drv3d_commonCode/renderPassGeneric.cpp @@ -12,6 +12,14 @@ RenderPass *activeRP = nullptr; RenderPassArea activeRenderArea; int32_t subpass = 0; eastl::vector targets; + +struct MSAAResolvePair +{ + int32_t src; + int32_t dst; +}; +eastl::vector msaaResolves; + }; // namespace rp_impl void RenderPass::addSubpassToList(const RenderPassDesc &rp_desc, int32_t subpass) @@ -34,6 +42,21 @@ const char *RenderPass::getDebugName() #endif } +void RenderPass::resolveMSAATargets() +{ + if (!rp_impl::msaaResolves.size()) + return; + + for (rp_impl::MSAAResolvePair i : rp_impl::msaaResolves) + { + RenderPassTarget &srcTgt = rp_impl::targets[i.src]; + RenderPassTarget &dstTgt = rp_impl::targets[i.dst]; + // TODO: layer & mip is not handled!!! + dstTgt.resource.tex->update(srcTgt.resource.tex); + } + rp_impl::msaaResolves.clear(); +} + void RenderPass::execute(uint32_t idx, ClearAccumulator &clear_acm) { G_ASSERT(idx < actions.size()); @@ -64,7 +87,7 @@ void RenderPass::execute(uint32_t idx, ClearAccumulator &clear_acm) d3d::set_depth(target.resource.tex, target.resource.layer, DepthAccess::SampledRO); } } - else + else if (bind.action & RP_TA_SUBPASS_WRITE) { if (bind.slot != RenderPassExtraIndexes::RP_SLOT_DEPTH_STENCIL) d3d::set_render_target(bind.slot, target.resource.tex, target.resource.layer, target.resource.mip_level); @@ -105,6 +128,14 @@ void RenderPass::execute(uint32_t idx, ClearAccumulator &clear_acm) } } } + else if (bind.action & RP_TA_SUBPASS_RESOLVE) + { + for (RenderPassBind &i : actions) + if ((i.slot == bind.slot) && (i.subpass == bind.subpass)) + { + rp_impl::msaaResolves.push_back({i.target, bind.target}); + } + } } RenderPass *render_pass_generic::create_render_pass(const RenderPassDesc &rp_desc) @@ -166,6 +197,8 @@ void render_pass_generic::next_subpass() d3d::set_render_target(); d3d::set_render_target(0, nullptr, 0); + rp_impl::activeRP->resolveMSAATargets(); + RenderPass::ClearAccumulator ca; for (int i = seq[rp_impl::subpass]; i < seq[rp_impl::subpass + 1]; ++i) rp_impl::activeRP->execute(i, ca); diff --git a/prog/engine/drv/drv3d_commonCode/renderPassGeneric.h b/prog/engine/drv/drv3d_commonCode/renderPassGeneric.h index c1818b49f..1970b3058 100644 --- a/prog/engine/drv/drv3d_commonCode/renderPassGeneric.h +++ b/prog/engine/drv/drv3d_commonCode/renderPassGeneric.h @@ -11,7 +11,6 @@ struct RenderPass #if DAGOR_DBGLEVEL > 0 String dbgName; #endif - eastl::vector actions; eastl::vector sequence; int32_t subpassCnt; @@ -28,6 +27,7 @@ struct RenderPass const char *getDebugName(); void addSubpassToList(const RenderPassDesc &rp_desc, int32_t subpass); void execute(uint32_t idx, ClearAccumulator &clear_acm); + void resolveMSAATargets(); }; RenderPass *create_render_pass(const RenderPassDesc &rp_desc); diff --git a/prog/engine/drv/drv3d_vulkan/device.cpp b/prog/engine/drv/drv3d_vulkan/device.cpp index 279cc1f9e..963f91b36 100644 --- a/prog/engine/drv/drv3d_vulkan/device.cpp +++ b/prog/engine/drv/drv3d_vulkan/device.cpp @@ -932,6 +932,12 @@ void Device::fillMobileCaps(Driver3dDesc &caps) if (caps.issues.hasRenderPassClearDataRace) debug("vulkan: running on device-driver combo with clear-store race"); + if (getPerDriverPropertyBlock("disableShaderFloat16")->getBool("affected", false)) + { + caps.caps.hasShaderFloat16Support = false; + debug("vulkan: running on device-driver with bad shader float16 support, related features are OFF!"); + } + caps.caps.hasLazyMemory = physicalDeviceInfo.hasLazyMemory; } #endif @@ -1039,6 +1045,8 @@ void Device::adjustCaps(Driver3dDesc &caps) caps.caps.hasRaytracing = false; #endif + caps.caps.hasShaderFloat16Support = physicalDeviceInfo.hasShaderFloat16; + #if _TARGET_ANDROID fillMobileCaps(caps); #endif diff --git a/prog/engine/drv/drv3d_vulkan/execution_sync.cpp b/prog/engine/drv/drv3d_vulkan/execution_sync.cpp index 2e5f00caf..f656362a2 100644 --- a/prog/engine/drv/drv3d_vulkan/execution_sync.cpp +++ b/prog/engine/drv/drv3d_vulkan/execution_sync.cpp @@ -305,8 +305,7 @@ void ExecutionSyncTracker::addBufferAccess(LogicAddress laddr, Buffer *buf, Buff bufOps.arr.push_back({laddr, buf, area, getCaller(), /*completed*/ false, /*dstConflict*/ false}); } -void ExecutionSyncTracker::addImageAccessFull(LogicAddress laddr, Image *img, VkImageLayout layout, ImageArea area, - uint16_t native_pass_idx) +void ExecutionSyncTracker::addImageAccess(LogicAddress laddr, Image *img, VkImageLayout layout, ImageArea area) { // 3d image has no array range, but image view uses it to select the slices, so reset array range. if (VK_IMAGE_TYPE_3D == img->getType()) @@ -321,30 +320,15 @@ void ExecutionSyncTracker::addImageAccessFull(LogicAddress laddr, Image *img, Vk area.mipIndex, area.mipIndex + area.mipRange, area.arrayIndex, area.arrayIndex + area.arrayRange, img->layout.mipLevels, img->layout.data.size() / img->layout.mipLevels); - ImageOpAdditionalParams opAddParams{layout, native_pass_idx}; + ImageOpAdditionalParams opAddParams{layout, currentRenderSubpass}; if (filterAccessTracking(gpuWorkId, imgOps, img, laddr, area, opAddParams)) return; - imgOps.arr.push_back({laddr, img, area, getCaller(), layout, native_pass_idx, /*completed*/ false, /*dstConflict*/ false, + imgOps.arr.push_back({laddr, img, area, getCaller(), layout, currentRenderSubpass, /*completed*/ false, /*dstConflict*/ false, /*changesLayout*/ false}); } -void ExecutionSyncTracker::addImageAccessAtNativePass(LogicAddress laddr, Image *img, VkImageLayout layout, ImageArea area) -{ - addImageAccessFull(laddr, img, layout, area, nativePassIdx); -} - -void ExecutionSyncTracker::addImageAccess(LogicAddress laddr, Image *img, VkImageLayout layout, ImageArea area) -{ - addImageAccessFull(laddr, img, layout, area, 0); -} - -void ExecutionSyncTracker::enterNativePass() -{ - for (size_t i = imgOps.lastIncompleted; i < imgOps.lastProcessed; ++i) - imgOps.arr[i].onNativePassEnter(nativePassIdx); - ++nativePassIdx; -} +void ExecutionSyncTracker::setCurrentRenderSubpass(uint8_t subpass) { currentRenderSubpass = subpass; } void ExecutionSyncTracker::ScratchData::clear() { @@ -459,7 +443,9 @@ void ExecutionSyncTracker::completeAll(VulkanCommandBufferHandle cmd_buffer, con InternalPipelineBarrier barrier(dev, srcLA.stage, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); barrier.addMemory({srcLA.access, VK_ACCESS_MEMORY_WRITE_BIT | VK_ACCESS_MEMORY_READ_BIT}); - barrier.submit(cmd_buffer); + // can be empty due to native RP sync exclusion + if (srcLA.stage != VK_PIPELINE_STAGE_NONE) + barrier.submit(cmd_buffer); clearOps(); } diff --git a/prog/engine/drv/drv3d_vulkan/execution_sync.h b/prog/engine/drv/drv3d_vulkan/execution_sync.h index e7f8444f1..125ae6290 100644 --- a/prog/engine/drv/drv3d_vulkan/execution_sync.h +++ b/prog/engine/drv/drv3d_vulkan/execution_sync.h @@ -163,10 +163,15 @@ class ExecutionSyncTracker static bool processPartials() { return false; } }; + enum + { + SUBPASS_NON_NATIVE = 255 + }; + struct ImageOpAdditionalParams { VkImageLayout layout; - uint16_t nativePassIdx; + uint8_t subpassIdx; }; struct ImageOp @@ -176,7 +181,7 @@ class ExecutionSyncTracker ImageArea area; OpCaller caller; VkImageLayout layout; - uint16_t nativePassIdx; + uint8_t subpassIdx; bool completed : 1; bool dstConflict : 1; bool changesLayout : 1; @@ -190,7 +195,6 @@ class ExecutionSyncTracker void onConflictWithDst(ImageOp &dst, size_t gpu_work_id); static bool allowsConflictFromObject() { return true; } bool hasObjConflict(); - void onNativePassEnter(uint16_t pass_idx); bool mergeCheck(ImageArea area, ImageOpAdditionalParams extra); bool isAreaPartiallyCoveredBy(const ImageOp &dst); static bool processPartials() { return true; } @@ -325,8 +329,7 @@ class ExecutionSyncTracker void addBufferAccess(LogicAddress laddr, Buffer *buf, BufferArea area); void addImageAccess(LogicAddress laddr, Image *img, VkImageLayout layout, ImageArea area); - void addImageAccessAtNativePass(LogicAddress laddr, Image *img, VkImageLayout layout, ImageArea area); - void enterNativePass(); + void setCurrentRenderSubpass(uint8_t subpass); void completeNeeded(VulkanCommandBufferHandle cmd_buffer, const VulkanDevice &dev); void completeAll(VulkanCommandBufferHandle cmd_buffer, const VulkanDevice &dev, size_t gpu_work_id); @@ -334,12 +337,11 @@ class ExecutionSyncTracker bool allCompleted(); private: - void addImageAccessFull(LogicAddress laddr, Image *img, VkImageLayout layout, ImageArea area, uint16_t native_pass_idx); void clearOps(); ScratchData scratch; ImageOpsArray imgOps; BufferOpsArray bufOps; - uint16_t nativePassIdx = 1; + uint8_t currentRenderSubpass = SUBPASS_NON_NATIVE; size_t gpuWorkId = 0; }; diff --git a/prog/engine/drv/drv3d_vulkan/execution_sync_image.cpp b/prog/engine/drv/drv3d_vulkan/execution_sync_image.cpp index 52b2dbacb..20d3a9b6e 100644 --- a/prog/engine/drv/drv3d_vulkan/execution_sync_image.cpp +++ b/prog/engine/drv/drv3d_vulkan/execution_sync_image.cpp @@ -48,7 +48,10 @@ bool ExecutionSyncTracker::ImageOp::verifySelfConflict(const ImageOp &cmp) const bool ExecutionSyncTracker::ImageOp::conflicts(const ImageOp &cmp) const { - return area.intersects(cmp.area) && (laddr.conflicting(cmp.laddr) || layout != cmp.layout) && !completed && !cmp.completed; + return area.intersects(cmp.area) && (laddr.conflicting(cmp.laddr) || layout != cmp.layout) && !completed && + !cmp.completed + // treat only "external" subpasses as conflicting, leave internal subpasses sync to subpass dependencies + && ((subpassIdx == ExecutionSyncTracker::SUBPASS_NON_NATIVE) || (cmp.subpassIdx == ExecutionSyncTracker::SUBPASS_NON_NATIVE)); } void ExecutionSyncTracker::ImageOp::addToBarrierByTemplateSrc(PipelineBarrier &barrier) @@ -67,14 +70,6 @@ void ExecutionSyncTracker::ImageOp::addToBarrierByTemplateSrc(PipelineBarrier &b barrier.addImageByTemplate({laddr.access, VK_ACCESS_NONE}); } -void ExecutionSyncTracker::ImageOp::onNativePassEnter(uint16_t pass_idx) -{ - // operation will be handled by render pass subpass deps - // so we should not treat it as pending operation right after sync/layout barrier is filled - if (nativePassIdx == pass_idx) - completed = true; -} - void ExecutionSyncTracker::ImageOp::addToBarrierByTemplateDst(PipelineBarrier &barrier, size_t gpu_work_id) { // layout changing barriers only! @@ -176,7 +171,7 @@ bool ExecutionSyncTracker::ImageOp::mergeCheck(ImageArea, ImageOpAdditionalParam // better to know this ahead of time and trigger assert if (extra.layout != layout) return false; - else if (extra.nativePassIdx != nativePassIdx) + else if (extra.subpassIdx != subpassIdx) return false; return true; diff --git a/prog/engine/drv/drv3d_vulkan/physical_device_set.h b/prog/engine/drv/drv3d_vulkan/physical_device_set.h index 4e67fe610..4f2847e17 100644 --- a/prog/engine/drv/drv3d_vulkan/physical_device_set.h +++ b/prog/engine/drv/drv3d_vulkan/physical_device_set.h @@ -78,6 +78,11 @@ struct PhysicalDeviceSet VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT, nullptr}; #endif +#if VK_KHR_shader_float16_int8 + VkPhysicalDeviceShaderFloat16Int8Features shaderFloat16Int8Features = // + {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES, nullptr, false, false}; +#endif + bool hasDevProps2 = false; bool hasConditionalRender = false; @@ -92,6 +97,7 @@ struct PhysicalDeviceSet bool hasDepthStencilResolve = false; bool hasBindless = false; bool hasLazyMemory = false; + bool hasShaderFloat16 = false; uint32_t maxBindlessTextures = 0; uint32_t maxBindlessSamplers = 0; #if D3D_HAS_RAY_TRACING @@ -272,6 +278,13 @@ struct PhysicalDeviceSet chain_structs(target, indexingFeatures); } #endif + +#if VK_KHR_shader_float16_int8 + if (hasExtension()) + { + chain_structs(target, shaderFloat16Int8Features); + } +#endif } uint32_t getAvailableVideoMemoryKb() const { return deviceLocalHeapSizeKb; } @@ -429,6 +442,14 @@ struct PhysicalDeviceSet indexingFeatures.pNext = nullptr; } #endif + +#if VK_KHR_shader_float16_int8 + if (hasExtension()) + { + hasShaderFloat16 = shaderFloat16Int8Features.shaderFloat16; + shaderFloat16Int8Features.pNext = nullptr; + } +#endif } template @@ -1300,6 +1321,9 @@ struct PhysicalDeviceSet debug("Driver version: %u.%u.%u.%u", driverVersionDecoded[0], driverVersionDecoded[1], driverVersionDecoded[2], driverVersionDecoded[3]); debug("hasLazyMemory: %s", hasLazyMemory ? "yes" : "no"); +#if VK_KHR_shader_float16_int8 + debug("hasShaderFloat16: %s", hasShaderFloat16 ? "yes" : "no"); +#endif } inline void print() const diff --git a/prog/engine/drv/drv3d_vulkan/render_pass_resource.cpp b/prog/engine/drv/drv3d_vulkan/render_pass_resource.cpp index 6da8a21ae..79adc86e9 100644 --- a/prog/engine/drv/drv3d_vulkan/render_pass_resource.cpp +++ b/prog/engine/drv/drv3d_vulkan/render_pass_resource.cpp @@ -127,20 +127,23 @@ void RenderPassResource::setFrameImageLayout(ExecutionContext &ctx, uint32_t att switch (sync_type) { - case ImageLayoutSync::END_EDGE: - ctx.back.syncTrack.addImageAccessAtNativePass(ExecutionSyncTracker::LogicAddress::forAttachmentWithLayout(new_layout), tgt.image, - new_layout, {tgt.mipLevel, 1, arrayBase, arrayRange}); + case ImageLayoutSync::INNER: for (int i = 0; i < arrayRange; ++i) tgt.image->layout.set(tgt.mipLevel, arrayBase + i, new_layout); break; - case ImageLayoutSync::INNER: + case ImageLayoutSync::END_EDGE: for (int i = 0; i < arrayRange; ++i) tgt.image->layout.set(tgt.mipLevel, arrayBase + i, new_layout); - break; + // fallthrough case ImageLayoutSync::START_EDGE: - ctx.back.syncTrack.addImageAccessAtNativePass(ExecutionSyncTracker::LogicAddress::forAttachmentWithLayout(new_layout), tgt.image, - new_layout, {tgt.mipLevel, 1, arrayBase, arrayRange}); + { + uint32_t extOpIdx = + sync_type == ImageLayoutSync::END_EDGE ? RenderPassDescription::EXTERNAL_OP_END : RenderPassDescription::EXTERNAL_OP_START; + ctx.back.syncTrack.addImageAccess( + {desc.attImageExtrenalOperations[extOpIdx][att_index].stage, desc.attImageExtrenalOperations[extOpIdx][att_index].access}, + tgt.image, new_layout, {tgt.mipLevel, 1, arrayBase, arrayRange}); break; + } default: G_ASSERTF(0, "vulkan: RenderPassResource::setFrameImageLayout %p unknown sync type %u", this, sync_type); break; } } @@ -197,6 +200,7 @@ void RenderPassResource::advanceSubpass(ExecutionContext &ctx) performSelfDepsForSubpass(activeSubpass, ctx.frameCore); ++activeSubpass; ctx.popEventRaw(); + ctx.back.syncTrack.setCurrentRenderSubpass(activeSubpass); if (activeSubpass != desc.subpasses) updateImageStatesForCurrentSubpass(ctx); @@ -211,9 +215,9 @@ void RenderPassResource::beginPass(ExecutionContext &ctx) if (ctx.isDebugEventsAllowed()) ctx.pushEventRaw(String(64, "NRP: <%s>", getDebugName()), nativePassDebugMarkerColor); + ctx.back.syncTrack.setCurrentRenderSubpass(0); updateImageStatesForCurrentSubpass(ctx); ctx.back.syncTrack.completeNeeded(ctx.frameCore, ctx.vkDev); - ctx.back.syncTrack.enterNativePass(); VkRenderPassBeginInfo rpbi = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, nullptr}; @@ -252,6 +256,7 @@ void RenderPassResource::endPass(ExecutionContext &ctx) "vulkan: there is %u subpasses in RP %p [ %p ] <%s>, but we ending it at activeSubpass %u", desc.subpasses, this, getBaseHandle(), getDebugName(), activeSubpass); ctx.vkDev.vkCmdEndRenderPass(ctx.frameCore); + ctx.back.syncTrack.setCurrentRenderSubpass(ExecutionSyncTracker::SUBPASS_NON_NATIVE); state = nullptr; bakedAttachments = nullptr; diff --git a/prog/engine/drv/drv3d_vulkan/render_pass_resource.h b/prog/engine/drv/drv3d_vulkan/render_pass_resource.h index af0b0eb79..b2b9d6b99 100644 --- a/prog/engine/drv/drv3d_vulkan/render_pass_resource.h +++ b/prog/engine/drv/drv3d_vulkan/render_pass_resource.h @@ -31,6 +31,13 @@ struct RenderPassDescription Tab selfDeps; Tab> inputAttachments; Tab> attImageLayouts; + enum + { + EXTERNAL_OP_START = 0, + EXTERNAL_OP_END = 1, + EXTERNAL_OP_CNT = 2 + }; + Tab attImageExtrenalOperations[EXTERNAL_OP_CNT]; uint64_t hash; void fillAllocationDesc(AllocationDesc &alloc_desc) const; diff --git a/prog/engine/drv/drv3d_vulkan/render_pass_resource_convert.cpp b/prog/engine/drv/drv3d_vulkan/render_pass_resource_convert.cpp index b52817271..d0f25034c 100644 --- a/prog/engine/drv/drv3d_vulkan/render_pass_resource_convert.cpp +++ b/prog/engine/drv/drv3d_vulkan/render_pass_resource_convert.cpp @@ -145,8 +145,12 @@ void RenderPassResource::fillSubpassDeps(const RenderPassDesc &rp_desc, Tab &subpa } desc.attImageLayouts.push_back(imgStates); } + + clear_and_shrink(desc.attImageExtrenalOperations[RenderPassDescription::EXTERNAL_OP_START]); + clear_and_shrink(desc.attImageExtrenalOperations[RenderPassDescription::EXTERNAL_OP_END]); + for (uint32_t i = 0; i < desc.targetCount; ++i) + { + { + // external visible operation at pass end - find stage & access from overall usage + VkSubpassDependency vkDep; + SubpassDep dep(vkDep); + addStoreDependencyFromOverallAttachmentUsage(dep, rpDesc, i); + desc.attImageExtrenalOperations[RenderPassDescription::EXTERNAL_OP_END].push_back({vkDep.srcStageMask, vkDep.srcAccessMask}); + } + + { + // external visible operation at pass start - by default find stage & access from initial layout + // but handle resolve differently due to them happening at color output-like stage & access regardless of depth/color targets + bool initialUsageIsResolve = false; + for (uint32_t j = 0; j < rpDesc.bindCount; ++j) + { + // filter ext dep subpass & other targets + if (rpDesc.binds[j].target != i) + continue; + if (rpDesc.binds[j].subpass == RenderPassExtraIndexes::RP_SUBPASS_EXTERNAL_END) + continue; + + if (rpDesc.binds[j].action & RP_TA_LOAD_MASK) + { + initialUsageIsResolve = (rpDesc.binds[j].action & RP_TA_SUBPASS_RESOLVE) != 0; + break; + } + } + + ExecutionSyncTracker::LogicAddress initialLaddr; + if (initialUsageIsResolve) + initialLaddr = ExecutionSyncTracker::LogicAddress::forAttachmentWithLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + else + initialLaddr = ExecutionSyncTracker::LogicAddress::forAttachmentWithLayout(desc.attImageLayouts[0][i]); + + desc.attImageExtrenalOperations[RenderPassDescription::EXTERNAL_OP_START].push_back({initialLaddr.stage, initialLaddr.access}); + } + } } void RenderPassResource::storeSubpassAttachmentInfos() diff --git a/prog/engine/drv/drv3d_vulkan/swapchain.cpp b/prog/engine/drv/drv3d_vulkan/swapchain.cpp index c1c64bbaf..1a8f86ccd 100644 --- a/prog/engine/drv/drv3d_vulkan/swapchain.cpp +++ b/prog/engine/drv/drv3d_vulkan/swapchain.cpp @@ -254,6 +254,8 @@ bool Swapchain::acquireSwapImage(FrameInfo &frame) if (checkVkSwapchainError(rc, "vkAcquireNextImageKHR")) { device.getQueue(DeviceQueueType::GRAPHICS).addSubmitSemaphore(syncSemaphore, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + // we can't read from it later on, so set layout as underfined to ignore contents on later usage for faster transitioning + swapImages[colorTargetIndex]->layout.set(0, 0, VK_IMAGE_LAYOUT_UNDEFINED); return true; } else diff --git a/prog/engine/drv/drv3d_vulkan/vulkan_device.h b/prog/engine/drv/drv3d_vulkan/vulkan_device.h index 68c7ac48b..94b15ba2f 100644 --- a/prog/engine/drv/drv3d_vulkan/vulkan_device.h +++ b/prog/engine/drv/drv3d_vulkan/vulkan_device.h @@ -185,6 +185,15 @@ VULKAN_DECLARE_EXTENSION(ShaderFloatControlsKHR, KHR_SHADER_FLOAT_CONTROLS); #endif // VK_KHR_shader_float_controls +#if VK_KHR_shader_float16_int8 + +VULKAN_BEGIN_EXTENSION_FUNCTION_PACK +VULKAN_END_EXTENSION_FUCTION_PACK(ShaderFloat16Int8KHR); + +VULKAN_DECLARE_EXTENSION(ShaderFloat16Int8KHR, KHR_SHADER_FLOAT16_INT8); + +#endif // VK_KHR_shader_float16_int8 + #if VK_KHR_spirv_1_4 // required by VK_KHR_ray_query VULKAN_BEGIN_EXTENSION_FUNCTION_PACK @@ -646,6 +655,10 @@ typedef VulkanDeviceCore 0 + int64_t reft = profile_ref_ticks(); +#endif { std::lock_guard scopedLock(pendingReloadResListMutex); @@ -326,6 +329,7 @@ static void batch_reload_res(void *) pendingReloadResList.clear(); } +#if DAGOR_DBGLEVEL > 0 if (dagor_frame_no() > mss.end_frame_no + 16 || mss.end_frame_no > mss.start_frame_no + 600) mss.reset(); mss.end_frame_no = dagor_frame_no(); @@ -333,6 +337,7 @@ static void batch_reload_res(void *) mss.brr_rcnt.add(rcnt); mss.pendint_cnt.add(dmUnitedVdata.getPendingReloadResCount()); mss.failed_cnt.add(dmUnitedVdata.getFailedReloadResCount()); +#endif } static void on_higher_lod_required(DynamicRenderableSceneLodsResource *res, unsigned req_lod, unsigned /*cur_lod*/) { diff --git a/prog/engine/gameRes/gameResSystem.cpp b/prog/engine/gameRes/gameResSystem.cpp index 7d2012ff3..5b018626a 100644 --- a/prog/engine/gameRes/gameResSystem.cpp +++ b/prog/engine/gameRes/gameResSystem.cpp @@ -1553,7 +1553,7 @@ void set_gameres_scan_recorder(DataBlock *rootBlk, const char *grp_pref, const c gameresprivate::recListBlk = rootBlk; } -void scan_for_game_resources(const char *path, bool scan_subdirs, bool scan_dxp, bool allow_override) +void scan_for_game_resources(const char *path, bool scan_subdirs, bool scan_dxp, bool allow_override, bool scan_vromfs) { Tab list; int grp_num = 0, dxp_num = 0; @@ -1573,11 +1573,11 @@ void scan_for_game_resources(const char *path, bool scan_subdirs, bool scan_dxp, gameresprivate::gameResPatchInProgress = allow_override; // scan gameres packs - find_files_in_folder(list, path, ".grp", false, true, scan_subdirs); + find_files_in_folder(list, path, ".grp", scan_vromfs, true, scan_subdirs); remove_duplicates(list); for (auto &_fn : list) { - SimpleString fn(df_get_real_name(_fn)); + SimpleString fn(df_get_abs_fname(_fn)); dd_simplify_fname_c(fn); if (!fn.empty()) gameresprivate::scanGameResPack(fn), grp_num++; @@ -1587,13 +1587,13 @@ void scan_for_game_resources(const char *path, bool scan_subdirs, bool scan_dxp, if (scan_dxp) { list.clear(); - find_files_in_folder(list, path, ".dxp.bin", false, true, scan_subdirs); + find_files_in_folder(list, path, ".dxp.bin", scan_vromfs, true, scan_subdirs); remove_duplicates(list); for (auto &_fn : list) { if (strstr(_fn, "-hq.dxp.bin")) // delay -hq to next pass continue; - SimpleString fn(df_get_real_name(_fn)); + SimpleString fn(df_get_abs_fname(_fn)); dd_simplify_fname_c(fn); if (!fn.empty()) gameresprivate::scanDdsxTexPack(fn), dxp_num++; @@ -1602,7 +1602,7 @@ void scan_for_game_resources(const char *path, bool scan_subdirs, bool scan_dxp, for (auto &_fn : list) // process -hq in second pass if (!_fn.empty()) { - SimpleString fn(df_get_real_name(_fn)); + SimpleString fn(df_get_abs_fname(_fn)); dd_simplify_fname_c(fn); if (!fn.empty()) gameresprivate::scanDdsxTexPack(fn), dxp_num++; diff --git a/prog/engine/imgui/imguiImpl.cpp b/prog/engine/imgui/imguiImpl.cpp index 4a063c35e..c98f3ed88 100644 --- a/prog/engine/imgui/imguiImpl.cpp +++ b/prog/engine/imgui/imguiImpl.cpp @@ -216,10 +216,10 @@ void imgui_update() d3d::get_screen_size(w, h); io.DisplaySize = ImVec2(w, h); - static int64_t reft = 0; - int usecs = get_time_usec(reft); - reft = ref_time_ticks(); - io.DeltaTime = usecs * 1e-6f; + static int64_t reft = ref_time_ticks(); + int64_t curt = ref_time_ticks(); + io.DeltaTime = ref_time_delta_to_usec(curt - reft) * 1e-6f; + reft = curt; // work-around to handle issue when fullscreen game loses focus and throw endless assertion: // "(g.FrameCount == 0 || g.FrameCountEnded == g.FrameCount) && "Forgot to call Render() or EndFrame() at the end of the previous @@ -376,9 +376,9 @@ void imgui_perform_registered() } // Window queue - if (ImGui::BeginMenu("Window")) + if (ImGuiFunctionQueue::windowHead != nullptr) { - if (ImGuiFunctionQueue::windowHead != nullptr) + if (ImGui::BeginMenu("Window")) { const char *currentGroup = ImGuiFunctionQueue::windowHead->group; bool currentGroupOpened = ImGui::BeginMenu(currentGroup); @@ -402,9 +402,8 @@ void imgui_perform_registered() } if (currentGroupOpened) ImGui::EndMenu(); + ImGui::EndMenu(); } - - ImGui::EndMenu(); } ImGui::EndMainMenuBar(); diff --git a/prog/engine/lib3d/occlusionSystem.cpp b/prog/engine/lib3d/occlusionSystem.cpp index e524f548b..4a859bc5c 100644 --- a/prog/engine/lib3d/occlusionSystem.cpp +++ b/prog/engine/lib3d/occlusionSystem.cpp @@ -35,7 +35,7 @@ class OcclusionSystemImpl final : public OcclusionSystem void buildMips() override; void prepareDebug() override; void prepareNextFrame(vec3f viewPos, mat44f_cref view, mat44f_cref proj, mat44f_cref viewProj, float zn, float zf, - Texture *mipped_depth, Texture *depth, StereoIndex stereo_index) override; + TextureIDPair mipped_depth, Texture *depth, StereoIndex stereo_index) override; void setReprojectionUseCameraTranslatedSpace(bool enabled) override; bool getReprojectionUseCameraTranslatedSpace() const override; void initSWRasterization() override; @@ -91,6 +91,7 @@ class OcclusionSystemImpl final : public OcclusionSystem bool reprojectionUseCameraTranslatedSpace = false; Texture *currentTarget = nullptr; + TEXTUREID currentTargetId = BAD_TEXTUREID; }; OcclusionSystem *OcclusionSystem::create() { return new OcclusionSystemImpl; } @@ -307,11 +308,11 @@ void OcclusionSystemImpl::startRasterization(float zn) } void OcclusionSystemImpl::prepareNextFrame(vec3f viewPos, mat44f_cref view, mat44f_cref proj, mat44f_cref viewProj, float zn, float zf, - Texture *depth, Texture *base_depth, StereoIndex stereo_index) + TextureIDPair depth, Texture *base_depth, StereoIndex stereo_index) { - G_ASSERT_RETURN(depth, ); + G_ASSERT_RETURN(depth.getTex2D(), ); if (stereo_index != StereoIndex::Right) - currentTarget = ringTextures.getNewTarget(lastRenderedFrame); + currentTarget = ringTextures.getNewTargetAndId(lastRenderedFrame, currentTargetId); if (stereo_index != StereoIndex::Left) nextFramePrepared = !!currentTarget; if (!currentTarget) @@ -324,16 +325,16 @@ void OcclusionSystemImpl::prepareNextFrame(vec3f viewPos, mat44f_cref view, mat4 if (base_depth) d3d::resource_barrier({base_depth, RB_RO_SRV | RB_STAGE_PIXEL, 0, 0}); TextureInfo tinfo; - depth->getinfo(tinfo, 0); + depth.getTex2D()->getinfo(tinfo, 0); const int w = tinfo.w, h = tinfo.h; int lod = 0; - while (((w >> (lod + 1)) > width || (h >> (lod + 1)) > height) && lod < depth->level_count() - 1) + while (((w >> (lod + 1)) > width || (h >> (lod + 1)) > height) && lod < depth.getTex2D()->level_count() - 1) lod++; - depth->texfilter(TEXFILTER_POINT); - depth->texaddr(TEXADDR_CLAMP); + depth.getTex2D()->texfilter(TEXFILTER_POINT); + depth.getTex2D()->texaddr(TEXADDR_CLAMP); static int depthSourceSzVarId = get_shader_variable_id("depth_source_sz", true); static int depthTargetSzVarId = get_shader_variable_id("depth_target_sz", true); @@ -355,7 +356,7 @@ void OcclusionSystemImpl::prepareNextFrame(vec3f viewPos, mat44f_cref view, mat4 base_depth->texfilter(TEXFILTER_POINT); base_depth->texaddr(TEXADDR_CLAMP); bool finalRendered = false; - for (int i = -1, e = depth->level_count(); i < e;) // current lod + for (int i = -1, e = depth.getTex2D()->level_count(); i < e;) // current lod { int srcSizeW = base_tinfo.w, srcSizeH = base_tinfo.h; if (i == -1) @@ -366,9 +367,9 @@ void OcclusionSystemImpl::prepareNextFrame(vec3f viewPos, mat44f_cref view, mat4 { srcSizeW = tinfo.w >> i; srcSizeH = tinfo.h >> i; - depth->texmiplevel(i, i); - d3d::resource_barrier({depth, RB_RO_SRV | RB_STAGE_PIXEL, unsigned(i), 1}); - d3d::settex(source_tex_const_no, depth); + depth.getTex2D()->texmiplevel(i, i); + d3d::resource_barrier({depth.getTex2D(), RB_RO_SRV | RB_STAGE_PIXEL, unsigned(i), 1}); + d3d::settex(source_tex_const_no, depth.getTex2D()); } int targetW = srcSizeW >> 1, targetH = srcSizeH >> 1; bool downsample4X = false; @@ -392,7 +393,7 @@ void OcclusionSystemImpl::prepareNextFrame(vec3f viewPos, mat44f_cref view, mat4 { const int renderTargetLod = i + (downsample4X ? 2 : 1); G_ASSERT((tinfo.w >> renderTargetLod) == targetW && (tinfo.h >> renderTargetLod) == targetH); - d3d::set_render_target(depth, renderTargetLod); + d3d::set_render_target(depth.getTex2D(), renderTargetLod); i = renderTargetLod; } @@ -413,13 +414,13 @@ void OcclusionSystemImpl::prepareNextFrame(vec3f viewPos, mat44f_cref view, mat4 ShaderGlobal::set_color4(depthTargetSzVarId, width, height, 0, 0); ShaderGlobal::set_int(downsampleTypeIdVarId, 0); - depth->texmiplevel(lod, lod); - d3d::settex(source_tex_const_no, depth); + depth.getTex2D()->texmiplevel(lod, lod); + d3d::settex(source_tex_const_no, depth.getTex2D()); d3d::set_render_target(currentTarget, 0); downsample.render(); } - depth->texmiplevel(-1, -1); + depth.getTex2D()->texmiplevel(-1, -1); } else { @@ -433,26 +434,29 @@ void OcclusionSystemImpl::prepareNextFrame(vec3f viewPos, mat44f_cref view, mat4 TIME_D3D_PROFILE(downsample_hzb); TextureInfo tinfo; - depth->getinfo(tinfo, 0); + depth.getTex2D()->getinfo(tinfo, 0); static int depthSourceSzVarId = get_shader_variable_id("depth_source_sz"); static int depthTargetSzVarId = get_shader_variable_id("depth_target_sz"); + static int depthSourceVarId = get_shader_variable_id("source_depth_hzb_vr"); + static int depthTargetVarId = get_shader_variable_id("target_depth_hzb_vr"); static int depthLodVarId = get_shader_variable_id("depth_lod"); int widthLod = static_cast(log2(float(tinfo.w) / width)); int heightLod = static_cast(log2(float(tinfo.h) / height)); - int lod = eastl::min({widthLod, heightLod, depth->level_count() - 1}); + int lod = eastl::min({widthLod, heightLod, depth.getTex2D()->level_count() - 1}); { IPoint2 sourceSize(tinfo.w >> lod, tinfo.h >> lod); ShaderGlobal::set_color4(depthSourceSzVarId, sourceSize.x, sourceSize.y, 0, 0); ShaderGlobal::set_color4(depthTargetSzVarId, width, height, 0, 0); + ShaderGlobal::set_int(depthLodVarId, lod); - d3d::set_tex(STAGE_CS, 1, depth, false); - d3d::set_rwtex(STAGE_CS, 0, currentTarget, 0, 0, true); + ShaderGlobal::set_texture(depthSourceVarId, depth.getId()); + ShaderGlobal::set_texture(depthTargetVarId, currentTargetId); - downsample_vr->dispatch((sourceSize.x + 15) / 16, (sourceSize.y + 15) / 16, 1); + downsample_vr->dispatchThreads(sourceSize.x, sourceSize.y, 1); } } diff --git a/prog/engine/lib3d/ringCPUQueryLock.cpp b/prog/engine/lib3d/ringCPUQueryLock.cpp index d07a1b26a..fd579222c 100644 --- a/prog/engine/lib3d/ringCPUQueryLock.cpp +++ b/prog/engine/lib3d/ringCPUQueryLock.cpp @@ -1,3 +1,4 @@ +#include <3d/dag_resMgr.h> #include <3d/dag_ringCPUQueryLock.h> #include <3d/dag_drv3d.h> #include <3d/dag_drv3dCmd.h> @@ -8,7 +9,7 @@ void RingCPUBufferLock::close() { for (int i = 0; i < buffers.size(); ++i) { - del_d3dres(buffers[i].gpu); + release_managed_res_verified(buffers[i].id, buffers[i].gpu); buffers[i].gpu = 0; d3d::release_event_query(buffers[i].event); buffers[i].event = 0; @@ -30,12 +31,13 @@ void RingCPUBufferLock::init(uint32_t element_size, uint32_t elements, int buffe else buffers[i].gpu = d3d::create_sbuffer(element_size, elements, flags, texfmt, name); buffers[i].event = d3d::create_event_query(); + buffers[i].id = register_managed_res(cname, buffers[i].gpu); } resourceName = name; state = NORMAL; } -D3dResource *RingCPUBufferLock::getNewTarget(uint32_t &frame) +D3dResource *RingCPUBufferLock::getNewTargetAndId(uint32_t &frame, D3DRESID &id) { if (!buffers.size()) return nullptr; @@ -50,6 +52,7 @@ D3dResource *RingCPUBufferLock::getNewTarget(uint32_t &frame) state = NEWTARGET; frame = currentBufferIssued; currentBufferIssued++; + id = buffers[bufferIdx].id; return buffers[bufferIdx].gpu; } diff --git a/prog/engine/osApiWrappers/getRealFname.cpp b/prog/engine/osApiWrappers/getRealFname.cpp index eb6ea2a92..8642d478f 100644 --- a/prog/engine/osApiWrappers/getRealFname.cpp +++ b/prog/engine/osApiWrappers/getRealFname.cpp @@ -13,8 +13,10 @@ static thread_local char frn_tls[512]; static inline const char *get_abs_vrom_name(const char *fname) { - return iterate_base_paths_fast_s(fname, frn_tls, sizeof(frn_tls), true, true, - [](const char *fn) { return vromfs_get_file_data_one(fn, nullptr).data() != nullptr; }); + return iterate_base_paths_fast_s(fname, frn_tls, sizeof(frn_tls), true, true, [](const char *fn) { + VirtualRomFsData *out_vrom = nullptr; + return vromfs_get_file_data_one(fn, &out_vrom).data() != nullptr; + }); } static inline const char *get_real_name(const char *fname, bool folder, bool allow_vrom = false) { diff --git a/prog/engine/osApiWrappers/namedMounts.cpp b/prog/engine/osApiWrappers/namedMounts.cpp index f70b3064d..63d9e0906 100644 --- a/prog/engine/osApiWrappers/namedMounts.cpp +++ b/prog/engine/osApiWrappers/namedMounts.cpp @@ -38,6 +38,17 @@ void dd_set_named_mount_path(const char *mount_name, const char *path_to) } } +const char *dd_get_named_mount_by_path(const char *fpath) +{ + ScopedLockReadTemplate lock(named_mounts_rwlock); + for (auto &it : named_mounts) + { + if (strncmp(fpath, it.second.c_str(), it.second.size()) == 0) + return it.first.c_str(); + } + return nullptr; +} + const char *dd_get_named_mount_path(const char *mount_name, int mount_name_len) { ScopedLockReadTemplate lock(named_mounts_rwlock); diff --git a/prog/engine/osApiWrappers/vromfs.cpp b/prog/engine/osApiWrappers/vromfs.cpp index 3545238a9..2d645d6ce 100644 --- a/prog/engine/osApiWrappers/vromfs.cpp +++ b/prog/engine/osApiWrappers/vromfs.cpp @@ -147,9 +147,13 @@ VromReadHandle vromfs_get_file_data_one(const char *fname, VirtualRomFsData **ou if (out_vrom) *out_vrom = NULL; + + // We can't check vromfs[0] without locking + // During remove_vromfs() call we could write nullptr to vromfs[0] just before memmove() call. + // At this moment vromfs[0] is nullptr and any attempt to df_open() vrom files will be failed. + LockForRead lock(VromReadHandle::lock); if (vromfs[0]) { - LockForRead lock(VromReadHandle::lock); char namebuf[DAGOR_MAX_PATH]; resolve_named_mount_s(namebuf, sizeof(namebuf), fname); dd_simplify_fname_c(namebuf); diff --git a/prog/engine/perfMon/jamfile b/prog/engine/perfMon/jamfile index 1658db5ec..26398b5b3 100644 --- a/prog/engine/perfMon/jamfile +++ b/prog/engine/perfMon/jamfile @@ -27,13 +27,6 @@ Sources = memoryReportLog.cpp ; -if $(Platform) in ps4 && $(Config) != rel { - AddLibs += - -lScePerf_stub_weak - -lSceRazorCpu_stub_weak - ; -} - CPPopt = -D__B_CORE ; if $(Platform) = win64 { diff --git a/prog/engine/phys/physJolt/jamfile b/prog/engine/phys/physJolt/jamfile index cf3f066c3..49f43b84f 100644 --- a/prog/engine/phys/physJolt/jamfile +++ b/prog/engine/phys/physJolt/jamfile @@ -32,5 +32,13 @@ UseProgLibs = CPPopt = -D__B_CORE -DUSE_JOLT_PHYSICS ; +if $(Platform) = linux64 || $(PlatformSpec) = clang { + if $(Platform) in win32 win64 xboxOne scarlett { + CPPopt += -fp:fast /clang:-fno-unsafe-math-optimizations ; + } else { + CPPopt += -fno-unsafe-math-optimizations ; + } +} + include $(Root)/prog/3rdPartyLibs/phys/joltPhysics/setup.jam ; include $(Root)/prog/_jBuild/build.jam ; diff --git a/prog/engine/phys/physJolt/joltPhysics.cpp b/prog/engine/phys/physJolt/joltPhysics.cpp index 1898659fa..a6c2b38f4 100644 --- a/prog/engine/phys/physJolt/joltPhysics.cpp +++ b/prog/engine/phys/physJolt/joltPhysics.cpp @@ -277,16 +277,15 @@ class JoltJobSystemImpl final : public JPH::JobSystem void WaitForJobs(Barrier *inBarrier) override { static_cast(inBarrier)->activeWait(); } protected: - static bool submitJob(JobImpl *j) + static void submitJob(JobImpl *j) { if (interlocked_compare_exchange(j->istate, j->S_ADDING, j->S_INITIAL) != j->S_INITIAL) - return false; + return; j->AddRef(); G_FAST_ASSERT(interlocked_acquire_load(j->done)); // Freshly allocated job should have `done` set uint32_t qPos; threadpool::add(j, j->tprio, qPos, threadpool::AddFlags::IgnoreNotDone); j->setState(j->S_SUBMITTED); - return true; } void QueueJob(Job *inJob) override { submitJob(static_cast(inJob)); } void QueueJobs(Job **inJobs, JPH::uint inNumJobs) override @@ -302,8 +301,11 @@ class JoltJobSystemImpl final : public JPH::JobSystem { auto jptr = static_cast(inJob); G_FAST_ASSERT(inJob->IsDone()); - // Addition to barrier can be skipped if job was already done (IsDone()=true) at that moment. - threadpool::wait(jptr); + + // Addition to barrier can be skipped if job was already done (IsDone()=true) at Jolt, + // but we still have to wait for it to be done in threadpool + threadpool::wait(jptr, 0, jptr->tprio); + jptr->~JobImpl(); OSSpinlockScopedLock lock(fbaJobsSL); fbaJobs.freeOneBlock(jptr); @@ -835,8 +837,19 @@ JPH::RefConst PhysBody::create_jolt_collision_shape(const PhysCollis for (auto s = (const unsigned *)meshColl->idata, se = s + meshColl->inum; s < se; s += 3, d++) d->mIdx[0] = s[0], d->mIdx[1] = s[rev_face ? 2 : 1], d->mIdx[2] = s[rev_face ? 1 : 2]; } - shape.Sanitize(); - return check_and_return_shape(shape.Create(), __LINE__); + + auto res = shape.Create(); + if (res.IsValid()) + return res.Get(); + + // TODO: promote this to logerr when either all project resources are fixed or add per-project setting + logwarn("Failed to create non sanitized mesh shape <%s>: %s", meshColl->debugName, res.GetError().c_str()); + + decltype(shape) sanitizedShape; + sanitizedShape.mTriangleVertices = eastl::move(shape.mTriangleVertices); + sanitizedShape.mIndexedTriangles = eastl::move(shape.mIndexedTriangles); + sanitizedShape.Sanitize(); + return check_and_return_shape(sanitizedShape.Create(), __LINE__); } break; diff --git a/prog/engine/shaders/shAssert.cpp b/prog/engine/shaders/shAssert.cpp index 9ab5bb5b6..0b1994c02 100644 --- a/prog/engine/shaders/shAssert.cpp +++ b/prog/engine/shaders/shAssert.cpp @@ -100,6 +100,7 @@ void readback() char *next_format = first_format; for (int id = 0; next_format; id++) { + G_ASSERT(id < 16); bool is_string = next_format[1] == 's'; next_format = strchr(next_format + 1, '%'); char symbol = next_format ? *next_format : 0; @@ -108,6 +109,17 @@ void readback() if (is_string) { int string_id = (int)it->variables[id]; + const bool oob = string_id >= 0 && get_dump_v2()->messagesByShclass[failed_shader_id].size() <= string_id; + if (oob) + for (uint32_t i = 0; i < get_dump_v2()->messagesByShclass[failed_shader_id].size(); ++i) + debug("String %d: %s", i, get_dump_v2()->messagesByShclass[failed_shader_id][i].c_str()); + G_ASSERTF(!oob, + "In correct string-id %d" + "(raw: %f, arg-idx: %d).\n String collection size: %d\n Current message: %s\n Current output: %s", + string_id, it->variables[id], id, get_dump_v2()->messagesByShclass[failed_shader_id].size(), message.c_str(), + output.c_str()); + if (oob) + break; const char *str = string_id >= 0 ? get_dump_v2()->messagesByShclass[failed_shader_id][string_id].c_str() : ""; output.aprintf(0, message_str, str); } diff --git a/prog/engine/shaders/shaderResUnitedData.cpp b/prog/engine/shaders/shaderResUnitedData.cpp index be2964274..79cc8c8eb 100644 --- a/prog/engine/shaders/shaderResUnitedData.cpp +++ b/prog/engine/shaders/shaderResUnitedData.cpp @@ -776,7 +776,7 @@ inline void ShaderResUnitedVdata::initUpdateJob(UpdateModelCtx &ctx, RES *r ctx.res = r; ctx.res->setResLoadingFlag(true); ctx.reqLod = r->getQlReqLodEff(); - pendingVdataReloadResCount++; + interlocked_increment(pendingVdataReloadResCount); } template inline void ShaderResUnitedVdata::doUpdateJob(UpdateModelCtx &ctx) @@ -1230,9 +1230,9 @@ void ShaderResUnitedVdata::stopPendingJobs() else break; cpujobs::reset_job_queue(reloadJobMgrId); - if (cpujobs::is_job_manager_busy(reloadJobMgrId) || pendingVdataReloadResCount) + if (cpujobs::is_job_manager_busy(reloadJobMgrId) || getPendingReloadResCount()) logwarn("failed to finish pending jobs for %d msec, busy=%d pendReload=%d", get_time_msec() - t0, - cpujobs::is_job_manager_busy(reloadJobMgrId), pendingVdataReloadResCount); + cpujobs::is_job_manager_busy(reloadJobMgrId), getPendingReloadResCount()); } } template @@ -1260,7 +1260,7 @@ template void ShaderResUnitedVdata::clear() { stopPendingJobs(); - G_ASSERTF(!pendingVdataReloadResCount, "pendingVdataReloadResCount=%d", pendingVdataReloadResCount); + G_ASSERTF(!getPendingReloadResCount(), "pendingVdataReloadResCount=%d", getPendingReloadResCount()); std::lock_guard scopedLock(appendMutex); if (buf.getIB()) @@ -1306,7 +1306,7 @@ void ShaderResUnitedVdata::buildStatusStr(String &out_str, bool full_res_li { updateLocalMaximum(false); out_str.aprintf(0, "\nmax buf used [%dM+%dM=%dM] pendingVdataReloadResCount=%d", maxIbTotalUsed >> 20, maxVbTotalUsed >> 20, - (maxIbTotalUsed + maxVbTotalUsed) >> 20, pendingVdataReloadResCount); + (maxIbTotalUsed + maxVbTotalUsed) >> 20, getPendingReloadResCount()); if (vbSizeToFree > 0 || ibSizeToFree > 0) out_str.aprintf(0, "\nfailedVdataReloadResList=%d vbShortage=%dK ibShortage=%dK uselessDiscardAttempts=%d", failedVdataReloadResList.size(), vbSizeToFree >> 10, ibSizeToFree >> 10, uselessDiscardAttempts); diff --git a/prog/engine/shaders/shadersBinaryDataVars.cpp b/prog/engine/shaders/shadersBinaryDataVars.cpp index 7e6d98ff7..e21daeb81 100644 --- a/prog/engine/shaders/shadersBinaryDataVars.cpp +++ b/prog/engine/shaders/shadersBinaryDataVars.cpp @@ -278,6 +278,7 @@ const char *ShaderVariableInfo::getName() const return data; } +extern bool dgs_all_shader_vars_optionals; void ShaderVariableInfo::resolve() { G_STATIC_ASSERT(sizeof(Color4) == 16); // verifies header inline get @@ -296,7 +297,7 @@ void ShaderVariableInfo::resolve() } if (var_id < 0) return; - if (!optional && !VariableMap::isVariablePresent(var_id)) + if (!optional && !VariableMap::isVariablePresent(var_id) && !dgs_all_shader_vars_optionals) logerr("shader variable %s is mandatory (not optional), but is not present in shaders dump", getName()); data = nullptr; iid = -1; diff --git a/prog/engine/videoEncoder/jamfile b/prog/engine/videoEncoder/jamfile index 299bf28a1..b28e775c4 100644 --- a/prog/engine/videoEncoder/jamfile +++ b/prog/engine/videoEncoder/jamfile @@ -27,7 +27,6 @@ if $(Platform) in win32 win64 { } AddIncludes += - $(Root)/prog/gameLibs/publicInclude $(Root)/prog/engine/drv/drv3d_commonCode ; diff --git a/prog/engine/videoEncoder/videoEncoder.cpp b/prog/engine/videoEncoder/videoEncoder.cpp index 505190a2e..7d5c93146 100644 --- a/prog/engine/videoEncoder/videoEncoder.cpp +++ b/prog/engine/videoEncoder/videoEncoder.cpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/prog/engine/workCycle/jamfile b/prog/engine/workCycle/jamfile index d08929aa3..5df497189 100644 --- a/prog/engine/workCycle/jamfile +++ b/prog/engine/workCycle/jamfile @@ -49,12 +49,6 @@ if $(Platform) in ps4 ps5 { ; } -if $(Platform) = ps5 { - AddLibs += - -lSceShare_stub_weak - ; -} - if $(Platform) = macosx { Sources += macosx/macIdleCycle.mm diff --git a/prog/engine/workCycle/mainWndProc.cpp b/prog/engine/workCycle/mainWndProc.cpp index dc1799b5f..75ed594cf 100644 --- a/prog/engine/workCycle/mainWndProc.cpp +++ b/prog/engine/workCycle/mainWndProc.cpp @@ -227,18 +227,19 @@ eastl::pair default_wnd_proc(void *hwnd, unsigned message, uintp case WM_POWERBROADCAST: { - static intptr_t prevTmt = 0; + static int prevTmt = -1; if (wParam == PBT_APMSUSPEND) { dgs_last_suspend_at = timeGetTime(); debug("Windows suspended @ %ums", dgs_last_suspend_at); - prevTmt = watchdog_set_option(WATCHDOG_OPTION_TRIG_THRESHOLD, 0); + prevTmt = (int)watchdog_set_option(WATCHDOG_OPTION_TRIG_THRESHOLD, WATCHDOG_DISABLE); } if (wParam == PBT_APMRESUMEAUTOMATIC) // The system always sends a PBT_APMRESUMEAUTOMATIC message whenever the system resumes. { dgs_last_resume_at = timeGetTime(); debug("Windows resumed @ %ums", dgs_last_resume_at); - watchdog_set_option(WATCHDOG_OPTION_TRIG_THRESHOLD, prevTmt); + if (prevTmt >= 0) // If suspend code called + watchdog_set_option(WATCHDOG_OPTION_TRIG_THRESHOLD, prevTmt); } return {true, TRUE}; } diff --git a/prog/gameLibs/breakpad/binder/callbacks.h b/prog/gameLibs/breakpad/binder/callbacks.h index b6c8aae64..5d9ae0bad 100644 --- a/prog/gameLibs/breakpad/binder/callbacks.h +++ b/prog/gameLibs/breakpad/binder/callbacks.h @@ -2,7 +2,7 @@ * Dagor Engine 3 - Game Libraries * Copyright (C) 2023 Gaijin Games KFT. All rights reserved * - * (for conditions of distribution and use, see EULA in "prog/eula.txt") + * (for conditions of use see prog/license.txt) */ #ifndef DAGOR2_GAMELIBS_BREAKPAD_BINDER_CALLBACKS_H_ diff --git a/prog/gameLibs/breakpad/sender/configuration.h b/prog/gameLibs/breakpad/sender/configuration.h index 62d51a6d3..e9407b790 100644 --- a/prog/gameLibs/breakpad/sender/configuration.h +++ b/prog/gameLibs/breakpad/sender/configuration.h @@ -2,7 +2,7 @@ * Dagor Engine 3 - Game Libraries * Copyright (C) 2023 Gaijin Games KFT. All rights reserved * - * (for conditions of distribution and use, see EULA in "prog/eula.txt") + * (for conditions of use see prog/license.txt) */ #ifndef DAGOR_GAMELIBS_BREAKPAD_SENDER_CONFIGURATION_H_ diff --git a/prog/gameLibs/breakpad/sender/files.h b/prog/gameLibs/breakpad/sender/files.h index eacb905f8..a2a62c710 100644 --- a/prog/gameLibs/breakpad/sender/files.h +++ b/prog/gameLibs/breakpad/sender/files.h @@ -2,7 +2,7 @@ * Dagor Engine 3 - Game Libraries * Copyright (C) 2023 Gaijin Games KFT. All rights reserved * - * (for conditions of distribution and use, see EULA in "prog/eula.txt") + * (for conditions of use see prog/license.txt) */ #ifndef DAGOR_GAMELIBS_BREAKPAD_SENDER_FILES_H_ diff --git a/prog/gameLibs/breakpad/sender/sender.h b/prog/gameLibs/breakpad/sender/sender.h index 48374f448..0f16cf1b3 100644 --- a/prog/gameLibs/breakpad/sender/sender.h +++ b/prog/gameLibs/breakpad/sender/sender.h @@ -2,7 +2,7 @@ * Dagor Engine 3 - Game Libraries * Copyright (C) 2023 Gaijin Games KFT. All rights reserved * - * (for conditions of distribution and use, see EULA in "prog/eula.txt") + * (for conditions of use see prog/license.txt) */ #ifndef DAGOR_GAMELIBS_BREAKPAD_SENDER_SENDER_H_ diff --git a/prog/gameLibs/breakpad/sender/stats.h b/prog/gameLibs/breakpad/sender/stats.h index 4833f82a4..a61c64511 100644 --- a/prog/gameLibs/breakpad/sender/stats.h +++ b/prog/gameLibs/breakpad/sender/stats.h @@ -2,7 +2,7 @@ * Dagor Engine 3 - Game Libraries * Copyright (C) 2023 Gaijin Games KFT. All rights reserved * - * (for conditions of distribution and use, see EULA in "prog/eula.txt") + * (for conditions of use see prog/license.txt) */ #ifndef DAGOR_GAMELIBS_BREAKPAD_SENDER_STATS_H_ diff --git a/prog/gameLibs/breakpad/sender/ui.h b/prog/gameLibs/breakpad/sender/ui.h index 672251311..990a29949 100644 --- a/prog/gameLibs/breakpad/sender/ui.h +++ b/prog/gameLibs/breakpad/sender/ui.h @@ -2,7 +2,7 @@ * Dagor Engine 3 - Game Libraries * Copyright (C) 2023 Gaijin Games KFT. All rights reserved * - * (for conditions of distribution and use, see EULA in "prog/eula.txt") + * (for conditions of use see prog/license.txt) */ #ifndef DAGOR_GAMELIBS_BREAKPAD_SENDER_UI_H_ diff --git a/prog/gameLibs/breakpad/sender/upload.h b/prog/gameLibs/breakpad/sender/upload.h index 66f6ec0b1..6549c01a9 100644 --- a/prog/gameLibs/breakpad/sender/upload.h +++ b/prog/gameLibs/breakpad/sender/upload.h @@ -2,7 +2,7 @@ * Dagor Engine 3 - Game Libraries * Copyright (C) 2023 Gaijin Games KFT. All rights reserved * - * (for conditions of distribution and use, see EULA in "prog/eula.txt") + * (for conditions of use see prog/license.txt) */ #ifndef DAGOR_GAMELIBS_BREAKPAD_SENDER_UPLOAD_H_ diff --git a/prog/gameLibs/daECS/dasEcsUnitTest/entities.blk b/prog/gameLibs/daECS/dasEcsUnitTest/entities.blk index fae1ff5cc..7e2f2c68c 100644 --- a/prog/gameLibs/daECS/dasEcsUnitTest/entities.blk +++ b/prog/gameLibs/daECS/dasEcsUnitTest/entities.blk @@ -27,7 +27,7 @@ ballistics { vel:p3= 1,0,1 } ballistics2 { - _extends:t = ballistics + _use:t = ballistics no_int_value:i =101 } @@ -51,12 +51,12 @@ testReCreate1 { } testReCreate2 { - _extends:t=testReCreate1 + _use:t=testReCreate1 some_int_var2:i = 0 } testReCreateMemLeak { - _extends:t=testReCreate2 + _use:t=testReCreate2 string_variable:t="11i2hoshisdhsidhksjdhksdjhkadhkjhdsikabhskdhakdh" } @@ -71,7 +71,7 @@ testReCreateInit1 testReCreateInit2 { - _extends:t=testReCreateInit1 + _use:t=testReCreateInit1 some_int_var3:i = 0 } @@ -104,6 +104,6 @@ entityWith_tracked_int_var1 { } entityWith_tracked_int_var1_and_2 { - _extends:t = entityWith_tracked_int_var1 + _use:t = entityWith_tracked_int_var1 not_tracked_int_var2:i = 0 } \ No newline at end of file diff --git a/prog/gameLibs/daECS/io/datablock/dataBlockReader.cpp b/prog/gameLibs/daECS/io/datablock/dataBlockReader.cpp index ad8c692b1..faec6bd62 100644 --- a/prog/gameLibs/daECS/io/datablock/dataBlockReader.cpp +++ b/prog/gameLibs/daECS/io/datablock/dataBlockReader.cpp @@ -627,10 +627,10 @@ static void resolve_templates_imports(const char *path, const DataBlock &blk, Te static void load_templates_blk_file(const char *path, const DataBlock &blk, TemplateRefs &templates, TemplateRefs &overrides, service_datablock_cb &cb, TemplateDBInfo *info) { - const int parentNid = blk.getNameId("_extends"), trackedNid = blk.getNameId("_tracked"), - replicatedNid = blk.getNameId("_replicated"), hiddenNid = blk.getNameId("_hidden"), - overrideNid = blk.getNameId("_override"), skipInitialNid = blk.getNameId("_skipInitialReplication"), - singletonNid = blk.getNameId("_singleton"), replNid = blk.getNameId("_replicate"), trackNid = blk.getNameId("_track"), + const int parentNid = blk.getNameId("_use"), trackedNid = blk.getNameId("_tracked"), replicatedNid = blk.getNameId("_replicated"), + hiddenNid = blk.getNameId("_hidden"), overrideNid = blk.getNameId("_override"), + skipInitialNid = blk.getNameId("_skipInitialReplication"), singletonNid = blk.getNameId("_singleton"), + replNid = blk.getNameId("_replicate"), trackNid = blk.getNameId("_track"), ignoreNid = blk.getNameId("_ignoreInitialReplication"), hideNid = blk.getNameId("_hide"), infoNid = blk.getNameId("_info"); // second pass, create templates diff --git a/prog/gameLibs/daGI/shaders/dagi_scene_common_write.sh b/prog/gameLibs/daGI/shaders/dagi_scene_common_write.sh index 78a056b53..edc985b56 100644 --- a/prog/gameLibs/daGI/shaders/dagi_scene_common_write.sh +++ b/prog/gameLibs/daGI/shaders/dagi_scene_common_write.sh @@ -44,8 +44,8 @@ macro SSGE_WRITE_VOXEL_DATA(code, color_reg, alpha_reg) } endmacro -int ssge_scene_common_color_reg_no = 7; -int ssge_scene_common_alpha_reg_no = 6; +int ssge_scene_common_color_reg_no = 6; +int ssge_scene_common_alpha_reg_no = 5; macro SSGE_SCENE_COMMON_WRITE(code) USE_VOXELS(code) diff --git a/prog/gameLibs/daGI/shaders/debug_inline_rt.sh b/prog/gameLibs/daGI/shaders/debug_inline_rt.sh index 6d8124f75..913e4242d 100644 --- a/prog/gameLibs/daGI/shaders/debug_inline_rt.sh +++ b/prog/gameLibs/daGI/shaders/debug_inline_rt.sh @@ -65,4 +65,5 @@ shader debug_inline_rt_cs } } compile("cs_6_5", "main"); + if (gi_quality != raytracing) {dont_render;} } \ No newline at end of file diff --git a/prog/gameLibs/daGI/shaders/octahedral_distances.sh b/prog/gameLibs/daGI/shaders/octahedral_distances.sh index 592a66697..452ec5f33 100644 --- a/prog/gameLibs/daGI/shaders/octahedral_distances.sh +++ b/prog/gameLibs/daGI/shaders/octahedral_distances.sh @@ -98,4 +98,5 @@ shader octahedral_distances_cs } } compile("cs_6_5", "main_cs"); + if (gi_quality != raytracing) {dont_render;} } diff --git a/prog/gameLibs/daGI25D/scene.cpp b/prog/gameLibs/daGI25D/scene.cpp index 6aca5e71e..b006ffaf8 100644 --- a/prog/gameLibs/daGI25D/scene.cpp +++ b/prog/gameLibs/daGI25D/scene.cpp @@ -172,7 +172,8 @@ UpdateResult Scene::updateOrigin(const Point3 &baseOrigin, const voxelize_scene_ sceneBox[0] = Point3::xVy(point2(stInvalid) * voxelSizeXZ, 0); sceneBox[1] = Point3::xVy(point2(stInvalid + res) * voxelSizeXZ, +voxelSizeY * VOXEL_25D_RESOLUTION_Y); - STATE_GUARD_NULLPTR(d3d::set_rwbuffer(STAGE_PS, 7, VALUE), sceneAlpha.getBuf()); + const int voxels_25d_no = ShaderGlobal::get_int(get_shader_variable_id("voxels_25d_no")); + STATE_GUARD_NULLPTR(d3d::set_rwbuffer(STAGE_PS, voxels_25d_no, VALUE), sceneAlpha.getBuf()); voxelize_cb(sceneBox, 0.5 * Point3(voxelSizeXZ, voxelSizeY, voxelSizeXZ)); // decrease voxel size twice, as we supersample alpha // twice d3d::resource_barrier({sceneAlpha.getBuf(), RB_RO_SRV | RB_STAGE_PIXEL | RB_STAGE_COMPUTE}); diff --git a/prog/gameLibs/daProfilerPlugins/daProfilerVSync.cpp b/prog/gameLibs/daProfilerPlugins/daProfilerVSync.cpp index 82417bc09..83d7cf35e 100644 --- a/prog/gameLibs/daProfilerPlugins/daProfilerVSync.cpp +++ b/prog/gameLibs/daProfilerPlugins/daProfilerVSync.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/prog/gameLibs/daRg/canvasDraw.cpp b/prog/gameLibs/daRg/canvasDraw.cpp index 3fb0dc1c0..8bee4657c 100644 --- a/prog/gameLibs/daRg/canvasDraw.cpp +++ b/prog/gameLibs/daRg/canvasDraw.cpp @@ -246,6 +246,34 @@ void RenderCanvasContext::renderRectangle(const Sqrat::Array &cmd) const } +void RenderCanvasContext::renderQuads(const Sqrat::Array &cmd) const +{ + // VECTOR_QUADS, (x, y, color) * 4 times, ... + bool isValidParams = cmd.Length() > 1 && (cmd.Length() - 1) % 12 == 0; + + if (!isValidParams) + { + darg_assert_trace_var("invalid number of parameters for VECTOR_QUADS", cmd, 0); + return; + } + + Point2 p[4]; + E3DCOLOR colors[4]; + + for (int i = 1; i < cmd.Length(); i += 12) + { + for (int k = 0, index = 0; k < 12; k += 3, index++) // 3 numbers per vertex - x, y, color + { + p[index] = offset + Point2(cmd[i + k].Cast() * scale.x, cmd[i + k + 1].Cast() * scale.y); + colors[index] = e3dcolor_mul(fillColor, script_decode_e3dcolor(cmd[i + k + 2].Cast())); + } + + ctx->render_quad_color(p[0], p[1], p[2], p[3], Point2(0, 0), Point2(0, 0), Point2(0, 0), Point2(0, 0), colors[0], colors[1], + colors[2], colors[3]); + } +} + + static RenderCanvasContext *get_ctx(HSQUIRRELVM vm) { SQUserPointer ptr = nullptr; diff --git a/prog/gameLibs/daRg/canvasDraw.h b/prog/gameLibs/daRg/canvasDraw.h index 2e7c935b9..25c73f321 100644 --- a/prog/gameLibs/daRg/canvasDraw.h +++ b/prog/gameLibs/daRg/canvasDraw.h @@ -29,6 +29,7 @@ struct RenderCanvasContext void renderFillPoly(const Sqrat::Array &cmd) const; void renderFillInversePoly(const Sqrat::Array &cmd) const; void renderLineDashed(const Sqrat::Array &cmd) const; + void renderQuads(const Sqrat::Array &cmd) const; void bind_delegate_to_handle(HSQUIRRELVM vm); diff --git a/prog/gameLibs/daRg/scriptBinding.cpp b/prog/gameLibs/daRg/scriptBinding.cpp index d90bb8c79..69edccb86 100644 --- a/prog/gameLibs/daRg/scriptBinding.cpp +++ b/prog/gameLibs/daRg/scriptBinding.cpp @@ -127,14 +127,15 @@ static void register_constants(HSQUIRRELVM vm) CONST(VECTOR_CENTER_LINE) CONST(VECTOR_INNER_LINE) CONST(VECTOR_TM_OFFSET) CONST(VECTOR_TM_SCALE) CONST(VECTOR_LINE) CONST(VECTOR_LINE_INDENT_PX) CONST(VECTOR_LINE_INDENT_PCT) CONST(VECTOR_ELLIPSE) CONST(VECTOR_SECTOR) CONST(VECTOR_RECTANGLE) CONST(VECTOR_POLY) CONST(VECTOR_INVERSE_POLY) CONST(VECTOR_OPACITY) CONST(VECTOR_LINE_DASHED) CONST(VECTOR_NOP) + CONST(VECTOR_QUADS) - CONST(FFT_NONE) CONST(FFT_SHADOW) CONST(FFT_GLOW) CONST(FFT_BLUR) CONST(FFT_OUTLINE) + CONST(FFT_NONE) CONST(FFT_SHADOW) CONST(FFT_GLOW) CONST(FFT_BLUR) CONST(FFT_OUTLINE) - CONST(O_HORIZONTAL) CONST(O_VERTICAL) + CONST(O_HORIZONTAL) CONST(O_VERTICAL) - CONST(TOVERFLOW_CLIP) CONST(TOVERFLOW_CHAR) CONST(TOVERFLOW_WORD) CONST(TOVERFLOW_LINE) + CONST(TOVERFLOW_CLIP) CONST(TOVERFLOW_CHAR) CONST(TOVERFLOW_WORD) CONST(TOVERFLOW_LINE) - CONST(DIR_UP) CONST(DIR_DOWN) CONST(DIR_LEFT) CONST(DIR_RIGHT) + CONST(DIR_UP) CONST(DIR_DOWN) CONST(DIR_LEFT) CONST(DIR_RIGHT) .Const("EVENT_BREAK", GuiScene::EVENT_BREAK) .Const("EVENT_CONTINUE", GuiScene::EVENT_CONTINUE) diff --git a/prog/gameLibs/daRg/stdRendObj.cpp b/prog/gameLibs/daRg/stdRendObj.cpp index fd494a413..d9050bf8e 100644 --- a/prog/gameLibs/daRg/stdRendObj.cpp +++ b/prog/gameLibs/daRg/stdRendObj.cpp @@ -873,6 +873,8 @@ void RenderObjectVectorCanvas::renderCustom(StdGuiRender::GuiContext &ctx, const case VECTOR_INVERSE_POLY: rctx.renderFillInversePoly(cmd); break; + case VECTOR_QUADS: rctx.renderQuads(cmd); break; + case VECTOR_NOP: break; default: darg_assert_trace_var(String(0, "'VectorCanvas: invalid command in commands[%d]", idx), params->commands, idx); @@ -1508,6 +1510,7 @@ void RenderObjectTextArea::renderCustom(StdGuiRender::GuiContext &ctx, const Ele numBlocksToRender = 0; bool hadAllSymbols = true; + bool nowHaveAllSymbols = true; for (int i = 0; i < numBlocksToRender && hadAllSymbols; ++i) { textlayout::TextBlock *block = line.blocks[i]; @@ -1522,13 +1525,14 @@ void RenderObjectTextArea::renderCustom(StdGuiRender::GuiContext &ctx, const Ele else if (halign == ALIGN_CENTER) xLineOffs += floorf((sc.size.x - lineWidth) * 0.5f); - for (int i = 0; i < numBlocks; ++i) - { - textlayout::TextBlock *block = line.blocks[i]; - darg::GuiTextCache &guiText = block->guiText; + auto iterateBlocks = [&]() { + for (int i = 0; i < numBlocks; ++i) + { + textlayout::TextBlock *block = line.blocks[i]; + darg::GuiTextCache &guiText = block->guiText; - float x = block->position.x + xLineOffs; - float y = block->position.y + fmtText->yOffset + line.baseLineY; + float x = block->position.x + xLineOffs; + float y = block->position.y + fmtText->yOffset + line.baseLineY; #if 0 // debug blocks int ascent = StdGuiRender::get_font_ascent(block->fontId, block->fontHt); @@ -1536,52 +1540,60 @@ void RenderObjectTextArea::renderCustom(StdGuiRender::GuiContext &ctx, const Ele sc.screenPos.x - sc.scrollOffs.x + x + block->size.x, sc.screenPos.y - sc.scrollOffs.y + y - ascent + block->size.y, 1); #endif - if (block->type == textlayout::TextBlock::TBT_SPACE) // don't neeed to draw anything - continue; + if (block->type == textlayout::TextBlock::TBT_SPACE) // don't neeed to draw anything + continue; - if (block->useCustomColor) - ctx.set_color(color_apply_mods(block->customColor, render_state.opacity, params->brightness)); + if (block->useCustomColor) + ctx.set_color(color_apply_mods(block->customColor, render_state.opacity, params->brightness)); - if (block->fontId != lastFontId || block->fontHt != lastFontHt) - { - lastFontId = block->fontId; - lastFontHt = block->fontHt; - monoWidth = font_mono_width_from_sq(block->fontId, block->fontHt, objMonoWidth); - } + if (block->fontId != lastFontId || block->fontHt != lastFontHt) + { + lastFontId = block->fontId; + lastFontHt = block->fontHt; + monoWidth = font_mono_width_from_sq(block->fontId, block->fontHt, objMonoWidth); + } - ctx.set_font(block->fontId, spacing, monoWidth); - if (block->fontHt) - ctx.set_font_ht(block->fontHt); + ctx.set_font(block->fontId, spacing, monoWidth); + if (block->fontHt) + ctx.set_font_ht(block->fontHt); - ctx.goto_xy(sc.screenPos.x - sc.scrollOffs.x + x, sc.screenPos.y - sc.scrollOffs.y + y); + ctx.goto_xy(sc.screenPos.x - sc.scrollOffs.x + x, sc.screenPos.y - sc.scrollOffs.y + y); - if (shouldBreakWithEllipsis && (ellipsisOnSeparateLine || i > lastBlockIndexToRender)) - { - ctx.draw_str_u(ellipsisUtf16, 1); - break; - } + if (shouldBreakWithEllipsis && (ellipsisOnSeparateLine || i > lastBlockIndexToRender)) + { + ctx.draw_str_u(ellipsisUtf16, 1); + break; + } - bool all_glyphs_ready = true; - if (!guiText.isReady()) - { - tmpU16.resize(block->text.length() + 1); - tmpU16.resize(utf8_to_wcs_ex(block->text, tmpU16.size() - 1, tmpU16.data(), tmpU16.size())); - all_glyphs_ready = - ctx.draw_str_scaled_u_buf(guiText.v, guiText.c, StdGuiRender::DSBFLAG_rel, 1.0f, tmpU16.data(), tmpU16.size()); - } + bool all_glyphs_ready = true; + if (!guiText.isReady()) + { + tmpU16.resize(block->text.length() + 1); + tmpU16.resize(utf8_to_wcs_ex(block->text, tmpU16.size() - 1, tmpU16.data(), tmpU16.size())); + all_glyphs_ready = + ctx.draw_str_scaled_u_buf(guiText.v, guiText.c, StdGuiRender::DSBFLAG_rel, 1.0f, tmpU16.data(), tmpU16.size()); + } + nowHaveAllSymbols &= all_glyphs_ready; + if (all_glyphs_ready && hadAllSymbols) + { + ctx.goto_xy(sc.screenPos.x - sc.scrollOffs.x + x, sc.screenPos.y - sc.scrollOffs.y + y); + ctx.start_font_str(1.0f); + ctx.render_str_buf(guiText.v, guiText.c, + StdGuiRender::DSBFLAG_rel | StdGuiRender::DSBFLAG_curColor | StdGuiRender::DSBFLAG_checkVis); + } + if (!all_glyphs_ready) + guiText.discard(); - if (all_glyphs_ready && hadAllSymbols) - { - ctx.goto_xy(sc.screenPos.x - sc.scrollOffs.x + x, sc.screenPos.y - sc.scrollOffs.y + y); - ctx.start_font_str(1.0f); - ctx.render_str_buf(guiText.v, guiText.c, - StdGuiRender::DSBFLAG_rel | StdGuiRender::DSBFLAG_curColor | StdGuiRender::DSBFLAG_checkVis); + if (block->useCustomColor) + ctx.set_color(color); } - if (!all_glyphs_ready) - guiText.discard(); + }; - if (block->useCustomColor) - ctx.set_color(color); + iterateBlocks(); + if (!hadAllSymbols && nowHaveAllSymbols) + { + hadAllSymbols = true; + iterateBlocks(); } } @@ -1607,7 +1619,11 @@ class RobjParamsFrame : public RendObjParams const Sqrat::Table &scriptDesc = elem->props.scriptDesc; Sqrat::Object bWidthObj = scriptDesc.RawGetSlot(elem->csk->borderWidth); const char *errMsg = nullptr; - if (!script_parse_offsets(elem, bWidthObj, &borderWidth.x, &errMsg)) + if (bWidthObj.IsNull()) + { + borderWidth[0] = borderWidth[1] = borderWidth[2] = borderWidth[3] = 1; + } + else if (!script_parse_offsets(elem, bWidthObj, &borderWidth.x, &errMsg)) { borderWidth[0] = borderWidth[1] = borderWidth[2] = borderWidth[3] = 1; darg_assert_trace_var(errMsg, scriptDesc, elem->csk->borderWidth); diff --git a/prog/gameLibs/daSkies2/daSkies.cpp b/prog/gameLibs/daSkies2/daSkies.cpp index 7daf76be5..ed9d310fe 100644 --- a/prog/gameLibs/daSkies2/daSkies.cpp +++ b/prog/gameLibs/daSkies2/daSkies.cpp @@ -788,6 +788,8 @@ void DaSkies::reset() invalidate(); if (clouds) clouds->reset(); + if (skyStars) + skyStars->afterReset(); ShaderGlobal::setBlock(-1, ShaderGlobal::LAYER_FRAME); prepare(getSunDir(), false, 0.f); } diff --git a/prog/gameLibs/daSkies2/daSkiesExporterConsole.cpp b/prog/gameLibs/daSkies2/daSkiesExporterConsole.cpp index 52db10f4a..f3b01f87a 100644 --- a/prog/gameLibs/daSkies2/daSkiesExporterConsole.cpp +++ b/prog/gameLibs/daSkies2/daSkiesExporterConsole.cpp @@ -78,7 +78,7 @@ static DataBlock convert_to_entity(const NamedDataBlock &weather_blk) { DataBlock weatherTemplate; DataBlock &entityBlk = *weatherTemplate.addBlock(weather_blk.name.c_str()); - entityBlk.setStr("_extends", "skies_settings"); + entityBlk.setStr("_use", "skies_settings"); { const DataBlock &blk = *weather_blk.blk.getBlockByNameEx("clouds_rendering"); diff --git a/prog/gameLibs/daSkies2/daStars.cpp b/prog/gameLibs/daSkies2/daStars.cpp index dbc31948c..13c1550cb 100644 --- a/prog/gameLibs/daSkies2/daStars.cpp +++ b/prog/gameLibs/daSkies2/daStars.cpp @@ -75,10 +75,10 @@ void DaStars::init(const char *stars, const char *moon) starsRendElem.numVert = star_catalog::g_star_count * 4; starsRendElem.startIndex = 0; starsRendElem.numPrim = star_catalog::g_star_count * 2; - starsVb = dag::create_vb(starsRendElem.numVert * starsRendElem.stride, 0, "starsVb"); + starsVb = dag::create_vb(starsRendElem.numVert * starsRendElem.stride, SBCF_MAYBELOST, "starsVb"); G_ASSERT(starsVb); - starsIb = dag::create_ib(starsRendElem.numPrim * 3 * sizeof(uint16_t), 0, + starsIb = dag::create_ib(starsRendElem.numPrim * 3 * sizeof(uint16_t), SBCF_MAYBELOST, "starsIb"); // To be filled on scene change. G_ASSERT(starsIb); diff --git a/prog/gameLibs/daSkies2/daStars.h b/prog/gameLibs/daSkies2/daStars.h index 82b3c371c..e65fc925a 100644 --- a/prog/gameLibs/daSkies2/daStars.h +++ b/prog/gameLibs/daSkies2/daStars.h @@ -24,6 +24,7 @@ class DaStars void close(); DaStars() = default; ~DaStars(); + void afterReset() { generateStars(); } protected: ShaderMaterial *moonMaterial = nullptr; diff --git a/prog/gameLibs/das/math/easing.das b/prog/gameLibs/das/math/easing.das index 55cc90ad4..982871368 100644 --- a/prog/gameLibs/das/math/easing.das +++ b/prog/gameLibs/das/math/easing.das @@ -1,5 +1,6 @@ module easing shared require math +require math.base [generic] def linear(p : float) diff --git a/prog/gameLibs/dasModules/phys/dacoll.cpp b/prog/gameLibs/dasModules/phys/dacoll.cpp index 3a61b6b7b..9f914ad5b 100644 --- a/prog/gameLibs/dasModules/phys/dacoll.cpp +++ b/prog/gameLibs/dasModules/phys/dacoll.cpp @@ -98,6 +98,8 @@ class DacollModule final : public das::Module das::SideEffects::modifyArgument, "bind_dascript::dacoll_tracedown_normalized_with_norm"); das::addExtern(*this, lib, "tracedown_normalized", das::SideEffects::modifyArgument, "bind_dascript::dacoll_tracedown_normalized_with_pmid"); + das::addExtern(*this, lib, "tracedown_normalized", + das::SideEffects::modifyArgument, "bind_dascript::dacoll_tracedown_normalized_with_norm_and_pmid"); das::addExtern(*this, lib, "tracedown_normalized", das::SideEffects::modifyArgument, "bind_dascript::dacoll_tracedown_normalized_trace_handle_with_pmid"); das::addExtern(*this, lib, "traceht_water", das::SideEffects::modifyArgument, diff --git a/prog/gameLibs/devices/jamfile b/prog/gameLibs/devices/jamfile index 60c86070d..647a27379 100644 --- a/prog/gameLibs/devices/jamfile +++ b/prog/gameLibs/devices/jamfile @@ -25,7 +25,6 @@ if $(Platform) in win32 win64 { ps4HeadTrack.cpp stub/jetSeatStub.cpp ; - AddLibs += -lSceFace_stub_weak ; UseProgLibs += engine/drv/camera_sony ; } else { Exit $(Platform) is not supported: use devices/stub library instead ; diff --git a/prog/gameLibs/dxil/compiler_dxc.cpp b/prog/gameLibs/dxil/compiler_dxc.cpp index 56d5fc95c..574137718 100644 --- a/prog/gameLibs/dxil/compiler_dxc.cpp +++ b/prog/gameLibs/dxil/compiler_dxc.cpp @@ -1,7 +1,7 @@ // clang-format off #include #include -#include +#include #include #include diff --git a/prog/gameLibs/ecs/rendInst/rendinstFloatingES.cpp.inl b/prog/gameLibs/ecs/rendInst/rendinstFloatingES.cpp.inl index 13760a8ca..3d71bbca7 100644 --- a/prog/gameLibs/ecs/rendInst/rendinstFloatingES.cpp.inl +++ b/prog/gameLibs/ecs/rendInst/rendinstFloatingES.cpp.inl @@ -59,6 +59,12 @@ inline void draw_floating_phys_ripples_ecs_query(Callable c); static float frac(float v) { return v - floorf(v); } +// We probably have such function somewhere, but couldn't find. +static float remap_range_clamp(float v, float from_min, float from_max, float to_min, float to_max) +{ + return saturate((v - from_min) / (from_max - from_min)) * (to_max - to_min) + to_min; +} + // Mass is distributed across volumes proportionally to their volumes. static Point3 calculate_center_of_gravity(BSphere3 *volumes, int count) { @@ -599,7 +605,7 @@ static void update_floating_rendinsts_es(const ParallelUpdateFrameDelayed &info, ? floatingRiGroup__interactionType : rendinstfloating::NO_INTERACTION; - float mass = lerp(floatingRiGroup__riPhysFloatingModel.massMin, floatingRiGroup__riPhysFloatingModel.massMax, instNoise); + float mass = lerp(floatingRiGroup__riPhysFloatingModel.randMassMin, floatingRiGroup__riPhysFloatingModel.randMassMax, instNoise); float invMass = 1.0f / mass; update_floating_phys(localObjectAtTime, riFloatingPhys.curTick, interactionType, invMass, floatingRiGroup__elasticity, @@ -706,23 +712,44 @@ static __forceinline void init_floating_rendinst_res_group_es_event_handler(cons box.lim[1].y = 1; } floatingRiGroup__riPhysFloatingModel.physBbox = box; - floatingRiGroup__riPhysFloatingModel.spheresRad = (box.lim[1].y - box.lim[0].y) * 0.5f; construct_floating_volumes_ecs_query([&](const ecs::Object &floatingRiSystem__volumePresets) { floatingRiGroup__riPhysFloatingModel.spheresCoords = extract_sphere_coords(floatingRiSystem__volumePresets, floatingRiGroup__volumesCount, floatingRiGroup__volumePresetName); }); + const int nVolumes = floatingRiGroup__riPhysFloatingModel.spheresCoords.size(); + + constexpr float waterDensity = 1000.0f; + constexpr float initialDensityMin = 0.0f; + constexpr float initialDensityMax = waterDensity; + + // For physics stability. + // And to be able to make object stand on water at 0 density and be just underwater on 1000 density + // (that's what artists actually want and they don't care about physical meanings). + constexpr float addRadius = 0.15f; constexpr float sphereVolumeCf = 4.0 / 3.0 * PI; - constexpr float densityClampMin = 1.0f; // An object can't be weightless. - constexpr float densityClampMax = 999.0f; // With bigger values the volume will just drown. - - float sphereVolume = sphereVolumeCf * pow(floatingRiGroup__riPhysFloatingModel.spheresRad, 3); - float totalVolume = sphereVolume * floatingRiGroup__riPhysFloatingModel.spheresCoords.size(); - float densityMin = clamp(floatingRiGroup__density - floatingRiGroup__densityRandRange, densityClampMin, densityClampMax); - float densityMax = clamp(floatingRiGroup__density + floatingRiGroup__densityRandRange, densityClampMin, densityClampMax); - floatingRiGroup__riPhysFloatingModel.massMin = totalVolume * densityMin; - floatingRiGroup__riPhysFloatingModel.massMax = totalVolume * densityMax; + + float rInit = (box.lim[1].y - box.lim[0].y) * 0.5f; + float rExt = rInit + addRadius; + float hMin = rExt - rInit; + float hMax = rExt + rInit; + + float rExt3 = pow(rExt, 3); + // We have to recalculate acceptable density range to preserve object position on water. + float extendedDensityMin = waterDensity * hMin * hMin * (3.0f * rExt - hMin) / (4.0f * rExt3); + float extendedDensityMax = waterDensity * hMax * hMax * (3.0f * rExt - hMax) / (4.0f * rExt3); + + float sphereVolume = sphereVolumeCf * rExt3; + float totalVolume = sphereVolume * nVolumes; + float randDensityMin = remap_range_clamp(floatingRiGroup__density - floatingRiGroup__densityRandRange, initialDensityMin, + initialDensityMax, extendedDensityMin, extendedDensityMax); + float randDensityMax = remap_range_clamp(floatingRiGroup__density + floatingRiGroup__densityRandRange, initialDensityMin, + initialDensityMax, extendedDensityMin, extendedDensityMax); + + floatingRiGroup__riPhysFloatingModel.randMassMin = totalVolume * randDensityMin; + floatingRiGroup__riPhysFloatingModel.randMassMax = totalVolume * randDensityMax; + floatingRiGroup__riPhysFloatingModel.spheresRad = rExt; Point3 momentOfInertiaCoeff = Point3(1, 1, 1); if (floatingRiGroup__useBoxInertia) diff --git a/prog/gameLibs/fftWater/flowMap.cpp b/prog/gameLibs/fftWater/flowMap.cpp index 9dc22662a..ca1224fb9 100644 --- a/prog/gameLibs/fftWater/flowMap.cpp +++ b/prog/gameLibs/fftWater/flowMap.cpp @@ -4,6 +4,7 @@ #include #include #include <3d/dag_textureIDHolder.h> +#include <3d/dag_lockTexture.h> #include #include #include @@ -216,4 +217,140 @@ bool is_flowmap_active(const FlowmapParams &flowmap_params) return flowmap_params.tex || flowmap_params.texA || flowmap_params.texB; } +void flowmap_floodfill(int texSize, Texture *heightmapTex, Texture *floodfillTex, uint16_t heightmapLevel) +{ + TIME_D3D_PROFILE(flowmap_floodfill); + + int heightmapStrideX = sizeof(uint16_t); + int heightmapStrideY = texSize * heightmapStrideX; + LockedTexture heightmapLockedTex = lock_texture(heightmapTex, heightmapStrideY, 0, TEXLOCK_READ); + + int floodfillStrideX = sizeof(uint16_t); + int floodfillStrideY = texSize * floodfillStrideX; + LockedTexture floodfillLockedTex = lock_texture(floodfillTex, floodfillStrideY, 0, TEXLOCK_WRITE); + + if (heightmapLockedTex && floodfillLockedTex) + { + uint8_t *heightmapData = heightmapLockedTex.get(); + uint8_t *floodfillData = floodfillLockedTex.get(); + memset(floodfillData, 0, texSize * floodfillStrideY); + + int queueSize = (texSize + 1) * 2; + int queueBegin = 0; + int queueEnd = 0; + int *queue = new int[queueSize]; + + for (int y = 0; y < texSize; y++) + { + for (int x = 0; x < texSize; x++) + { + uint16_t *height = (uint16_t *)(heightmapData + x * heightmapStrideX + y * heightmapStrideY); + if (height[0] < heightmapLevel) + { + uint16_t *flood = (uint16_t *)(floodfillData + x * floodfillStrideX + y * floodfillStrideY); + if (flood[0] == 0) + { + queue[queueEnd++] = x; + queue[queueEnd++] = y; + if (queueEnd >= queueSize) + queueEnd = 0; + + while (queueBegin != queueEnd) + { + int u = queue[queueBegin++]; + int v = queue[queueBegin++]; + if (queueBegin >= queueSize) + queueBegin = 0; + + height = (uint16_t *)(heightmapData + u * heightmapStrideX + v * heightmapStrideY); + flood = (uint16_t *)(floodfillData + u * floodfillStrideX + v * floodfillStrideY); + + int fx = 0; + int fy = 0; + + if ((u - 1 >= 0) && (height[-1] < heightmapLevel)) + { + if (flood[-1] == 0) + { + flood[-1] = 1; + queue[queueEnd++] = u - 1; + queue[queueEnd++] = v; + if (queueEnd >= queueSize) + queueEnd = 0; + } + else if (flood[-1] > 1) + fx++; + } + if ((u + 1 < texSize) && (height[1] < heightmapLevel)) + { + if (flood[1] == 0) + { + flood[1] = 1; + queue[queueEnd++] = u + 1; + queue[queueEnd++] = v; + if (queueEnd >= queueSize) + queueEnd = 0; + } + else if (flood[1] > 1) + fx--; + } + if ((v - 1 >= 0) && (height[-texSize] < heightmapLevel)) + { + if (flood[-texSize] == 0) + { + flood[-texSize] = 1; + queue[queueEnd++] = u; + queue[queueEnd++] = v - 1; + if (queueEnd >= queueSize) + queueEnd = 0; + } + else if (flood[-texSize] > 1) + fy++; + } + if ((v + 1 < texSize) && (height[texSize] < heightmapLevel)) + { + if (flood[texSize] == 0) + { + flood[texSize] = 1; + queue[queueEnd++] = u; + queue[queueEnd++] = v + 1; + if (queueEnd >= queueSize) + queueEnd = 0; + } + else if (flood[texSize] > 1) + fy--; + } + + flood[0] = uint16_t(((fy * 0x7f + 0x80) << 8) | (fx * 0x7f + 0x80)); + } + } + } + } + } + + delete[] queue; + + for (int y = 0; y < texSize; y++) + { + for (int x = 0; x < texSize; x++) + { + uint16_t *flood = (uint16_t *)(floodfillData + x * floodfillStrideX + y * floodfillStrideY); + if (flood[0] <= 1) + { + if ((x - 1 >= 0) && (flood[-1] > 1)) + flood[0] = flood[-1]; + else if ((x + 1 < texSize) && (flood[1] > 1)) + flood[0] = flood[1]; + else if ((y - 1 >= 0) && (flood[-texSize] > 1)) + flood[0] = flood[-texSize]; + else if ((y + 1 < texSize) && (flood[texSize] > 1)) + flood[0] = flood[texSize]; + else + flood[0] = 0; + } + } + } + } +} + } // namespace fft_water diff --git a/prog/gameLibs/fftWater/waterGPGPUData.h b/prog/gameLibs/fftWater/waterGPGPUData.h index 341030384..b5642b98d 100644 --- a/prog/gameLibs/fftWater/waterGPGPUData.h +++ b/prog/gameLibs/fftWater/waterGPGPUData.h @@ -26,8 +26,9 @@ class GPGPUData ~GPGPUData() { close(); } private: - void updateH0(int num); + void updateH0(const NVWaveWorks_FFT_CPU_Simulation *fft, int num); bool fillOmega(const NVWaveWorks_FFT_CPU_Simulation *fft, int num); + void fillBuffers(const NVWaveWorks_FFT_CPU_Simulation *fft, int numCascades); UniqueTex butterfly; @@ -50,4 +51,5 @@ class GPGPUData ShaderElement *fftHElement, *fftVElement; Vbuffer *fftVbuf; bool h0GPUUpdateRequired = true, omegaGPUUpdateRequired = true; + bool buffersReady = false; }; diff --git a/prog/gameLibs/fftWater/waterRenderGpGPU.cpp b/prog/gameLibs/fftWater/waterRenderGpGPU.cpp index 4025b5c86..33b0a46c5 100644 --- a/prog/gameLibs/fftWater/waterRenderGpGPU.cpp +++ b/prog/gameLibs/fftWater/waterRenderGpGPU.cpp @@ -283,35 +283,13 @@ bool GPGPUData::init(const NVWaveWorks_FFT_CPU_Simulation *fft, int numCascades) G_ASSERT(h0Mat); h0Element = h0Mat->make_elem(); int num_quads = (numCascades + 1) / 2; - ht0Ibuf = d3d::create_ib(sizeof(uint16_t) * 6 * num_quads, 0); + ht0Ibuf = d3d::create_ib(sizeof(uint16_t) * 6 * num_quads, SBCF_MAYBELOST, "ht0Ibuf"); d3d_err(ht0Ibuf); - uint16_t *indices; - d3d_err(ht0Ibuf->lock(0, 0, &indices, VBLOCK_WRITEONLY)); - for (int i = 0; i < num_quads; ++i, indices += 6) - { - int base = i * 4; - indices[0] = base; - indices[1] = base + 1; - indices[2] = base + 2; - indices[3] = base + 2; - indices[4] = base + 1; - indices[5] = base + 3; - } - ht0Ibuf->unlock(); // create vbuffer for fft/butterflies - fftVbuf = d3d::create_vb(sizeof(Point3) * 3 * miNumButterflies, 0, "fftVbuf"); + fftVbuf = d3d::create_vb(sizeof(Point3) * 3 * miNumButterflies, SBCF_MAYBELOST, "fftVbuf"); d3d_err(fftVbuf); - Point3 *fftVertices; - d3d_err(fftVbuf->lock(0, 0, (void **)&fftVertices, VBLOCK_WRITEONLY)); - for (int i = 0; i < miNumButterflies; ++i, fftVertices += 3) - { - float index = (i + 0.5f) / miNumButterflies; - fftVertices[0] = Point3(-1, +1, index); - fftVertices[1] = Point3(-1, -3, index); - fftVertices[2] = Point3(+3, +1, index); - } - fftVbuf->unlock(); + buffersReady = false; fftVMat = new_shader_material_by_name("fftV"); G_ASSERT(fftVMat); fftVElement = fftVMat->make_elem(); @@ -339,93 +317,136 @@ void GPGPUData::updateHt0WindowsVB(const NVWaveWorks_FFT_CPU_Simulation *fft, in { ShaderGlobal::set_real(small_waves_fractionVarId, fft[0].getParams().small_wave_fraction); - int gauss_resolution, gauss_stride; - get_global_gauss_data(gauss_resolution, gauss_stride); - int num_quads = (numCascades + 1) / 2; - Ht0Vertex *vertices; del_d3dres(ht0Vbuf); - ht0Vbuf = d3d::create_vb(sizeof(Ht0Vertex) * 4 * num_quads, 0, "ht0Vbuf"); + ht0Vbuf = d3d::create_vb(sizeof(Ht0Vertex) * 4 * num_quads, SBCF_MAYBELOST, "ht0Vbuf"); d3d_err(ht0Vbuf); G_ASSERT(ht0Vbuf); - d3d_err(ht0Vbuf->lock(0, 0, (void **)&vertices, VBLOCK_WRITEONLY)); + h0GPUUpdateRequired = true; + omegaGPUUpdateRequired = true; + buffersReady = false; +} + +void GPGPUData::fillBuffers(const NVWaveWorks_FFT_CPU_Simulation *fft, int numCascades) +{ + if (buffersReady) + return; + int num_quads = (numCascades + 1) / 2; const int N = 1 << fft[0].getParams().fft_resolution_bits; - G_ASSERT(N <= gauss_resolution); - float gauss_corner0 = (gauss_resolution - N) * 0.5f / (gauss_resolution + 1.0f); - float halfTexelOffsetX = 0.5f; - float halfTexelOffsetY = 0.5f; - float gauss_corner1 = 1.0 - gauss_corner0; - gauss_corner0 += HALF_TEXEL_OFSF / (gauss_resolution + 1.0f); - gauss_corner1 += HALF_TEXEL_OFSF / (gauss_resolution + 1.0f); - float quad_width = 2.0f / num_quads; - for (int i = 0; i < num_quads; ++i, vertices += 4) + if (ht0Vbuf) + { + int gauss_resolution, gauss_stride; + get_global_gauss_data(gauss_resolution, gauss_stride); + Ht0Vertex *vertices; + d3d_err(ht0Vbuf->lock(0, 0, (void **)&vertices, VBLOCK_WRITEONLY)); + G_ASSERT(N <= gauss_resolution); + float gauss_corner0 = (gauss_resolution - N) * 0.5f / (gauss_resolution + 1.0f); + float halfTexelOffsetX = 0.5f; + float halfTexelOffsetY = 0.5f; + float gauss_corner1 = 1.0 - gauss_corner0; + gauss_corner0 += HALF_TEXEL_OFSF / (gauss_resolution + 1.0f); + gauss_corner1 += HALF_TEXEL_OFSF / (gauss_resolution + 1.0f); + float quad_width = 2.0f / num_quads; + for (int i = 0; i < num_quads; ++i, vertices += 4) + { + int c0 = i * 2; + int c1 = c0 + 1 < numCascades ? c0 + 1 : c0; + float fft_period0 = fft[c0].getParams().fft_period; + float fft_period1 = fft[c1].getParams().fft_period; + + // kStep = 2PI/L; norm = kStep * sqrt(1/2) + float norm0 = 2 * PI * 0.7071068 / (fft_period0), norm1 = 2 * PI * 0.7071068 / (fft_period1); + vertices[0].pos = Point2(-1 + i * quad_width, +1); + vertices[1].pos = Point2(vertices[0].pos.x + quad_width, +1); + vertices[2].pos = Point2(vertices[0].pos.x, -1); + vertices[3].pos = Point2(vertices[0].pos.x + quad_width, -1); + + vertices[0].tc = Point2(-N / 2 - halfTexelOffsetX + HALF_TEXEL_OFSF, -N / 2 - halfTexelOffsetY + HALF_TEXEL_OFSF); + vertices[1].tc = Point2(+N / 2 + halfTexelOffsetX + HALF_TEXEL_OFSF, -N / 2 - halfTexelOffsetY + HALF_TEXEL_OFSF); + vertices[2].tc = Point2(-N / 2 - halfTexelOffsetX + HALF_TEXEL_OFSF, +N / 2 + halfTexelOffsetY + HALF_TEXEL_OFSF); + vertices[3].tc = Point2(+N / 2 + halfTexelOffsetX + HALF_TEXEL_OFSF, +N / 2 + halfTexelOffsetY + HALF_TEXEL_OFSF); + for (int j = 0; j < 4; ++j) + { + vertices[j].fft_tc = Point4(vertices[j].tc.x * TWOPI / fft_period0, vertices[j].tc.y * TWOPI / fft_period0, + vertices[j].tc.x * TWOPI / fft_period1, vertices[j].tc.y * TWOPI / fft_period1); + } + + vertices[0].gaussTc__norm = Point4(gauss_corner0, gauss_corner0, norm0, norm1); + vertices[1].gaussTc__norm = Point4(gauss_corner1, gauss_corner0, norm0, norm1); + vertices[2].gaussTc__norm = Point4(gauss_corner0, gauss_corner1, norm0, norm1); + vertices[3].gaussTc__norm = Point4(gauss_corner1, gauss_corner1, norm0, norm1); + + Point2 window0 = Point2(fft[c0].getParams().window_in, fft[c0].getParams().window_out); + Point2 window1 = Point2(fft[c1].getParams().window_in, fft[c1].getParams().window_out); + Point4 windows(window0.x, window0.y, window1.x, window1.y); + vertices[0].windows = windows; + vertices[1].windows = windows; + vertices[2].windows = windows; + vertices[3].windows = windows; + + Point4 windProp = Point4(fft[c0].getParams().wind_dependency, fft[c1].getParams().wind_dependency, + fft[c0].getParams().wind_alignment, fft[c1].getParams().wind_alignment); + vertices[0].windProp = windProp; + vertices[1].windProp = windProp; + vertices[2].windProp = windProp; + vertices[3].windProp = windProp; + + Point2 ampSpeed0 = Point2(fft[c0].getParams().wave_amplitude, fft[c0].getParams().wind_speed); + Point2 ampSpeed1 = Point2(fft[c1].getParams().wave_amplitude, fft[c1].getParams().wind_speed); + // Use square of amplitude, because Phillips is an *energy* spectrum + ampSpeed0.x *= ampSpeed0.x; + ampSpeed1.x *= ampSpeed1.x; + // Encoded vector for passing into shaders + Point4 ampSpeed = Point4(ampSpeed0.x, ampSpeed0.y, ampSpeed1.x, ampSpeed1.y); + + vertices[0].ampSpeed = ampSpeed; + vertices[1].ampSpeed = ampSpeed; + vertices[2].ampSpeed = ampSpeed; + vertices[3].ampSpeed = ampSpeed; + } + ht0Vbuf->unlock(); + } + + if (ht0Ibuf) { - int c0 = i * 2; - int c1 = c0 + 1 < numCascades ? c0 + 1 : c0; - float fft_period0 = fft[c0].getParams().fft_period; - float fft_period1 = fft[c1].getParams().fft_period; - - // kStep = 2PI/L; norm = kStep * sqrt(1/2) - float norm0 = 2 * PI * 0.7071068 / (fft_period0), norm1 = 2 * PI * 0.7071068 / (fft_period1); - vertices[0].pos = Point2(-1 + i * quad_width, +1); - vertices[1].pos = Point2(vertices[0].pos.x + quad_width, +1); - vertices[2].pos = Point2(vertices[0].pos.x, -1); - vertices[3].pos = Point2(vertices[0].pos.x + quad_width, -1); - - vertices[0].tc = Point2(-N / 2 - halfTexelOffsetX + HALF_TEXEL_OFSF, -N / 2 - halfTexelOffsetY + HALF_TEXEL_OFSF); - vertices[1].tc = Point2(+N / 2 + halfTexelOffsetX + HALF_TEXEL_OFSF, -N / 2 - halfTexelOffsetY + HALF_TEXEL_OFSF); - vertices[2].tc = Point2(-N / 2 - halfTexelOffsetX + HALF_TEXEL_OFSF, +N / 2 + halfTexelOffsetY + HALF_TEXEL_OFSF); - vertices[3].tc = Point2(+N / 2 + halfTexelOffsetX + HALF_TEXEL_OFSF, +N / 2 + halfTexelOffsetY + HALF_TEXEL_OFSF); - for (int j = 0; j < 4; ++j) + uint16_t *indices; + d3d_err(ht0Ibuf->lock(0, 0, &indices, VBLOCK_WRITEONLY)); + for (int i = 0; i < num_quads; ++i, indices += 6) { - vertices[j].fft_tc = Point4(vertices[j].tc.x * TWOPI / fft_period0, vertices[j].tc.y * TWOPI / fft_period0, - vertices[j].tc.x * TWOPI / fft_period1, vertices[j].tc.y * TWOPI / fft_period1); + int base = i * 4; + indices[0] = base; + indices[1] = base + 1; + indices[2] = base + 2; + indices[3] = base + 2; + indices[4] = base + 1; + indices[5] = base + 3; } + ht0Ibuf->unlock(); + } - vertices[0].gaussTc__norm = Point4(gauss_corner0, gauss_corner0, norm0, norm1); - vertices[1].gaussTc__norm = Point4(gauss_corner1, gauss_corner0, norm0, norm1); - vertices[2].gaussTc__norm = Point4(gauss_corner0, gauss_corner1, norm0, norm1); - vertices[3].gaussTc__norm = Point4(gauss_corner1, gauss_corner1, norm0, norm1); - - Point2 window0 = Point2(fft[c0].getParams().window_in, fft[c0].getParams().window_out); - Point2 window1 = Point2(fft[c1].getParams().window_in, fft[c1].getParams().window_out); - Point4 windows(window0.x, window0.y, window1.x, window1.y); - vertices[0].windows = windows; - vertices[1].windows = windows; - vertices[2].windows = windows; - vertices[3].windows = windows; - - Point4 windProp = Point4(fft[c0].getParams().wind_dependency, fft[c1].getParams().wind_dependency, - fft[c0].getParams().wind_alignment, fft[c1].getParams().wind_alignment); - vertices[0].windProp = windProp; - vertices[1].windProp = windProp; - vertices[2].windProp = windProp; - vertices[3].windProp = windProp; - - Point2 ampSpeed0 = Point2(fft[c0].getParams().wave_amplitude, fft[c0].getParams().wind_speed); - Point2 ampSpeed1 = Point2(fft[c1].getParams().wave_amplitude, fft[c1].getParams().wind_speed); - // Use square of amplitude, because Phillips is an *energy* spectrum - ampSpeed0.x *= ampSpeed0.x; - ampSpeed1.x *= ampSpeed1.x; - // Encoded vector for passing into shaders - Point4 ampSpeed = Point4(ampSpeed0.x, ampSpeed0.y, ampSpeed1.x, ampSpeed1.y); - - vertices[0].ampSpeed = ampSpeed; - vertices[1].ampSpeed = ampSpeed; - vertices[2].ampSpeed = ampSpeed; - vertices[3].ampSpeed = ampSpeed; + const int miNumButterflies = get_log2w(N); + { + Point3 *fftVertices; + d3d_err(fftVbuf->lock(0, 0, (void **)&fftVertices, VBLOCK_WRITEONLY)); + for (int i = 0; i < miNumButterflies; ++i, fftVertices += 3) + { + float index = (i + 0.5f) / miNumButterflies; + fftVertices[0] = Point3(-1, +1, index); + fftVertices[1] = Point3(-1, -3, index); + fftVertices[2] = Point3(+3, +1, index); + } + fftVbuf->unlock(); } - ht0Vbuf->unlock(); - h0GPUUpdateRequired = true; - omegaGPUUpdateRequired = true; + buffersReady = true; } -void GPGPUData::updateH0(int numCascades) +void GPGPUData::updateH0(const NVWaveWorks_FFT_CPU_Simulation *fft, int numCascades) { if (!h0GPUUpdateRequired) return; if (!h0Element) return; + fillBuffers(fft, numCascades); ShaderGlobal::set_texture(k_texVarId, BAD_TEXTUREID); ShaderGlobal::set_texture(gauss_texVarId, gauss); d3d::set_render_target(ht0.getTex2D(), 0); @@ -509,7 +530,7 @@ void GPGPUData::perform(const NVWaveWorks_FFT_CPU_Simulation *fft, int numCascad fillOmega(fft, numCascades); Driver3dRenderTarget prevRt; d3d::get_render_target(prevRt); - updateH0(numCascades); + updateH0(fft, numCascades); d3d::set_render_target(); #if _TARGET_TVOS diff --git a/prog/gameLibs/gamePhys/collision/collisionLib.cpp b/prog/gameLibs/gamePhys/collision/collisionLib.cpp index 736e1dea5..089f316ff 100644 --- a/prog/gameLibs/gamePhys/collision/collisionLib.cpp +++ b/prog/gameLibs/gamePhys/collision/collisionLib.cpp @@ -537,7 +537,7 @@ CollisionObject dacoll::add_dynamic_collision(const DataBlock &props, void *user G_ASSERTF(false, "unsupported coll shape %s", blk->getBlockName()); } - G_ASSERT(shape && (shape != &compShape || compShape.getChildrenCount())); + G_ASSERT_RETURN(shape && (shape != &compShape || compShape.getChildrenCount()), {}); CollisionObject co = create_coll_obj_from_shape(*shape, userPtr, /*kinematic*/ true, add_to_world, EPL_KINEMATIC, mask, wtm); #if ENABLE_APEX @@ -796,8 +796,9 @@ CollisionObject dacoll::add_dynamic_collision_from_coll_resource(const DataBlock G_ASSERTF_AND_DO(meshNode->indices.size() / 3 < 300 * 1024, break, "Too much triangles in mesh: %d verts and %d faces! 300k is too much already!", meshNode->vertices.size(), meshNode->indices.size() / 3); - shape.addChildCollision( - new PhysTriMeshCollision(meshNode->vertices, meshNode->indices, nullptr, false, false /*reverse normals*/), meshNode->tm); + auto trim = new PhysTriMeshCollision(meshNode->vertices, meshNode->indices, nullptr, false, false /*reverse normals*/); + trim->setDebugName(meshNode->name.c_str()); + shape.addChildCollision(trim, meshNode->tm); } break; diff --git a/prog/gameLibs/gamePhys/phys/rendinstDestr.cpp b/prog/gameLibs/gamePhys/phys/rendinstDestr.cpp index a3b0c60ea..dd7e3d25a 100644 --- a/prog/gameLibs/gamePhys/phys/rendinstDestr.cpp +++ b/prog/gameLibs/gamePhys/phys/rendinstDestr.cpp @@ -790,9 +790,10 @@ static bool sort_by_offset(const rendinst::DestroyedInstanceRange &left, const r bool rendinstdestr::serialize_destr_data(danet::BitStream &bs) { - return rendinst::getDestrCellData(0 /*primary layer*/, [&](const Tab &destrCellData) { + uint16_t cellCount = 0; + const bool written = rendinst::getDestrCellData(0 /*primary layer*/, [&](const Tab &destrCellData) { G_ASSERT(destrCellData.size() <= USHRT_MAX); - uint16_t cellCount = min(destrCellData.size(), USHRT_MAX); + cellCount = min(destrCellData.size(), USHRT_MAX); bs.WriteCompressed(cellCount); for (int i = 0; i < cellCount; ++i) @@ -831,8 +832,13 @@ bool rendinstdestr::serialize_destr_data(danet::BitStream &bs) } } - return cellCount > 0; + return true; }); + + // if nothing was written, just write 0 cell count + if (!written) + bs.WriteCompressed(cellCount); + return cellCount > 0; } void rendinstdestr::deserialize_destr_data(const danet::BitStream &bs, int apply_flags, int max_simultaneous_destrs) @@ -841,12 +847,14 @@ void rendinstdestr::deserialize_destr_data(const danet::BitStream &bs, int apply Tab cellsNewDestrInfo(framemem_ptr()); int newDestrs = 0; + // always read cell count + uint16_t cellCount = 0; + bs.ReadCompressed(cellCount); + rendinst::getDestrCellData(0 /*primary layer*/, [&](const Tab &destrCellData) { - uint16_t cellCount = 0; if (!apply_reflection) { cachedDestr = bs; - bs.ReadCompressed(cellCount); for (int i = 0; i < cellCount; ++i) { uint16_t poolCount = 0; @@ -867,7 +875,6 @@ void rendinstdestr::deserialize_destr_data(const danet::BitStream &bs, int apply return true; } - bs.ReadCompressed(cellCount); cellsNewDestrInfo.resize(cellCount); for (int i = 0; i < cellCount; ++i) diff --git a/prog/gameLibs/gamePhys/phys/walker/humanPhys.cpp b/prog/gameLibs/gamePhys/phys/walker/humanPhys.cpp index f5735c68b..b38f00c56 100644 --- a/prog/gameLibs/gamePhys/phys/walker/humanPhys.cpp +++ b/prog/gameLibs/gamePhys/phys/walker/humanPhys.cpp @@ -2499,7 +2499,7 @@ void HumanPhys::updatePhys(float at_time, float dt, bool /*is_for_real*/) const float slidingFriction = min(1.f, frictionViscosityMult * currentState.frictionMult); const float externalDecceleration = max(0.f, frictionViscosityMult * currentState.frictionMult - 1.f); - const float stateAcceleration = accelerationByState[accState]; + const float stateAcceleration = accelerationByState[accState] * currentState.accelerationMult; const float stateDecceleration = stateAcceleration * slidingFriction; for (int i = 0; i < accelSubframes; ++i) diff --git a/prog/gameLibs/landMesh/lmeshManager.cpp b/prog/gameLibs/landMesh/lmeshManager.cpp index 31ad617d8..07123d2f8 100644 --- a/prog/gameLibs/landMesh/lmeshManager.cpp +++ b/prog/gameLibs/landMesh/lmeshManager.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #define MIN_TILE_SIZE 0.5 @@ -166,6 +167,8 @@ static bool load_land_class(LandClassDetailTextures &land, const char *name, con land.bumpScales = Point4(blk.getReal("bumpScale", 1.0f), 0, 0, 0); land.compatibilityDiffuseScales = Point4(blk.getReal("compatibilityDiffuseScale", 1.0f), 0, 0, 0); land.waterDecalBumpScale = Point4(blk.getReal("waterDecalBumpScale", 1.0f), 0, 0, 0); + const char *defaultPhysmat = blk.getStr("physMat", NULL); + land.physmatIds = IPoint4(PhysMat::getMaterialId(defaultPhysmat), 0, 0, 0); if (blk.getStr("shader", 0)) { @@ -308,10 +311,19 @@ static bool load_land_class(LandClassDetailTextures &land, const char *name, con // provide detail struct size via shader to avoid reading garbadge in shader! logerr("landclass: missing lmesh_hc_floats_per_detail, detail buffer can contain garbadge for shaders"); - static constexpr int DETAIL_INFO_CNT_OFS = 15; // offset of details_cnt inside DetailInfo in ints - int lcDetailsWithoutHeaderCnt = ((int)land.lcDetails.size() - lcDetailsArrayStart) * 4 / cbElementSize; - // we store the cnt in an unused member of the first detail (so we don't need extra padding for the header this way) - reinterpret_cast(&land.lcDetails[0].x)[lcDetailsArrayStart * 4 + DETAIL_INFO_CNT_OFS] = lcDetailsWithoutHeaderCnt; + int biome_lc_ofs_to_detail_info_cntVarId = ::get_shader_glob_var_id("biome_lc_ofs_to_detail_info_cnt", true); + if (VariableMap::isVariablePresent(biome_lc_ofs_to_detail_info_cntVarId)) + { + int DETAIL_INFO_CNT_OFS = ShaderGlobal::get_int(biome_lc_ofs_to_detail_info_cntVarId); // offset of details_cnt inside + // DetailInfo in ints + int lcDetailsWithoutHeaderCnt = ((int)land.lcDetails.size() - lcDetailsArrayStart) * 4 / cbElementSize; + // we store the cnt in an unused member of the first detail (so we don't need extra padding for the header this way) + reinterpret_cast(&land.lcDetails[0].x)[lcDetailsArrayStart * 4 + DETAIL_INFO_CNT_OFS] = lcDetailsWithoutHeaderCnt; + } + else + { + logwarn("landclass: missing biome_lc_ofs_to_detail_info_cnt shadervar, can't validate biome count in index texture"); + } const uint32_t maxDetailElements = (floatsPerDetail * 4 * maxDetailArraySize + detailsHeaderSize) / cbElementSize; uint32_t bufSize = max(maxDetailElements, land.lcDetails.size()); @@ -381,6 +393,11 @@ static bool load_land_class(LandClassDetailTextures &land, const char *name, con land.compatibilityDiffuseScales.z = blk.getReal("compatibilityDiffuseScaleBlue", 1.0f); land.compatibilityDiffuseScales.w = blk.getReal("compatibilityDiffuseScaleBlack", 1.0f); + land.physmatIds.x = PhysMat::getMaterialId(blk.getStr("physMatRed", defaultPhysmat)); + land.physmatIds.y = PhysMat::getMaterialId(blk.getStr("physMatGreen", defaultPhysmat)); + land.physmatIds.z = PhysMat::getMaterialId(blk.getStr("physMatBlue", defaultPhysmat)); + land.physmatIds.w = PhysMat::getMaterialId(blk.getStr("physMatBlack", defaultPhysmat)); + flowmapTiling = safediv(size.x, max(max(detailSizeRed, detailSizeGreen), max(detailSizeBlue, detailSizeBlack))); for (int dType = 0; dType < NUM_TEXTURES_STACK; ++dType) diff --git a/prog/gameLibs/landMesh/lmeshRenderer.cpp b/prog/gameLibs/landMesh/lmeshRenderer.cpp index b16a7e1d2..542429ac9 100644 --- a/prog/gameLibs/landMesh/lmeshRenderer.cpp +++ b/prog/gameLibs/landMesh/lmeshRenderer.cpp @@ -48,6 +48,8 @@ struct LCTexturesLoaded Point4 randomFlowmapParams = {64.0, 0.0, 0.0, 0.0}; Point4 flowmapMask = {1.0, 1.0, 1.0, 1.0}; Point4 waterDecalBumpScale = {1.0, 0.0, 0.0, 0.0}; + IPoint4 physmatIDs = {0, 0, 0, 0}; + mutable bool lastUsedGrassMask = false; }; @@ -112,6 +114,8 @@ static int lmesh_sampler__max_used_sampler = -1; static int lmesh_ps_const_land_detail_array_slices = -1; static int lmesh_sampler__land_detail_array1 = -1; +static int lmesh_physmats__buffer_idx = -1; + static int get_shader_int_constant(const char *name, int def) { int varId = ::get_shader_variable_id(name, true); @@ -248,6 +252,7 @@ struct CellState } mirrorState; int numDetailTextures; carray lcIds; + Point4 posToWorld[2]; Color4 detMapTc; Color4 invTexSizes[2]; @@ -265,28 +270,43 @@ struct CellState ShaderGlobal::set_int_fast(num_detail_textures_gvid, numDetailTextures); // d3d::set_vs_const(lmesh_vs_const__mul_offset_base+8, (const float*)detMapTcSet, 1); } - inline void set(bool grass_mask, dag::ConstSpan lc, bool force_trivial, bool water_decals) const + inline void set(bool grass_mask, dag::ConstSpan lc, bool force_trivial, bool water_decals, + Sbuffer *physmatIdsBuf = NULL) const { if (!water_decals) setBase(); + uint32_t physmats[4 * 7]; // fixme: fill with nulls or leave samplers untouched? if ((force_trivial || trivial || grass_mask) && !water_decals) { for (int i = 0; i < numDetailTextures; ++i) // LandMeshRenderer::DET_TEX_NUM + { if (lcIds[i] < lc.size()) { TEXTUREID tid = grass_mask ? lc[lcIds[i]].grassMask : lc[lcIds[i]].colorMap; mark_managed_tex_lfu(tid); d3d::set_tex(STAGE_PS, lmesh_sampler__land_detail_tex1 + i, D3dResManagerData::getBaseTex(tid)); if (grass_mask) + { + physmats[i * 4 + 0] = lc[lcIds[i]].physmatIDs.x; + physmats[i * 4 + 1] = lc[lcIds[i]].physmatIDs.y; + physmats[i * 4 + 2] = lc[lcIds[i]].physmatIDs.z; + physmats[i * 4 + 3] = lc[lcIds[i]].physmatIDs.w; lc[lcIds[i]].lastUsedGrassMask = true; + } } else d3d::set_tex(STAGE_PS, lmesh_sampler__land_detail_tex1 + i, nullptr); + } d3d::set_vs_const(lmesh_vs_const__mul_offset_base, (float *)mul_offset[mirrorState.x][mirrorState.y], 8); // if (normalmap) if (!grass_mask && lmesh_ps_const__invtexturesizes >= 0) d3d::set_ps_const(lmesh_ps_const__invtexturesizes, (float *)&invTexSizes[0].r, 2); + if (grass_mask && lmesh_physmats__buffer_idx > 0 && physmatIdsBuf) + { + physmatIdsBuf->updateDataWithLock(0, 4 * 7 * 4, &physmats[0], VBLOCK_WRITEONLY | VBLOCK_DISCARD); + d3d::set_buffer(STAGE_PS, lmesh_physmats__buffer_idx, physmatIdsBuf); + } } } @@ -546,6 +566,12 @@ LandMeshRenderer::LandMeshRenderer(LandMeshManager &provider, dag::ConstSpan 0) + physmatIdsBuf = d3d::buffers::create_one_frame_sr_structured(sizeof(uint32_t), DET_TEX_NUM * 4 * 4, "physmats_IDS"); + else + physmatIdsBuf = NULL; + G_ASSERT(lmesh_sampler__land_detail_map >= 0); G_ASSERT(lmesh_sampler__land_detail_tex1 >= 0); #undef GET_SHADER_CONSTANT @@ -663,6 +689,7 @@ LandMeshRenderer::~LandMeshRenderer() if (useConditionalRendering) bboxShader.close(); del_d3dres(one_quad); + del_d3dres(physmatIdsBuf); landclassShader.clear(); shadersNames.erase(shadersNames.begin(), shadersNames.end()); } @@ -960,6 +987,8 @@ void LandMeshRenderer::prepareLandClasses(LandMeshManager &provider) landClassesLoaded[i].flowmapTex = query_tex_loading(landClasses[i].flowmapTex, true); + landClassesLoaded[i].physmatIDs = landClasses[i].physmatIds; + for (int dtype = 0; dtype < landClasses[i].lcDetailTextures.size(); ++dtype) { landClassesLoaded[i].lcDetailTextures[dtype] = landClasses[i].lcDetailTextures[dtype]; @@ -1767,7 +1796,8 @@ void LandMeshRenderer::renderCell(LandMeshManager &provider, int cellNo, int lod if (rtype <= MAX_RENDER_SPLATTING__) { mirroredCell.setDetMapTc(); - curState.set(rtype == RENDER_GRASS_MASK, landClassesLoaded, shouldRenderTrivially, false); + curState.set(rtype == RENDER_GRASS_MASK, landClassesLoaded, shouldRenderTrivially, false, + rtype == RENDER_GRASS_MASK ? physmatIdsBuf : NULL); } diff --git a/prog/gameLibs/landMesh/shaders/biomes.sh b/prog/gameLibs/landMesh/shaders/biomes.sh index 5129aa91b..3a7963426 100644 --- a/prog/gameLibs/landMesh/shaders/biomes.sh +++ b/prog/gameLibs/landMesh/shaders/biomes.sh @@ -8,12 +8,10 @@ macro INIT_BIOMES(stage) (stage) { land_detail_mul_offset@f4 = land_detail_mul_offset; biomeIndicesTex@smp2d = biomeIndicesTex; - biomeDetailAlbedoTexArray@smpArray = biomeDetailAlbedoTexArray; biome_indices_tex_size@f4 = biome_indices_tex_size; // xy: size, zw: inv size biome_group_indices_buffer@buf = biome_group_indices_buffer hlsl { StructuredBuffer biome_group_indices_buffer@buf; } - current_time@f1 = (time_phase(0, 0)); } endmacro @@ -48,17 +46,5 @@ macro USE_BIOMES(stage) float4 indexComp = floor(biomeIndicesTex.GatherRed(biomeIndicesTex_samplerstate, useDetailTC) * 255 + 0.1f) == index; return dot(indexComp, baseWeights); } - - float4 getBiomeColorByIndex(float2 world_pos, float4 index0, float4 index1) - { - uint texw, texh, layers, max_mip; - biomeDetailAlbedoTexArray.GetDimensions(0, texw, texh, layers, max_mip); - int mip = max(max_mip - 3, 0); - float2 noiseTC = world_pos.xy * current_time; - float2 tc = float2(noise_Perlin2D(noiseTC.xy), noise_Perlin2D(noiseTC.yx)) * 0.5 + 0.5; - float4 diffuse0 = tex3Dlod(biomeDetailAlbedoTexArray, float4(tc, index0.x, mip)); - float4 diffuse1 = tex3Dlod(biomeDetailAlbedoTexArray, float4(tc, index1.x, mip)); - return lerp(diffuse0, diffuse1, noise_Value2D(current_time)); - } } endmacro diff --git a/prog/gameLibs/publicInclude/ADT/fastHashNameMap.h b/prog/gameLibs/publicInclude/ADT/fastHashNameMap.h index 201c3d704..7bb4f8f12 100644 --- a/prog/gameLibs/publicInclude/ADT/fastHashNameMap.h +++ b/prog/gameLibs/publicInclude/ADT/fastHashNameMap.h @@ -20,7 +20,7 @@ struct equal_to_2 : public eastl::equal_to_2 template <> struct equal_to_2 : eastl::binary_function { - bool operator()(const char *a, const eastl::string_view &b) const { return strcmp(a, b.data()) == 0; } + bool operator()(const eastl::string_view &a, const char *b) const { return strcmp(a.data(), b) == 0; } }; } // namespace detail diff --git a/prog/gameLibs/publicInclude/daRg/dag_guiConstants.h b/prog/gameLibs/publicInclude/daRg/dag_guiConstants.h index 530b8a826..fe32d0e04 100644 --- a/prog/gameLibs/publicInclude/daRg/dag_guiConstants.h +++ b/prog/gameLibs/publicInclude/daRg/dag_guiConstants.h @@ -67,6 +67,7 @@ enum VectorCanvasCommand VECTOR_SECTOR, VECTOR_RECTANGLE, VECTOR_POLY, + VECTOR_QUADS, VECTOR_INVERSE_POLY, VECTOR_OPACITY, VECTOR_LINE_DASHED, diff --git a/prog/gameLibs/publicInclude/dasModules/aotDacoll.h b/prog/gameLibs/publicInclude/dasModules/aotDacoll.h index 60b992f66..5996f2d4f 100644 --- a/prog/gameLibs/publicInclude/dasModules/aotDacoll.h +++ b/prog/gameLibs/publicInclude/dasModules/aotDacoll.h @@ -81,6 +81,11 @@ inline bool dacoll_tracedown_normalized_with_pmid(Point3 p, float &out_t, int &o return dacoll::tracedown_normalized(p, out_t, &out_pmid, nullptr, flags); } +inline bool dacoll_tracedown_normalized_with_norm_and_pmid(Point3 p, float &out_t, int &out_pmid, Point3 &out_norm, int flags) +{ + return dacoll::tracedown_normalized(p, out_t, &out_pmid, &out_norm, flags); +} + inline bool dacoll_tracedown_normalized_trace_handle_with_pmid(Point3 p, float &out_t, int &out_pmid, int flags, const TraceMeshFaces *handle) { diff --git a/prog/gameLibs/publicInclude/dasModules/aotDm.h b/prog/gameLibs/publicInclude/dasModules/aotDm.h index b093e8cbf..139ee3a2f 100644 --- a/prog/gameLibs/publicInclude/dasModules/aotDm.h +++ b/prog/gameLibs/publicInclude/dasModules/aotDm.h @@ -40,7 +40,6 @@ MAKE_TYPE_FACTORY(CollisionData, dm::CollisionData); MAKE_TYPE_FACTORY(DamageModelData, dm::DamageModelData); MAKE_TYPE_FACTORY(DamageModel, dm::DamageModel); MAKE_TYPE_FACTORY(HitData, dm::HitData); -MAKE_TYPE_FACTORY(DamagePartPropsCached, dm::DamagePartPropsCached); MAKE_TYPE_FACTORY(DamagePart, dm::DamagePart); MAKE_TYPE_FACTORY(DamagePartProps, dm::DamagePartProps); DAS_BIND_VECTOR(DamageModelDataPartProps, DamageModelDataPartProps, dm::DamagePartProps, "DamageModelDataPartProps"); @@ -161,7 +160,8 @@ inline float get_max_hp(const dm::DamageModelData &dm_data, int part_id) inline bool is_part_inner(const dm::DamageModelData &dm_data, int part_id) { - return get_part_props(dm_data, dm::PartId(part_id, -1)).testFlag(dm::DamagePartProps::Flag::INNER); + const dm::DamagePartProps *props = get_part_props(dm_data, dm::PartId(part_id, -1)); + return props && props->testFlag(dm::DamagePartProps::Flag::INNER); } inline dm::splash::Params calc_splash_params(int damage_props_id, bool underwater) @@ -187,7 +187,8 @@ inline const dm::effect::ActionCluster *get_damage_effect_action_cluster(const d inline float get_part_hp_prop_value(const dm::DamageModelData &dm_data, const dm::PartId &part_id) { - return dm::get_part_props(dm_data, part_id).hp; + const dm::DamagePartProps *props = dm::get_part_props(dm_data, part_id); + return props ? props->hp : 0.f; } } // namespace bind_dascript diff --git a/prog/gameLibs/publicInclude/fftWater/fftWater.h b/prog/gameLibs/publicInclude/fftWater/fftWater.h index 72df9d2cf..81db4271b 100644 --- a/prog/gameLibs/publicInclude/fftWater/fftWater.h +++ b/prog/gameLibs/publicInclude/fftWater/fftWater.h @@ -246,6 +246,7 @@ void set_flowmap_params(FlowmapParams &flowmap_params); void set_flowmap_foam_params(FlowmapParams &flowmap_params); void close_flowmap(FlowmapParams &flowmap_params); bool is_flowmap_active(const FlowmapParams &flowmap_params); +void flowmap_floodfill(int texSize, Texture *heightmapTex, Texture *floodfillTex, uint16_t heightmapLevel); void deferred_wet_ground(FFTWater *handle, const Point3 &pos); void prepare_refraction(FFTWater *handle, Texture *scene_target_tex); void set_current_time(FFTWater *handle, double time); // remove me! should not be used! diff --git a/prog/gameLibs/publicInclude/gamePhys/phys/commonPhysBase.h b/prog/gameLibs/publicInclude/gamePhys/phys/commonPhysBase.h index 9e50ad736..457bd6548 100644 --- a/prog/gameLibs/publicInclude/gamePhys/phys/commonPhysBase.h +++ b/prog/gameLibs/publicInclude/gamePhys/phys/commonPhysBase.h @@ -558,6 +558,10 @@ class PhysicsBase : public IPhysBase if (max_queue_size > 0 && unapprovedCT.size() > max_queue_size) safe_erase_items(unapprovedCT, 0, unapprovedCT.size() - 1); + // Ctrls from a far future are abnormal and may break the logic. Can happen briefly when we switch tickrate. + if (max_queue_size > 0 && state.producedAtTick > currentState.atTick + max_queue_size) + return true; + // TODO: count lost controls for controlling player here. if (!unapprovedCT.empty()) { diff --git a/prog/gameLibs/publicInclude/gamePhys/phys/rendinstFloating.h b/prog/gameLibs/publicInclude/gamePhys/phys/rendinstFloating.h index 803d86950..89b72b36e 100644 --- a/prog/gameLibs/publicInclude/gamePhys/phys/rendinstFloating.h +++ b/prog/gameLibs/publicInclude/gamePhys/phys/rendinstFloating.h @@ -37,8 +37,8 @@ struct PhysFloatingModel { int resIdx = -1; int processedRiTmCount = 0; - float massMin = 0.0f; - float massMax = 0.0f; + float randMassMin = 0.0f; + float randMassMax = 0.0f; float spheresRad = 0.0f; Point3 invMomentOfInertiaCoeff; BBox3 physBbox; diff --git a/prog/gameLibs/publicInclude/landMesh/landClass.h b/prog/gameLibs/publicInclude/landMesh/landClass.h index 2baf657f9..42b4f691a 100644 --- a/prog/gameLibs/publicInclude/landMesh/landClass.h +++ b/prog/gameLibs/publicInclude/landMesh/landClass.h @@ -6,6 +6,7 @@ #pragma once #include <3d/dag_texMgr.h> +#include class Sbuffer; @@ -58,6 +59,9 @@ struct LandClassDetailTextures Point4 waterDecalBumpScale; // todo: we can just use dfferent Constant Buffers char shader_name[64] = {0}; + + IPoint4 physmatIds; + enum { DETAIL_RED = 0, diff --git a/prog/gameLibs/publicInclude/landMesh/lmeshHoles.h b/prog/gameLibs/publicInclude/landMesh/lmeshHoles.h index 3baa9072a..f94d14f28 100644 --- a/prog/gameLibs/publicInclude/landMesh/lmeshHoles.h +++ b/prog/gameLibs/publicInclude/landMesh/lmeshHoles.h @@ -9,7 +9,7 @@ * Dagor Engine 4 - Game Libraries * Copyright (C) 2003-2023 Gaijin Entertainment. All rights reserved * - * (for conditions of distribution and use, see EULA in "prog/eula.txt") + * (for conditions of use see prog/license.txt) */ #ifndef _DAGOR_GAMELIB_LANDMESH_LMESHHOLES_H_ diff --git a/prog/gameLibs/publicInclude/landMesh/lmeshRenderer.h b/prog/gameLibs/publicInclude/landMesh/lmeshRenderer.h index f3e1fd0c0..40e0d0201 100644 --- a/prog/gameLibs/publicInclude/landMesh/lmeshRenderer.h +++ b/prog/gameLibs/publicInclude/landMesh/lmeshRenderer.h @@ -231,6 +231,9 @@ class LandMeshRenderer TEXTUREID vertTexId; TEXTUREID vertNmTexId; TEXTUREID vertDetTexId; + + Sbuffer *physmatIdsBuf; // physmats for mega landclass + struct MirroredCellState { Point4 posToWorldSet[2]; diff --git a/prog/gameLibs/publicInclude/quirrel/sqModules/sqModules.h b/prog/gameLibs/publicInclude/quirrel/sqModules/sqModules.h index cc6c05f22..3134a5ccd 100644 --- a/prog/gameLibs/publicInclude/quirrel/sqModules/sqModules.h +++ b/prog/gameLibs/publicInclude/quirrel/sqModules/sqModules.h @@ -92,6 +92,7 @@ class SqModules void registerIoStreamLib(); void registerIoLib(); void registerDateTimeLib(); + void registerDebugLib(); template void forEachNativeModule(const F &cb); // 'cb' called as cb(const char *module_name, const Sqrat::Object &module) diff --git a/prog/gameLibs/publicInclude/render/bcCompressor.h b/prog/gameLibs/publicInclude/render/bcCompressor.h index 7cc7dac33..6a9ebc7c1 100644 --- a/prog/gameLibs/publicInclude/render/bcCompressor.h +++ b/prog/gameLibs/publicInclude/render/bcCompressor.h @@ -83,6 +83,13 @@ class BcCompressor }; SmallTab verts; Vbuffer *vb; + struct VbFiller : public Sbuffer::IReloadData + { + void reloadD3dRes(Sbuffer *sb); + void destroySelf() {} + const SmallTab &verts; + VbFiller(const SmallTab &verts) : verts(verts) {} + } vbFiller; Ptr compressElem; Ptr compressElemCompute; Ptr compressMat; diff --git a/prog/gameLibs/publicInclude/render/burningDecals.h b/prog/gameLibs/publicInclude/render/burningDecals.h index b2aea6b4d..5c88dbf7f 100644 --- a/prog/gameLibs/publicInclude/render/burningDecals.h +++ b/prog/gameLibs/publicInclude/render/burningDecals.h @@ -52,7 +52,7 @@ class BurningDecals int clipmapDecalType = 0; int resolution = 1024; DynamicShaderHelper material; - UniqueBufHolder decalDataVS; + UniqueBuf decalDataVS; struct InstData { diff --git a/prog/gameLibs/publicInclude/render/daBfg/autoResolutionRequest.h b/prog/gameLibs/publicInclude/render/daBfg/autoResolutionRequest.h index bbbeaf2ff..3d26568d0 100644 --- a/prog/gameLibs/publicInclude/render/daBfg/autoResolutionRequest.h +++ b/prog/gameLibs/publicInclude/render/daBfg/autoResolutionRequest.h @@ -8,7 +8,7 @@ namespace dabfg { -struct InternalRegistry; +struct ResourceProvider; namespace detail { struct VirtualResourceRequestBase; @@ -31,7 +31,8 @@ class AutoResolutionRequest friend class NameSpaceRequest; friend struct detail::VirtualResourceRequestBase; - AutoResolutionRequest(AutoResTypeNameId id, float mult, InternalRegistry *r) : autoResTypeId{id}, multiplier{mult}, registry{r} {} + AutoResolutionRequest(AutoResTypeNameId id, float mult, const ResourceProvider *p) : autoResTypeId{id}, multiplier{mult}, provider{p} + {} public: /** @@ -47,7 +48,7 @@ class AutoResolutionRequest private: AutoResTypeNameId autoResTypeId; float multiplier = 1.f; - InternalRegistry *registry; + const ResourceProvider *provider; }; } // namespace dabfg \ No newline at end of file diff --git a/prog/gameLibs/publicInclude/render/daBfg/nameSpace.h b/prog/gameLibs/publicInclude/render/daBfg/nameSpace.h index 577aa26a1..80d86ac32 100644 --- a/prog/gameLibs/publicInclude/render/daBfg/nameSpace.h +++ b/prog/gameLibs/publicInclude/render/daBfg/nameSpace.h @@ -6,6 +6,7 @@ #pragma once #include +#include #include #include @@ -35,6 +36,7 @@ namespace dabfg class NameSpace { friend NameSpace root(); + friend struct eastl::hash; NameSpace(); NameSpace(NameSpaceNameId nid); @@ -163,6 +165,8 @@ class NameSpace */ void unmarkResourceExternallyConsumed(const char *res_name); + friend bool operator==(const NameSpace &fst, const NameSpace &snd) { return fst.nameId == snd.nameId; } + private: auto resolveName(const char *name) const; @@ -170,3 +174,17 @@ class NameSpace }; } // namespace dabfg + +namespace eastl +{ + +template <> +struct hash +{ + size_t operator()(dabfg::NameSpace ns) const + { + return eastl::hash>{}(eastl::to_underlying(ns.nameId)); + } +}; + +} // namespace eastl diff --git a/prog/gameLibs/publicInclude/render/foam/foamFx.h b/prog/gameLibs/publicInclude/render/foam/foamFx.h index 7cd627da3..d89d3d6b5 100644 --- a/prog/gameLibs/publicInclude/render/foam/foamFx.h +++ b/prog/gameLibs/publicInclude/render/foam/foamFx.h @@ -31,7 +31,7 @@ class FoamFx void setParams(const FoamFxParams ¶ms); - void prepare(); + void prepare(const TMatrix4 &view_tm, const TMatrix4 &proj_tm); void renderHeight(); void renderFoam(); diff --git a/prog/gameLibs/publicInclude/render/fx/dag_demonPostFx.h b/prog/gameLibs/publicInclude/render/fx/dag_demonPostFx.h index 7328caa5f..1a993edb8 100644 --- a/prog/gameLibs/publicInclude/render/fx/dag_demonPostFx.h +++ b/prog/gameLibs/publicInclude/render/fx/dag_demonPostFx.h @@ -306,6 +306,12 @@ class DemonPostFx int currentHistogramTexture; int histogramLockCounter; UniqueBuf histogramVb; + struct HistBufferFiller : public Sbuffer::IReloadData + { + void reloadD3dRes(Sbuffer *buf); + void destroySelf() {} + IPoint2 vbSize; + } histBufferFiller; bool centerWeightedAdaptation; ShaderMaterial *histogramCalcMat; ShaderElement *histogramCalcElement; diff --git a/prog/gameLibs/publicInclude/render/gpuGrass.h b/prog/gameLibs/publicInclude/render/gpuGrass.h index 0df51c005..7220235dd 100644 --- a/prog/gameLibs/publicInclude/render/gpuGrass.h +++ b/prog/gameLibs/publicInclude/render/gpuGrass.h @@ -64,7 +64,6 @@ class GPUGrassBase typedef eastl::function frustum_heights_cb_t; void generate(const Point3 &pos, const Point3 &view_dir, const frustum_heights_cb_t &cb, GrassPreRenderCallback pre_render_cb); - void bindGrassBuffers(); enum RenderType { diff --git a/prog/gameLibs/publicInclude/render/resourceSlot/actions.h b/prog/gameLibs/publicInclude/render/resourceSlot/actions.h index cdc705c8e..2091a7df4 100644 --- a/prog/gameLibs/publicInclude/render/resourceSlot/actions.h +++ b/prog/gameLibs/publicInclude/render/resourceSlot/actions.h @@ -25,8 +25,8 @@ struct Create const char *slotName; const char *resourceName; - friend NodeHandleWithSlotsAccess resource_slot::detail::register_access(const char *, const char *, - resource_slot::detail::ActionList &&, resource_slot::detail::AccessCallback &&, unsigned); + friend NodeHandleWithSlotsAccess resource_slot::detail::register_access(dabfg::NameSpace, const char *, const char *, + resource_slot::detail::ActionList &&, resource_slot::detail::AccessCallback &&); }; /** Update request @@ -54,8 +54,8 @@ struct Update const char *resourceName; int priority; - friend NodeHandleWithSlotsAccess resource_slot::detail::register_access(const char *, const char *, - resource_slot::detail::ActionList &&, resource_slot::detail::AccessCallback &&, unsigned); + friend NodeHandleWithSlotsAccess resource_slot::detail::register_access(dabfg::NameSpace, const char *, const char *, + resource_slot::detail::ActionList &&, resource_slot::detail::AccessCallback &&); }; /** Read request @@ -79,8 +79,8 @@ struct Read int priority; static constexpr int DEFAULT_READ_PRIORITY = INT_MAX; - friend NodeHandleWithSlotsAccess resource_slot::detail::register_access(const char *, const char *, - resource_slot::detail::ActionList &&, resource_slot::detail::AccessCallback &&, unsigned); + friend NodeHandleWithSlotsAccess resource_slot::detail::register_access(dabfg::NameSpace, const char *, const char *, + resource_slot::detail::ActionList &&, resource_slot::detail::AccessCallback &&); }; } // namespace resource_slot \ No newline at end of file diff --git a/prog/gameLibs/publicInclude/render/resourceSlot/detail/registerAccess.h b/prog/gameLibs/publicInclude/render/resourceSlot/detail/registerAccess.h index ceac136e2..ec9877770 100644 --- a/prog/gameLibs/publicInclude/render/resourceSlot/detail/registerAccess.h +++ b/prog/gameLibs/publicInclude/render/resourceSlot/detail/registerAccess.h @@ -2,6 +2,7 @@ #include #include +#include #include @@ -22,8 +23,8 @@ namespace detail inline constexpr size_t MAX_CALLBACK_SIZE = 128; typedef dag::FixedMoveOnlyFunction AccessCallback; -[[nodiscard]] NodeHandleWithSlotsAccess register_access(const char *name, const char *source_location, ActionList &&action_list, - AccessCallback &&declaration_callback, unsigned storage_id); +[[nodiscard]] NodeHandleWithSlotsAccess register_access(dabfg::NameSpace ns, const char *name, const char *source_location, + ActionList &&action_list, AccessCallback &&declaration_callback); } // namespace detail diff --git a/prog/gameLibs/publicInclude/render/resourceSlot/nodeHandleWithSlotsAccess.h b/prog/gameLibs/publicInclude/render/resourceSlot/nodeHandleWithSlotsAccess.h index 8ad1c3c9c..0ccfec9cf 100644 --- a/prog/gameLibs/publicInclude/render/resourceSlot/nodeHandleWithSlotsAccess.h +++ b/prog/gameLibs/publicInclude/render/resourceSlot/nodeHandleWithSlotsAccess.h @@ -1,5 +1,8 @@ #pragma once +#include + + namespace resource_slot { @@ -40,15 +43,15 @@ struct NodeHandleWithSlotsAccess * INTERNAL use only * \private */ - NodeHandleWithSlotsAccess(unsigned storage_id, int handle_id, unsigned generation_number); + NodeHandleWithSlotsAccess(dabfg::NameSpace ns, int handle_id, unsigned generation_number); private: - unsigned storageId : 4; - int id : 28; + dabfg::NameSpace nameSpace; + int id; unsigned generation : 31; unsigned valid : 1; }; -static_assert(sizeof(NodeHandleWithSlotsAccess) == sizeof(unsigned) * 2); +static_assert(sizeof(NodeHandleWithSlotsAccess) == sizeof(unsigned) * 3); } // namespace resource_slot \ No newline at end of file diff --git a/prog/gameLibs/publicInclude/render/resourceSlot/registerAccess.h b/prog/gameLibs/publicInclude/render/resourceSlot/registerAccess.h index 7f6df8faf..fecaeedac 100644 --- a/prog/gameLibs/publicInclude/render/resourceSlot/registerAccess.h +++ b/prog/gameLibs/publicInclude/render/resourceSlot/registerAccess.h @@ -45,6 +45,7 @@ namespace resource_slot * }); * \endcode * + * \param ns name space where the slot, the node, and all of the resources will be looked up in * \param name node name * \param source_location SHOULD be DABFG_PP_NODE_SRC * \param action_list list of slots, that will be created, updated or read by the node @@ -54,16 +55,22 @@ namespace resource_slot * \returns handle for access to storage */ template -[[nodiscard]] resource_slot::NodeHandleWithSlotsAccess register_access(const char *name, const char *source_location, - resource_slot::detail::ActionList &&action_list, F &&declaration_callback, unsigned storage_id = 0) +[[nodiscard]] resource_slot::NodeHandleWithSlotsAccess register_access(dabfg::NameSpace ns, const char *name, + const char *source_location, resource_slot::detail::ActionList &&action_list, F &&declaration_callback) { - return resource_slot::detail::register_access( - name, source_location, eastl::move(action_list), - [declCb = eastl::forward(declaration_callback), name, source_location](resource_slot::State s) mutable { - return dabfg::register_node(name, source_location, + return resource_slot::detail::register_access(ns, name, source_location, eastl::move(action_list), + [ns, declCb = eastl::forward(declaration_callback), name, source_location](resource_slot::State s) mutable { + return ns.registerNode(name, source_location, [declCb2 = eastl::forward(declCb), s](dabfg::Registry r) { return declCb2(eastl::move(s), r); }); - }, - storage_id); + }); +} + +template +[[nodiscard]] resource_slot::NodeHandleWithSlotsAccess register_access(const char *name, const char *source_location, + resource_slot::detail::ActionList &&action_list, F &&declaration_callback) +{ + return resource_slot::register_access(dabfg::root(), name, source_location, eastl::move(action_list), + eastl::forward(declaration_callback)); } } // namespace resource_slot \ No newline at end of file diff --git a/prog/gameLibs/publicInclude/render/resourceSlot/resolveAccess.h b/prog/gameLibs/publicInclude/render/resourceSlot/resolveAccess.h index 2baf78f63..d7b8caf7e 100644 --- a/prog/gameLibs/publicInclude/render/resourceSlot/resolveAccess.h +++ b/prog/gameLibs/publicInclude/render/resourceSlot/resolveAccess.h @@ -8,5 +8,5 @@ namespace resource_slot * * \param storage_id RESERVED for future use */ -void resolve_access(unsigned storage_id = 0); +void resolve_access(); } // namespace resource_slot \ No newline at end of file diff --git a/prog/gameLibs/publicInclude/render/resourceSlot/state.h b/prog/gameLibs/publicInclude/render/resourceSlot/state.h index 16885199f..da1c4abe8 100644 --- a/prog/gameLibs/publicInclude/render/resourceSlot/state.h +++ b/prog/gameLibs/publicInclude/render/resourceSlot/state.h @@ -39,13 +39,13 @@ struct State const char *resourceToCreateFor(const char *slot_name) const; private: - unsigned storageId : 4; - int nodeId : 28; + dabfg::NameSpace nameSpace; + int nodeId; - State(unsigned storage_id, int node_id); - friend void resource_slot::resolve_access(unsigned); + State(dabfg::NameSpace ns, int node_id); + friend void resource_slot::resolve_access(); }; -static_assert(sizeof(State) == sizeof(int)); +static_assert(sizeof(State) == sizeof(int) * 2); } // namespace resource_slot \ No newline at end of file diff --git a/prog/gameLibs/publicInclude/render/shipWakeFx.h b/prog/gameLibs/publicInclude/render/shipWakeFx.h index 036d4a9c2..b0d8fd31d 100644 --- a/prog/gameLibs/publicInclude/render/shipWakeFx.h +++ b/prog/gameLibs/publicInclude/render/shipWakeFx.h @@ -37,6 +37,7 @@ class ShipWakeFx void clearShips(); int getShipsCount() const; bool isShipRemoved(uint32_t index) const; + const ShipDesc &getDesc(uint32_t index) const; void setShipState(uint32_t index, const ShipState &state); void resetShipSpawnCounters(uint32_t index, bool jump = false); @@ -66,6 +67,8 @@ class ShipWakeFx struct ShipDesc { BBox3 box; + float scale; + float trailLifeScale; }; struct ShipState @@ -76,6 +79,7 @@ class ShipWakeFx float wakeHeadOffset = 0.f; float wakeHeadShift = 0.f; bool hasFront = true; + bool hasBack = true; eastl::optional> foamVelocityThresholds; }; diff --git a/prog/gameLibs/publicInclude/render/tireTracks.h b/prog/gameLibs/publicInclude/render/tireTracks.h index 14bbf2347..959445701 100644 --- a/prog/gameLibs/publicInclude/render/tireTracks.h +++ b/prog/gameLibs/publicInclude/render/tireTracks.h @@ -50,6 +50,9 @@ void delete_emitter(int id); // level specific params void set_current_params(const DataBlock *data); +// removes tire tracks in given bounding box +void invalidate_region(const BBox3 &bbox); + // track updated regions holder void add_updated_region(const BBox3 &bbox); const Tab &get_updated_regions(); diff --git a/prog/gameLibs/publicInclude/render/tracer.h b/prog/gameLibs/publicInclude/render/tracer.h index 891a8335a..e58d619d7 100644 --- a/prog/gameLibs/publicInclude/render/tracer.h +++ b/prog/gameLibs/publicInclude/render/tracer.h @@ -105,7 +105,7 @@ class TracerManager : public cpujobs::IJob void update(float dt); void beforeRender(const Frustum *frustum_); - void renderTrans(bool heads = true, bool trails = true, float *hk = NULL, HeadPrimType head_prim_type = HEAD_PRIM_DIR); + void renderTrans(bool heads = true, bool trails = true, const float *hk = NULL, HeadPrimType head_prim_type = HEAD_PRIM_DIR); void finishPreparingIfNecessary(); Tracer *createTracer(const Point3 &start_pos, const Point3 &speed, int tracerType, int trailType, float caliber, bool force = false, @@ -137,7 +137,8 @@ class TracerManager : public cpujobs::IJob int lock(uint32_t ofs_bytes, uint32_t size_bytes, void **p, int flags); void unlock(); void append(uint32_t id, dag::ConstSpan elem); - void process(ComputeShaderElement *cs, int fx_create_cmd, int element_count); + void process(ComputeShaderElement *cs, int commands_array_const_no, int commands_count_const_no, int fx_create_cmd, + int element_count); inline Sbuffer *getSbuffer() const { return buf.get(); } inline uint8_t *getData() { return data.data(); } @@ -208,6 +209,9 @@ class TracerManager : public cpujobs::IJob eastl::unique_ptr tailIndirectRingBuffer; volatile int ringBufferPos = 0; + int commandsCountConstNo; + int commandsArrayConstNo; + DrawBuffer tracerBuffer; DrawBuffer tracerDynamicBuffer; DrawBuffer segmentBuffer; diff --git a/prog/gameLibs/publicInclude/render/viewVecs.h b/prog/gameLibs/publicInclude/render/viewVecs.h index 5f8e3dfcc..ab99c9b32 100644 --- a/prog/gameLibs/publicInclude/render/viewVecs.h +++ b/prog/gameLibs/publicInclude/render/viewVecs.h @@ -15,7 +15,5 @@ extern void set_viewvecs_to_shader(const TMatrix &viewTm, const TMatrix4 &projTm // TODO remove this, uses gettm extern void set_viewvecs_to_shader(); -extern void set_inv_globtm_to_shader(const TMatrix4 &viewTm, const TMatrix4 &projTm, bool optional); // if optional, will not set - // non-existent variables -// TODO remove this, uses gettm -extern void set_inv_globtm_to_shader(bool optional); // if optional, will not set non-existent variables +// if optional, will not set non-existent variables +extern void set_inv_globtm_to_shader(const TMatrix4 &viewTm, const TMatrix4 &projTm, bool optional); diff --git a/prog/gameLibs/publicInclude/render/wakePs.h b/prog/gameLibs/publicInclude/render/wakePs.h index 11eef73c6..6a15eafa8 100644 --- a/prog/gameLibs/publicInclude/render/wakePs.h +++ b/prog/gameLibs/publicInclude/render/wakePs.h @@ -240,7 +240,6 @@ class EffectManager eastl::unique_ptr clearShader; DynamicShaderHelper renderShaders[ParticleSystem::RENDER_TYPE_END]; - BufPtr particleQuadIB; TexPtr randomBuffer; int fTimeVarId; diff --git a/prog/gameLibs/publicInclude/soundSystem/banks.h b/prog/gameLibs/publicInclude/soundSystem/banks.h index 23ecc417c..970fcc8a0 100644 --- a/prog/gameLibs/publicInclude/soundSystem/banks.h +++ b/prog/gameLibs/publicInclude/soundSystem/banks.h @@ -21,8 +21,8 @@ namespace sndsys namespace banks { using PresetLoadedCallback = eastl::function; -using ErrorCallback = - eastl::function; +using ErrorCallback = eastl::function; using PathTags = dag::ConstSpan>; void init(const DataBlock &blk); diff --git a/prog/gameLibs/publicInclude/vromfsPacker/vromfsPacker.h b/prog/gameLibs/publicInclude/vromfsPacker/vromfsPacker.h index 19828de6e..2902733c3 100644 --- a/prog/gameLibs/publicInclude/vromfsPacker/vromfsPacker.h +++ b/prog/gameLibs/publicInclude/vromfsPacker/vromfsPacker.h @@ -9,7 +9,7 @@ * Dagor Engine 3 - Game Libraries * Copyright (C) 2023 Gaijin Games KFT. All rights reserved * - * (for conditions of distribution and use, see EULA in "prog/eula.txt") + * (for conditions of use see prog/license.txt) */ diff --git a/prog/gameLibs/publicInclude/waterDecals/waterDecalsRenderer.h b/prog/gameLibs/publicInclude/waterDecals/waterDecalsRenderer.h index 523569a2d..b55d4e27a 100644 --- a/prog/gameLibs/publicInclude/waterDecals/waterDecalsRenderer.h +++ b/prog/gameLibs/publicInclude/waterDecals/waterDecalsRenderer.h @@ -9,7 +9,7 @@ * Dagor Engine 3 - Game Libraries * Copyright (C) 2023 Gaijin Games KFT. All rights reserved * - * (for conditions of distribution and use, see EULA in "prog/eula.txt") + * (for conditions of use see prog/license.txt) */ struct IWaterDecalsRenderHelper diff --git a/prog/gameLibs/quirrel/sqModules/sqModules.cpp b/prog/gameLibs/quirrel/sqModules/sqModules.cpp index fe715d50e..04082e9b4 100644 --- a/prog/gameLibs/quirrel/sqModules/sqModules.cpp +++ b/prog/gameLibs/quirrel/sqModules/sqModules.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -906,6 +907,8 @@ void SqModules::registerSystemLib() { registerStdLibNativeModule("system", sqstd void SqModules::registerDateTimeLib() { registerStdLibNativeModule("datetime", sqstd_register_datetimelib); } +void SqModules::registerDebugLib() { registerStdLibNativeModule("debug", sqstd_register_debuglib); } + void SqModules::registerIoStreamLib() { HSQOBJECT hModule; diff --git a/prog/gameLibs/quirrel/udp/udp.cpp b/prog/gameLibs/quirrel/udp/udp.cpp index fffb8c6ec..b9309e946 100644 --- a/prog/gameLibs/quirrel/udp/udp.cpp +++ b/prog/gameLibs/quirrel/udp/udp.cpp @@ -39,6 +39,7 @@ using InputBuffer = eastl::fixed_ring_buffer; static WinCritSec input_buffer_mutex; static eastl::unique_ptr input_buffer; +static UDPPacket current_packet; static eastl::unordered_map sockets; static volatile int sockets_num = 0; @@ -75,24 +76,20 @@ class SocketsPollThread final : public DaThread { os_socket_addr from; int recvts = get_time_msec(); - WinAutoLock lock(input_buffer_mutex); - while (!input_buffer->full()) + while (true) { - UDPPacket &p = input_buffer->push_back(); + UDPPacket &p = current_packet; p.recvTime = recvts; p.sinfo = sinfo; int fromLen = sizeof(os_socket_addr); p.data.resize(p.data.max_size()); int nread = os_socket_recvfrom(sinfo->s, p.data.data(), p.data.max_size(), 0, &p.from, &fromLen); if (nread <= 0) - { - input_buffer->pop_back(); - return; - } - else - { - p.data.resize(nread); - } + break; + p.data.resize(nread); + WinAutoLock lock(input_buffer_mutex); + if (!input_buffer->full()) + input_buffer->push_back(p); } } diff --git a/prog/gameLibs/rendInst/render/extra/riExtraRendererT.h b/prog/gameLibs/rendInst/render/extra/riExtraRendererT.h index 04a8f54ad..9b24db4ba 100644 --- a/prog/gameLibs/rendInst/render/extra/riExtraRendererT.h +++ b/prog/gameLibs/rendInst/render/extra/riExtraRendererT.h @@ -430,6 +430,13 @@ class RiExtraRendererT : public DynamicVariantsPolicy //-V730 bool ignore_optimization_instances_limits, IPoint2 ofsAndCnt, int lod, uint16_t pool_order, const TexStreamingContext &texCtx, float dist2, const ShaderElement *shader_override = nullptr, bool gpu_instancing = false) { + if (ri_idx >= rendinst::riExtra.size()) + { + logerr("Attempted to add riex with pool index '%d' to RiExtraRendererT, total pool amount was '%d'.", ri_idx, + rendinst::riExtra.size()); + return; + } + if (should_hide_ri_extra_object_with_id(ri_idx)) return; diff --git a/prog/gameLibs/rendInst/render/genRender.cpp b/prog/gameLibs/rendInst/render/genRender.cpp index 4839a5b30..f4e129876 100644 --- a/prog/gameLibs/rendInst/render/genRender.cpp +++ b/prog/gameLibs/rendInst/render/genRender.cpp @@ -1747,6 +1747,13 @@ void RendInstGenData::renderByCells(rendinst::RenderPass render_pass, const rend int x = visibility.cellsLod[lodI][i].x; int z = visibility.cellsLod[lodI][i].z; int cellId = x + z * cellNumW; + if (cellId >= cells.size()) + { + logerr("RiGenVisibility::cellsLod[%d][%d] contained an invalid cell (%d, %d) while rendering riGen!" + " Cell dimensions were (%d, %d)", + lodI, i, x, z, cellNumW, cellNumH); + continue; + } RendInstGenData::Cell &cell = cells[cellId]; RendInstGenData::CellRtData *crt_ptr = cell.isReady(); if (!crt_ptr) diff --git a/prog/gameLibs/render/cascadeShadows.cpp b/prog/gameLibs/render/cascadeShadows.cpp index 4be84b544..fe1c5aab5 100644 --- a/prog/gameLibs/render/cascadeShadows.cpp +++ b/prog/gameLibs/render/cascadeShadows.cpp @@ -338,28 +338,13 @@ void CascadeShadowsPrivate::renderShadowsCascadesCb(csm_render_cascades_cb_t ren TIME_D3D_PROFILE(renderShadows); - Driver3dRenderTarget prevRt; - d3d::get_render_target(prevRt); - - DagorCurView savedView = ::grs_cur_view; - - Driver3dPerspective p; - bool op = d3d::getpersp(p); - + SCOPE_RENDER_TARGET; + SCOPE_VIEW_PROJ_MATRIX; ShaderGlobal::set_texture(shadowCascades.getVarId(), BAD_TEXTUREID); ShaderGlobal::setBlock(-1, ShaderGlobal::LAYER_SCENE); - - TMatrix4 viewTm, projTm; - d3d::gettm(TM_PROJ, &projTm); - d3d::gettm(TM_VIEW, &viewTm); - - d3d::settm(TM_VIEW, &TMatrix4::IDENT); - ::grs_cur_view.tm = TMatrix::IDENT; - ::grs_cur_view.itm = TMatrix::IDENT; - d3d::set_render_target(); d3d::set_render_target(nullptr, 0); bool clearPerView = false; @@ -391,16 +376,6 @@ void CascadeShadowsPrivate::renderShadowsCascadesCb(csm_render_cascades_cb_t ren if (curStateId) shaders::overrides::set(curStateId); - // Restore. - - d3d::set_render_target(prevRt); - ::grs_cur_view = savedView; - d3d::settm(TM_VIEW, &viewTm); - if (op) - d3d::setpersp(p); - else - d3d::settm(TM_PROJ, &projTm); - d3d::resource_barrier({shadowCascades.getTex2D(), RB_RO_SRV | RB_STAGE_PIXEL, 0, 0}); shadowCascades.setVar(); @@ -615,12 +590,14 @@ void CascadeShadowsPrivate::prepareShadowCascades(const CascadeShadows::ModeSett vec3f frustumPoints[8]; shadowSplits[numCascadesToRender - 1].frustum.generateAllPointFrustm(frustumPoints); - mat44f globtm; - d3d::getglobtm(globtm); + mat44f globtm44; + TMatrix4_vec4 globtm; + d3d::calcglobtm(view_matrix, proj_tm, globtm); + memcpy(&globtm44, globtm.m, sizeof(mat44f)); vec4f farPt = v_zero(); for (int i = 0; i < 8; ++i) { - vec4f point = v_mat44_mul_vec3p(globtm, frustumPoints[i]); + vec4f point = v_mat44_mul_vec3p(globtm44, frustumPoints[i]); farPt = v_sel(farPt, point, v_splat_w(v_cmp_gt(point, farPt))); } csmDistance = v_extract_w(farPt); @@ -864,8 +841,8 @@ void CascadeShadowsPrivate::buildShadowProjectionMatrix(const Point3 &dir_to_sun bbox3f frustumWorldBox; shadowFrustum.calcFrustumBBox(frustumWorldBox); - v_stu(&split.worldBox[0].x, v_add(frustumWorldBox.bmin, v_ldu(&::grs_cur_view.pos.x))); - v_stu_p3(&split.worldBox[1].x, v_add(frustumWorldBox.bmax, v_ldu(&::grs_cur_view.pos.x))); + v_stu(&split.worldBox[0].x, v_add(frustumWorldBox.bmin, v_ldu(&camera_pos.x))); + v_stu_p3(&split.worldBox[1].x, v_add(frustumWorldBox.bmax, v_ldu(&camera_pos.x))); } diff --git a/prog/gameLibs/render/daBfg/api/autoResolutionRequest.cpp b/prog/gameLibs/render/daBfg/api/autoResolutionRequest.cpp index 8818cf5f5..6a74a5554 100644 --- a/prog/gameLibs/render/daBfg/api/autoResolutionRequest.cpp +++ b/prog/gameLibs/render/daBfg/api/autoResolutionRequest.cpp @@ -6,6 +6,6 @@ namespace dabfg { -IPoint2 AutoResolutionRequest::get() const { return registry->autoResTypes[autoResTypeId].dynamicResolution; } +IPoint2 AutoResolutionRequest::get() const { return provider->resolutions[autoResTypeId]; } } // namespace dabfg diff --git a/prog/gameLibs/render/daBfg/api/nameSpaceRequest.cpp b/prog/gameLibs/render/daBfg/api/nameSpaceRequest.cpp index 7df947dad..eba918416 100644 --- a/prog/gameLibs/render/daBfg/api/nameSpaceRequest.cpp +++ b/prog/gameLibs/render/daBfg/api/nameSpaceRequest.cpp @@ -14,7 +14,7 @@ NameSpaceRequest NameSpaceRequest::operator/(const char *child_name) const AutoResolutionRequest NameSpaceRequest::getResolution(const char *type_name, float multiplier) const { const auto autoResTypeId = registry->knownNames.addNameId(nameSpaceId, type_name); - return {autoResTypeId, multiplier, registry}; + return {autoResTypeId, multiplier, ®istry->resourceProviderReference}; } // === Resource requesting === diff --git a/prog/gameLibs/render/daBfg/api/resourceProvider.h b/prog/gameLibs/render/daBfg/api/resourceProvider.h index bb79dd511..34e736cb9 100644 --- a/prog/gameLibs/render/daBfg/api/resourceProvider.h +++ b/prog/gameLibs/render/daBfg/api/resourceProvider.h @@ -4,7 +4,9 @@ #include #include <3d/dag_resPtr.h> #include +#include #include +#include namespace dabfg @@ -17,6 +19,8 @@ struct ResourceProvider dag::VectorMap providedResources; dag::VectorMap providedHistoryResources; + IdIndexedMapping resolutions; + void clear() { providedResources.clear(); diff --git a/prog/gameLibs/render/daBfg/nodes/nodeExecutor.cpp b/prog/gameLibs/render/daBfg/nodes/nodeExecutor.cpp index 617f4390d..4e3cf9db8 100644 --- a/prog/gameLibs/render/daBfg/nodes/nodeExecutor.cpp +++ b/prog/gameLibs/render/daBfg/nodes/nodeExecutor.cpp @@ -61,6 +61,11 @@ void populate_resource_provider(ResourceProvider &provider, // passed by ref to void NodeExecutor::execute(int prev_frame, int curr_frame, multiplexing::Extents multiplexing_extents, const ResourceScheduler::FrameEventsRef &events, eastl::span state_deltas) { + currentlyProvidedResources.resolutions.resize(registry.knownNames.nameCount()); + for (auto [unresolvedId, resolution] : currentlyProvidedResources.resolutions.enumerate()) + if (auto resolvedId = nameResolver.resolve(unresolvedId); resolvedId != AutoResTypeNameId::Invalid) + resolution = registry.autoResTypes[resolvedId].dynamicResolution; + uint32_t userNodeIndex = 0; for (auto i : IdRange(graph.nodes.size())) { diff --git a/prog/gameLibs/render/foam/foamFx.cpp b/prog/gameLibs/render/foam/foamFx.cpp index 0f27b6401..e94232dca 100644 --- a/prog/gameLibs/render/foam/foamFx.cpp +++ b/prog/gameLibs/render/foam/foamFx.cpp @@ -140,11 +140,11 @@ void FoamFx::setParams(const FoamFxParams ¶ms) debugTextures[FoamTexture::GRADIENT] = foamGeneratorGradientTex.getBaseTex(); } -void FoamFx::prepare() +void FoamFx::prepare(const TMatrix4 &view_tm, const TMatrix4 &proj_tm) { TIME_D3D_PROFILE(FoamFx_Preapare); - set_inv_globtm_to_shader(false); + set_inv_globtm_to_shader(view_tm, proj_tm, false); ShaderGlobal::set_texture(foam_maskVarId, maskTarget); ShaderGlobal::set_texture(foam_mask_depthVarId, maskDepth); diff --git a/prog/gameLibs/render/fx/demonPostFx.cpp b/prog/gameLibs/render/fx/demonPostFx.cpp index 36705c5fc..2fe061f95 100644 --- a/prog/gameLibs/render/fx/demonPostFx.cpp +++ b/prog/gameLibs/render/fx/demonPostFx.cpp @@ -234,25 +234,15 @@ void DemonPostFx::closeAdaptation() lowresBrightness1.close(); } -void DemonPostFx::initHistogramVb() +struct HistogramVertex { - histogramVb.close(); - IPoint2 vbSize = centerWeightedAdaptation ? IPoint2(CENTER_WEIGHTED_ADAPTATION_SIZE, 1) : lowResSize; - ShaderGlobal::set_real(adaptation_cw_samples_countVarId, CENTER_WEIGHTED_ADAPTATION_SIZE); - ShaderGlobal::set_int(adaptation_use_center_weightedVarId, centerWeightedAdaptation ? 1 : 0); + uint16_t x, y; +}; - struct HistogramVertex - { - uint16_t x, y; - }; -#if HIST_USE_INSTANCING - histogramVb = dag::create_vb(sizeof(HistogramVertex), 0, "histogramInst"); -#else - histogramVb = dag::create_vb(vbSize.x * vbSize.y * sizeof(HistogramVertex), 0, "histogram"); -#endif - d3d_err(histogramVb.getBuf()); +void DemonPostFx::HistBufferFiller::reloadD3dRes(Sbuffer *buf) +{ HistogramVertex *vert; - d3d_err(histogramVb->lock(0, 0, (void **)&vert, VBLOCK_WRITEONLY)); + d3d_err(buf->lock(0, 0, (void **)&vert, VBLOCK_WRITEONLY)); #if !HIST_USE_INSTANCING if (vert) { @@ -261,7 +251,25 @@ void DemonPostFx::initHistogramVb() vert->x = x, vert->y = y; } #endif - histogramVb->unlock(); + buf->unlock(); +} + +void DemonPostFx::initHistogramVb() +{ + histogramVb.close(); + IPoint2 vbSize = centerWeightedAdaptation ? IPoint2(CENTER_WEIGHTED_ADAPTATION_SIZE, 1) : lowResSize; + ShaderGlobal::set_real(adaptation_cw_samples_countVarId, CENTER_WEIGHTED_ADAPTATION_SIZE); + ShaderGlobal::set_int(adaptation_use_center_weightedVarId, centerWeightedAdaptation ? 1 : 0); + +#if HIST_USE_INSTANCING + histogramVb = dag::create_vb(sizeof(HistogramVertex), SBCF_MAYBELOST, "histogramInst"); +#else + histogramVb = dag::create_vb(vbSize.x * vbSize.y * sizeof(HistogramVertex), SBCF_MAYBELOST, "histogram"); +#endif + d3d_err(histogramVb.getBuf()); + histBufferFiller.vbSize = vbSize; + histBufferFiller.reloadD3dRes(histogramVb.getBuf()); + histogramVb.getBuf()->setReloadCallback(&histBufferFiller); } float DemonPostFx::getCurrentAdaptationValueSlow() { return currentExposure.adaptationScale; } diff --git a/prog/gameLibs/render/gpuGrass.cpp b/prog/gameLibs/render/gpuGrass.cpp index dd736f3c2..27882bd78 100644 --- a/prog/gameLibs/render/gpuGrass.cpp +++ b/prog/gameLibs/render/gpuGrass.cpp @@ -49,6 +49,8 @@ enum VAR_OPT(grass_gen_lod_index) \ VAR(grass_gen_order) \ VAR(grass_grid_params) \ + VAR(grass_draw_instances_buffer) \ + VAR(grass_draw_instances_indirect_buffer) \ VAR_OPT(grass_average_ht__ht_extent__avg_hor__hor_extent) \ VAR_OPT(grass_instancing) @@ -704,7 +706,6 @@ void GPUGrassBase::generateGrass(const Point2 &pos, const Point3 &view_dir, floa } ShaderGlobal::set_color4(get_shader_variable_id("lod_grass_instances_start_at", true), startsAt[0], startsAt[1], startsAt[2], startsAt[3]); - ShaderGlobal::set_int(get_shader_variable_id("max_grass_instances", true), maxInstanceCount); if (indexBufferInited) { index_buffer::release_quads_32bit(); @@ -742,9 +743,9 @@ void GPUGrassBase::generateGrass(const Point2 &pos, const Point3 &view_dir, floa ShaderGlobal::set_real(grass_inv_vis_distanceVarId, 1. / grassDistance); ShaderGlobal::set_color4(grass_gen_orderVarId, fabsf(view_XZ.x) > fabsf(view_XZ.y) ? 1 : 0, view_XZ.x < 0 ? 1 : 0, view_XZ.y < 0 ? 1 : 0, 0); - d3d::set_rwbuffer(STAGE_CS, 6, grassInstancesIndirect.getBuf()); + ShaderGlobal::set_buffer(grass_draw_instances_indirect_bufferVarId, grassInstancesIndirect.getBufId()); + ShaderGlobal::set_buffer(grass_draw_instances_bufferVarId, grassInstances.getBufId()); createIndirect->dispatch(1, 1, 1); // clear - d3d::set_rwbuffer(STAGE_CS, 7, grassInstances.getBuf()); d3d::resource_barrier({{grassInstancesIndirect.getBuf(), grassInstances.getBuf()}, {RB_FLUSH_UAV | RB_STAGE_COMPUTE | RB_SOURCE_STAGE_COMPUTE, RB_FLUSH_UAV | RB_STAGE_COMPUTE | RB_SOURCE_STAGE_COMPUTE}}); @@ -805,8 +806,6 @@ void GPUGrassBase::generateGrass(const Point2 &pos, const Point3 &view_dir, floa break; } d3d::set_const_buffer(STAGE_CS, 1, 0); - d3d::set_rwbuffer(STAGE_CS, 6, 0); - d3d::set_rwbuffer(STAGE_CS, 7, 0); d3d::resource_barrier({{grassInstancesIndirect.getBuf(), grassInstances.getBuf()}, {(indirectSrv ? RB_RO_SRV | RB_STAGE_VERTEX | RB_RO_INDIRECT_BUFFER : RB_RO_INDIRECT_BUFFER), RB_RO_SRV | RB_STAGE_VERTEX}}); @@ -858,12 +857,6 @@ void GPUGrassBase::render(RenderType rtype) shaders::overrides::reset(); } -void GPUGrassBase::bindGrassBuffers() -{ - d3d::set_rwbuffer(STAGE_PS, 6, grassInstancesIndirect.getBuf()); - d3d::set_rwbuffer(STAGE_PS, 7, grassInstances.getBuf()); -} - void GPUGrassBase::invalidate() { generated = false; } GPUGrassBase::~GPUGrassBase() { close(); } diff --git a/prog/gameLibs/render/heroWetness.cpp b/prog/gameLibs/render/heroWetness.cpp index 394c7ece6..5c5b5a517 100644 --- a/prog/gameLibs/render/heroWetness.cpp +++ b/prog/gameLibs/render/heroWetness.cpp @@ -123,7 +123,7 @@ void HeroWetness::init() int vbSize = getVbSize(); G_ASSERT(!waterHeightRendererVb); - waterHeightRendererVb = d3d::create_vb(sizeof(float) * vbSize, 0, "wetnessCalculationPostfx"); + waterHeightRendererVb = d3d::create_vb(sizeof(float) * vbSize, SBCF_MAYBELOST, "wetnessCalculationPostfx"); d3d_err(waterHeightRendererVb); fillVertexBuffer(vbSize); diff --git a/prog/gameLibs/render/lruCollision/lruCollision.cpp b/prog/gameLibs/render/lruCollision/lruCollision.cpp index 258c22a74..09f4d7eba 100644 --- a/prog/gameLibs/render/lruCollision/lruCollision.cpp +++ b/prog/gameLibs/render/lruCollision/lruCollision.cpp @@ -484,9 +484,9 @@ void LRURendinstCollision::drawInstances(dag::ConstSpan { TIME_D3D_PROFILE(LRU_draw_instances); if (alpha) - d3d::set_rwtex(STAGE_PS, 6, alpha, 0, 0); + d3d::set_rwtex(STAGE_PS, 5, alpha, 0, 0); if (color) - d3d::set_rwtex(STAGE_PS, 7, color, 0, 0); + d3d::set_rwtex(STAGE_PS, 6, color, 0, 0); d3d::setind(ibAllocator.getHeap().getBuf()); d3d::setvsrc_ex(0, vbAllocator.getHeap().getBuf(), 0, sizeof(CollisionVertex)); // we can set with different offset, but we rely on @@ -505,9 +505,9 @@ void LRURendinstCollision::drawInstances(dag::ConstSpan d3d::setvsrc(0, 0, 0); // we can set with different offset, but we rely on same vertex size d3d::setvsrc(1, 0, 0); // we can set with different offset, but we rely on same vertex size if (color) - d3d::set_rwtex(STAGE_PS, 7, 0, 0, 0); - if (alpha) d3d::set_rwtex(STAGE_PS, 6, 0, 0, 0); + if (alpha) + d3d::set_rwtex(STAGE_PS, 5, 0, 0, 0); } void LRURendinstCollision::drawInstances(uint32_t start_instance, const uint32_t *types_counts, uint32_t batches, VolTexture *color, @@ -609,9 +609,9 @@ void LRURendinstCollision::dispatchInstances(dag::ConstSpangetFlags() & SBCF_BIND_SHADER_RES); TIME_D3D_PROFILE(LRU_dispatch_instances); if (alpha) - d3d::set_rwtex(STAGE_CS, 6, alpha, 0, 0); + d3d::set_rwtex(STAGE_CS, 5, alpha, 0, 0); if (color) - d3d::set_rwtex(STAGE_CS, 7, color, 0, 0); + d3d::set_rwtex(STAGE_CS, 6, color, 0, 0); cs.setStates(); ShaderGlobal::set_buffer(gi_voxelization_vbufferVarId, vbAllocator.getHeap().getBufId()); ShaderGlobal::set_buffer(gi_voxelization_ibufferVarId, ibAllocator.getHeap().getBufId()); @@ -619,9 +619,9 @@ void LRURendinstCollision::dispatchInstances(dag::ConstSpan handles, VolTexture *color, VolTexture *alpha, diff --git a/prog/gameLibs/render/mobile_ssao.cpp b/prog/gameLibs/render/mobile_ssao.cpp index c942838d2..70e3b150c 100644 --- a/prog/gameLibs/render/mobile_ssao.cpp +++ b/prog/gameLibs/render/mobile_ssao.cpp @@ -91,6 +91,7 @@ void MobileSSAORenderer::applyBlur() ssaoBlurRenderer->getMat()->set_color4_param(ssaoBlurTexelOffsetVarId, texelOffset); d3d::set_render_target(ssaoTex[blurId].getTex2D(), 0); + d3d::clearview(CLEAR_DISCARD, 0, 0, 0); ShaderGlobal::set_texture(ssao_texVarId, ssaoTex[renderId]); ssaoBlurRenderer->render(); diff --git a/prog/gameLibs/render/resourceSlot/detail/storage.cpp b/prog/gameLibs/render/resourceSlot/detail/storage.cpp index 6fe97acc7..506ec2c05 100644 --- a/prog/gameLibs/render/resourceSlot/detail/storage.cpp +++ b/prog/gameLibs/render/resourceSlot/detail/storage.cpp @@ -1,4 +1,3 @@ #include -dag::RelocatableFixedVector - resource_slot::detail::storage_list{1}; \ No newline at end of file +resource_slot::detail::StorageList resource_slot::detail::storage_list; diff --git a/prog/gameLibs/render/resourceSlot/detail/storage.h b/prog/gameLibs/render/resourceSlot/detail/storage.h index f7e7413cd..5d4b0a261 100644 --- a/prog/gameLibs/render/resourceSlot/detail/storage.h +++ b/prog/gameLibs/render/resourceSlot/detail/storage.h @@ -1,11 +1,14 @@ #pragma once #include +#include #include #include #include +#include + namespace resource_slot::detail { @@ -29,7 +32,7 @@ struct Storage Storage &operator=(const Storage &) = delete; }; -// NOTE: in the future, we could have several storages for several frame graphs -extern dag::RelocatableFixedVector storage_list; +using StorageList = ska::flat_hash_map; +extern StorageList storage_list; } // namespace resource_slot::detail \ No newline at end of file diff --git a/prog/gameLibs/render/resourceSlot/nodeHandleWithSlotsAccess.cpp b/prog/gameLibs/render/resourceSlot/nodeHandleWithSlotsAccess.cpp index e3395737b..19f824036 100644 --- a/prog/gameLibs/render/resourceSlot/nodeHandleWithSlotsAccess.cpp +++ b/prog/gameLibs/render/resourceSlot/nodeHandleWithSlotsAccess.cpp @@ -2,6 +2,8 @@ #include #include +#include + ECS_REGISTER_RELOCATABLE_TYPE(resource_slot::NodeHandleWithSlotsAccess, nullptr); @@ -12,25 +14,24 @@ void resource_slot::NodeHandleWithSlotsAccess::reset() valid = false; detail::NodeId nodeId = detail::NodeId{id}; - detail::Storage &storage = detail::storage_list[storageId]; + detail::Storage &storage = detail::storage_list[nameSpace]; detail::unregister_access(storage, nodeId, generation); } resource_slot::NodeHandleWithSlotsAccess::~NodeHandleWithSlotsAccess() { reset(); } -resource_slot::NodeHandleWithSlotsAccess::NodeHandleWithSlotsAccess(unsigned storage_id, int handle_id, unsigned generation_number) : - storageId(storage_id), id(handle_id), generation(generation_number), valid(true) +resource_slot::NodeHandleWithSlotsAccess::NodeHandleWithSlotsAccess(dabfg::NameSpace ns, int handle_id, unsigned generation_number) : + nameSpace(ns), id(handle_id), generation(generation_number), valid(true) { G_ASSERT(handle_id >= 0); G_ASSERT(handle_id <= (1 << 27)); - G_ASSERT(storage_id <= (1 << 4)); G_ASSERT(generation_number <= (1U << 31U)); }; -resource_slot::NodeHandleWithSlotsAccess::NodeHandleWithSlotsAccess() : storageId(0), id(0), generation(0), valid(false) {} +resource_slot::NodeHandleWithSlotsAccess::NodeHandleWithSlotsAccess() : nameSpace(dabfg::root()), id(0), generation(0), valid(false) {} resource_slot::NodeHandleWithSlotsAccess::NodeHandleWithSlotsAccess(NodeHandleWithSlotsAccess &&h) : - storageId(h.storageId), id(h.id), generation(h.generation), valid(h.valid) + nameSpace(h.nameSpace), id(h.id), generation(h.generation), valid(h.valid) { h.valid = false; } @@ -38,7 +39,7 @@ resource_slot::NodeHandleWithSlotsAccess::NodeHandleWithSlotsAccess(NodeHandleWi resource_slot::NodeHandleWithSlotsAccess &resource_slot::NodeHandleWithSlotsAccess::operator=(NodeHandleWithSlotsAccess &&h) { reset(); - storageId = h.storageId; + nameSpace = h.nameSpace; id = h.id; generation = h.generation; valid = h.valid; diff --git a/prog/gameLibs/render/resourceSlot/registerAccess.cpp b/prog/gameLibs/render/resourceSlot/registerAccess.cpp index ae0bf53a1..b7c354bf1 100644 --- a/prog/gameLibs/render/resourceSlot/registerAccess.cpp +++ b/prog/gameLibs/render/resourceSlot/registerAccess.cpp @@ -3,10 +3,10 @@ #include -resource_slot::NodeHandleWithSlotsAccess resource_slot::detail::register_access(const char *name, const char *source_location, - ActionList &&action_list, AccessCallback &&declaration_callback, unsigned storage_id) +resource_slot::NodeHandleWithSlotsAccess resource_slot::detail::register_access(dabfg::NameSpace ns, const char *name, + const char *source_location, ActionList &&action_list, AccessCallback &&declaration_callback) { - Storage &storage = storage_list[storage_id]; + Storage &storage = storage_list[ns]; storage.isNodeRegisterRequired = true; NodeId nodeId = storage.nodeMap.id(name); @@ -37,5 +37,5 @@ resource_slot::NodeHandleWithSlotsAccess resource_slot::detail::register_access( declaration); } - return NodeHandleWithSlotsAccess{storage_id, static_cast(nodeId), generation}; + return NodeHandleWithSlotsAccess{ns, static_cast(nodeId), generation}; } diff --git a/prog/gameLibs/render/resourceSlot/resolveAccess.cpp b/prog/gameLibs/render/resourceSlot/resolveAccess.cpp index b4eda9633..d8dc7f7eb 100644 --- a/prog/gameLibs/render/resourceSlot/resolveAccess.cpp +++ b/prog/gameLibs/render/resourceSlot/resolveAccess.cpp @@ -288,93 +288,94 @@ static inline void fill_slots_state(resource_slot::detail::Storage &storage, Nod } } - -void resource_slot::resolve_access(unsigned storage_id) +void resource_slot::resolve_access() { // TODO: move all dump to separate function and dump graph on error - detail::Storage &storage = detail::storage_list[storage_id]; - - if (register_nodes || register_nodes_every_frame) + for (auto &[ns, storage] : detail::storage_list) { - register_nodes.set(false); - storage.isNodeRegisterRequired = true; - } - if (!storage.isNodeRegisterRequired) - return; + if (register_nodes || register_nodes_every_frame) + { + register_nodes.set(false); + storage.isNodeRegisterRequired = true; + } - TIME_PROFILE(resource_slot__perform_access); - storage.isNodeRegisterRequired = false; - storage.validNodeCount = 0; + if (!storage.isNodeRegisterRequired) + return; - // Reset nodes state - for (int i = 0; i < storage.registeredNodes.size(); ++i) - { - detail::NodeId nodeId = detail::NodeId{i}; - detail::NodeDeclaration &node = storage.registeredNodes[nodeId]; + TIME_PROFILE(resource_slot__perform_access); + storage.isNodeRegisterRequired = false; + storage.validNodeCount = 0; - if (node.status == detail::NodeStatus::Pruned) - detail::unregister_access(storage, nodeId, node.generation); + // Reset nodes state + for (int i = 0; i < storage.registeredNodes.size(); ++i) + { + detail::NodeId nodeId = detail::NodeId{i}; + detail::NodeDeclaration &node = storage.registeredNodes[nodeId]; - if (node.status == resource_slot::detail::NodeStatus::Empty) - continue; + if (node.status == detail::NodeStatus::Pruned) + detail::unregister_access(storage, nodeId, node.generation); - G_ASSERTF_CONTINUE(node.id == nodeId, "Unexpected node.id=%d for node %s<%d>", int(node.id), storage.nodeMap.name(nodeId), i); + if (node.status == resource_slot::detail::NodeStatus::Empty) + continue; - node.nodeHandle = dabfg::NodeHandle{}; - node.status = resource_slot::detail::NodeStatus::Valid; - ++storage.validNodeCount; - } + G_ASSERTF_CONTINUE(node.id == nodeId, "Unexpected node.id=%d for node %s<%d>", int(node.id), storage.nodeMap.name(nodeId), i); - // Make topological sort - { - FRAMEMEM_REGION; + node.nodeHandle = dabfg::NodeHandle{}; + node.status = resource_slot::detail::NodeStatus::Valid; + ++storage.validNodeCount; + } - typedef dag::RelocatableFixedVector UsageList; - typedef detail::AutoGrowVector UsageMap; - UsageMap slotUsage{storage.slotMap.nameCount()}; + // Make topological sort + { + FRAMEMEM_REGION; - if (debug_topological_order) - debug("resource_slot::resolve_access(): start graph generation"); + typedef dag::RelocatableFixedVector UsageList; + typedef detail::AutoGrowVector UsageMap; + UsageMap slotUsage{storage.slotMap.nameCount()}; - add_all_nodes_to_usage_list(slotUsage, storage); - sort_usage_list(slotUsage); + if (debug_topological_order) + debug("resource_slot::resolve_access(): start graph generation"); - typedef dag::RelocatableFixedVector NodeList; - NodeList topSortOrder; + add_all_nodes_to_usage_list(slotUsage, storage); + sort_usage_list(slotUsage); - int prevIterationValidNodeCount = storage.validNodeCount; - bool isFirstIteration = true; - while (true) - { - G_ASSERT_RETURN(isFirstIteration || prevIterationValidNodeCount > storage.validNodeCount, ); - isFirstIteration = false; - prevIterationValidNodeCount = storage.validNodeCount; + typedef dag::RelocatableFixedVector NodeList; + NodeList topSortOrder; - validate_usage_list(slotUsage, storage); + int prevIterationValidNodeCount = storage.validNodeCount; + bool isFirstIteration = true; + while (true) + { + G_ASSERT_RETURN(isFirstIteration || prevIterationValidNodeCount > storage.validNodeCount, ); + isFirstIteration = false; + prevIterationValidNodeCount = storage.validNodeCount; - typedef detail::Graph Dependencies; - Dependencies dependencies{storage.registeredNodes.size()}; - build_edges_from_usage_list(dependencies, slotUsage, storage); + validate_usage_list(slotUsage, storage); - // Topological sort - if (!make_topological_sort(dependencies, slotUsage, storage, topSortOrder)) - continue; // Some nodes were removed. Have to rebuild dependency graph + typedef detail::Graph Dependencies; + Dependencies dependencies{storage.registeredNodes.size()}; + build_edges_from_usage_list(dependencies, slotUsage, storage); - break; - } + // Topological sort + if (!make_topological_sort(dependencies, slotUsage, storage, topSortOrder)) + continue; // Some nodes were removed. Have to rebuild dependency graph - fill_slots_state(storage, topSortOrder); - } + break; + } - // Call declarations outside FRAMEMEM_REGION - for (resource_slot::detail::NodeDeclaration &node : storage.registeredNodes) - { - if (node.status != resource_slot::detail::NodeStatus::Valid) - continue; + fill_slots_state(storage, topSortOrder); + } + + // Call declarations outside FRAMEMEM_REGION + for (resource_slot::detail::NodeDeclaration &node : storage.registeredNodes) + { + if (node.status != resource_slot::detail::NodeStatus::Valid) + continue; - node.nodeHandle = dabfg::NodeHandle{}; - node.nodeHandle = node.declaration_callback(resource_slot::State{storage_id, static_cast(node.id)}); + node.nodeHandle = dabfg::NodeHandle{}; + node.nodeHandle = node.declaration_callback(resource_slot::State{ns, static_cast(node.id)}); + } } } \ No newline at end of file diff --git a/prog/gameLibs/render/resourceSlot/state.cpp b/prog/gameLibs/render/resourceSlot/state.cpp index 08d0ce393..36c6d0d48 100644 --- a/prog/gameLibs/render/resourceSlot/state.cpp +++ b/prog/gameLibs/render/resourceSlot/state.cpp @@ -2,12 +2,11 @@ #include -resource_slot::State::State(unsigned storage_id, int node_id) : storageId(storage_id), nodeId(node_id) +resource_slot::State::State(dabfg::NameSpace ns, int node_id) : nameSpace(ns), nodeId(node_id) { // Fits into storage bits G_ASSERT(node_id >= 0); G_ASSERT(node_id <= (1 << 26)); - G_ASSERT(storage_id <= (1 << 4)); } [[nodiscard]] static inline bool is_node_registered(resource_slot::detail::NodeId node_id, resource_slot::detail::NodeStatus status) @@ -19,7 +18,7 @@ resource_slot::State::State(unsigned storage_id, int node_id) : storageId(storag // Read current slots const char *resource_slot::State::resourceToReadFrom(const char *slot_name) const { - detail::Storage &storage = detail::storage_list[storageId]; + detail::Storage &storage = detail::storage_list[nameSpace]; G_ASSERTF_RETURN(nodeId >= 0 && nodeId < storage.nodeMap.nameCount(), nullptr, "Unexpected nodeId: %d", nodeId); detail::NodeId ownerNodeId = detail::NodeId{nodeId}; @@ -44,7 +43,7 @@ const char *resource_slot::State::resourceToReadFrom(const char *slot_name) cons const char *resource_slot::State::resourceToCreateFor(const char *slot_name) const { - detail::Storage &storage = detail::storage_list[storageId]; + detail::Storage &storage = detail::storage_list[nameSpace]; G_ASSERTF_RETURN(nodeId >= 0 && nodeId < storage.nodeMap.nameCount(), nullptr, "Unexpected nodeId: %d", nodeId); detail::NodeId ownerNodeId = detail::NodeId{nodeId}; diff --git a/prog/gameLibs/render/shaders/contrast_adaptive_sharpening.sh b/prog/gameLibs/render/shaders/contrast_adaptive_sharpening.sh index 3caa788a9..bb0c43dfc 100644 --- a/prog/gameLibs/render/shaders/contrast_adaptive_sharpening.sh +++ b/prog/gameLibs/render/shaders/contrast_adaptive_sharpening.sh @@ -16,17 +16,18 @@ macro USE_CONTRAST_ADAPTIVE_SHARPENING(code) return half4(color.rgb * rcp(max(1e-5, 1 - abs(color.r))), color.a); } - half4 tex2DCAS(Texture2D tex, int2 pixelCoord, float sharpening) + half4 tex2DCAS(Texture2D tex, SamplerState tex_samplerstate, float2 uv, float2 res, float2 invRes, float sharpening) { - half4 a = tonemap(PackToYCoCgAlpha(tex.Load(int3(pixelCoord + int2(-1, -1), 0)))); - half4 b = tonemap(PackToYCoCgAlpha(tex.Load(int3(pixelCoord + int2(0, -1), 0)))); - half4 c = tonemap(PackToYCoCgAlpha(tex.Load(int3(pixelCoord + int2(1, -1), 0)))); - half4 d = tonemap(PackToYCoCgAlpha(tex.Load(int3(pixelCoord + int2(-1, 0), 0)))); - half4 e = tonemap(PackToYCoCgAlpha(tex.Load(int3(pixelCoord, 0)))); - half4 f = tonemap(PackToYCoCgAlpha(tex.Load(int3(pixelCoord + int2(1, 0), 0)))); - half4 g = tonemap(PackToYCoCgAlpha(tex.Load(int3(pixelCoord + int2(-1, 1), 0)))); - half4 h = tonemap(PackToYCoCgAlpha(tex.Load(int3(pixelCoord + int2(0, 1), 0)))); - half4 i = tonemap(PackToYCoCgAlpha(tex.Load(int3(pixelCoord + int2(1, 1), 0)))); + float2 pixelCoord = (floor(uv * res) + 0.5) * invRes; + half4 a = tonemap(PackToYCoCgAlpha(tex2Dlod(tex, float4(pixelCoord + int2(-1, -1) * invRes, 0, 0)))); + half4 b = tonemap(PackToYCoCgAlpha(tex2Dlod(tex, float4(pixelCoord + int2(0, -1) * invRes, 0, 0)))); + half4 c = tonemap(PackToYCoCgAlpha(tex2Dlod(tex, float4(pixelCoord + int2(1, -1) * invRes, 0, 0)))); + half4 d = tonemap(PackToYCoCgAlpha(tex2Dlod(tex, float4(pixelCoord + int2(-1, 0) * invRes, 0, 0)))); + half4 e = tonemap(PackToYCoCgAlpha(tex2Dlod(tex, float4(pixelCoord, 0, 0)))); + half4 f = tonemap(PackToYCoCgAlpha(tex2Dlod(tex, float4(pixelCoord + int2(1, 0) * invRes, 0, 0)))); + half4 g = tonemap(PackToYCoCgAlpha(tex2Dlod(tex, float4(pixelCoord + int2(-1, 1) * invRes, 0, 0)))); + half4 h = tonemap(PackToYCoCgAlpha(tex2Dlod(tex, float4(pixelCoord + int2(0, 1) * invRes, 0, 0)))); + half4 i = tonemap(PackToYCoCgAlpha(tex2Dlod(tex, float4(pixelCoord + int2(1, 1) * invRes, 0, 0)))); // Soft min and max. // a b c b diff --git a/prog/gameLibs/render/shaders/debug_ri_shaded.sh b/prog/gameLibs/render/shaders/debug_ri_shaded.sh index b95f05e15..11f836b73 100644 --- a/prog/gameLibs/render/shaders/debug_ri_shaded.sh +++ b/prog/gameLibs/render/shaders/debug_ri_shaded.sh @@ -4,6 +4,7 @@ texture debug_triplanar_tex; int debug_triplanar_tex_size; int debug_ri_wireframe; int debug_ri_diff; +int debug_ri_face_orientation; float4 debug_ri_wire_color; shader debug_ri_shaded @@ -38,6 +39,7 @@ shader debug_ri_shaded from_sun_direction@f3 = from_sun_direction; wireframe@i1 = debug_ri_wireframe; diff@i1 = debug_ri_diff; + face_orientation@i1 = debug_ri_face_orientation; wire_color@f4 = debug_ri_wire_color; downsampled_far_depth_tex@smp2d = downsampled_far_depth_tex; local_view_z@f3 = local_view_z; @@ -49,7 +51,7 @@ shader debug_ri_shaded return tex2Dlod(downsampled_far_depth_tex, float4(tc, 0, 0)).x; } - half4 debug_shaded_ps(VsOutput input HW_USE_SCREEN_POS) : SV_Target + half4 debug_shaded_ps(VsOutput input HW_USE_SCREEN_POS INPUT_VFACE) : SV_Target { if (wireframe == 1) return wire_color; @@ -90,6 +92,13 @@ shader debug_ri_shaded float ambientAmount = saturate(length(GetSkySHDiffuseSimple(normal))); float3 diffuse = max(0, dot(from_sun_direction, normal)); + + if (face_orientation == 1) + { + diffuse = float3(0, 0, 1); + SET_IF_IS_BACK_FACE(diffuse, float3(1, 0, 0)); + } + return float4((diffuse + 0.5 * ambientAmount) * triplanarColor, 1.0); } } diff --git a/prog/gameLibs/render/shaders/depth_hierarchy.sh b/prog/gameLibs/render/shaders/depth_hierarchy.sh index 300e4e84f..55ee91abf 100644 --- a/prog/gameLibs/render/shaders/depth_hierarchy.sh +++ b/prog/gameLibs/render/shaders/depth_hierarchy.sh @@ -25,7 +25,7 @@ shader depth_hierarchy } } - if (hardware.xbox) + if (hardware.xbox || hardware.ps4) { hlsl { // Xbox produces buggy results with wave-based quad reduction @@ -37,13 +37,23 @@ shader depth_hierarchy (cs) { mips_and_group_count@i2 = (required_mip_count, work_group_count); - if (!hardware.ps5) { + + // TODO: try RWByteAddressBuffer instead + if (hardware.ps5) { g_global_counter@uav : register(g_global_counter_no) hlsl { - globallycoherent RWStructuredBuffer g_global_counter@uav; + RW_RegularBuffer g_global_counter@uav; //atomic access, should be fine } - } else { + } + else if (hardware.ps4) + { g_global_counter@uav : register(g_global_counter_no) hlsl { - RW_RegularBuffer g_global_counter@uav; //atomic access, should be fine + RW_RegularBuffer g_global_counter@uav; + } + } + else + { + g_global_counter@uav : register(g_global_counter_no) hlsl { + globallycoherent RWStructuredBuffer g_global_counter@uav; } } } diff --git a/prog/gameLibs/render/shaders/flexible_scale_rasterization.sh b/prog/gameLibs/render/shaders/flexible_scale_rasterization.sh new file mode 100644 index 000000000..0d93cb43e --- /dev/null +++ b/prog/gameLibs/render/shaders/flexible_scale_rasterization.sh @@ -0,0 +1,59 @@ +// If the FSR was used during gbuffer rendering, then this var will have YES for the whole frame +int fsr_distortion = 0; +interval fsr_distortion: no < 1, yes; + +int fsr_lut_id = 0; + +macro USE_FSR(code) + if (hardware.ps5 && fsr_distortion == yes) + { + (code) + { + fsr_lut_id@i1 = fsr_lut_id; + fsr_viewport@f4 = get_viewport(); + } + + hlsl(code) + { + RegularBuffer static_textures : BINDLESS_TEX_REGISTER; + RegularBuffer static_samplers : BINDLESS_SAMPLER_REGISTER; + + uint2 fsrPos(uint2 pos, uint2 size) + { + Texture1D fsrLutH = static_textures[fsr_lut_id]; + Texture1D fsrLutV = static_textures[fsr_lut_id + 1]; + SamplerState smp = static_samplers[0]; + + float2 tc = float2(pos) / float2(size); + return uint2(fsrLutH.Sample(smp, tc.x) * size.x, fsrLutV.Sample(smp, tc.y) * size.y); + } + + float2 getTexcoord(float2 pos) + { + return (pos - fsr_viewport.xy) / fsr_viewport.zw; + } + + float2 getTexcoord(float2 pos, float2 texcoord) + { + return getTexcoord(pos); + } + + #define FSR_DISTORTION 1 + } + } + else + { + hlsl(code) + { + uint2 fsrPos(uint2 pos, uint2 size) + { + return pos; + } + + float2 getTexcoord(float2 pos, float2 texcoord) + { + return texcoord; + } + } + } +endmacro diff --git a/prog/gameLibs/render/shaders/flow_map.sh b/prog/gameLibs/render/shaders/flow_map.sh index ad65aa931..8ada8cde2 100644 --- a/prog/gameLibs/render/shaders/flow_map.sh +++ b/prog/gameLibs/render/shaders/flow_map.sh @@ -9,6 +9,7 @@ float flowmap_texture_size_meters = 200; texture flowmap_heightmap_tex; int height_texture_size = 1024; float4 flowmap_heightmap_min_max = (0, 0, 0, 0); +texture flowmap_floodfill_tex; float wind_dir_x = 0.6; float wind_dir_y = 0.8; float dir_scale = 0.01; @@ -41,6 +42,7 @@ shader water_flowmap height_texture_size@f4 = (1.0/height_texture_size, height_texture_size, 1./flowmap_texture_size, flowmap_texture_size); flowmap_heightmap_tex@smp2d = flowmap_heightmap_tex; flowmap_heightmap_min_max@f4 = flowmap_heightmap_min_max; + flowmap_floodfill_tex@smp2d = flowmap_floodfill_tex; waterLevel_radius_flowmap_damping@f4 = (water_level, height_texture_size/flowmap_texture_size+2, height_texture_size/flowmap_texture_size, flowmap_damping); world_to_flowmap_prev@f4 = world_to_flowmap_prev; world_to_flowmap_heightmap@f4 = world_to_flowmap_heightmap; @@ -138,6 +140,22 @@ shader water_flowmap f.xy += depthGradient * water_flowmap_depth.x * max(1 - waterDepth * water_flowmap_depth.z, 0); ##endif + ##if flowmap_floodfill_tex != NULL + f.xy = (l.xy + r.xy + u.xy + d.xy) * 0.25; + float4 heightNeighbours = h; + heightNeighbours.x = tex2Dlod(flowmap_heightmap_tex, float4(htc.x - height_texture_size.x, htc.y, 0, 0)).r * flowmap_heightmap_min_max.z + flowmap_heightmap_min_max.w; + heightNeighbours.y = tex2Dlod(flowmap_heightmap_tex, float4(htc.x + height_texture_size.x, htc.y, 0, 0)).r * flowmap_heightmap_min_max.z + flowmap_heightmap_min_max.w; + heightNeighbours.z = tex2Dlod(flowmap_heightmap_tex, float4(htc.x, htc.y - height_texture_size.x, 0, 0)).r * flowmap_heightmap_min_max.z + flowmap_heightmap_min_max.w; + heightNeighbours.w = tex2Dlod(flowmap_heightmap_tex, float4(htc.x, htc.y + height_texture_size.x, 0, 0)).r * flowmap_heightmap_min_max.z + flowmap_heightmap_min_max.w; + if (any(heightNeighbours > waterHeight)) + { + float2 heightGradient = float2(heightNeighbours.w - heightNeighbours.z, heightNeighbours.x - heightNeighbours.y); + float2 floodfillVec = tex2Dlod(flowmap_floodfill_tex, float4(htc,0,0)).rg * 2 - 1; + heightGradient *= heightGradient.x * floodfillVec.x + heightGradient.y * floodfillVec.y; + f.xy += heightGradient; + } + ##endif + float4 waterNeighbours = waterLevel; get_water_height(worldPos - float2(1, 0), waterNeighbours.x); get_water_height(worldPos + float2(1, 0), waterNeighbours.y); diff --git a/prog/gameLibs/render/shaders/hardware_defines.sh b/prog/gameLibs/render/shaders/hardware_defines.sh index 1ce0decf0..ab46fa225 100644 --- a/prog/gameLibs/render/shaders/hardware_defines.sh +++ b/prog/gameLibs/render/shaders/hardware_defines.sh @@ -644,6 +644,7 @@ hlsl { static uint bounds_check_dim; static uint bounds_check_stride; static uint2 bounds_check_2dim; + static uint3 bounds_check_3dim; void checkTexture2DBounds(int2 tc, uint2 dim, int lod, int file, int ln, int name) { @@ -685,6 +686,9 @@ hlsl { uint4 dim; \ a.GetDimensions(lod, dim.x, dim.y, dim.z, dim.w); \ checkTexture3DBounds(tc, dim.xyz, lod, file, ln, name) + #define CHECK_TEXTURE3D_EXPR(a, tc) \ + a.GetDimensions(bounds_check_3dim.x, bounds_check_3dim.y, bounds_check_3dim.z), \ + checkTexture3DBounds(tc, bounds_check_3dim.xyz, 0, _FILE_, __LINE__, -1) #define CHECK_BUFFER(file, ln, name) \ uint dim; \ a.GetDimensions(dim); \ @@ -708,6 +712,7 @@ hlsl { #define CHECK_TEXTURE2D_EXPR(a, tc) 0 #define CHECK_TEXTURE2DARRAY #define CHECK_TEXTURE3D + #define CHECK_TEXTURE3D_EXPR(a, tc) 0 #define CHECK_BUFFER(file, ln, name) #define CHECK_BUFFER_EXPR(a, tc) 0 #define CHECK_STRUCTURED_BUFFER(file, ln, name) @@ -787,6 +792,7 @@ hlsl { #define structuredBufferAt(a, tc) a[uint((CHECK_STRUCTURED_BUFFER_EXPR(a, tc), tc))] #define bufferAt(a, tc) a[uint((CHECK_BUFFER_EXPR(a, tc), tc))] #define texture2DAt(a, tc) a[int2((CHECK_TEXTURE2D_EXPR(a, tc), tc))] + #define texture3DAt(a, tc) a[int3((CHECK_TEXTURE3D_EXPR(a, tc), tc))] #endif ##if (hardware.xbox && !hardware.dx12) || hardware.vulkan diff --git a/prog/gameLibs/render/shaders/tiledLights.sh b/prog/gameLibs/render/shaders/tiledLights.sh index 74dab6f3f..2bfccf17e 100644 --- a/prog/gameLibs/render/shaders/tiledLights.sh +++ b/prog/gameLibs/render/shaders/tiledLights.sh @@ -201,15 +201,15 @@ shader spot_lights_tiles, omni_lights_tiles depthTile = tileIdx * TILE_EDGE + TILE_EDGE - 1 < screen_size.xy ? depthTile : depthTile - 1; uint index = input.index; uint finalIdx = (tileIdx.x * tiledGridSize.y + (tileIdx.y)) * DWORDS_PER_TILE + (index / BITS_IN_UINT); - float closeDepth = linearize_z(texelFetch(close_depth_tex, depthTile, DIVIDE_RESOLUTION_BITS - 1).x, zn_zfar.zw); - float farDepth = linearize_z(texelFetch(downsampled_far_depth_tex, depthTile, DIVIDE_RESOLUTION_BITS - 1).x, zn_zfar.zw); - float3 viewVecTileLT = lerp_view_vec(screenpos.xy * screen_size.zw * TILE_EDGE); - float3 viewVecTileLB = lerp_view_vec((screenpos.xy + float2(0, 1)) * screen_size.zw * TILE_EDGE); - float3 viewVecTileRT = lerp_view_vec((screenpos.xy + float2(1, 0)) * screen_size.zw * TILE_EDGE); - float3 viewVecTileRB = lerp_view_vec((screenpos.xy + float2(1, 1)) * screen_size.zw * TILE_EDGE); #if DISABLE_RAY_LIGHT_INTERSECTION InterlockedOr(structuredBufferAt(perTileLights, finalIdx), 1u << (index % BITS_IN_UINT)); #else + float closeDepth = linearize_z(texelFetch(close_depth_tex, depthTile, DIVIDE_RESOLUTION_BITS - 1).x, zn_zfar.zw); + float farDepth = linearize_z(texelFetch(downsampled_far_depth_tex, depthTile, DIVIDE_RESOLUTION_BITS - 1).x, zn_zfar.zw); + float3 viewVecTileLT = lerp_view_vec(screenpos.xy * screen_size.zw * TILE_EDGE); + float3 viewVecTileLB = lerp_view_vec((screenpos.xy + float2(0, 1)) * screen_size.zw * TILE_EDGE); + float3 viewVecTileRT = lerp_view_vec((screenpos.xy + float2(1, 0)) * screen_size.zw * TILE_EDGE); + float3 viewVecTileRB = lerp_view_vec((screenpos.xy + float2(1, 1)) * screen_size.zw * TILE_EDGE); if ( check_ray_light_intersection(input, float2(closeDepth, farDepth), viewVecTileLT) || check_ray_light_intersection(input, float2(closeDepth, farDepth), viewVecTileLB) diff --git a/prog/gameLibs/render/shaders/tracer.sh b/prog/gameLibs/render/shaders/tracer.sh index 8fd1269c0..dce85d006 100644 --- a/prog/gameLibs/render/shaders/tracer.sh +++ b/prog/gameLibs/render/shaders/tracer.sh @@ -40,6 +40,9 @@ float tracer_start_color_fade_time_inv = 4.0; int tracer_prim_type = 0; interval tracer_prim_type: tracer_prim_type_dir < 1, tracer_prim_type_caps; +int tracer_commands_count_const_no = 10 always_referenced; +int tracer_commands_array_const_no = 11 always_referenced; + block(scene) tracer_frame { supports global_frame; @@ -84,12 +87,12 @@ shader fx_create_cmd_cs #include } hlsl(cs) { - uint commandsCount: register(c10); + uint commandsCount: register(c10); // Keep constant insync with tracer_commands_count_const_no ##if fx_create_cmd == fx_create_tracer - GPUFxTracerCreate commands[FX_TRACER_MAX_CREATE_COMMANDS]: register(c11); + GPUFxTracerCreate commands[FX_TRACER_MAX_CREATE_COMMANDS]: register(c11); // Keep constant index sync with tracer_commands_array_const_no RWStructuredBuffer dataBuffer: register(u0); ##else - GPUFxSegmentCreate commands[FX_TRACER_MAX_CREATE_COMMANDS]: register(c11); + GPUFxSegmentCreate commands[FX_TRACER_MAX_CREATE_COMMANDS]: register(c11); // Keep constant index sync with tracer_commands_array_const_no RWStructuredBuffer dataBuffer: register(u0); ##endif [numthreads(FX_TRACER_COMMAND_WARP_SIZE, 1, 1)] diff --git a/prog/gameLibs/render/texcompressors/bcCompressor.cpp b/prog/gameLibs/render/texcompressors/bcCompressor.cpp index d73dc7332..d2d8149af 100644 --- a/prog/gameLibs/render/texcompressors/bcCompressor.cpp +++ b/prog/gameLibs/render/texcompressors/bcCompressor.cpp @@ -78,7 +78,7 @@ static bool isMobileFormat(BcCompressor::ECompressionType type) BcCompressor::BcCompressor(ECompressionType compr_type, unsigned int buffer_mips, unsigned int buffer_width, unsigned int buffer_height, int htiles, const char *bc_shader) : - vb(NULL), bufferTex(NULL), bufferMips(0), bufferWidth(0), bufferHeight(0), compressionType(compr_type) + vb(NULL), bufferTex(NULL), bufferMips(0), bufferWidth(0), bufferHeight(0), compressionType(compr_type), vbFiller(verts) { G_ASSERT(compressionType < COMPRESSION_ERR); srcTexVarId = ::get_shader_variable_id(shader_var_src_tex, true); @@ -129,6 +129,16 @@ BcCompressor::~BcCompressor() releaseBuffer(); } +void BcCompressor::VbFiller::reloadD3dRes(Sbuffer *sb) +{ + Vertex *p; + d3d_err(sb->lock(0, 0, (void **)&p, VBLOCK_WRITEONLY)); + if (!p) + return; + memcpy(p, verts.data(), data_size(verts)); + d3d_err(sb->unlock()); +} + bool BcCompressor::resetBuffer(unsigned int mips, unsigned int width, unsigned int height, int htiles) { G_ASSERT(compressionType < COMPRESSION_ERR); @@ -182,16 +192,12 @@ bool BcCompressor::resetBuffer(unsigned int mips, unsigned int width, unsigned i } #if !(_TARGET_C1 | _TARGET_C2) - vb = d3d::create_vb(data_size(verts), 0, "bcCompr"); + vb = d3d::create_vb(data_size(verts), SBCF_MAYBELOST, "bcCompr"); d3d_err(vb); if (!vb) return false; - Vertex *p; - d3d_err(vb->lock(0, 0, (void **)&p, VBLOCK_WRITEONLY)); - if (!p) - return false; - memcpy(p, verts.data(), data_size(verts)); - d3d_err(vb->unlock()); + vbFiller.reloadD3dRes(vb); + vb->setReloadCallback(&vbFiller); #endif return true; } diff --git a/prog/gameLibs/render/tireTracks.cpp b/prog/gameLibs/render/tireTracks.cpp index b966d94e6..fb7ac0c33 100644 --- a/prog/gameLibs/render/tireTracks.cpp +++ b/prog/gameLibs/render/tireTracks.cpp @@ -27,6 +27,8 @@ #include #include #include +#include +#include // TODO: boxes. fast and more correct (grid?) visibility for vtex. alttab. @@ -46,6 +48,14 @@ static bool has_vertex_normal = false; static Tab allVertices; static Tab updated_regions; +struct TracksInvalidateCommand +{ + Point3 pos; + float radius_sq = 0; + int emitter_id = -1; + int track_id = -1; +}; +static eastl::deque invalidateRegionsQueue; static int default_texture_idx = 0; static int maxTrackVertices = 800; @@ -234,6 +244,18 @@ class TireTrack TireTrackVertexNorm *getLastSegment() { return &lastSegmentVertices[0]; } + template + void invalidateVtxBuf(VType *vbufOrig, Point3 pos, float radius_sq) + { + TIME_D3D_PROFILE(tire_tracks_invalidate_region); + VType *vbuf = vbufOrig + vofs; + for (int i = 0; i < maxTrackVertices; i++) + { + if ((pos - vbuf[i].pos).lengthSq() <= radius_sq) + vbuf[i].tex.w = 0; + } + } + template void updateVtxBuf(VType *vbufOrig, int emitterIndex, int batchId) { @@ -890,6 +912,12 @@ static void beforeRenderProxy(float dt, const Point3 &orig); void beforeRender(float dt, const Point3 &origin) { + TracksInvalidateCommand inv; + if (invalidateRegionsQueue.size() > 0) + { + inv = invalidateRegionsQueue.front(); + invalidateRegionsQueue.pop_front(); + } TIME_D3D_PROFILE(tire_tracks_update); if (updated_emitters.size() > used_emitters.size()) updated_emitters.clear(); // for safety @@ -902,16 +930,27 @@ void beforeRender(float dt, const Point3 &origin) bool bUpdated = false; for (int j = 0; j < 2; ++j) { + bool invalidate_track = used_emitters[i] == inv.emitter_id && j == inv.track_id; TireTrack *track = emitters[used_emitters[i]].getTrack(j); - if (track->wasChanged()) + if (track->wasChanged() || invalidate_track) { if (!vertices) { if (!vbuffer->lock(0, 0, (void **)&vertices, VBLOCK_NOOVERWRITE | VBLOCK_WRITEONLY | VBLOCK_NOSYSLOCK)) return; } - track->updateVbuf(vertices, used_emitters[i]); - bUpdated = true; + if (track->wasChanged()) + { + track->updateVbuf(vertices, used_emitters[i]); + bUpdated = true; + } + else // invalidate track + { + if (tire_tracks::has_vertex_normal) + track->invalidateVtxBuf((TireTrackVertexNorm *)vertices, inv.pos, inv.radius_sq); + else + track->invalidateVtxBuf((TireTrackVertexNoNorm *)vertices, inv.pos, inv.radius_sq); + } } } if (bUpdated) @@ -921,6 +960,21 @@ void beforeRender(float dt, const Point3 &origin) vbuffer->unlock(); } +void invalidate_region(const BBox3 &bbox) +{ + float radius = max(bbox.width().x, max(bbox.width().y, bbox.width().z)) / 2; + for (int i = 0; i < used_emitters.size(); i++) + { + for (int j = 0; j < 2; ++j) + { + TireTrack *track = emitters[used_emitters[i]].getTrack(j); + bbox3f track_bbox = track->getBbox(); + if (v_bbox3_test_box_intersect(track_bbox, v_ldu_bbox3(bbox))) + invalidateRegionsQueue.push_back({bbox.center(), radius * radius, used_emitters[i], j}); + } + } +} + // render tires void render(const Frustum &frustum, bool for_displacement) { diff --git a/prog/gameLibs/render/tracer/tracer.cpp b/prog/gameLibs/render/tracer/tracer.cpp index 5fc75dc9a..cdd8a1b19 100644 --- a/prog/gameLibs/render/tracer/tracer.cpp +++ b/prog/gameLibs/render/tracer/tracer.cpp @@ -349,7 +349,8 @@ void TracerManager::DrawBuffer::append(uint32_t id, dag::ConstSpan elem } } -void TracerManager::DrawBuffer::process(ComputeShaderElement *cs, int fx_create_cmd, int element_count) +void TracerManager::DrawBuffer::process(ComputeShaderElement *cs, int commands_array_const_no, int commands_count_const_no, + int fx_create_cmd, int element_count) { if (!buf || cmds.empty()) return; @@ -367,19 +368,19 @@ void TracerManager::DrawBuffer::process(ComputeShaderElement *cs, int fx_create_ int elemCount = cmds.size() / elemSize; const int commandSizeInConsts = (elemSize + 15) / 16; - const int reqSize = 1 + elemCount * commandSizeInConsts; - const int cbufferSize = d3d::set_cs_constbuffer_size(reqSize); + const int reqSize = commands_array_const_no + elemCount * commandSizeInConsts; + const int commandCbufferSize = d3d::set_cs_constbuffer_size(reqSize) - commands_array_const_no; uint32_t v[4] = {0}; G_ASSERT(elemCount >= cmd); - for (int i = max(elemCount - cmd, 0); i < elemCount; i += (cbufferSize - 1) / commandSizeInConsts) + for (int i = max(elemCount - cmd, 0); i < elemCount; i += commandCbufferSize / commandSizeInConsts) { - int batch_size = min(elemCount - i, (int)(cbufferSize - 1) / commandSizeInConsts); + int batch_size = min(elemCount - i, commandCbufferSize / commandSizeInConsts); v[0] = batch_size; - d3d::set_cs_const(10, (float *)v, 1); + d3d::set_cs_const(commands_count_const_no, (float *)v, 1); - d3d::set_cs_const(11, (float *)&cmds[i * elemSize], batch_size * commandSizeInConsts); + d3d::set_cs_const(commands_array_const_no, (float *)&cmds[i * elemSize], batch_size * commandSizeInConsts); cs->dispatch((batch_size + FX_TRACER_COMMAND_WARP_SIZE - 1) / FX_TRACER_COMMAND_WARP_SIZE, 1, 1); } @@ -513,6 +514,9 @@ TracerManager::TracerManager(const DataBlock *blk) : if (computeSupported) createCmdCs = new_compute_shader("fx_create_cmd_cs"); + commandsCountConstNo = ShaderGlobal::get_int_fast(::get_shader_variable_id("tracer_commands_count_const_no")); + commandsArrayConstNo = ShaderGlobal::get_int_fast(::get_shader_variable_id("tracer_commands_array_const_no")); + initHeads(); initTrails(); @@ -1152,14 +1156,14 @@ void TracerManager::beforeRender(const Frustum *f) mFrustum = f; - tracerBuffer.process(createCmdCs, 0, maxTracerNo + 1); - segmentBuffer.process(createCmdCs, 1, (maxTracerNo + 1) * MAX_FX_SEGMENTS); + tracerBuffer.process(createCmdCs, commandsArrayConstNo, commandsCountConstNo, 0, maxTracerNo + 1); + segmentBuffer.process(createCmdCs, commandsArrayConstNo, commandsCountConstNo, 1, (maxTracerNo + 1) * MAX_FX_SEGMENTS); preparing = true; threadpool::add(this); } -void TracerManager::renderTrans(bool heads, bool trails, float *hk, HeadPrimType head_prim_type) +void TracerManager::renderTrans(bool heads, bool trails, const float *hk, HeadPrimType head_prim_type) { threadpool::wait(this); preparing = false; diff --git a/prog/gameLibs/render/viewVecs.cpp b/prog/gameLibs/render/viewVecs.cpp index 604ae0652..4f03cf76d 100644 --- a/prog/gameLibs/render/viewVecs.cpp +++ b/prog/gameLibs/render/viewVecs.cpp @@ -40,17 +40,6 @@ void set_inv_globtm_to_shader(const TMatrix4 &viewTm, const TMatrix4 &projTm, bo ShaderGlobal::set_float4x4(globtm_invVarId, globTmInv); } -void set_inv_globtm_to_shader(bool optional) -{ - init_inv_globtm_vars(optional); - if (globtm_invVarId < 0) - return; - TMatrix4 viewTm, projTm; - d3d::gettm(TM_PROJ, &projTm); - d3d::gettm(TM_VIEW, &viewTm); - set_inv_globtm_to_shader(viewTm, projTm, optional); -} - void get_viewvecs(Point4 &viewVecLT, Point4 &viewVecRT, Point4 &viewVecLB, Point4 &viewVecRB, const TMatrix &viewTm, const TMatrix4 &projTm) { diff --git a/prog/gameLibs/render/wakePs/shipWakeFx.cpp b/prog/gameLibs/render/wakePs/shipWakeFx.cpp index ef20289c3..af894dec7 100644 --- a/prog/gameLibs/render/wakePs/shipWakeFx.cpp +++ b/prog/gameLibs/render/wakePs/shipWakeFx.cpp @@ -108,7 +108,7 @@ uint32_t ShipWakeFx::addShip(const ShipDesc &desc) float boxLen = desc.box.width().length(); float wrp = cvt(boxLen, 20.0f, 30.0f, 15.0f, 25.0f); wrp = cvt(boxLen, 55.0f, 85.0f, wrp, 40.0f); - wrp = cvt(boxLen, 130.0f, 180.0f, wrp, 60.0f); + wrp = cvt(boxLen, 130.0f, 180.0f, wrp, 60.0f) * desc.scale; ship.wrp = wrp; ship.scaleZ = min(0.75f + wrp * 0.01f, desc.box.width().y * 0.05f); @@ -152,7 +152,7 @@ uint32_t ShipWakeFx::addShip(const ShipDesc &desc) const float radius1 = wrp * 0.14f; const float emitPerMeter1 = 0.7f / radius1; const float posSpread1 = radius1 * 0.143f; - const float lifeTime1 = radius1 * 4.0f; + const float lifeTime1 = radius1 * 4.0f * desc.trailLifeScale; ParticleSystem::EmitterParams emitterParams; emitterParams.spawn.emitPerSecond = 0.0f; @@ -210,7 +210,7 @@ uint32_t ShipWakeFx::addShip(const ShipDesc &desc) const float radius1 = wrp * 0.06f; const float emitPerMeter1 = 0.75f / radius1; const float posSpread1 = radius1 * 0.167f; - const float lifeTime1 = radius1 * 1.0f; + const float lifeTime1 = radius1 * 1.0f * desc.trailLifeScale; ParticleSystem::EmitterParams emitterParams; emitterParams.spawn.emitPerSecond = 0.0f; @@ -361,7 +361,7 @@ uint32_t ShipWakeFx::addShip(const ShipDesc &desc) const float radiusSpread = radius * 0.25f; const float emitPerMeter = 0.8f / radius; const float posSpread = radius * 0.25f; - const float lifeTime = radius * 3.5f; + const float lifeTime = radius * 3.5f * desc.trailLifeScale; ParticleSystem::EmitterParams emitterParams; emitterParams.spawn.emitPerSecond = 0.0f; @@ -516,6 +516,12 @@ bool ShipWakeFx::isShipRemoved(uint32_t index) const return ships[index].removed; } +const ShipWakeFx::ShipDesc &ShipWakeFx::getDesc(uint32_t index) const +{ + VERIFY_SHIP_INDEX; + return ships[index].desc; +} + void ShipWakeFx::setShipState(uint32_t index, const ShipState &state) { const float WAKE_LATERAL = 0.45f; @@ -625,17 +631,19 @@ void ShipWakeFx::setShipState(uint32_t index, const ShipState &state) psFoam->setEmitterAlpha(ship.s[sNo].foamBack, foamAlphaValue); } - - emitterPose = psFoam->getEmitterPose(ship.s[sNo].foamTrailWave); - emitterPose.pos = shipPos + shipDir * (shipBack.x + WAKE_TRAIL_POS) + right[sNo] * (shipBack.y + FOAM_TRAIL_OFFSET); - emitterPose.rot = foamAngle[sNo]; - psFoam->setEmitterPose(ship.s[sNo].foamTrailWave, emitterPose); - const Point2 foamVel = right[sNo] * fabsf(longVel) * FOAM_TRAIL_LATERIAL; - emitterVelocity = psFoam->getEmitterVelocity(ship.s[sNo].foamTrailWave); - emitterVelocity.dir = normalizeDef(foamVel, shipDir); - emitterVelocity.vel = foamVel.length(); - psFoam->setEmitterVelocity(ship.s[sNo].foamTrailWave, emitterVelocity); - psFoam->setEmitterAlpha(ship.s[sNo].foamTrailWave, foamAlphaValue); + if (state.hasBack) + { + emitterPose = psFoam->getEmitterPose(ship.s[sNo].foamTrailWave); + emitterPose.pos = shipPos + shipDir * (shipBack.x + WAKE_TRAIL_POS) + right[sNo] * (shipBack.y + FOAM_TRAIL_OFFSET); + emitterPose.rot = foamAngle[sNo]; + psFoam->setEmitterPose(ship.s[sNo].foamTrailWave, emitterPose); + const Point2 foamVel = right[sNo] * fabsf(longVel) * FOAM_TRAIL_LATERIAL; + emitterVelocity = psFoam->getEmitterVelocity(ship.s[sNo].foamTrailWave); + emitterVelocity.dir = normalizeDef(foamVel, shipDir); + emitterVelocity.vel = foamVel.length(); + psFoam->setEmitterVelocity(ship.s[sNo].foamTrailWave, emitterVelocity); + psFoam->setEmitterAlpha(ship.s[sNo].foamTrailWave, foamAlphaValue); + } } if (!settings.reduceFoam && state.hasFront) @@ -675,17 +683,21 @@ void ShipWakeFx::setShipState(uint32_t index, const ShipState &state) } } + const float speedScaleZ = saturate((longVel - WAKE_TRAIL_SCALEZ_MIN_VEL) / WAKE_TRAIL_SCALEZ_MIN_VEL); // psWakeTrail + if (state.hasBack) { - const float speedScaleZ = saturate((longVel - WAKE_TRAIL_SCALEZ_MIN_VEL) / WAKE_TRAIL_SCALEZ_MIN_VEL); ParticleSystem::Pose emitterPose = psWakeTrail->getEmitterPose(ship.wakeTrail); emitterPose.pos = shipPos + shipDir * (shipBack.x + WAKE_TRAIL_POS) + shipRight * shipBack.y; emitterPose.scale.z = ship.scaleZ * speedScaleZ; psWakeTrail->setEmitterPose(ship.wakeTrail, emitterPose); - + } + // front of psWakeTrail + if (state.hasFront) + { for (int sNo = 0; sNo < 2; ++sNo) { - emitterPose = psWakeTrail->getEmitterPose(ship.s[sNo].wakeBack); + ParticleSystem::Pose emitterPose = psWakeTrail->getEmitterPose(ship.s[sNo].wakeBack); emitterPose.pos = shipPos + shipDir * (shipBack.x + WAKE_SEC_TRAIL_POS) + right[sNo] * (shipBack.y + WAKE_TRAIL_OFFSET); emitterPose.scale.z = ship.scaleZ * speedScaleZ; psWakeTrail->setEmitterPose(ship.s[sNo].wakeBack, emitterPose); @@ -699,6 +711,7 @@ void ShipWakeFx::setShipState(uint32_t index, const ShipState &state) } // psFoamTrail + if (state.hasBack) { ParticleSystem::Pose emitterPose = psFoamTrail->getEmitterPose(ship.foamTrail); emitterPose.pos = shipPos + shipDir * (shipBack.x + WAKE_TRAIL_POS) + shipRight * shipBack.y; @@ -707,7 +720,7 @@ void ShipWakeFx::setShipState(uint32_t index, const ShipState &state) psFoamTrail->setEmitterAlpha(ship.foamTrail, foamAlphaValue); } - if (psFoamDistorted) + if (psFoamDistorted && state.hasBack) { ParticleSystem::Pose emitterPose = psFoamDistorted->getEmitterPose(ship.foamDistorted); emitterPose.pos = shipPos + shipDir * (shipBack.x + WAKE_TRAIL_POS) + shipRight * shipBack.y; @@ -716,7 +729,7 @@ void ShipWakeFx::setShipState(uint32_t index, const ShipState &state) psFoamDistorted->setEmitterAlpha(ship.foamDistorted, foamAlphaValue); } - if (psFoamMask) + if (psFoamMask && state.hasBack) { ParticleSystem::Pose emitterPose = psFoamMask->getEmitterPose(ship.foamMask); emitterPose.pos = shipPos + shipDir * (shipBack.x + WAKE_TRAIL_POS) + shipRight * shipBack.y; diff --git a/prog/gameLibs/render/wakePs/wakePs.cpp b/prog/gameLibs/render/wakePs/wakePs.cpp index 1d54b8458..a20cd6e73 100644 --- a/prog/gameLibs/render/wakePs/wakePs.cpp +++ b/prog/gameLibs/render/wakePs/wakePs.cpp @@ -1,6 +1,7 @@ #include #include <3d/dag_drv3d.h> #include <3d/dag_drv3dCmd.h> +#include <3d/dag_quadIndexBuffer.h> #include #include #include @@ -533,10 +534,12 @@ EffectManager::EffectManager() fTimeVarId = ::get_shader_variable_id("wfx_ftime"); initRes(); + index_buffer::init_quads_16bit(); } EffectManager::~EffectManager() { + index_buffer::release_quads_16bit(); releaseRes(); clearPSystems(); } @@ -551,24 +554,6 @@ void EffectManager::initRes() for (int renderType = 0; renderType < ParticleSystem::RENDER_TYPE_END; renderType++) renderShaders[renderType].init(SHADER_NAMES[renderType], NULL, 0, SHADER_NAMES[renderType]); - particleQuadIB = dag::create_ib(MAX_PARTICLES * INDICIES_PER_PARTICLE * sizeof(uint16_t), 0, "particleQuadIB"); - G_ASSERT(particleQuadIB); - - uint16_t *particleQuadIBData; - if (!particleQuadIB->lock(0, 0, &particleQuadIBData, VBLOCK_WRITEONLY) || !particleQuadIBData) - return; - for (uint32_t particleNo = 0; particleNo < MAX_PARTICLES; particleNo++) - { - particleQuadIBData[0] = particleNo * VERTICES_PER_PARTICLE + 0; - particleQuadIBData[1] = particleNo * VERTICES_PER_PARTICLE + 1; - particleQuadIBData[2] = particleNo * VERTICES_PER_PARTICLE + 2; - particleQuadIBData[3] = particleNo * VERTICES_PER_PARTICLE + 0; - particleQuadIBData[4] = particleNo * VERTICES_PER_PARTICLE + 2; - particleQuadIBData[5] = particleNo * VERTICES_PER_PARTICLE + 3; - particleQuadIBData += INDICIES_PER_PARTICLE; - } - particleQuadIB->unlock(); - randomBuffer = dag::create_tex(NULL, RANDOM_BUFFER_RESOLUTION_X, RANDOM_BUFFER_RESOLUTION_Y, TEXFMT_A8R8G8B8 | TEXCF_MAYBELOST, 1, "wfxRandomBuffer"); uint8_t *randomBufferData = NULL; @@ -592,7 +577,6 @@ void EffectManager::releaseRes() for (int renderType = 0; renderType < ParticleSystem::RENDER_TYPE_END; renderType++) renderShaders[renderType].close(); - particleQuadIB.close(); randomBuffer.close(); } @@ -645,7 +629,7 @@ bool EffectManager::render(ParticleSystem::RenderType render_type) return false; d3d::setvsrc(0, 0, 0); - d3d::setind(particleQuadIB.get()); + index_buffer::use_quads_16bit(); bool renderedAnything = false; for (auto &pSystem : pSystems) diff --git a/prog/gameLibs/render/waterProjFx.cpp b/prog/gameLibs/render/waterProjFx.cpp index d764d60de..63eb7963e 100644 --- a/prog/gameLibs/render/waterProjFx.cpp +++ b/prog/gameLibs/render/waterProjFx.cpp @@ -88,7 +88,7 @@ bool WaterProjectedFx::getView(TMatrix4 &view_tm, TMatrix4 &proj_tm, Point3 &cam return true; } -bool WaterProjectedFx::isValidView() const { return numIntersections > 0 && savedCamPos.y > waterLevel; } +bool WaterProjectedFx::isValidView() const { return numIntersections > 0; } void WaterProjectedFx::prepare(const TMatrix &view_tm, const TMatrix4 &proj_tm, const TMatrix4 &glob_tm, float water_level, float significant_wave_height, int frame_no) @@ -110,9 +110,9 @@ void WaterProjectedFx::prepare(const TMatrix &view_tm, const TMatrix4 &proj_tm, Point4 bottomPlane; v_stu(&bottomPlane.x, Frustum(glob_tm).camPlanes[Frustum::BOTTOM]); float cosA = min(bottomPlane.y, CAMERA_PLANE_BOTTOM_MIN_ANGLE); - cameraPos += -normalize(Point3(cameraDir.x, 0.0f, cameraDir.z)) * max(waterHeightTop + CAMERA_PLANE_ELEVATION - cameraPos.y, 0.0f) * - safediv(cosA, safe_sqrt(1.0f - SQR(cosA))); - cameraPos.y = max(cameraPos.y, waterHeightTop + CAMERA_PLANE_ELEVATION); + cameraPos += -normalize(Point3(cameraDir.x, 0.0f, cameraDir.z)) * + max(waterHeightTop + CAMERA_PLANE_ELEVATION - abs(cameraPos.y), 0.0f) * safediv(cosA, safe_sqrt(1.0f - SQR(cosA))); + cameraPos.y = max(abs(cameraPos.y), waterHeightTop + CAMERA_PLANE_ELEVATION) * (cameraPos.y > 0 ? 1.0f : -1.0f); newViewItm.setcol(3, cameraPos); newViewTM = orthonormalized_inverse(newViewItm); diff --git a/prog/gameLibs/soundSystem/banks.cpp b/prog/gameLibs/soundSystem/banks.cpp index 7bb6aaad3..90a432d31 100644 --- a/prog/gameLibs/soundSystem/banks.cpp +++ b/prog/gameLibs/soundSystem/banks.cpp @@ -8,8 +8,6 @@ #include #include #include -#include -#include #include #include #include @@ -38,42 +36,48 @@ static WinCritSec g_banks_cs; static const size_t max_banks = 512; using Bitset = eastl::bitset; -static bool enable_mod = false; static bool g_report_bank_loading_time = false; struct Bank { FMOD::Studio::Bank *fmodBank = nullptr; - eastl::string path; - uint32_t id = 0; + const eastl::string path; + const uint32_t id = 0; - bool isAsync = false; - bool isPreload = false; - bool isLoadToMemory = false; - bool isOptional = false; + const bool isAsync = false; + const bool isPreload = false; + const bool isLoadToMemory = false; + const bool isOptional = false; + const bool isMod = false; Bank() = delete; - Bank(const char *path_, uint32_t id_, bool is_async, bool is_preload, bool is_load_to_memory, bool is_optional) : - path(path_), id(id_), isAsync(is_async), isPreload(is_preload), isLoadToMemory(is_load_to_memory), isOptional(is_optional) + Bank(const char *path_, uint32_t id_, bool is_async, bool is_preload, bool is_load_to_memory, bool is_optional, bool is_mod) : + path(path_), + id(id_), + isAsync(is_async), + isPreload(is_preload), + isLoadToMemory(is_load_to_memory), + isOptional(is_optional), + isMod(is_mod) {} }; struct Preset { Bitset banks; - eastl::string name; - str_hash_t hash = 0; + const eastl::string name; + const str_hash_t hash = {}; bool isEnabled = false; bool isLoaded = false; Preset() = delete; - Preset(const char *name_) : name(name_) { hash = SND_HASH_SLOW(name_); } + Preset(const char *name_) : name(name_), hash(SND_HASH_SLOW(name_)) {} }; struct Plugin { uint32_t handle = 0; - eastl::string path; + const eastl::string path; Plugin() = delete; Plugin(const char *path_) : path(path_) {} @@ -90,48 +94,20 @@ static Bitset failed_banks; static eastl::fixed_string locale; static bool is_inited = false; -static void def_err_cb(const char *sndsys_message, const char *fmod_error_message, const char *bank_path) +static void def_err_cb(const char *sndsys_message, const char *fmod_error_message, const char *bank_path, bool is_mod) { #if DAGOR_DBGLEVEL == 0 - if (!enable_mod) + if (!is_mod) #endif + { logerr("[SNDSYS] %s \"%s\" \"%s\"", sndsys_message, bank_path, fmod_error_message); + } + G_UNREFERENCED(is_mod); } static ErrorCallback err_cb = def_err_cb; static PresetLoadedCallback preset_loaded_cb = nullptr; -template -static inline void parse(const char *name, Func func) -{ - FrameStr tag; - for (; name;) - { - const char *next = strchr(name, '_'); - if (!next) - next = strchr(name, '.'); - size_t len = next ? next - name : strlen(name); - tag.assign(name, len); - func(tag); - name = next && *next != '.' ? next + 1 : nullptr; - } -} - -// cmn_loc_vo_-de.bank -static inline bool is_skip_bank_by_locale(const char *str) -{ - FrameStr type; - bool have = false; - parse(str, [&have, &type](const FrameStr &tag_str) { - if (tag_str.size() >= 1 && tag_str[0] == '-') - { - type.assign(tag_str.begin() + 1, tag_str.end()); - have = true; - } - }); - return have && type != locale.c_str(); -} - static inline bool is_async(uint32_t bank_id) { return all_banks[bank_id].isAsync; } static inline bool is_preload(uint32_t bank_id) { return all_banks[bank_id].isPreload; } @@ -146,19 +122,6 @@ static inline void replace(FrameStr &path, const char *what, const char *with) } static inline void make_localized(FrameStr &str) { replace(str, "", locale.c_str()); } -static inline void add_mod_path(FrameStr &str) -{ - eastl_size_t idx = str.find(""); - if (idx != FrameStr::npos) - { - FrameStr backupStr = str; - str.replace(idx, strlen(""), "mod/"); - const char *realPathMod = df_get_real_name(str.c_str()); - if (!realPathMod) - str.replace(idx, strlen("mod/"), ""); - } -} - static inline FMOD_RESULT load_bank_memory(const char *filename, FMOD_STUDIO_LOAD_BANK_FLAGS flags, FMOD::Studio::Bank **fmod_bank) { file_ptr_t fp = df_open(filename, DF_READ); @@ -201,9 +164,6 @@ static inline void load_bank(Bank &bank, const PathTags &path_tags) for (auto &tag : path_tags) replace(taggedPath, tag.first, tag.second); - if (enable_mod) - add_mod_path(taggedPath); - const char *realPath = df_get_real_name(taggedPath.c_str()); if (!realPath) { @@ -213,7 +173,7 @@ static inline void load_bank(Bank &bank, const PathTags &path_tags) debug_trace_warn("Optional sound bank load was skipped because file \"%s\" is missing", taggedPath.c_str()); } else - err_cb("bank could not be loaded because there is no such file", "", taggedPath.c_str()); + err_cb("bank could not be loaded because there is no such file", "", taggedPath.c_str(), bank.isMod); return; } @@ -226,7 +186,7 @@ static inline void load_bank(Bank &bank, const PathTags &path_tags) if (FMOD_OK != result) { failed_banks.set(bank.id); - err_cb("bank could not be loaded", FMOD_ErrorString(result), realPath); + err_cb("bank could not be loaded", FMOD_ErrorString(result), realPath, bank.isMod); if (bank.fmodBank) { SOUND_VERIFY(bank.fmodBank->unload()); @@ -264,20 +224,23 @@ static inline void unload_bank(Bank &bank, eastl::vectorisMod == is_mod && it->isOptional == is_optional && it->isOptional == is_optional && it->isAsync == is_async && + it->isPreload == is_preload && it->isLoadToMemory == is_load_to_memory, + "Append new to existing bank parameters mismatch: there is already bank with same path but different options"); + } else { bankId = all_banks.size(); - all_banks.emplace_back(path, bankId, is_async, is_preload, is_load_to_memory, is_optional); + all_banks.emplace_back(path, bankId, is_async, is_preload, is_load_to_memory, is_optional, is_mod); G_ASSERT(all_banks.size() <= max_banks); } preset.banks.set(bankId); @@ -405,7 +368,7 @@ void update() SOUND_VERIFY(bank.fmodBank->unload()); bank.fmodBank = nullptr; } - err_cb("error loading bank", FMOD_ErrorString(result), bank.path.c_str()); + err_cb("error loading bank", FMOD_ErrorString(result), bank.path.c_str(), bank.isMod); continue; } @@ -419,7 +382,7 @@ void update() { const FMOD_RESULT result = bank.fmodBank->loadSampleData(); if (result != FMOD_OK) - err_cb("error preload bank sample data", FMOD_ErrorString(result), bank.path.c_str()); + err_cb("error preload bank sample data", FMOD_ErrorString(result), bank.path.c_str(), bank.isMod); } failed_banks.set(bank.id, false); } @@ -428,7 +391,7 @@ void update() failed_banks.set(bank.id); SOUND_VERIFY(bank.fmodBank->unload()); bank.fmodBank = nullptr; - err_cb("load bank failed", "", bank.path.c_str()); + err_cb("load bank failed", "", bank.path.c_str(), bank.isMod); } pending_banks.set(bank.id, false); @@ -457,6 +420,45 @@ static __forceinline Preset *find_preset(const char *name) static HashedKeySet g_guid_prohibited; +static void add_bank(const char *name, const DataBlock &blk, const char *banks_folder, const char *extension, bool enable_mod, + Preset &preset) +{ + const char *overridedPath = blk.getStr("path", nullptr); + + bool isMod = false; + + FrameStr path; + + if (enable_mod) + { + if (overridedPath) + path.sprintf("%s/mod/%s%s", overridedPath, name, extension); + else if (banks_folder && *banks_folder) + path.sprintf("%s/mod/%s%s", banks_folder, name, extension); + else + path.sprintf("mod/%s%s", name, extension); + + make_localized(path); + + isMod = df_get_real_name(path.c_str()) != nullptr; + } + + if (!isMod) + { + if (overridedPath) + path.sprintf("%s/%s%s", overridedPath, name, extension); + else if (banks_folder && *banks_folder) + path.sprintf("%s/%s%s", banks_folder, name, extension); + else + path.sprintf("%s%s", name, extension); + + make_localized(path); + } + + append_bank(path.c_str(), blk.getBool("async", false), blk.getBool("preload", false), blk.getBool("loadToMemory", false), + blk.getBool("optional", false), isMod, preset); +}; + void init(const DataBlock &blk) { G_ASSERT_RETURN(sndsys::is_inited(), ); @@ -464,25 +466,18 @@ void init(const DataBlock &blk) G_ASSERT_RETURN(!is_inited, ); const DataBlock &banksBlk = *blk.getBlockByNameEx("banks"); - const DataBlock &groupsBlk = *banksBlk.getBlockByNameEx("groups"); + const DataBlock &modBlk = *blk.getBlockByNameEx("mod"); init_locale(blk, banksBlk); debug_trace_log("locale is \"%s\"", locale.c_str()); - const char *folder = blk.getStr("banksFolder", ""); - const char *extension = blk.getStr("banksExtension", ".bank"); + const char *folder = banksBlk.getStr("folder", "sound"); + const char *extension = banksBlk.getStr("extension", ".bank"); + + const bool enableMod = blk.getBool("enableMod", false) && modBlk.getBool("allow", true); - enable_mod = blk.getBool("enableMod", false); g_report_bank_loading_time = blk.getBool("reportBankLoadingTime", false); - if (enable_mod) - { - FrameStr modPath; - modPath.sprintf("%s/mod/*.bank", folder); - alefind_t fnd; - if (!dd_find_first(modPath.c_str(), DA_FILE, &fnd)) - enable_mod = false; - } FrameStr name, path; const DataBlock *presetsBlk = banksBlk.getBlockByNameEx("presets"); all_presets.reserve(presetsBlk->blockCount()); @@ -492,70 +487,16 @@ void init(const DataBlock &blk) all_presets.emplace_back(presetBlk->getBlockName()); Preset &preset = all_presets.back(); - auto addBank = [folder, extension, &preset](const char *name, const DataBlock &blk) { - FrameStr localizedName = name; - make_localized(localizedName); - - FrameStr path; - const char *overridedPath = blk.getStr("path", nullptr); - if (folder && *folder) - { - if (enable_mod) - path.sprintf("%s/%s%s", folder, localizedName.c_str(), extension); - else - { - if (overridedPath) - path.sprintf("%s/%s%s", overridedPath, localizedName.c_str(), extension); - else - path.sprintf("%s/%s%s", folder, localizedName.c_str(), extension); - } - } - else - { - if (overridedPath) - path.sprintf("%s/%s%s", overridedPath, localizedName.c_str(), extension); - else - path.sprintf("%s%s", localizedName.c_str(), extension); - } - make_localized(path); - - add_bank(localizedName.c_str(), path.c_str(), blk.getBool("async", false), blk.getBool("preload", false), - blk.getBool("loadToMemory", false), blk.getBool("optional", false), preset); - }; - for (int i = 0; i < presetBlk->blockCount(); ++i) { const DataBlock *bankBlk = presetBlk->getBlock(i); - addBank(bankBlk->getBlockName(), *bankBlk); + add_bank(bankBlk->getBlockName(), *bankBlk, folder, extension, enableMod, preset); } for (int i = 0; i < presetBlk->paramCount(); ++i) { - name = presetBlk->getStr(i); - make_localized(name); - - if (strcmp(presetBlk->getParamName(i), "group") == 0) - { - if (const DataBlock *groupBlk = groupsBlk.getBlockByNameEx(name.c_str(), nullptr)) - { - for (int j = 0; j < groupBlk->paramCount(); ++j) - { - G_ASSERT_CONTINUE(strcmp(groupBlk->getParamName(j), "bank") == 0); - addBank(groupBlk->getStr(j), DataBlock::emptyBlock); - } - for (int j = 0; j < groupBlk->blockCount(); ++j) - { - const DataBlock *bankBlk = groupBlk->getBlock(j); - addBank(bankBlk->getBlockName(), *bankBlk); - } - } - else - { - logerr("group \"%s\" of banks not found", name.c_str()); - } - } - else if (strcmp(presetBlk->getParamName(i), "bank") == 0) - addBank(name.c_str(), DataBlock::emptyBlock); + if (strcmp(presetBlk->getParamName(i), "bank") == 0) + add_bank(presetBlk->getStr(i), DataBlock::emptyBlock, folder, extension, enableMod, preset); else G_ASSERTF(false, "Unexpected param name \"%s\"", presetBlk->getParamName(i)); } diff --git a/prog/gameLibs/spirv/compiler_dxc.cpp b/prog/gameLibs/spirv/compiler_dxc.cpp index b97c1d21e..c54cb5183 100644 --- a/prog/gameLibs/spirv/compiler_dxc.cpp +++ b/prog/gameLibs/spirv/compiler_dxc.cpp @@ -312,7 +312,7 @@ CompileToSpirVResult spirv::compileHLSL_DXC(dag::ConstSpan source, const c #if _TARGET_PC_WIN const String libPath("dxcompiler.dll"); #else - const String libPath = folders::get_exe_dir() + "libdxcompiler.dylib"; + const String libPath = folders::get_exe_dir() + "dxcompiler.dylib"; #endif eastl::unique_ptr library; library.reset(os_dll_load(libPath.c_str())); diff --git a/prog/gameLibs/spirv/jamfile b/prog/gameLibs/spirv/jamfile index 80162b152..72c9000ef 100644 --- a/prog/gameLibs/spirv/jamfile +++ b/prog/gameLibs/spirv/jamfile @@ -31,12 +31,14 @@ AddIncludes += $(Root)/prog/gameLibs/publicInclude ; -if $(Platform) != macosx { - AddIncludes += $(_DEVTOOL)/DXC/include -; -} else { - AddIncludes += $(_DEVTOOL)/DXC-mac/include +include $(Root)/$(Location)/jamfile-dxc-ver ; + +if ! [ GLOB $(_DEVTOOL)/DXC-$(DXC_VERSION)/include : * ] { exit FATAL\: \"DXC-$(DXC_VERSION)/include\" not found! Please, update DEVTOOLS ; } + +AddIncludes += $(_DEVTOOL)/DXC-$(DXC_VERSION)/include ; + +if $(Platform) = macosx { UseProgLibs += gameLibs/folders ; } diff --git a/prog/gameLibs/spirv/jamfile-dxc-ver b/prog/gameLibs/spirv/jamfile-dxc-ver new file mode 100644 index 000000000..5d447e7dc --- /dev/null +++ b/prog/gameLibs/spirv/jamfile-dxc-ver @@ -0,0 +1 @@ +DXC_VERSION = 1.7.2207 ; \ No newline at end of file diff --git a/prog/gameLibs/webui/plugins/grapheditor/dialog.js b/prog/gameLibs/webui/plugins/grapheditor/dialog.js index 67b318ebf..23702401c 100644 --- a/prog/gameLibs/webui/plugins/grapheditor/dialog.js +++ b/prog/gameLibs/webui/plugins/grapheditor/dialog.js @@ -136,7 +136,7 @@ function show_prompt(description, defaultText, callback) defaultText = ("" + defaultText).replace(/&/g, "&").replace(//g, ">").replace(/"/g, """); var html = '
 ' + description + '
'; - html += '  '; + html += '  '; show_dialog(null, html, [ ["OK", function() { diff --git a/prog/gameLibs/webui/plugins/grapheditor/graphEditor.html b/prog/gameLibs/webui/plugins/grapheditor/graphEditor.html index 910dabe71..a7652979d 100644 --- a/prog/gameLibs/webui/plugins/grapheditor/graphEditor.html +++ b/prog/gameLibs/webui/plugins/grapheditor/graphEditor.html @@ -303,7 +303,7 @@ onclick="document.getElementById('elemFilterEdit').focus();" > -
Error
@@ -314,7 +314,7 @@ >
Open Graph:
-
Error
@@ -329,7 +329,7 @@ onkeydown="onBigTextAreaKeyDown(event)"> - +
__SPLASH_SCREEN_TEXT__ diff --git a/prog/scripts/sq/daRg/darg_library.nut b/prog/scripts/sq/daRg/darg_library.nut index 831c9e2ea..1fac19063 100644 --- a/prog/scripts/sq/daRg/darg_library.nut +++ b/prog/scripts/sq/daRg/darg_library.nut @@ -2,6 +2,7 @@ from "%sqstd/frp.nut" import * from "daRg" import * let {tostring_r} = require("%sqstd/string.nut") +let {min} = require("math") /* //===== DARG specific methods===== diff --git a/prog/scripts/sq/daRg/helpers/mkGradientImg.nut b/prog/scripts/sq/daRg/helpers/mkGradientImg.nut index 1f30ddf9f..c21b3940c 100644 --- a/prog/scripts/sq/daRg/helpers/mkGradientImg.nut +++ b/prog/scripts/sq/daRg/helpers/mkGradientImg.nut @@ -3,6 +3,8 @@ from "%darg/ui_imports.nut" import * from "base64" import encodeString +let math = require("math") + const BLEND_MODE_PREMULTIPLIED = "PREMULTIPLIED" const BLEND_MODE_NONPREMULTIPLIED = "NONPREMULTIPLIED" const BLEND_MODE_ADDITIVE = "ADDITIVE" @@ -71,7 +73,7 @@ let function mkRadialGradSvgTxtImpl(points, width, height, cx=null, cy=null, r=n fx != null ? $"fx='{fx}'" : "", fy != null ? $"fy='{fy}'" : "" ]) - r = r==null ? min(width, height) * 0.5 : r + r = r==null ? math.min(width, height) * 0.5 : r let center = " ".join([ cx!=null ? $"cx='{cx}'" : "", cy!=null ? $"cy='{cy}'" : "", diff --git a/prog/scripts/sq/daeditor/attrPanel.nut b/prog/scripts/sq/daeditor/attrPanel.nut index cfe1069be..d30112c2f 100644 --- a/prog/scripts/sq/daeditor/attrPanel.nut +++ b/prog/scripts/sq/daeditor/attrPanel.nut @@ -3,6 +3,7 @@ from "%darg/laconic.nut" import * from "%sqstd/ecs.nut" import * let { Point2, Point3, Point4 } = require("dagor.math") +let math = require("math") let {endswith} = require("string") let {getValFromObj, isCompReadOnly, updateComp} = require("components/attrUtil.nut") @@ -50,10 +51,10 @@ let windowState = Watched({ let function onMoveResize(dx, dy, dw, dh) { let w = windowState.value - w.pos[0] = clamp(w.pos[0]+dx, -(sw(100)-w.size[0]), 0) - w.pos[1] = max(w.pos[1]+dy, 0) - w.size[0] = clamp(w.size[0]+dw, sw(14), sw(80)) - w.size[1] = clamp(w.size[1]+dh, sh(20), sh(95)) + w.pos[0] = math.clamp(w.pos[0]+dx, -(sw(100)-w.size[0]), 0) + w.pos[1] = math.max(w.pos[1]+dy, 0) + w.size[0] = math.clamp(w.size[0]+dw, sw(14), sw(80)) + w.size[1] = math.clamp(w.size[1]+dh, sh(20), sh(95)) return w } diff --git a/prog/scripts/sq/daeditor/components/attrUtil.nut b/prog/scripts/sq/daeditor/components/attrUtil.nut index 6556b9a2e..11ac9d3ed 100644 --- a/prog/scripts/sq/daeditor/components/attrUtil.nut +++ b/prog/scripts/sq/daeditor/components/attrUtil.nut @@ -4,6 +4,7 @@ let { regexp, strip, format } = require("string") let dagorMath = require("dagor.math") let {tostring_r} = require("%sqstd/string.nut") let {command} = require("console") +let math = require("math") let rexFloat = regexp(@"(\+|-)?([0-9]+\.?[0-9]*|\.[0-9]+)([eE](\+|-)?[0-9]+)?") let rexInt = regexp(@"[\+\-]?[0-9]+") @@ -104,7 +105,7 @@ let function convertTextToVal(cur_value, comp_type, text) { if (comp_type == "E3DCOLOR") { if (fields.len()!=4) return null - let f = fields.map(pipe(strip, tointeger, @(v) clamp(v, 0, 255))) + let f = fields.map(pipe(strip, tointeger, @(v) math.clamp(v, 0, 255))) let res = dagorMath.E3DCOLOR() foreach (idx, field in ["r","g","b","a"]) { res[field] = f[idx] diff --git a/prog/scripts/sq/daeditor/components/slider.nut b/prog/scripts/sq/daeditor/components/slider.nut index 5d844478a..eb53b5709 100644 --- a/prog/scripts/sq/daeditor/components/slider.nut +++ b/prog/scripts/sq/daeditor/components/slider.nut @@ -66,17 +66,17 @@ let function slider(orient, var, options={}) { hotkeys = [ ["Left | J:D.Left", sliderLeftLoc, function() { let delta = maxval > minval ? -pageScroll : pageScroll - onChange(clamp(scaling.to(var.value + delta, minval, maxval), 0, 1)) + onChange(math.clamp(scaling.to(var.value + delta, minval, maxval), 0, 1)) }], ["Right | J:D.Right", sliderRightLoc, function() { let delta = maxval > minval ? pageScroll : -pageScroll - onChange(clamp(scaling.to(var.value + delta, minval, maxval), 0, 1)) + onChange(math.clamp(scaling.to(var.value + delta, minval, maxval), 0, 1)) }], ] } return function() { - let factor = clamp(scaling.to(var.value, minval, maxval), 0, 1) + let factor = math.clamp(scaling.to(var.value, minval, maxval), 0, 1) return { size = flex() behavior = Behaviors.Slider diff --git a/prog/scripts/sq/daeditor/components/window.nut b/prog/scripts/sq/daeditor/components/window.nut index 97d15c749..2110a914f 100644 --- a/prog/scripts/sq/daeditor/components/window.nut +++ b/prog/scripts/sq/daeditor/components/window.nut @@ -1,5 +1,6 @@ from "%darg/ui_imports.nut" import * let cursors = require("cursors.nut") +let math = require("math") let mkWindow = kwarg(function(id, content, onAttach=null, initialSize = [sw(40), sh(65)], minSize = [sw(14), sh(25)], maxSize = [sw(80), sh(90)], @@ -15,10 +16,10 @@ let mkWindow = kwarg(function(id, content, let w = windowState.value let pos = clone w.pos let size = clone w.size - pos[0] = clamp(pos[0]+dx, -size[0]/2, (sw(100)-size[0]/2)) - pos[1] = clamp(pos[1]+dy, 0, (sh(100)-size[1]/2)) - size[0] = clamp(size[0]+dw, minSize[0], maxSize[0]) - size[1] = clamp(size[1]+dh, minSize[1], maxSize[1]) + pos[0] = math.clamp(pos[0]+dx, -size[0]/2, (sw(100)-size[0]/2)) + pos[1] = math.clamp(pos[1]+dy, 0, (sh(100)-size[1]/2)) + size[0] = math.clamp(size[0]+dw, minSize[0], maxSize[0]) + size[1] = math.clamp(size[1]+dh, minSize[1], maxSize[1]) w.pos = pos w.size = size return w diff --git a/prog/scripts/sq/daeditor/extensions/extraIcon3DView.nut b/prog/scripts/sq/daeditor/extensions/extraIcon3DView.nut index f46391a11..1acceb956 100644 --- a/prog/scripts/sq/daeditor/extensions/extraIcon3DView.nut +++ b/prog/scripts/sq/daeditor/extensions/extraIcon3DView.nut @@ -2,11 +2,12 @@ from "%darg/ui_imports.nut" import * import "%sqstd/ecs.nut" as ecs let iconWidget = require_optional("%ui/components/icon3d.nut") +let math = require("math") let function mkIconView(eid){ if (ecs.obsolete_dbg_get_comp_val(eid, "animchar__res") != null && ecs.obsolete_dbg_get_comp_val(eid, "item__iconYaw") != null) { // it has icon in it most likely! let itemParams = Watched(null) - let iconParams = {width=min(hdpx(256), fsh(40)), height=min(hdpx(256), fsh(40))} + let iconParams = {width=math.min(hdpx(256), fsh(40)), height=math.min(hdpx(256), fsh(40))} let function updateItemParams(){ let iconOffs = ecs.obsolete_dbg_get_comp_val(eid, "item__iconOffset") let itemTbl = { diff --git a/prog/scripts/sq/daeditor/riSelect.nut b/prog/scripts/sq/daeditor/riSelect.nut index 377e6cdf0..451e72214 100644 --- a/prog/scripts/sq/daeditor/riSelect.nut +++ b/prog/scripts/sq/daeditor/riSelect.nut @@ -15,7 +15,7 @@ let entity_editor = require_optional("entity_editor") let {propPanelVisible, selectedEntity, editorUnpause} = require("state.nut") let {registerPerCompPropEdit} = require("%daeditor/propPanelControls.nut") -let {floor} = require("math") +let math = require("math") let {startswith} = require("string") @@ -97,7 +97,7 @@ let function riCalcNameInGroup(name, group) { let function riCalcNameInGroups(name) { local result = 0 foreach (group in riGroupsData) - result = max(result, riCalcNameInGroup(name, group)) + result = math.max(result, riCalcNameInGroup(name, group)) return result } @@ -566,7 +566,7 @@ let riFiltered = Computed(function() { let riPages = Computed(function() { let filtered = riFiltered.value - local pages = floor(filtered.len() / riPageCount) + local pages = math.floor(filtered.len() / riPageCount) if (filtered.len() > pages * riPageCount) ++pages if (pages < 1) @@ -614,7 +614,7 @@ let function riGotoPageByValue(v) { let fcount = filtered.len() for (local i = 0; i < fcount; i++) { if (filtered[i] == v) { - local page = floor(i / riPageCount) + local page = math.floor(i / riPageCount) if (page < 0) page = 0 if (page >= riPages.value) @@ -792,7 +792,7 @@ let function riAddToGroup(name, group_idx) { group.list.append(name) group.count += 1 let isFavorites = group.mode == GRPMODE_FAVORITES - riNamesGroups[name] <- max(isFavorites ? 1 : 2, riNamesGroups?[name] ?? 0) + riNamesGroups[name] <- math.max(isFavorites ? 1 : 2, riNamesGroups?[name] ?? 0) riRebuildGroupsList() if (groupSeen) riGroup(riGroupListName(group.name, group.count)) diff --git a/prog/scripts/sq/std/debugMemory.nut b/prog/scripts/sq/std/debugMemory.nut index 3b1b46e24..a4adefa8e 100644 --- a/prog/scripts/sq/std/debugMemory.nut +++ b/prog/scripts/sq/std/debugMemory.nut @@ -1,6 +1,8 @@ const bytes_per_allocation = 16 const bytes_per_object = 16 +let math = require("math") + let function calculate_allocated_memory(obj) { local sum = 0 local items = 0 @@ -15,7 +17,7 @@ let function calculate_allocated_memory(obj) { switch(typeName) { case "null": sum += bytes_per_object; break - case "table": sum += bytes_per_object + bytes_per_allocation * 2 + 32 + max(items, 4) * bytes_per_object * 4; break + case "table": sum += bytes_per_object + bytes_per_allocation * 2 + 32 + math.max(items, 4) * bytes_per_object * 4; break case "array": sum += bytes_per_object + bytes_per_allocation * 2 + (items / 2) * bytes_per_object; break case "closure": sum += bytes_per_object + 144; break case "string": sum += bytes_per_object + 32 + bytes_per_allocation + ((obj.len() | 15) + 1); break @@ -26,7 +28,7 @@ let function calculate_allocated_memory(obj) { case "function": sum += bytes_per_object + 32; break case "generator": sum += bytes_per_object + 64; break case "thread": sum += bytes_per_object + 32; break - case "class": sum += bytes_per_object + bytes_per_allocation * 2 + 32 + max(items, 4) * bytes_per_object * 4; break + case "class": sum += bytes_per_object + bytes_per_allocation * 2 + 32 + math.max(items, 4) * bytes_per_object * 4; break case "instance": sum += bytes_per_object + 32; break case "bool": sum += bytes_per_object; break default: break diff --git a/prog/scripts/sq/std/log.nut b/prog/scripts/sq/std/log.nut index e7f4cad95..6ae472106 100644 --- a/prog/scripts/sq/std/log.nut +++ b/prog/scripts/sq/std/log.nut @@ -2,6 +2,7 @@ let dagorDebug = require("dagor.debug") let string = require("string.nut") +let math = require("math") let tostring_r = string.tostring_r let join = string.join //like join, but skip emptylines @@ -16,7 +17,7 @@ let function Log(tostringfunc=null) { out = tostring_r(vargv[0],{splitlines=false, compact=true, maxdeeplevel=DEF_MAX_DEEPLEVEL, tostringfunc=tostringfunc}) else out = join(vargv.map(@(val) tostring_r(val,{splitlines=false, compact=true, maxdeeplevel=DEF_MAX_DEEPLEVEL, tostringfunc=tostringfunc}))," ") - dagorDebug.screenlog(out.slice(0,min(out.len(),200))) + dagorDebug.screenlog(out.slice(0,math.min(out.len(),200))) } let function log(...) { @@ -37,7 +38,7 @@ let function Log(tostringfunc=null) { vargv=vargv[0] let out = tostring_r(vargv,{tostringfunc=tostringfunc}) let s = string.split_by_chars(out,"\n") - for (local i=0; i < min(80,s.len()); i++) { + for (local i=0; i < math.min(80,s.len()); i++) { dagorDebug.screenlog(s[i]) } } diff --git a/prog/scripts/sq/std/math.nut b/prog/scripts/sq/std/math.nut index dc31074a3..79e827a2a 100644 --- a/prog/scripts/sq/std/math.nut +++ b/prog/scripts/sq/std/math.nut @@ -60,7 +60,7 @@ let function lerp(valueMin, valueMax, resMin, resMax, value) { */ let lerpClamped = @(valueMin, valueMax, resMin, resMax, tvalue) lerp(valueMin, valueMax, resMin, resMax, - valueMax > valueMin ? clamp(tvalue, valueMin, valueMax) : clamp(tvalue, valueMax, valueMin)) + valueMax > valueMin ? math.clamp(tvalue, valueMin, valueMax) : math.clamp(tvalue, valueMax, valueMin)) let function interpolateArray(arr, value) { @@ -98,7 +98,7 @@ local function color2uint(r,g=0,b=0,a=255){ b = r?.b ?? b a = r?.a ?? a } - return clamp(r+g*256+b*65536+a*16777216, 0, 4294967295) + return math.clamp(r+g*256+b*65536+a*16777216, 0, 4294967295) } let romanNumeralLookup = [ diff --git a/prog/scripts/sq/std/mkEventLogState.nut b/prog/scripts/sq/std/mkEventLogState.nut index 640a9daa0..4871d0e20 100644 --- a/prog/scripts/sq/std/mkEventLogState.nut +++ b/prog/scripts/sq/std/mkEventLogState.nut @@ -2,6 +2,7 @@ let { Watched } = require("%sqstd/frp.nut") let { setTimeout, clearTimer } = require("dagor.workcycle") let { kwarg } = require("%sqstd/functools.nut") let { get_time_msec } = require("dagor.time") +let math = require("math") //when event have parameter ttl it will be automatically removed on time finish //isEventsEqual = @(event1, event2) bool - used only to remove events not only by uid. @@ -41,7 +42,7 @@ let function mkEventLogState(persistId, maxActiveEvents = 10, defTtl = 0, isEven if (uid in timersCb) delete timersCb[uid] } - setTimeout(max(0.001 * (removeMsec - get_time_msec()), 0.01), timersCb[uid]) + setTimeout(math.max(0.001 * (removeMsec - get_time_msec()), 0.01), timersCb[uid]) } curEvents.value.each(startRemoveTimer) diff --git a/prog/scripts/sq/std/moduleInfo.nut b/prog/scripts/sq/std/moduleInfo.nut index b40ff0862..dbccb633f 100644 --- a/prog/scripts/sq/std/moduleInfo.nut +++ b/prog/scripts/sq/std/moduleInfo.nut @@ -1,4 +1,5 @@ let log = require("%sqstd/log.nut")().log +let math = require("math") let typesByTypechecks ={ [0x00000001] = "null", @@ -90,7 +91,7 @@ let function mkFunStubStr(func, name=null, indent = 0, verbose=false, manualModI : paramscheck < -1 ? ", ..." : "..." - local args = array(max(actParams, typecheck?.len() ?? 0)).map(@(_, i) argumentsNames[i]) + local args = array(math.max(actParams, typecheck?.len() ?? 0)).map(@(_, i) argumentsNames[i]) let defined_args = args.map(function(arg, i){ let isOptional = paramscheck < 0 && i >= actParams && varargs != "" return isOptional diff --git a/prog/scripts/sq/std/rand.nut b/prog/scripts/sq/std/rand.nut index 5a45f11f6..f93969890 100644 --- a/prog/scripts/sq/std/rand.nut +++ b/prog/scripts/sq/std/rand.nut @@ -3,6 +3,7 @@ let random = require("dagor.random") let cdate = (require_optional("datetime")?.date ?? @(_date=null,_format=null) {sec=0, min=0, hour=0, day=0, month=0, year=0, wday=0, yday=0})() let _default_seed = random.get_rnd_seed() + cdate.sec + cdate.min*60 + cdate.yday*86400 +let math = require("math") local position = 0 let function new_rnd_seed() {//setting new rnd @@ -42,8 +43,8 @@ let class Rand{ function rfloat(start=0.0, end=1.0){ // return float in range [start,end) this._count += 1 - let start_ = min(end,start) - let end_ = max(end,start) + let start_ = math.min(end,start) + let end_ = math.max(end,start) let runit = (random.uint_noise1D(this._seed, this._count) & maxrndfloatmask) / maxrndfloat // [0,1] return runit * (end_-start_) + start_ } @@ -56,8 +57,8 @@ let class Rand{ seed = params?.seed ?? new_rnd_seed() count = params?.count ?? count } - let start_ = min(end,start) - let end_ = max(end,start) + let start_ = math.min(end,start) + let end_ = math.max(end,start) let runit = (random.uint_noise1D(seed, count ?? seed) & maxrndfloatmask) / maxrndfloat // [0,1] return runit * (end_-start_) + start_ } @@ -70,7 +71,7 @@ let class Rand{ seed = params?.seed ?? new_rnd_seed() count = params?.count ?? count } - return randint_uniform(min(end,start), max(end,start), @() random.uint_noise1D(seed, count ?? seed)) + return randint_uniform(math.min(end,start), math.max(end,start), @() random.uint_noise1D(seed, count ?? seed)) } function rint(start=0, end = null) { // return int in range [start, end], i.e. inclusive @@ -80,7 +81,7 @@ let class Rand{ else { end = end?.tointeger() ?? DEFAULT_MAX_INT_RAND start = start.tointeger() - return randint_uniform(min(end,start), max(end,start), @() random.uint_noise1D(this._seed, this._count)) + return randint_uniform(math.min(end,start), math.max(end,start), @() random.uint_noise1D(this._seed, this._count)) } } diff --git a/prog/scripts/sq/std/string.nut b/prog/scripts/sq/std/string.nut index 061b27de1..a6e1cee2e 100644 --- a/prog/scripts/sq/std/string.nut +++ b/prog/scripts/sq/std/string.nut @@ -409,7 +409,7 @@ function substring(str, start = 0, length = null) { local total = str.len() if (start < 0) start += total - start = clamp(start, 0, total) + start = math.clamp(start, 0, total) end = start + length } return slice(str, start, end) @@ -900,7 +900,7 @@ function splitStringBySize(str, maxSize) { local start = 0 let l = str.len() while (start < l) { - let pieceSize = min(l - start, maxSize) + let pieceSize = math.min(l - start, maxSize) result.append(str.slice(start, start + pieceSize)) start += pieceSize } diff --git a/prog/scripts/sq/std/timers.nut b/prog/scripts/sq/std/timers.nut index 3011c33aa..06cc6dd51 100644 --- a/prog/scripts/sq/std/timers.nut +++ b/prog/scripts/sq/std/timers.nut @@ -1,6 +1,6 @@ from "dagor.workcycle" import setTimeout, clearTimer from "dagor.random" import frnd -from "math" import abs +let math = require("math") /* Creates and returns a new debounced version of the passed function which will postpone its execution until @@ -20,7 +20,7 @@ let function debounce(func, delay_s, delay_s_max = null){ clearTimer(action) let time = delay_s_max == null ? delay_s - : min(delay_s, delay_s_max) + frnd() * abs(delay_s_max - delay_s) + : math.min(delay_s, delay_s_max) + frnd() * math.abs(delay_s_max - delay_s) setTimeout(time, action) } return debounced diff --git a/prog/scripts/sq/stubs/daRg b/prog/scripts/sq/stubs/daRg index 0b3fd4bf3..27dfafba2 100644 --- a/prog/scripts/sq/stubs/daRg +++ b/prog/scripts/sq/stubs/daRg @@ -259,6 +259,7 @@ global const VECTOR_LINE_INDENT_PCT="VECTOR_LINE_INDENT_PCT" global const VECTOR_LINE_INDENT_PX="VECTOR_LINE_INDENT_PX" global const VECTOR_LINE_DASHED = "VECTOR_LINE_DASHED" global const VECTOR_SECTOR="VECTOR_SECTOR" +global const VECTOR_QUADS="VECTOR_QUADS" global const VECTOR_INVERSE_POLY="VECTOR_INVERSE_POLY" global const VECTOR_TM_OFFSET="VECTOR_TM_OFFSET" global const VECTOR_NOP="VECTOR_NOP" @@ -389,6 +390,7 @@ global const PANEL_POINT_EVENT_LEAVE = 1 global const PANEL_POINT_EVENT_MOVE = 2 global const PANEL_RENDER_CAST_SHADOW = 1 global const PANEL_RENDER_OPAQUE = 2 +global const PANEL_RENDER_ALWAYS_ON_TOP = 4 global const FMT_NO_WRAP = 0x01 global const FMT_KEEP_SPACES = 0x02 diff --git a/prog/scripts/validateAllSq.bat b/prog/scripts/validateAllSq.bat index 57a97a281..694d5a60b 100644 --- a/prog/scripts/validateAllSq.bat +++ b/prog/scripts/validateAllSq.bat @@ -1,5 +1,5 @@ set DAGOR=..\.. -set SCRIPTS=%DAGOR%\launcher\client\scilauncher2 %DAGOR%\active_matter\prog %DAGOR%\cuisine_royale\prog %DAGOR%\enlisted\prog %DAGOR%\to_the_sky\prog %DAGOR%\modern_conflict\prog %DAGOR%\skyquake\prog\scripts\wt %DAGOR%\skyquake\prog\scripts\wtm %DAGOR%\skyquake\prog\scripts\vrt +set SCRIPTS=%DAGOR%\prog\commonFx\commonFxGame %DAGOR%\launcher\client\scilauncher2 %DAGOR%\active_matter\prog %DAGOR%\cuisine_royale\prog %DAGOR%\enlisted\prog %DAGOR%\to_the_sky\prog %DAGOR%\modern_conflict\prog %DAGOR%\skyquake\prog\scripts\wt %DAGOR%\skyquake\prog\scripts\wtm %DAGOR%\skyquake\prog\scripts\vrt setlocal EnableDelayedExpansion diff --git a/prog/tools/AssetViewer/collision/collision.cpp b/prog/tools/AssetViewer/collision/collision.cpp index d83368fac..7bb9deeb7 100644 --- a/prog/tools/AssetViewer/collision/collision.cpp +++ b/prog/tools/AssetViewer/collision/collision.cpp @@ -28,6 +28,8 @@ const unsigned int phys_collidable_color = 0xFF00FF00; const unsigned int traceable_color = 0xFFFF0000; +static int debug_ri_face_orientationVarId = -1; + struct CollisionNodesData { int nodeId; @@ -77,6 +79,7 @@ CollisionPlugin::CollisionPlugin() showPhysCollidable = false; showTraceable = false; drawSolid = false; + showFaceOrientation = false; collisionRes = NULL; nodeTree = NULL; selectedNodeId = -1; @@ -87,6 +90,12 @@ CollisionPlugin::CollisionPlugin() isSolidMatValid = debugCollisionMat != nullptr; initScriptPanelEditor("collision.scheme.nut", "collision by scheme"); + debug_ri_face_orientationVarId = get_shader_variable_id("debug_ri_face_orientation", true); + if (VariableMap::isVariablePresent(debug_ri_face_orientationVarId) && !::dgs_get_game_params()->getStr("debugRiTexture", nullptr)) + { + debug_ri_face_orientationVarId = -1; + logerr("debugRiTexture:t= not set in gameParams, \"Show face orientation\" is disabled"); + } } void CollisionPlugin::onSaveLibrary() { nodesProcessing.saveCollisionNodes(); } @@ -134,7 +143,7 @@ void CollisionPlugin::renderTransObjects() if (!collisionRes) return; - RenderCollisionResource(*collisionRes, nodeTree, showPhysCollidable, showTraceable, drawSolid, selectedNodeId, + RenderCollisionResource(*collisionRes, nodeTree, showPhysCollidable, showTraceable, drawSolid, showFaceOrientation, selectedNodeId, nodesProcessing.editMode, nodesProcessing.selectionNodesProcessing.hiddenNodes); nodesProcessing.renderNodes(selectedNodeId, drawSolid); @@ -149,6 +158,11 @@ void CollisionPlugin::fillPropPanel(PropertyContainerControlBase &panel) panel.createCheckBox(PID_SHOW_PHYS_COLLIDABLE, "Show Phys Collidable (green)", showPhysCollidable); panel.createCheckBox(PID_SHOW_TRACEABLE, "Show Traceable (red)", showTraceable); panel.createCheckBox(PID_DRAW_SOLID, "Draw collision solid", drawSolid, isSolidMatValid); + if (VariableMap::isVariablePresent(debug_ri_face_orientationVarId)) + { + panel.createCheckBox(PID_SHOW_FACE_ORIENTATION, "Show face orientation", showFaceOrientation, isSolidMatValid); + panel.setTooltipId(PID_SHOW_FACE_ORIENTATION, "The front side of triangles is filled by blue color, and back side is red."); + } nodesProcessing.setPropPanel(&panel); nodesProcessing.fillCollisionInfoPanel(); @@ -179,6 +193,11 @@ void CollisionPlugin::onClick(int pcb_id, PropertyContainerControlBase *panel) repaintView(); break; + case PID_SHOW_FACE_ORIENTATION: + showFaceOrientation = panel->getBool(pcb_id); + repaintView(); + break; + case PID_PRINT_KDOP_LOG: printKdopLog(); break; case PID_NEXT_EDIT_NODE: selectedNodeId = -1; break; } @@ -199,7 +218,7 @@ void CollisionPlugin::onChange(int pcb_id, PropertyContainerControlBase *panel) String sel_name = tree->getCaption(leaf); NodesProcessing::delete_flags_prefix(sel_name); for (const auto &n : collisionRes->getAllNodes()) - if (sel_name == n.name) + if (sel_name == n.name.c_str()) { selectedNodeId = &n - collisionRes->getAllNodes().data(); break; @@ -456,9 +475,19 @@ void ReleaseCollisionResource(CollisionResource **collision_res, GeomNodeTree ** } } -static void draw_collision_mesh(const CollisionNode &node, const TMatrix &tm, const E3DCOLOR &color, bool draw_solid) +static void draw_collision_mesh(const CollisionNode &node, const TMatrix &tm, const E3DCOLOR &color, bool draw_solid, + bool show_face_orientation) { - if (draw_solid) + if (show_face_orientation) + { + ShaderGlobal::set_int(debug_ri_face_orientationVarId, 1); + + draw_debug_solid_mesh(node.indices.data(), node.indices.size() / 3, &node.vertices.data()->x, elem_size(node.vertices), + node.vertices.size(), tm, E3DCOLOR(255, 255, 255), true, DrawSolidMeshCull::FLIP); + + ShaderGlobal::set_int(debug_ri_face_orientationVarId, 0); + } + else if (draw_solid) { draw_debug_solid_mesh(node.indices.data(), node.indices.size() / 3, &node.vertices.data()->x, elem_size(node.vertices), node.vertices.size(), tm, color, false, DrawSolidMeshCull::FLIP); @@ -477,8 +506,12 @@ static void draw_collision_mesh(const CollisionNode &node, const TMatrix &tm, co } void RenderCollisionResource(const CollisionResource &collision_res, GeomNodeTree *node_tree, bool show_phys_collidable, - bool show_traceable, bool draw_solid, int selected_node_id, bool edit_mode, const dag::Vector &hidden_nodes) + bool show_traceable, bool draw_solid, bool show_face_orientation, int selected_node_id, bool edit_mode, + const dag::Vector &hidden_nodes) { + if (show_face_orientation) + d3d::set_backbuf_depth(); + begin_draw_cached_debug_lines(); const auto allNodes = collision_res.getAllNodes(); @@ -547,7 +580,7 @@ void RenderCollisionResource(const CollisionResource &collision_res, GeomNodeTre E3DCOLOR color = customColor ? customColor.value() : E3DCOLOR(colors[i % (sizeof(colors) / sizeof(colors[0]))]); color.a = alpha; - draw_collision_mesh(node, nodeTm, color, draw_solid); + draw_collision_mesh(node, nodeTm, color, draw_solid, show_face_orientation); } else if (node.type == COLLISION_NODE_TYPE_CONVEX) { @@ -592,7 +625,7 @@ void RenderCollisionResource(const CollisionResource &collision_res, GeomNodeTre } color.a = clamp(alpha, 0, haveInvalidVertices ? 40 : 128); if (draw_solid) - draw_collision_mesh(node, TMatrix::IDENT, color, draw_solid); + draw_collision_mesh(node, TMatrix::IDENT, color, draw_solid, show_face_orientation); else draw_cached_debug_trilist(vertList.data(), vertList.size() / 3, color); } diff --git a/prog/tools/AssetViewer/collision/collision.h b/prog/tools/AssetViewer/collision/collision.h index 6de9d93ea..9edd2a591 100644 --- a/prog/tools/AssetViewer/collision/collision.h +++ b/prog/tools/AssetViewer/collision/collision.h @@ -65,6 +65,7 @@ class CollisionPlugin : public IGenEditorPlugin, public ControlEventHandler bool showTraceable; bool isSolidMatValid; bool drawSolid; + bool showFaceOrientation; void drawObjects(IGenViewportWnd *wnd); void printKdopLog(); @@ -75,5 +76,5 @@ class CollisionPlugin : public IGenEditorPlugin, public ControlEventHandler void InitCollisionResource(const DagorAsset &asset, CollisionResource **collision_res, GeomNodeTree **node_tree); void ReleaseCollisionResource(CollisionResource **collision_res, GeomNodeTree **node_tree); void RenderCollisionResource(const CollisionResource &collision_res, GeomNodeTree *node_tree, bool show_phys_collidable = false, - bool show_traceable = false, bool draw_solid = false, int selected_node_id = -1, bool edit_mode = false, - const dag::Vector &hidden_nodes = {}); + bool show_traceable = false, bool draw_solid = false, bool show_face_orientation = false, int selected_node_id = -1, + bool edit_mode = false, const dag::Vector &hidden_nodes = {}); diff --git a/prog/tools/AssetViewer/collision/collisionUtils.cpp b/prog/tools/AssetViewer/collision/collisionUtils.cpp index 7f263609c..52e3b2fcb 100644 --- a/prog/tools/AssetViewer/collision/collisionUtils.cpp +++ b/prog/tools/AssetViewer/collision/collisionUtils.cpp @@ -5,7 +5,7 @@ bool add_verts_from_node(const dag::ConstSpan &nodes, const Strin { for (const auto &node : nodes) { - if (node_name == node.name) + if (node_name == node.name.c_str()) { for (const auto &vertex : node.vertices) { @@ -22,7 +22,7 @@ bool add_verts_and_indices_from_node(const dag::ConstSpan &nodes, { for (const auto &node : nodes) { - if (node_name == node.name) + if (node_name == node.name.c_str()) { const auto vertsSize = verts.size(); for (const auto &vertex : node.vertices) @@ -44,7 +44,7 @@ bool add_verts_and_indices_from_node(const dag::ConstSpan &nodes, { for (const auto &node : nodes) { - if (node_name == node.name) + if (node_name == node.name.c_str()) { const auto vertsSize = verts.size() / 3; for (const auto &vertex : node.vertices) diff --git a/prog/tools/AssetViewer/collision/combinedNodesProcessing.cpp b/prog/tools/AssetViewer/collision/combinedNodesProcessing.cpp index 65131aa89..a5eece943 100644 --- a/prog/tools/AssetViewer/collision/combinedNodesProcessing.cpp +++ b/prog/tools/AssetViewer/collision/combinedNodesProcessing.cpp @@ -34,7 +34,7 @@ void CombinedNodesProcessing::calcCombinedNode(const SelectedNodesSettings &sett { for (const auto &node : collisionNodes) { - if (refNode == node.name) + if (refNode == node.name.c_str()) { if (node.type == COLLISION_NODE_TYPE_MESH || node.type == COLLISION_NODE_TYPE_CAPSULE || node.type == COLLISION_NODE_TYPE_CONVEX) @@ -51,7 +51,7 @@ void CombinedNodesProcessing::calcCombinedNode(const SelectedNodesSettings &sett { for (const auto &node : collisionNodes) { - if (refNode == node.name) + if (refNode == node.name.c_str()) { selectedNode.boundingSphere += node.tm * node.boundingSphere; } diff --git a/prog/tools/AssetViewer/collision/propPanelPids.h b/prog/tools/AssetViewer/collision/propPanelPids.h index 8e60d3557..009f3bf72 100644 --- a/prog/tools/AssetViewer/collision/propPanelPids.h +++ b/prog/tools/AssetViewer/collision/propPanelPids.h @@ -6,6 +6,7 @@ enum PID_SHOW_PHYS_COLLIDABLE, PID_SHOW_TRACEABLE, PID_DRAW_SOLID, + PID_SHOW_FACE_ORIENTATION, PID_SHOW_KDOP, PID_SHOW_KDOP_FACES, PID_SHOW_KDOP_DIRS, diff --git a/prog/tools/AssetViewer/collision/selectionNodesProcessing.cpp b/prog/tools/AssetViewer/collision/selectionNodesProcessing.cpp index 9974af8f0..5f82f37ea 100644 --- a/prog/tools/AssetViewer/collision/selectionNodesProcessing.cpp +++ b/prog/tools/AssetViewer/collision/selectionNodesProcessing.cpp @@ -647,7 +647,7 @@ static void update_hidden_nodes(const SelectedNodesSettings &settings, const dag { for (int i = 0; i < nodes.size(); ++i) { - if (refNode == nodes[i].name) + if (refNode == nodes[i].name.c_str()) { hidden_nodes[i] = true; break; diff --git a/prog/tools/ShaderCompiler2/codeBlocks.cpp b/prog/tools/ShaderCompiler2/codeBlocks.cpp index a5ae1b3ca..6e3b9530e 100644 --- a/prog/tools/ShaderCompiler2/codeBlocks.cpp +++ b/prog/tools/ShaderCompiler2/codeBlocks.cpp @@ -355,7 +355,7 @@ bool CodeSourceBlocks::parseSourceCode(const char *stage, const char *src, Shade erase_items(fn, i, 1); int pp_line = line_no; inc_lines(code_start, pp_start, pp_line); - if (!ppDoInclude(fn, incl_code, fileNames.getName(fname_id), pp_line)) + if (!ppDoInclude(fn, incl_code, fileNames.getName(fname_id), pp_line, ctx)) { sh_debug(SHLOG_ERROR, "failed to resolve include at %s,%d:\n %.*s\n", fileNames.getName(fname_id), line_no, fn_e - fn_line, fn_line); @@ -853,7 +853,7 @@ bool CodeSourceBlocks::ppDirective(char *s, int len, char *dtext, int fnameId, i String msg(0, "Assert failed in %s:%i\n\"%.*s\"%s%.*s\n", fileNames.getName(fnameId), line, end_expr - begin_expr, begin_expr, have_message ? "\n\n" : "", have_message ? end_quote - begin_quote - 1 : 0, begin_quote + 1); - int msg_id = ctx.evalCb.add_message(msg); + int msg_id = ctx.evalCb.add_message(msg, false); if (msg_id < 0) return true; @@ -866,7 +866,7 @@ bool CodeSourceBlocks::ppDirective(char *s, int len, char *dtext, int fnameId, i } return false; } -bool CodeSourceBlocks::ppDoInclude(const char *incl_fn, Tab &out_text, const char *src_fn, int src_ln) +bool CodeSourceBlocks::ppDoInclude(const char *incl_fn, Tab &out_text, const char *src_fn, int src_ln, ParserContext &ctx) { char buf[DAGOR_MAX_PATH]; String fn(0, "%s/%s", dd_get_fname_location(buf, src_fn), incl_fn); @@ -887,7 +887,7 @@ bool CodeSourceBlocks::ppDoInclude(const char *incl_fn, Tab &out_text, con "\n#undef _FILE_\n" "#define _FILE_ %d\n" "#line 1 \"%s\"\n", - glob_string_table.addNameId(incl_fn), incl_fn); + ctx.evalCb.add_message(incl_fn, true), incl_fn); append_items(out_text, s.size() - 1, s.data()); Tab fcont; @@ -923,7 +923,7 @@ bool CodeSourceBlocks::ppDoInclude(const char *incl_fn, Tab &out_text, con "\n#undef _FILE_\n" "#define _FILE_ %d\n" "#line %d \"%s\"\n", - glob_string_table.addNameId(src_fn), src_ln, src_fn); + ctx.evalCb.add_message(src_fn, true), src_ln, src_fn); append_items(out_text, s.size() - 1, s.data()); G_ASSERT(is_main_thread()); diff --git a/prog/tools/ShaderCompiler2/codeBlocks.h b/prog/tools/ShaderCompiler2/codeBlocks.h index 42f963ce3..fbf3d9688 100644 --- a/prog/tools/ShaderCompiler2/codeBlocks.h +++ b/prog/tools/ShaderCompiler2/codeBlocks.h @@ -111,6 +111,6 @@ class CodeSourceBlocks void ppSrcCode(char *s, int len, int fnameId, int line, ParserContext &ctx, char *st_comment, char *end_comment); bool ppCheckDirective(char *s, ParserContext &ctx); bool ppDirective(char *s, int len, char *dtext, int fnameId, int line, ParserContext &ctx); - bool ppDoInclude(const char *incl_fn, Tab &out_text, const char *src_fn, int src_ln); + bool ppDoInclude(const char *incl_fn, Tab &out_text, const char *src_fn, int src_ln, ParserContext &ctx); }; DAG_DECLARE_RELOCATABLE(CodeSourceBlocks::Fragment); diff --git a/prog/tools/ShaderCompiler2/dx12/asmShaderDXIL.cpp b/prog/tools/ShaderCompiler2/dx12/asmShaderDXIL.cpp index 36d8f22dd..2233eda35 100644 --- a/prog/tools/ShaderCompiler2/dx12/asmShaderDXIL.cpp +++ b/prog/tools/ShaderCompiler2/dx12/asmShaderDXIL.cpp @@ -11,7 +11,7 @@ #include -#include +#include #include #include diff --git a/prog/tools/ShaderCompiler2/gatherVar.cpp b/prog/tools/ShaderCompiler2/gatherVar.cpp index 41f9e9619..b376f343c 100644 --- a/prog/tools/ShaderCompiler2/gatherVar.cpp +++ b/prog/tools/ShaderCompiler2/gatherVar.cpp @@ -116,12 +116,17 @@ void GatherVarShaderEvalCB::decl_bool_alias(const char *name, bool_expr &expr) BoolVar::add(shname_token->text, decl, parser, true); } -int GatherVarShaderEvalCB::add_message(const char *message) +int GatherVarShaderEvalCB::add_message(const char *message, bool file_name) { float value = 0.0f; if (shc::getAssumedValue(debug_mode_enabled_interval, shname_token->text, true, value)) if (value > 0.0f) - return messages.addNameId(message); + { + int id = messages.addNameId(message); + if (!file_name) + nonFilenameMessages.set(id, true); + return id; + } return -1; } diff --git a/prog/tools/ShaderCompiler2/gatherVar.h b/prog/tools/ShaderCompiler2/gatherVar.h index 193401cb6..89f2ba07c 100644 --- a/prog/tools/ShaderCompiler2/gatherVar.h +++ b/prog/tools/ShaderCompiler2/gatherVar.h @@ -4,6 +4,8 @@ #ifndef __GATHERVAR_H #define __GATHERVAR_H +#include + #include "shsem.h" #include "shaderVariant.h" #include "shVarBool.h" @@ -51,7 +53,8 @@ class GatherVarShaderEvalCB : public ShaderEvalCB, public ShaderBoolEvalCB virtual void eval_static(static_var_decl &s); void eval_bool_decl(bool_decl &) override; void decl_bool_alias(const char *name, bool_expr &expr) override; - int add_message(const char *message) override; + int add_message(const char *message, bool file_name) override; + bool is_filename_message(int id) const { return !nonFilenameMessages.test(id, false); } const SCFastNameMap &get_messages() const { return messages; } void eval_channel_decl(channel_decl &s, int str_id = 0); @@ -93,6 +96,7 @@ class GatherVarShaderEvalCB : public ShaderEvalCB, public ShaderBoolEvalCB int dynCount; bool hasDynFlag; SCFastNameMap messages; + eastl::bitvector<> nonFilenameMessages; String hlslPs, hlslVs, hlslHs, hlslDs, hlslGs, hlslCs, hlslMs, hlslAs; diff --git a/prog/tools/ShaderCompiler2/hlsl2spirv/asmShaderSpirV.cpp b/prog/tools/ShaderCompiler2/hlsl2spirv/asmShaderSpirV.cpp index 97e5566dd..2b14209b2 100644 --- a/prog/tools/ShaderCompiler2/hlsl2spirv/asmShaderSpirV.cpp +++ b/prog/tools/ShaderCompiler2/hlsl2spirv/asmShaderSpirV.cpp @@ -15,7 +15,7 @@ #include #include -#include +#include #if _TARGET_PC_WIN #include @@ -439,27 +439,21 @@ CompileResult compileShaderSpirV(const char *source, const char *profile, const macros += "#define BINDLESS_TEXTURE_SET_META_ID " + std::to_string(spirv::bindless::TEXTURE_DESCRIPTOR_SET_META_INDEX) + "\n"; macros += "#define BINDLESS_SAMPLER_SET_META_ID " + std::to_string(spirv::bindless::SAMPLER_DESCRIPTOR_SET_META_INDEX) + "\n"; } - if (is_half) - { - macros += "#define half min16float\n" - "#define half1 min16float1\n" - "#define half2 min16float2\n" - "#define half3 min16float3\n" - "#define half4 min16float4\n"; - } - else + if (!is_half) { + // there is a bug(?) in DXC: it can't map half[] -> float[] correctly with disabled 16-bit types flag macros += "#define half float\n" "#define half1 float1\n" "#define half2 float2\n" "#define half3 float3\n" "#define half4 float4\n"; - } + }; codeCopy = macros + codeCopy; auto sourceRange = make_span(codeCopy.c_str(), codeCopy.size()); auto flags = enableBindless ? spirv::CompileFlags::ENABLE_BINDLESS_SUPPORT : spirv::CompileFlags::NONE; + flags |= is_half ? spirv::CompileFlags::ENABLE_HALFS : spirv::CompileFlags::NONE; auto finalSpirV = spirv::compileHLSL_DXC(sourceRange, entry, profile, flags, disabledSpirvOptims); spirv = eastl::move(finalSpirV.byteCode); diff --git a/prog/tools/ShaderCompiler2/jamfile-common b/prog/tools/ShaderCompiler2/jamfile-common index 927a48ad8..6dea4fcd5 100644 --- a/prog/tools/ShaderCompiler2/jamfile-common +++ b/prog/tools/ShaderCompiler2/jamfile-common @@ -2,10 +2,12 @@ if $(OS) = MACOSX { Platform ?= macosx ; } else { Platform ?= win64 ; PlatformSpec_win64 ?= clang ; } if ! $(Location) { Exit Location must be defined before including jamfile-common ; } +SkipLicenseBuild = no ; ReproducibleExeBuild = yes ; WinSdkVer = win.sdk.100 ; CPPStd = 20 ; MimDebug ?= 0 ; +CopyDxcLib ?= no ; Exceptions = yes ; @@ -125,11 +127,15 @@ actions together copy_file if not exist $(1) set errorlevel=13 } -# otherwise no update on library version change -rule CopyFileForced -{ - Depends $(1) : $(2) ; - copy_file $(1) : $(2) ; - Depends all : $(1) ; - ALWAYS $(2) ; +include $(Root)/prog/gameLibs/spirv/jamfile-dxc-ver ; + +if $(CopyDxcLib) = yes { + if ! [ GLOB $(_DEVTOOL)/DXC-$(DXC_VERSION)/lib/$(Platform) : * ] { exit FATAL\: \"DXC-$(DXC_VERSION)/lib/$(Platform)\" not found! Please, update DEVTOOLS ; } + ExplicitLicenseUsed += $(_DEVTOOL)/DXC-$(DXC_VERSION) ; + local library = [ AutoCompleteTargetName dxcompiler : dll ] ; + local src = $(_DEVTOOL)/DXC-$(DXC_VERSION)/lib/$(Platform)/$(library) ; + local dst = $(OutDir)/$(library) ; + Depends $(dst) : $(src) ; + copy_file $(dst) : $(src) ; + Depends all : $(dst) ; } diff --git a/prog/tools/ShaderCompiler2/jamfile-hlsl2metal b/prog/tools/ShaderCompiler2/jamfile-hlsl2metal index e63422e6d..6e817bdf3 100644 --- a/prog/tools/ShaderCompiler2/jamfile-hlsl2metal +++ b/prog/tools/ShaderCompiler2/jamfile-hlsl2metal @@ -6,7 +6,7 @@ FullOOPEnabled = no ; WError ?= no ; # treat all warnings as errors compileSources = yes ; -copyLib = no ; +CopyDxcLib = yes ; if $(OS) = NT { Target = tools/dsc2-metal.exe ; @@ -17,14 +17,14 @@ else if $(OS) = MACOSX { compileSources = no ; baseJam = jamfile-hlsl2metal ; include $(Root)/$(Location)/jamfile-universal-bin ; + CopyDxcLib = no ; } else if $(UniversalBinaryPart) { Target = $(Target)-$(MacOSXArch) ; - if $(MacOSXArch) = arm64 { - copyLib = yes ; # copy only once per universal binary + if $(MacOSXArch) != arm64 { + CopyDxcLib = no ; # copy only once per universal binary } } else { Target = tools/$(Target) ; - copyLib = yes ; } } else { @@ -90,8 +90,4 @@ else } -if [ GLOB $(_DEVTOOL)/DXC-mac/lib : libdxcompiler.dylib ] && $(copyLib) = yes { - CopyFileForced $(OutDir)/libdxcompiler.dylib : $(_DEVTOOL)/DXC-mac/lib/libdxcompiler.dylib ; -} - include $(Root)/prog/_jBuild/build.jam ; \ No newline at end of file diff --git a/prog/tools/ShaderCompiler2/jamfile-hlsl2spirv b/prog/tools/ShaderCompiler2/jamfile-hlsl2spirv index fb528db37..67a06cbfa 100644 --- a/prog/tools/ShaderCompiler2/jamfile-hlsl2spirv +++ b/prog/tools/ShaderCompiler2/jamfile-hlsl2spirv @@ -3,6 +3,8 @@ Location = prog/tools/ShaderCompiler2 ; FullOOPEnabled = no ; +CopyDxcLib = yes ; + include $(Root)/$(Location)/jamfile-common ; if $(OS) = NT { @@ -30,9 +32,6 @@ CPPopt += -D_CROSS_TARGET_SPIRV=1 -DBINDUMP_TARGET_BE=0 -D_CRT_SECURE_NO_DEPRECA if $(Platform) = macosx { CPPopt += -Wno-switch ; - if [ GLOB $(_DEVTOOL)/DXC-mac/lib : libdxcompiler.dylib ] { - CopyFileForced $(OutDir)/libdxcompiler.dylib : $(_DEVTOOL)/DXC-mac/lib/libdxcompiler.dylib ; - } } include $(Root)/prog/_jBuild/build.jam ; diff --git a/prog/tools/ShaderCompiler2/shsem.cpp b/prog/tools/ShaderCompiler2/shsem.cpp index c90588a01..ea5e67f78 100644 --- a/prog/tools/ShaderCompiler2/shsem.cpp +++ b/prog/tools/ShaderCompiler2/shsem.cpp @@ -702,7 +702,7 @@ static void add_shader(shader_decl *sh, ShaderSyntaxParser &parser, Terminal *sh { for (int i = 0; i < stVarCB.get_messages().nameCount(); i++) { - if (i < glob_string_table.nameCount()) + if (stVarCB.is_filename_message(i)) sclass->messages.emplace_back(stVarCB.get_messages().getName(i)); else sclass->messages.emplace_back(eastl::string::CtorSprintf{}, "%s: %s", shname->text, stVarCB.get_messages().getName(i)); diff --git a/prog/tools/ShaderCompiler2/shsem.h b/prog/tools/ShaderCompiler2/shsem.h index 73faa184a..5cdda9dc7 100644 --- a/prog/tools/ShaderCompiler2/shsem.h +++ b/prog/tools/ShaderCompiler2/shsem.h @@ -74,7 +74,7 @@ class ShaderBoolEvalCB virtual ShVarBool eval_bool_value(bool_value &) = 0; virtual int eval_interval_value(const char *ival_name) = 0; virtual void decl_bool_alias(const char *name, bool_expr &expr) {} - virtual int add_message(const char *message) { return 0; } + virtual int add_message(const char *message, bool file_name) { return 0; } }; void eval_shader(shader_decl &sh, ShaderEvalCB &cb); diff --git a/prog/tools/build_dagor3_cdk_mini.cmd b/prog/tools/build_dagor3_cdk_mini.cmd index 30612829b..00e45becf 100644 --- a/prog/tools/build_dagor3_cdk_mini.cmd +++ b/prog/tools/build_dagor3_cdk_mini.cmd @@ -89,22 +89,16 @@ rem GUI tools jam -s Root=../.. -f dargbox/jamfile if errorlevel 1 goto error -rem 3ds Max plugins +rem 3ds Max plugins, we don't care if these plugins fail to compile (this could happen due to missing SDK or compiler) jam -s Root=../.. -s Platform=win64 -s MaxVer=Max2024 -f maxplug/jamfile - if errorlevel 1 goto error jam -s Root=../.. -s Platform=win64 -s MaxVer=Max2024 -f maxplug/jamfile-imp - if errorlevel 1 goto error -rem we don't care if these plugins failed to compile (this could happen due to missing SDK or compiler) jam -s Root=../.. -s Platform=win64 -s MaxVer=Max2023 -f maxplug/jamfile - if errorlevel 1 goto EOF jam -s Root=../.. -s Platform=win64 -s MaxVer=Max2023 -f maxplug/jamfile-imp - if errorlevel 1 goto EOF jam -s Root=../.. -s Platform=win64 -s MaxVer=Max2022 -f maxplug/jamfile - if errorlevel 1 goto EOF jam -s Root=../.. -s Platform=win64 -s MaxVer=Max2022 -f maxplug/jamfile-imp - if errorlevel 1 goto EOF +if errorlevel 1 goto EOF goto EOF diff --git a/prog/tools/consoleSq/consoleSq.cpp b/prog/tools/consoleSq/consoleSq.cpp index 4ffb3d303..906ab595f 100644 --- a/prog/tools/consoleSq/consoleSq.cpp +++ b/prog/tools/consoleSq/consoleSq.cpp @@ -222,15 +222,22 @@ static Module modules[] = { {"register_dagor_fs_vrom", "module dagor.fs.vrom: scan_vrom_folder", [] { bindquirrel::register_dagor_fs_vrom_module(module_manager); }}, {"sqstd_register_io_lib", "see quirrel doc", [] { module_manager->registerIoLib(); }}, - {"sqstd_register_base_libs", "math, string, iostream", + {"sqstd_register_base_libs", "math, string, iostream, debug", [] { module_manager->registerMathLib(); module_manager->registerStringLib(); + if (!module_manager->findNativeModule("debug")) + module_manager->registerDebugLib(); if (!module_manager->findNativeModule("io")) module_manager->registerIoStreamLib(); }}, {"sqstd_register_system_lib", "system lib", [] { module_manager->registerSystemLib(); }}, {"sqstd_register_datetime_lib", "datetime lib", [] { module_manager->registerDateTimeLib(); }}, + {"sqstd_register_debug_lib", "debug lib", + [] { + if (!module_manager->findNativeModule("debug")) + module_manager->registerDebugLib(); + }}, {"sqrat_bind_dagor_logsys", "modules: dagor.debug, dagor.assertf, dagor.debug_dump_stack ...", [] { bindquirrel::sqrat_bind_dagor_logsys(module_manager, true); }}, {"register_platform_module", "get_platform_string_id ...", [] { bindquirrel::register_platform_module(module_manager); }}, @@ -979,6 +986,11 @@ static bool process_file(const char *filename, const char *code, const KeyValueF quit_game(1, false); } + if (do_static_analysis) + { + sq_mergeglobalnames(&bindings.GetObject()); + } + after_execute_module(module_manager->getVM(), exportName.c_str(), exportName.c_str()); } else diff --git a/prog/tools/converters/a2dCvt/old_animChannels.h b/prog/tools/converters/a2dCvt/old_animChannels.h index 835940053..01092f8c7 100644 --- a/prog/tools/converters/a2dCvt/old_animChannels.h +++ b/prog/tools/converters/a2dCvt/old_animChannels.h @@ -2,7 +2,7 @@ * Dagor Engine 3 * Copyright (C) 2023 Gaijin Games KFT. All rights reserved * - * (for conditions of distribution and use, see EULA in "prog/eula.txt") + * (for conditions of use see prog/license.txt) */ #ifndef _DAGOR3_PUBLIC_ANIM_DAG_ANIMCHANNELS_H_ diff --git a/prog/tools/converters/plants2asset/jamfile b/prog/tools/converters/plants2asset/jamfile index f3153f3cc..4b34ea1e6 100644 --- a/prog/tools/converters/plants2asset/jamfile +++ b/prog/tools/converters/plants2asset/jamfile @@ -14,8 +14,6 @@ AddIncludes = $(Root)/prog/tools/sceneTools ; -UseWTL = yes ; - Sources = gridCvt.cpp con_main.cpp diff --git a/prog/tools/converters/prefabs2entities/jamfile b/prog/tools/converters/prefabs2entities/jamfile index b0c7d2ed1..b8b50e829 100644 --- a/prog/tools/converters/prefabs2entities/jamfile +++ b/prog/tools/converters/prefabs2entities/jamfile @@ -10,8 +10,6 @@ OutDir = $(Root)/tools/util ; AddIncludes = $(Root)/prog/tools/sharedInclude ; -UseWTL = yes ; - Sources = blkCvt.cpp con_main.cpp diff --git a/prog/tools/dargbox/gamebase/samples_prog/_basic/animations/animated_text.ui.nut b/prog/tools/dargbox/gamebase/samples_prog/_basic/animations/animated_text.ui.nut index a625afa1d..0e1a6343c 100644 --- a/prog/tools/dargbox/gamebase/samples_prog/_basic/animations/animated_text.ui.nut +++ b/prog/tools/dargbox/gamebase/samples_prog/_basic/animations/animated_text.ui.nut @@ -1,4 +1,5 @@ from "%darg/ui_imports.nut" import * +from "math" import min, max let utf8 = require("utf8") diff --git a/prog/tools/dargbox/gamebase/samples_prog/_basic/behaviors/resize_move_scroll.ui.nut b/prog/tools/dargbox/gamebase/samples_prog/_basic/behaviors/resize_move_scroll.ui.nut index f921472bf..53b527976 100644 --- a/prog/tools/dargbox/gamebase/samples_prog/_basic/behaviors/resize_move_scroll.ui.nut +++ b/prog/tools/dargbox/gamebase/samples_prog/_basic/behaviors/resize_move_scroll.ui.nut @@ -1,5 +1,5 @@ from "%darg/ui_imports.nut" import * - +from "math" import max /* KNOWN ISSUES: - vertical align not working for text area valign = ALIGN_TOP | ALIGN_BOTTOM | ALIGN_CENTER diff --git a/prog/tools/dargbox/gamebase/samples_prog/_basic/behaviors/simple_scroll.ui.nut b/prog/tools/dargbox/gamebase/samples_prog/_basic/behaviors/simple_scroll.ui.nut index b7c6a3fb7..c36fb3699 100644 --- a/prog/tools/dargbox/gamebase/samples_prog/_basic/behaviors/simple_scroll.ui.nut +++ b/prog/tools/dargbox/gamebase/samples_prog/_basic/behaviors/simple_scroll.ui.nut @@ -1,5 +1,6 @@ from "%darg/ui_imports.nut" import * from "%darg/laconic.nut" import * +from "math" import max require("daRg").gui_scene.config.kbCursorControl = true let fa = require("samples_prog/_basic/goodies/fontawesome.map.nut") diff --git a/prog/tools/dargbox/gamebase/samples_prog/_basic/behaviors/textarea.ui.nut b/prog/tools/dargbox/gamebase/samples_prog/_basic/behaviors/textarea.ui.nut index 73e134574..bb14621e7 100644 --- a/prog/tools/dargbox/gamebase/samples_prog/_basic/behaviors/textarea.ui.nut +++ b/prog/tools/dargbox/gamebase/samples_prog/_basic/behaviors/textarea.ui.nut @@ -1,5 +1,5 @@ from "%darg/ui_imports.nut" import * - +from "math" import max /* KNOWN ISSUES: - ellipsis should be done by character by default (or may be even always) diff --git a/prog/tools/dargbox/gamebase/samples_prog/_basic/goodies/bitmap_gradient.ui.nut b/prog/tools/dargbox/gamebase/samples_prog/_basic/goodies/bitmap_gradient.ui.nut index 8aeb5b24c..deb334b15 100644 --- a/prog/tools/dargbox/gamebase/samples_prog/_basic/goodies/bitmap_gradient.ui.nut +++ b/prog/tools/dargbox/gamebase/samples_prog/_basic/goodies/bitmap_gradient.ui.nut @@ -1,6 +1,6 @@ from "%darg/ui_imports.nut" import * from "%darg/helpers/bitmap.nut" import mkBitmapPicture -from "math" import abs, fabs, sqrt +from "math" import abs, fabs, sqrt, clamp, max import "samples_prog/_cursors.nut" as cursors diff --git a/prog/tools/dargbox/gamebase/samples_prog/_basic/goodies/lens_flare.nut b/prog/tools/dargbox/gamebase/samples_prog/_basic/goodies/lens_flare.nut index aa87fd1bb..9473b87a2 100644 --- a/prog/tools/dargbox/gamebase/samples_prog/_basic/goodies/lens_flare.nut +++ b/prog/tools/dargbox/gamebase/samples_prog/_basic/goodies/lens_flare.nut @@ -1,6 +1,6 @@ from "%darg/ui_imports.nut" import * +from "math" import min, sqrt, max let { mkBitmapPicture } = require("%darg/helpers/bitmap.nut") -let { sqrt } = require("math") let mkWhite = @(part) part + (part << 8) + (part << 16) + (part << 24) let getDistance = @(x, y) sqrt(x*x + y*y) diff --git a/prog/tools/dargbox/gamebase/samples_prog/_basic/goodies/rumble.ui.nut b/prog/tools/dargbox/gamebase/samples_prog/_basic/goodies/rumble.ui.nut index ac9796f42..1799477bd 100644 --- a/prog/tools/dargbox/gamebase/samples_prog/_basic/goodies/rumble.ui.nut +++ b/prog/tools/dargbox/gamebase/samples_prog/_basic/goodies/rumble.ui.nut @@ -1,4 +1,5 @@ from "%darg/ui_imports.nut" import * +from "math" import clamp let cursors = require("samples_prog/_cursors.nut") diff --git a/prog/tools/dargbox/gamebase/samples_prog/_basic/render/circullar_vector_canvas.ui.nut b/prog/tools/dargbox/gamebase/samples_prog/_basic/render/circullar_vector_canvas.ui.nut index 168bfc636..441b86cf0 100644 --- a/prog/tools/dargbox/gamebase/samples_prog/_basic/render/circullar_vector_canvas.ui.nut +++ b/prog/tools/dargbox/gamebase/samples_prog/_basic/render/circullar_vector_canvas.ui.nut @@ -1,4 +1,5 @@ from "%darg/ui_imports.nut" import * +from "math" import max let cursors = require("samples_prog/_cursors.nut") diff --git a/prog/tools/dargbox/gamebase/samples_prog/_basic/render/text_overflow.ui.nut b/prog/tools/dargbox/gamebase/samples_prog/_basic/render/text_overflow.ui.nut index c880954b3..4b98a11a0 100644 --- a/prog/tools/dargbox/gamebase/samples_prog/_basic/render/text_overflow.ui.nut +++ b/prog/tools/dargbox/gamebase/samples_prog/_basic/render/text_overflow.ui.nut @@ -1,4 +1,5 @@ from "%darg/ui_imports.nut" import * +from "math" import max /* Horizontal overflow handling modes: diff --git a/prog/tools/dargbox/gamebase/samples_prog/_basic/render/vector_quads.nut b/prog/tools/dargbox/gamebase/samples_prog/_basic/render/vector_quads.nut new file mode 100644 index 000000000..8f53260f2 --- /dev/null +++ b/prog/tools/dargbox/gamebase/samples_prog/_basic/render/vector_quads.nut @@ -0,0 +1,46 @@ +from "%darg/ui_imports.nut" import * + +let cursors = require("samples_prog/_cursors.nut") + +let vectorCanvas = { + rendObj = ROBJ_VECTOR_CANVAS + flow = FLOW_HORIZONTAL + halign = ALIGN_CENTER + valign = ALIGN_CENTER + size = [hdpx(300), hdpx(300)] + lineWidth = hdpx(2.5) + color = Color(50, 200, 255) + fillColor = Color(255, 120, 100, 0) + commands = [ + [VECTOR_COLOR, Color(255, 255, 255)], // set stroke color = white + [VECTOR_QUADS, + 10, 10, Color(255, 255, 255), 10, 90, Color(255, 255, 255), 90, 90, Color(255, 255, 255), 90, 10, Color(255, 255, 255), // first quad + 20, 20, Color(255, 255, 255), 20, 80, Color(255, 0, 255), 80, 80, Color(255, 0, 255), 80, 20, Color(255, 255, 255)], // second quad + ] +} + + + +let function basicsRoot() { + return { + rendObj = ROBJ_SOLID + color = Color(30, 40, 50) + cursor = cursors.normal + size = flex() + padding = 50 + children = [ + { + valign = ALIGN_CENTER + halign = ALIGN_CENTER + flow = FLOW_VERTICAL + size = flex() + gap = 40 + children = [ + vectorCanvas + ] + } + ] + } +} + +return basicsRoot diff --git a/prog/tools/dargbox/gamebase/samples_prog/advanced/calc_comp_size.ui.nut b/prog/tools/dargbox/gamebase/samples_prog/advanced/calc_comp_size.ui.nut index 395bdd894..e63d84708 100644 --- a/prog/tools/dargbox/gamebase/samples_prog/advanced/calc_comp_size.ui.nut +++ b/prog/tools/dargbox/gamebase/samples_prog/advanced/calc_comp_size.ui.nut @@ -1,4 +1,5 @@ from "%darg/ui_imports.nut" import * +from "math" import max let {tostring_r} = require("%sqstd/string.nut") let cursor = Cursor({ rendObj = ROBJ_IMAGE size = [32, 32] image = Picture("!ui/atlas#cursor.svg:{0}:{0}:K".subst(hdpx(32))) }) diff --git a/prog/tools/dargbox/gamebase/samples_prog/showcases/colorBlend.ui.nut b/prog/tools/dargbox/gamebase/samples_prog/showcases/colorBlend.ui.nut index 0aa7b30ab..774212338 100644 --- a/prog/tools/dargbox/gamebase/samples_prog/showcases/colorBlend.ui.nut +++ b/prog/tools/dargbox/gamebase/samples_prog/showcases/colorBlend.ui.nut @@ -1,4 +1,6 @@ from "%darg/ui_imports.nut" import * +from "math" import clamp + let { format } = require("string") let bgColor = Watched(null) diff --git a/prog/tools/dargbox/gamebase/samples_prog/showcases/helicopterHud.ui.nut b/prog/tools/dargbox/gamebase/samples_prog/showcases/helicopterHud.ui.nut index 1c7c2339a..e65e10104 100644 --- a/prog/tools/dargbox/gamebase/samples_prog/showcases/helicopterHud.ui.nut +++ b/prog/tools/dargbox/gamebase/samples_prog/showcases/helicopterHud.ui.nut @@ -1,4 +1,5 @@ from "%darg/ui_imports.nut" import * +from "math" import clamp let math = require("math") diff --git a/prog/tools/dargbox/gamebase/samples_prog/zbugs/flex_children_more_parent.ui.nut b/prog/tools/dargbox/gamebase/samples_prog/zbugs/flex_children_more_parent.ui.nut new file mode 100644 index 000000000..e82414214 --- /dev/null +++ b/prog/tools/dargbox/gamebase/samples_prog/zbugs/flex_children_more_parent.ui.nut @@ -0,0 +1,41 @@ +from "%darg/ui_imports.nut" import * + +/* + Let's say a parent has a specific size, + and his children of the first level have a flex() size, + with max Width, then children of level 3 with a flex() size will also have to prescribe maxWidth, + otherwise they will be located according to the parent with specific sizes, + and not according to his parent. + Is this behavior correct? +*/ + + +let childrenFlex = @(color) { + rendObj = ROBJ_BOX + size = [flex(), sh(10)] + borderWidth = hdpx(1) + vplace = ALIGN_CENTER + hplace = ALIGN_CENTER + valign = ALIGN_CENTER + maxWidth = hdpx(135) + margin = hdpx(40) + children = { + size = [flex(), hdpx(60)] + rendObj = ROBJ_BOX + borderWidth = hdpx(3) + borderColor = color + } +} + +return { + size = [sw(50), fsh(6)] + vplace = ALIGN_CENTER + hplace = ALIGN_CENTER + flow = FLOW_HORIZONTAL + children = [ + childrenFlex(Color(66, 170, 255)) + childrenFlex(Color(255, 36, 36)) + childrenFlex(Color(63, 255, 5)) + childrenFlex(Color(255, 229, 20)) + ] +} \ No newline at end of file diff --git a/prog/tools/dargbox/jamfile b/prog/tools/dargbox/jamfile index e96b6ba22..2440d9d19 100644 --- a/prog/tools/dargbox/jamfile +++ b/prog/tools/dargbox/jamfile @@ -272,7 +272,7 @@ else if $(Platform) = nswitch { 3rdPartyLibs/posix engine/drv/hid_nswitch engine/drv/hid_nulldrv - gameLibs/nswitch + gameLibs/nswitch/kit gameLibs/nswitch/account gameLibs/nswitch/assets gameLibs/nswitch/savedata diff --git a/prog/tools/dargbox/scriptBindings.cpp b/prog/tools/dargbox/scriptBindings.cpp index 24862d1e8..46bc9480d 100644 --- a/prog/tools/dargbox/scriptBindings.cpp +++ b/prog/tools/dargbox/scriptBindings.cpp @@ -35,6 +35,7 @@ void bind_dargbox_script_api(SqModules *module_mgr) module_mgr->registerSystemLib(); module_mgr->registerIoLib(); module_mgr->registerDateTimeLib(); + module_mgr->registerDebugLib(); bindquirrel::register_dagor_localization_module(module_mgr); bindquirrel::register_dagor_shell(module_mgr); diff --git a/prog/tools/libTools/EditorCore/jamfile b/prog/tools/libTools/EditorCore/jamfile index d9e8dae1e..26d133bf4 100644 --- a/prog/tools/libTools/EditorCore/jamfile +++ b/prog/tools/libTools/EditorCore/jamfile @@ -4,8 +4,6 @@ Location = prog/tools/libTools/EditorCore ; TargetType = lib ; Target = tools/libTools/EditorCore.lib ; -UseWTL = yes ; - AddIncludes = $(Root)/prog/tools/sharedInclude $(Root)/prog/engine/sharedInclude diff --git a/prog/tools/libTools/IEditorCore/jamfile b/prog/tools/libTools/IEditorCore/jamfile index 5591dd7b1..7bff3c9c8 100644 --- a/prog/tools/libTools/IEditorCore/jamfile +++ b/prog/tools/libTools/IEditorCore/jamfile @@ -4,8 +4,6 @@ Location = prog/tools/libTools/IEditorCore ; TargetType = lib ; Target = tools/libTools/IEditorCore.lib ; -UseWTL = yes ; - AddIncludes = $(Root)/prog/tools/sharedInclude ; diff --git a/prog/tools/libTools/IEditorCoreBase/jamfile b/prog/tools/libTools/IEditorCoreBase/jamfile index 57abfffb7..10b2a4c41 100644 --- a/prog/tools/libTools/IEditorCoreBase/jamfile +++ b/prog/tools/libTools/IEditorCoreBase/jamfile @@ -4,8 +4,6 @@ Location = prog/tools/libTools/IEditorCoreBase ; TargetType = lib ; Target = tools/libTools/IEditorCoreBase.lib ; -UseWTL = yes ; - AddIncludes = $(Root)/prog/tools/sharedInclude ; diff --git a/prog/tools/libTools/ObjectEditor/jamfile b/prog/tools/libTools/ObjectEditor/jamfile index 89236cc14..df69e1368 100644 --- a/prog/tools/libTools/ObjectEditor/jamfile +++ b/prog/tools/libTools/ObjectEditor/jamfile @@ -4,8 +4,6 @@ Location = prog/tools/libTools/objectEditor ; TargetType = lib ; Target = tools/libTools/objectEditor.lib ; -UseWTL = yes ; - AddIncludes = $(Root)/prog/tools/sharedInclude ; diff --git a/prog/tools/libTools/pageAsg/asg_anim_tree.cpp b/prog/tools/libTools/pageAsg/asg_anim_tree.cpp index 0a3dee0b2..cc1d4d686 100644 --- a/prog/tools/libTools/pageAsg/asg_anim_tree.cpp +++ b/prog/tools/libTools/pageAsg/asg_anim_tree.cpp @@ -410,14 +410,14 @@ void AnimObjCtrlParametricSwitch::addNeededBnls(NameMap &bnls, NameMap &a2d, Ani { // if recursionCount will become more than then blockCount, so we are in deadlock int recursionCount = 0; - String parentEnumBlockName(enumBlock->getStr("_extends", "")); + String parentEnumBlockName(enumBlock->getStr("_use", "")); while (!parentEnumBlockName.empty() && recursionCount < je) { recursionCount++; if (const DataBlock *parentBlock = init_st->getBlockByName(parentEnumBlockName.c_str())) { nm = parentBlock->getStr(name, ""); - parentEnumBlockName = nm.empty() ? parentBlock->getStr("_extends", "") : ""; + parentEnumBlockName = nm.empty() ? parentBlock->getStr("_use", "") : ""; } else parentEnumBlockName.clear(); // break cycle diff --git a/prog/tools/libTools/shaderResBuilder/rendInstResSrc.cpp b/prog/tools/libTools/shaderResBuilder/rendInstResSrc.cpp index c464fa843..01a589c20 100644 --- a/prog/tools/libTools/shaderResBuilder/rendInstResSrc.cpp +++ b/prog/tools/libTools/shaderResBuilder/rendInstResSrc.cpp @@ -1321,15 +1321,11 @@ bool RenderableInstanceLodsResSrc::build(const DataBlock &blk) } } - if (hasImpostor) + if (hasImpostor && blk.getNameId("transition_lod") != -1) { const DataBlock *block = blk.getBlockByName("transition_lod"); - float transitionRange = 6.0f; - if (block) - { - int transitionRangeNameId = block->getNameId("transition_range"); - transitionRange = block->getRealByNameId(transitionRangeNameId, transitionRange); - } + int transitionRangeNameId = block->getNameId("transition_range"); + float transitionRange = block->getRealByNameId(transitionRangeNameId, 6.0f); String addMatScript; diff --git a/prog/tools/maxplug/jamfile b/prog/tools/maxplug/jamfile index 02d18b6d8..f765b6ae6 100644 --- a/prog/tools/maxplug/jamfile +++ b/prog/tools/maxplug/jamfile @@ -41,8 +41,6 @@ if $(Config) = rel { _GlobCopt_Optimize = /O1 /Os /Oi ; } -if ! [ GLOB $(_DEVTOOL)/$(MaxVer).sdk : * ] { exit FATAL\: \"$(_DEVTOOL)/$(MaxVer).sdk\" not found! Please, update it from \\\\FS.GAIJIN.LAN\\Y\\Soft\\forDevelopers\\devtools\\$(MaxVer).sdk.7z ; } - if $(Platform) = win64 { switch $(MaxVer) { @@ -80,6 +78,8 @@ if $(Platform) = win64 { MaxLibDir = $(_DEVTOOL)/$(MaxVer).sdk/lib ; } +if ! [ GLOB $(_DEVTOOL)/$(MaxVer).sdk : * ] { exit \"$(_DEVTOOL)/$(MaxVer).sdk\" not found! Install Max SDK and re-run make_devtools.py. $(OutDir)/$(Target:D=) is skipped now... ; } + AddIncludes = $(_DEVTOOL)/$(MaxVer).sdk/include $(Root)/$(Location)/stubInclude diff --git a/prog/tools/maxplug/jamfile-imp b/prog/tools/maxplug/jamfile-imp index 25cd49dc9..7636e179b 100644 --- a/prog/tools/maxplug/jamfile-imp +++ b/prog/tools/maxplug/jamfile-imp @@ -77,6 +77,8 @@ if $(Platform) = win64 { MaxLibDir = $(_DEVTOOL)/$(MaxVer).sdk/lib ; } +if ! [ GLOB $(_DEVTOOL)/$(MaxVer).sdk : * ] { exit \"$(_DEVTOOL)/$(MaxVer).sdk\" not found! Install Max SDK and re-run make_devtools.py. $(OutDir)/$(Target:D=) is skipped now... ; } + AddIncludes = $(_DEVTOOL)/$(MaxVer).sdk/include ; diff --git a/prog/tools/sceneTools/assetExp/exporters/exp_collision.cpp b/prog/tools/sceneTools/assetExp/exporters/exp_collision.cpp index 283214d44..d83e26a9c 100644 --- a/prog/tools/sceneTools/assetExp/exporters/exp_collision.cpp +++ b/prog/tools/sceneTools/assetExp/exporters/exp_collision.cpp @@ -943,7 +943,7 @@ class CollisionExporter : public IDagorAssetExporter if (n.cachedMaxTmScale <= 1.0f) for (unsigned i = 0; i < m.face.size(); i++) if (lengthSq((m.vert[m.face[i].v[1]] - m.vert[m.face[i].v[0]]) % (m.vert[m.face[i].v[2]] - m.vert[m.face[i].v[0]])) < - 1e-12f) + 5e-12f) { zeroarea_faces_cnt++; logerr("%s: %sdegenerate tri %d,%d,%d: %@, %@, %@ (edge len: %g, %g, %g)", a.getName(), label, m.face[i].v[0], diff --git a/prog/tools/sceneTools/assetExp/exporters/fxExp.cpp b/prog/tools/sceneTools/assetExp/exporters/fxExp.cpp index e47ffc688..a97f717be 100644 --- a/prog/tools/sceneTools/assetExp/exporters/fxExp.cpp +++ b/prog/tools/sceneTools/assetExp/exporters/fxExp.cpp @@ -25,7 +25,7 @@ class EffectExporter : public IDagorAssetExporter virtual const char *__stdcall getAssetType() const { return TYPE; } virtual unsigned __stdcall getGameResClassId() const { return EffectGameResClassId; } - virtual unsigned __stdcall getGameResVersion() const { return 104; } + virtual unsigned __stdcall getGameResVersion() const { return 106; } virtual void __stdcall onRegister() {} virtual void __stdcall onUnregister() {} diff --git a/prog/tools/sceneTools/daEditorX/Clipping/jamfile b/prog/tools/sceneTools/daEditorX/Clipping/jamfile index 371a2581c..dc2f1fc80 100644 --- a/prog/tools/sceneTools/daEditorX/Clipping/jamfile +++ b/prog/tools/sceneTools/daEditorX/Clipping/jamfile @@ -3,8 +3,6 @@ Location = prog/tools/sceneTools/daEditorX/Clipping ; include $(Root)/prog/_jBuild/defaults.jam ; -UseWTL = yes ; - TargetType = lib ; Target = tools/sceneTools/daEditorX/clipping.lib ; diff --git a/prog/tools/sceneTools/daEditorX/Environment/jamfile b/prog/tools/sceneTools/daEditorX/Environment/jamfile index bbb67ec3f..a4c0e8381 100644 --- a/prog/tools/sceneTools/daEditorX/Environment/jamfile +++ b/prog/tools/sceneTools/daEditorX/Environment/jamfile @@ -1,8 +1,6 @@ Root ?= ../../../../.. ; Location = prog/tools/sceneTools/daEditorX/Environment ; -UseWTL = yes ; - TargetType = lib ; Target = tools/sceneTools/daEditorX/environment.lib ; diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/brushMask.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/brushMask.cpp new file mode 100644 index 000000000..bdbb8d68b --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/brushMask.cpp @@ -0,0 +1,159 @@ +#include "brushMask.h" + +#include + +#include +#include + +#include +#include + +static inline unsigned get_power(int num) +{ + unsigned long power = 0; + _BitScanReverse(&power, num); + return power; +} + +float IBrushMask::Mask::getCenteredMask(float x1, float y1, float radius, float angle) +{ + if (!width || !height) + return 1; + + float x, y; + if (angle != 0) + { + float cosa = cosf(angle), sina = sinf(angle); + x = cosa * x1 + sina * y1; + y = -sina * x1 + cosa * y1; + } + else + { + x = x1; + y = y1; + } + + + float mx = (x / 2.0f + 0.5f) * width; + float my = (y / 2.0f + 0.5f) * height; + if (mx < 0) + mx = 0; + if (mx >= width) + mx = width - 1; + if (my < 0) + my = 0; + if (my >= height) + my = height - 1; + + float cellXf, cellYf; + float fracX = modff(mx, &cellXf); + float fracY = modff(my, &cellYf); + int cellX = int(cellXf), cellY = int(cellYf); + int cellX1 = cellX, cellY1 = cellY; + if (cellX < width - 1) + cellX1 = cellX + 1; + if (cellY < height - 1) + cellY1 = cellY + 1; + + int p11 = cellX + cellY * width; + int p12 = cellX1 + cellY * width; + int p21 = cellX + cellY1 * width; + int p22 = cellX1 + cellY1 * width; + + if (p11 < 0 || p12 < 0 || p21 < 0 || p22 < 0 || p11 >= mask.size() || p12 >= mask.size() || p21 >= mask.size() || p22 >= mask.size()) + return 1.0; + + float maskResult = + (mask[p11] * (1.0 - fracX) + mask[p12] * fracX) * (1.0f - fracY) + (mask[p21] * (1.0 - fracX) + mask[p22] * fracX) * fracY; + + if (maskResult > 1.0f) + maskResult = 1.0f; + + return maskResult; +} + +float IBrushMask::getCenteredMask(float x1, float y1, float radius, float angle) +{ + if (!maskChain.size()) + return 1; + + int maski; + + for (maski = 0; maski < maskChain.size(); ++maski) + { + if (maskChain[maski].width < radius) + break; + } + + if (maski == maskChain.size() || maski == 0) + return maskChain[maski ? maski - 1 : maski].getCenteredMask(x1, y1, radius, angle); + + float maskResult1 = maskChain[maski].getCenteredMask(x1, y1, radius, angle); + float maskResult2 = maskChain[maski - 1].getCenteredMask(x1, y1, radius, angle); + float maskIweight = (maskChain[maski - 1].width - radius) / (maskChain[maski - 1].width - maskChain[maski].width); + return maskResult2 * (1.0f - maskIweight) + maskResult2 * maskIweight; +} + + +bool IBrushMask::load(const char *file) +{ + maskChain.clear(); + + SmallTab mask; + int width, height; + bool ret = dagTools->loadmaskloadMaskFromFile(file, mask, width, height); + + if (!ret || !width || !height) + return false; + + float min = FLT_MAX, max = -FLT_MAX; + for (int i = 0; i < mask.size(); ++i) + if (mask[i] < min) + min = mask[i]; + else if (mask[i] > max) + max = mask[i]; + + if (max == min) + min = 0; + + for (int i = 0; i < mask.size(); ++i) + mask[i] = (mask[i] - min) / (max - min); + + int chains = width < height ? ::get_power(width) : ::get_power(height); + maskChain.resize(chains); + + if (!maskChain.size()) + return true; + + maskChain[0].width = width; + maskChain[0].height = height; + maskChain[0].mask = mask; + + for (int i = 1; i < maskChain.size(); ++i) + { + maskChain[i].width = width >> i; + maskChain[i].height = height >> i; + clear_and_resize(maskChain[i].mask, maskChain[i].width * maskChain[i].height); + + int subW = width / maskChain[i].width; + int subH = height / maskChain[i].height; + for (int id = 0, y = 0; y < maskChain[i].height; ++y) + { + for (int x = 0; x < maskChain[i].width; ++x, ++id) + { + double val = 0; + for (int sy = 0; sy < subH; ++sy) + { + for (int sx = 0; sx < subW; ++sx) + { + val += mask[(y * subH + sy) * width + (x * subW + sx)]; + } + } + maskChain[i].mask[id] = (val / (subW * subH)); + } + } + } + return ret; +} + +IBrushMask::IBrushMask() : maskChain(midmem) {} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/brushMask.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/brushMask.h new file mode 100644 index 000000000..3091b88de --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/brushMask.h @@ -0,0 +1,28 @@ +#ifndef __GAIJIN_HEIGHTMAPLAND_BRUSH_MASK__ +#define __GAIJIN_HEIGHTMAPLAND_BRUSH_MASK__ +#pragma once + +#include +#include + +class IBrushMask +{ +public: + IBrushMask(); + + float getCenteredMask(float x, float y, float radius, float angle = 0); + bool load(const char *file); + +protected: + struct Mask + { + SmallTab mask; + int width, height; + + Mask() : width(0), height(0) {} + float getCenteredMask(float x, float y, float radius, float angle); + }; + Tab maskChain; +}; + +#endif //__GAIJIN_HEIGHTMAP_BRUSH__ diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlAlignBrush.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlAlignBrush.cpp new file mode 100644 index 000000000..5d7e45465 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlAlignBrush.cpp @@ -0,0 +1,178 @@ +#include +#include "hmlAlignBrush.h" +#include "../hmlPlugin.h" +#include "../hmlCm.h" +#include + + +void HmapAlignLandBrush::fillParams(PropPanel2 &panel) +{ + HmapLandBrush::fillParams(panel); + + panel.createTrackInt(PID_BRUSH_TRAIL, "Trail:", trail * 100, 1, 100, 1); + panel.createTrackInt(PID_BRUSH_SIGMA, "Centered average", sigma * 100, 1, 100, 1); + + panel.createCheckBox(PID_BRUSH_ALIGN_SGEOMETRY, "Align to collision", alignCollision); + panel.createCheckBox(PID_BRUSH_ALIGN_TOP, "Collision top", alignCollisionTop, alignCollision); + panel.createEditFloat(PID_BRUSH_ALIGN_OFFSET, "Align offset", collisionOffset); + panel.createCheckBox(PID_BRUSH_CONTINUOS, "Align to first point", !continuos); +} + + +void HmapAlignLandBrush::updateToPanel(PropPanel2 &panel) +{ + __super::updateToPanel(panel); + + panel.setInt(PID_BRUSH_TRAIL, trail * 100); + panel.setInt(PID_BRUSH_SIGMA, sigma * 100); + + panel.setBool(PID_BRUSH_ALIGN_SGEOMETRY, alignCollision); + panel.setBool(PID_BRUSH_ALIGN_TOP, alignCollisionTop); + panel.setFloat(PID_BRUSH_ALIGN_OFFSET, collisionOffset); + panel.setBool(PID_BRUSH_CONTINUOS, !continuos); +} + + +bool HmapAlignLandBrush::updateFromPanelRef(PropPanel2 &panel, int pid) +{ + switch (pid) + { + case PID_BRUSH_ALIGN_SGEOMETRY: + { + int ar = panel.getBool(pid); + if (ar < 2) + alignCollision = ((bool)ar); + panel.setEnabledById(PID_BRUSH_ALIGN_TOP, alignCollision); + return true; + } + case PID_BRUSH_ALIGN_TOP: + { + int ar = panel.getBool(pid); + if (ar < 2) + alignCollisionTop = ((bool)ar); + return true; + } + case PID_BRUSH_ALIGN_OFFSET: collisionOffset = panel.getFloat(pid); return true; + case PID_BRUSH_CONTINUOS: + { + int ar = panel.getBool(pid); + if (ar < 2) + continuos = !((bool)ar); + return true; + } + case PID_BRUSH_TRAIL: trail = panel.getInt(pid) / 100.0; return true; + case PID_BRUSH_SIGMA: + { + sigma = panel.getInt(pid) / 100.0; + started = false; + return true; + } + default: return HmapLandBrush::updateFromPanelRef(panel, pid); + } +} + +void HmapAlignLandBrush::brushPaintApplyStart(const IBBox2 &where) +{ + HmapLandBrush::brushPaintApplyStart(where); + if (where.isEmpty()) + return; + if (started) + return; + if (alignCollision) + return; + if (sigma < 0.01) + sigma = 0.01; + + double calcAverage = 0.0, totalW = 0.0; + Point2 center = point2(where[1] + where[0]) / 2.0; + double radius = (point2(where[1]) - center).length(); + double radiusSigma2 = radius * sigma * 2; + radiusSigma2 *= radiusSigma2; + + for (int y = where[0].y; y <= where[1].y; ++y) + for (int x = where[0].x; x <= where[1].x; ++x) + { + double w = exp(-((double)(x - center.x) * (x - center.x) + (double)(y - center.y) * (y - center.y)) / (radiusSigma2)); + totalW += w; + calcAverage += heightMap.getBrushImageData(x, y, HmapLandPlugin::self->getEditedChannel()) * w; + } + average = calcAverage / totalW; + if (average > 1000000 || average < -1000000 || _isnan(average) || !_finite(average)) + { + started = false; + } + if (!continuos) + started = true; +} + +void HmapAlignLandBrush::brushPaintApplyEnd() { currentTrail *= trail; } + +bool HmapAlignLandBrush::brushPaintApply(int x, int y, float inc, bool rb) +{ + if (inc > 1.0f) + inc = 1.0f; + inc *= currentTrail; + if (alignCollision) + { + real maxDist = DAGORED2->getMaxTraceDistance(), dist = maxDist * 2; + bool hit = false; + Point3 p(gridCellSize * (x), maxDist, gridCellSize * (y)); + p += Point3(heightMapOffset.x, 0, heightMapOffset.y); + while (DAGORED2->traceRay(p, Point3(0, -1, 0), dist, NULL, false)) + { + p.y -= dist + 0.05; + dist = maxDist; + hit = true; + if (alignCollisionTop) + break; + } + if (hit) + { + float ht = p.y; + heightMap.setBrushImageData(x, y, + inc * (ht + collisionOffset) + heightMap.getBrushImageData(x, y, HmapLandPlugin::self->getEditedChannel()) * (1.0f - inc), + HmapLandPlugin::self->getEditedChannel()); + return true; + } + return false; + } + if (average > 1000000 || average < -1000000 || _isnan(average) || !_finite(average)) + return false; + heightMap.setBrushImageData(x, y, + inc * average + heightMap.getBrushImageData(x, y, HmapLandPlugin::self->getEditedChannel()) * (1.0f - inc), + HmapLandPlugin::self->getEditedChannel()); + return true; +} + +void HmapAlignLandBrush::saveToBlk(DataBlock &blk) const +{ + HmapLandBrush::saveToBlk(blk); + + blk.addReal("trail", trail); + blk.addReal("sigma", sigma); + blk.addBool("continuos", continuos); + blk.addBool("alignCollision", alignCollision); + blk.addReal("collisionOffset", collisionOffset); + blk.addBool("alignCollisionTop", alignCollisionTop); +} + +void HmapAlignLandBrush::loadFromBlk(const DataBlock &blk) +{ + HmapLandBrush::loadFromBlk(blk); + trail = blk.getReal("trail", trail); + sigma = blk.getReal("sigma", sigma); + continuos = blk.getBool("continuos", continuos); + alignCollision = blk.getBool("alignCollision", alignCollision); + collisionOffset = blk.getReal("collisionOffset", collisionOffset); + alignCollisionTop = blk.getBool("alignCollisionTop", alignCollisionTop); + started = false; + average = 0; +} + +namespace heightmap_land +{ +HmapLandBrush *getAlignBrush(IBrushClient *client, IHmapBrushImage &height_map) +{ + return new HmapAlignLandBrush(false, client, height_map); +} +}; // namespace heightmap_land diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlAlignBrush.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlAlignBrush.h new file mode 100644 index 000000000..41ea632c5 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlAlignBrush.h @@ -0,0 +1,49 @@ +#ifndef __GAIJIN_HEIGHTMAPLAND_SMOOTH_BRUSH__ +#define __GAIJIN_HEIGHTMAPLAND_SMOOTH_BRUSH__ +#pragma once + + +#include "hmlBrush.h" + +class HmapAlignLandBrush : public HmapLandBrush +{ +public: + HmapAlignLandBrush(bool continuos, IBrushClient *client, IHmapBrushImage &height_map) : + HmapLandBrush(client, height_map), + trail(1), + currentTrail(1), + average(0), + continuos(false), + sigma(1), + started(false), + alignCollision(false), + collisionOffset(-0.1) + {} + + virtual void fillParams(PropPanel2 &panel); + virtual void updateToPanel(PropPanel2 &panel); + + virtual void onRBBrushPaintStart(int buttons, int key_modif) { onBrushPaintStart(buttons, key_modif); } + virtual void onBrushPaintStart(int buttons, int key_modif) + { + HmapLandBrush::onBrushPaintStart(buttons, key_modif); + currentTrail = 1; + started = false; + } + virtual bool brushPaintApply(int x, int y, float inc, bool rb); + virtual void brushPaintApplyStart(const IBBox2 &where); + virtual void brushPaintApplyEnd(); + virtual void saveToBlk(DataBlock &blk) const; + virtual void loadFromBlk(const DataBlock &blk); + + virtual bool updateFromPanelRef(PropPanel2 &panel, int pid); + +protected: + float trail, sigma; + float average, currentTrail; + bool started, continuos, alignCollision, alignCollisionTop; + float collisionOffset; +}; + + +#endif //__GAIJIN_HEIGHTMAP_BRUSH__ diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlBrush.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlBrush.cpp new file mode 100644 index 000000000..f2b3b1d8e --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlBrush.cpp @@ -0,0 +1,300 @@ +#include "hmlBrush.h" +#include "../hmlPlugin.h" +#include "../hmlCm.h" +#include +#include +#include +#include + + +#define NONE_MASK_NAME ("") + +static DataBlock defProps; + +HmapLandBrush::HmapLandBrush(IBrushClient *client, IHmapBrushImage &height_map) : + Brush(client), + heightMap(height_map), + maskName(""), + applied(tmpmem), + applyOnlyOnce(false), + useAutoAngle(false), + currentAngle(0), + gridCellSize(0), + heightMapOffset(0, 0) +{ + setStepIgnoreDirection(Point3(0, 1, 0)); + + if (!defProps.paramCount()) + { + DataBlock app_blk; + if (!app_blk.load(DAGORED2->getWorkspace().getAppPath())) + DAEDITOR3.conError("cannot read <%s>", DAGORED2->getWorkspace().getAppPath()); + + defProps = *app_blk.getBlockByNameEx("heightMap")->getBlockByNameEx("brush"); + defProps.setBool("defauldPropsInited", true); + } +} + +void HmapLandBrush::fillParams(PropPanel2 &panel) +{ + fillCommonParams(panel, PID_BRUSH_RADIUS, PID_BRUSH_OPACITY, PID_BRUSH_HARDNESS, PID_BRUSH_AUTOREPEAT, PID_BRUSH_SPACING); + + if (!updateMask(maskName)) + maskName = NONE_MASK_NAME; + + Brush::addMaskList(PID_BRUSH_MASK, panel, maskName); + maskInd = panel.getInt(PID_BRUSH_MASK); + + // commented following option, 'couse it worked strange + // panel.createCheckBox(PID_BRUSH_APPLY_ONCE, "Apply once", applyOnlyOnce); + panel.createCheckBox(PID_BRUSH_AUTO_ANGLE, "Auto angle", useAutoAngle); + currentAngle = ::norm_s_ang(currentAngle); + panel.createEditFloat(PID_BRUSH_ANGLE, "Angle:", RadToDeg(currentAngle)); +} + + +void HmapLandBrush::updateToPanel(PropPanel2 &panel) +{ + __super::updateToPanel(panel); + + panel.setInt(PID_BRUSH_MASK, maskInd); + // commented following option, 'couse it worked strange + // panel.setBool(PID_BRUSH_APPLY_ONCE, applyOnlyOnce); + panel.setBool(PID_BRUSH_AUTO_ANGLE, useAutoAngle); + currentAngle = ::norm_s_ang(currentAngle); + panel.setFloat(PID_BRUSH_ANGLE, RadToDeg(currentAngle)); +} + + +bool HmapLandBrush::updateMask(const char *newMask) +{ + if (strcmp(newMask, NONE_MASK_NAME) == 0) + return mask.load(""); + if (mask.load(Brush::getMaskPath(newMask))) + return true; + + return false; +} + +bool HmapLandBrush::updateFromPanelRef(PropPanel2 &panel, int pid) +{ + String maskName2(panel.getText(PID_BRUSH_MASK)); + maskInd = panel.getInt(PID_BRUSH_MASK); + + if (stricmp(maskName2, maskName) != 0) + { + if (!updateMask(maskName2)) + { + maskName2 = NONE_MASK_NAME; + // panel.setParam(PID_BRUSH_MASK, (const char*)maskName2); + panel.setInt(PID_BRUSH_MASK, 0); + } + maskName = maskName2; + } + + switch (pid) + { + case PID_BRUSH_APPLY_ONCE: + { + int ar = panel.getBool(pid); + if (ar < 2) + applyOnlyOnce = (bool)ar; + return true; + } + case PID_BRUSH_AUTO_ANGLE: + { + int ar = panel.getBool(pid); + if (ar < 2) + useAutoAngle = (bool)ar; + return true; + } + case PID_BRUSH_ANGLE: + { + currentAngle = DegToRad(panel.getFloat(pid)); + return true; + } + default: return Brush::updateFromPanel(&panel, pid); + } +} + + +void HmapLandBrush::brushPaintApplyStart(const IBBox2 &where) {} + + +void HmapLandBrush::brushStartEnd() +{ + clear_and_shrink(applied); + currentVector = Point2(0, 0); +} + + +void HmapLandBrush::dynamicItemChange(PropPanel2 &panel) +{ + if (useAutoAngle) + { + real angle = RadToDeg(currentAngle); + panel.setFloat(PID_BRUSH_ANGLE, angle); + } +} + +void HmapLandBrush::paint(const Point3 ¢er, const Point3 &prev_center, real cell_size, bool rb) +{ + gridCellSize = cell_size; + + if (gridCellSize < 0.00001f) + return; + if (useAutoAngle) + { + Point2 nextVector = Point2(center.x - prev_center.x, center.z - prev_center.z); + nextVector.normalize(); + float angle = atan2f(nextVector.y * currentVector.x - nextVector.x * currentVector.y, nextVector * currentVector); + currentAngle += norm_s_ang(angle); + currentAngle = norm_s_ang(currentAngle); + currentVector = nextVector; + } + + const real radius = getRadius(); + const Point2 c = Point2(center.x, center.z); + IBBox2 where; + where[0].x = (int)((c.x - radius) / gridCellSize); + where[1].x = (int)((c.x + radius) / gridCellSize); + + where[0].y = (int)((c.y - radius) / gridCellSize); + where[1].y = (int)((c.y + radius) / gridCellSize); + brushPaintApplyStart(where); + float opacity = ((float)getOpacity()) / 100.0f; + int appliedAt = -1; + + for (int y = where[0].y; y <= where[1].y; ++y) + { + for (int x = where[0].x; x <= where[1].x; ++x) + { + float *applyOnceWeight = NULL; + if (applyOnlyOnce) + { + if (appliedAt >= 0 && appliedAt < applied.size()) + if (applied[appliedAt].at & IPoint2(x, y)) + applyOnceWeight = (applied[appliedAt][IPoint2(x, y)]); + + if (!applyOnceWeight) + for (appliedAt = 0; appliedAt < applied.size(); ++appliedAt) + if (applied[appliedAt].at & IPoint2(x, y)) + { + applyOnceWeight = (applied[appliedAt][IPoint2(x, y)]); + break; + } + if (!applyOnceWeight) + { + int rememberGridCell; + if (applied.size()) + rememberGridCell = applied[0].at[1].x - applied[0].at[0].x + 1; + else + { + rememberGridCell = 2 * int(radius / gridCellSize) + 1; + if (rememberGridCell < 5) + rememberGridCell = 5; + } + IBBox2 at; + at[0] = + IPoint2(floorf(float(x) / rememberGridCell) * rememberGridCell, floorf(float(y) / rememberGridCell) * rememberGridCell); + at[1] = at[0] + IPoint2(rememberGridCell - 1, rememberGridCell - 1); + + G_VERIFY(at & IPoint2(x, y)); + appliedAt = append_items(applied, 1); + applied[appliedAt].init(at); + applyOnceWeight = (applied[appliedAt][IPoint2(x, y)]); + } + }; + + Point2 brushCoord = Point2(x * gridCellSize, y * gridCellSize) - c; + const real dist = length(brushCoord); + + float inc = getHardnessFromDistance(dist) * opacity; + + if (inc <= 0) + continue; + if (applyOnceWeight && inc > 1.0f - *applyOnceWeight) + inc = 1.0f - *applyOnceWeight; + float brushMaskStrength = + mask.getCenteredMask(brushCoord.x / radius, brushCoord.y / radius, radius / gridCellSize, currentAngle); + if (brushPaintApply(x, y, inc * brushMaskStrength, rb)) + { + dirtyBrushBox += IPoint2(x, y); + if (applyOnceWeight) + { + *applyOnceWeight += inc; + } + } + } + } + brushPaintApplyEnd(); +} + +void HmapLandBrush::saveToBlk(DataBlock &blk) const +{ + blk.addReal("stepDiv", getStepDiv()); + blk.addReal("radius", getRadius()); + blk.addInt("opacity", getOpacity()); + blk.addInt("hardness", getHardness()); + blk.addBool("autorepeat", isRepeat()); + blk.addBool("useAutoAngle", useAutoAngle); + // blk.addBool("applyOnlyOnce", applyOnlyOnce); + blk.addReal("currentAngle", currentAngle); + blk.addStr("maskName", maskName); +} + +void HmapLandBrush::loadFromBlk(const DataBlock &blk) +{ + setStepDiv(blk.getReal("stepDiv", defProps.getReal("stepDiv", getStepDiv()))); + setRadius(blk.getReal("radius", defProps.getReal("radius", getRadius()))); + setOpacity(blk.getInt("opacity", defProps.getInt("opacity", getOpacity()))); + setHardness(blk.getInt("hardness", defProps.getInt("hardness", getHardness()))); + setRepeat(blk.getBool("autorepeat", defProps.getBool("autorepeat", isRepeat()))); + useAutoAngle = blk.getBool("useAutoAngle", defProps.getBool("useAutoAngle", useAutoAngle)); + // applyOnlyOnce = blk.getBool("applyOnlyOnce", defProps.getBool("applyOnlyOnce", applyOnlyOnce)); + currentAngle = blk.getReal("currentAngle", defProps.getReal("currentAngle", currentAngle)); + maskName = blk.getStr("maskName", defProps.getStr("maskName", NONE_MASK_NAME)); + if (maskName.empty()) + maskName = defProps.getStr("maskName", NONE_MASK_NAME); + if (!updateMask(maskName) && strcmp(maskName, NONE_MASK_NAME) != 0) + { + maskName = defProps.getStr("maskName", NONE_MASK_NAME); + if (!updateMask(maskName)) + maskName = NONE_MASK_NAME; + } +} + + +void HmapLandBrush::draw() +{ + setColor(HmapLandPlugin::self->getEditedScriptImage() ? E3DCOLOR(255, 0, 255, 255) : E3DCOLOR(255, 0, 0, 255)); + + Brush::draw(); +} + + +//================================================================================================== +bool HmapLandBrush::calcCenter(IGenViewportWnd *wnd) +{ + Point3 world; + Point3 dir; + real dist = DAGORED2->getMaxTraceDistance(); + + wnd->clientToWorld(coord, world, dir); + + if (HmapLandPlugin::self->traceRayPrivate(world, dir, dist, &normal)) + { + center = world + dir * dist; + return true; + } + + return false; +} + + +//================================================================================================== +bool HmapLandBrush::traceDown(const Point3 &pos, Point3 &clip_p, IGenViewportWnd *wnd) +{ + clip_p = pos; + return HmapLandPlugin::self->getHeightmapOnlyPointHt(clip_p, NULL); +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlBrush.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlBrush.h new file mode 100644 index 000000000..d8528d1dc --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlBrush.h @@ -0,0 +1,147 @@ +#ifndef __GAIJIN_HEIGHTMAPLAND_BRUSH__ +#define __GAIJIN_HEIGHTMAPLAND_BRUSH__ +#pragma once + + +#include "brushMask.h" + +#include +#include +#include + + +class DataBlock; +typedef class PropertyContainerControlBase PropPanel2; + + +class IHmapBrushImage +{ +public: + enum Channel + { + CHANNEL_RGB = 0, + CHANNEL_R, + CHANNEL_G, + CHANNEL_B, + CHANNEL_A, + + CHANNELS_COUNT, + }; + + virtual real getBrushImageData(int x, int y, Channel channel) = 0; + virtual void setBrushImageData(int x, int y, real v, Channel channel) = 0; +}; + + +class HmapLandBrush : public Brush +{ +public: + HmapLandBrush(IBrushClient *client, IHmapBrushImage &height_map); + virtual ~HmapLandBrush() {} + + virtual void saveToBlk(DataBlock &blk) const; + virtual void loadFromBlk(const DataBlock &blk); + + void brushStartEnd(); + + virtual void onBrushPaintStart(int buttons, int key_modif) + { + dirtyBrushBox.setEmpty(); + brushStartEnd(); + } + virtual void onBrushPaintEnd(int buttons, int key_modif) { brushStartEnd(); } + virtual void onBrushPaint(const Point3 ¢er, const Point3 &prev_center, const Point3 &normal, int buttons, int key_modif, + real cell_size) + { + paint(center, prev_center, cell_size, false); + } + virtual void brushPaintApplyStart(const IBBox2 &where); + virtual bool brushPaintApply(int x, int y, float inc, bool rb) = 0; // true if applied + virtual void brushPaintApplyEnd() {} + virtual void onRBBrushPaintStart(int buttons, int key_modif) + { + dirtyBrushBox.setEmpty(); + brushStartEnd(); + } + virtual void onRBBrushPaintEnd(int buttons, int key_modif) { brushStartEnd(); } + virtual void onRBBrushPaint(const Point3 ¢er, const Point3 &prev_center, const Point3 &normal, int buttons, int key_modif, + real cell_size) + { + paint(center, prev_center, cell_size, true); + } + + virtual void paint(const Point3 ¢er, const Point3 &prev_center, real cell_size, bool rb); + + + virtual void fillParams(PropPanel2 &panel); + virtual void updateToPanel(PropPanel2 &panel); + + virtual bool updateFromPanelRef(PropPanel2 &panel, int pid); + virtual void dynamicItemChange(PropPanel2 &panel); + + virtual void draw(); + + virtual IBBox2 getDirtyBox() const { return dirtyBrushBox; } + void resetDirtyBox() { dirtyBrushBox.setEmpty(); } + bool updateMask(const char *); + void setHeightmapOffset(const Point2 &p) { heightMapOffset = p; } + +protected: + Point2 heightMapOffset; + IBrushMask mask; + IHmapBrushImage &heightMap; + String maskName; + int maskInd; + IBBox2 dirtyBrushBox; + struct Applied + { + SmallTab weight; + IBBox2 at; + float *operator[](IPoint2 p) + { + if (!(at & p)) + return NULL; + p.x -= at[0].x; + p.y -= at[0].y; + return &weight[p.x + p.y * (at[1].x - at[0].x + 1)]; + } + const float *operator[](IPoint2 p) const { return (*const_cast(this))[p]; } + float getWeight(int x, int y) const + { + const float *p = (*this)[IPoint2(x, y)]; + if (!p) + return 1.0; + return *p; + } + void init(const IBBox2 &a) + { + at = a; + IPoint2 width = at[1] - at[0] + IPoint2(1, 1); + clear_and_resize(weight, width.x * width.y); + mem_set_0(weight); + } + }; + Tab applied; + bool applyOnlyOnce, useAutoAngle; + real currentAngle; + Point2 currentVector; + float gridCellSize; + + + virtual bool calcCenter(IGenViewportWnd *wnd); + virtual bool traceDown(const Point3 &pos, Point3 &clip_pos, IGenViewportWnd *wnd); +}; + + +namespace heightmap_land +{ +extern HmapLandBrush *getUpHillBrush(IBrushClient *, IHmapBrushImage &); +extern HmapLandBrush *getDownHillBrush(IBrushClient *, IHmapBrushImage &); +extern HmapLandBrush *getSmoothBrush(IBrushClient *, IHmapBrushImage &); +extern HmapLandBrush *getAlignBrush(IBrushClient *, IHmapBrushImage &); +extern HmapLandBrush *getShadowsBrush(IBrushClient *, IHmapBrushImage &); +extern HmapLandBrush *getScriptBrush(IBrushClient *, IHmapBrushImage &); +} // namespace heightmap_land + + +#endif //__GAIJIN_HEIGHTMAP_BRUSH__ diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlHillBrush.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlHillBrush.cpp new file mode 100644 index 000000000..f43b0d753 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlHillBrush.cpp @@ -0,0 +1,107 @@ +#include "hmlHillBrush.h" +#include "../hmlPlugin.h" +#include "../hmlCm.h" +#include + + +void HmapHillLandBrush::fillParams(PropPanel2 &panel) +{ + panel.createEditFloat(PID_BRUSH_POWER, "Power(height):", power); + HmapLandBrush::fillParams(panel); + panel.createCheckBox(PID_BRUSH_LIMIT_USE, "Use Limit", limitValueUse); + panel.createEditFloat(PID_BRUSH_LIMIT_VALUE, "Limit", limitValue); +} + + +void HmapHillLandBrush::updateToPanel(PropPanel2 &panel) +{ + panel.setFloat(PID_BRUSH_POWER, power); + __super::updateToPanel(panel); + panel.setBool(PID_BRUSH_LIMIT_USE, limitValueUse); + panel.setFloat(PID_BRUSH_LIMIT_VALUE, limitValue); +} + + +bool HmapHillLandBrush::updateFromPanelRef(PropPanel2 &panel, int pid) +{ + switch (pid) + { + case PID_BRUSH_LIMIT_USE: + { + int ar = panel.getBool(pid); + if (ar < 2) + limitValueUse = (bool)ar; + return true; + } + case PID_BRUSH_LIMIT_VALUE: limitValue = panel.getFloat(pid); return true; + case PID_BRUSH_POWER: power = panel.getFloat(pid); return true; + default: return HmapLandBrush::updateFromPanelRef(panel, pid); + } +} + +bool HmapHillLandBrush::brushPaintApply(int x, int y, float inc, bool rb) +{ + if (rb) + inc = -inc; + if (isDown) + inc = -inc; + float result = heightMap.getBrushImageData(x, y, HmapLandPlugin::self->getEditedChannel()) + inc * power; + + if (limitValueUse) + { + if (inc > 0) + { + if (result > limitValue) + { + if (result - inc < limitValue) + result = limitValue; + else + return false; + } + } + else + { + if (result < limitValue) + { + if (result - inc > limitValue) + result = limitValue; + else + return false; + } + } + } + + heightMap.setBrushImageData(x, y, result, HmapLandPlugin::self->getEditedChannel()); + return true; +} + +void HmapHillLandBrush::saveToBlk(DataBlock &blk) const +{ + HmapLandBrush::saveToBlk(blk); + + blk.addReal("limitValue", limitValue); + blk.addReal("power", power); + blk.addBool("limitValueUse", limitValueUse); +} + +void HmapHillLandBrush::loadFromBlk(const DataBlock &blk) +{ + HmapLandBrush::loadFromBlk(blk); + + power = blk.getReal("power", power); + limitValue = blk.getReal("limitValue", limitValue); + limitValueUse = blk.getBool("limitValueUse", limitValueUse); +} + +namespace heightmap_land +{ +HmapLandBrush *getUpHillBrush(IBrushClient *client, IHmapBrushImage &height_map) +{ + return new HmapHillLandBrush(false, client, height_map); +} + +HmapLandBrush *getDownHillBrush(IBrushClient *client, IHmapBrushImage &height_map) +{ + return new HmapHillLandBrush(true, client, height_map); +} +}; // namespace heightmap_land diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlHillBrush.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlHillBrush.h new file mode 100644 index 000000000..6add34cd5 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlHillBrush.h @@ -0,0 +1,31 @@ +#ifndef __GAIJIN_HEIGHTMAPLAND_HILL_BRUSH__ +#define __GAIJIN_HEIGHTMAPLAND_HILL_BRUSH__ +#pragma once + + +#include "hmlBrush.h" + +class HmapHillLandBrush : public HmapLandBrush +{ +public: + HmapHillLandBrush(bool down, IBrushClient *client, IHmapBrushImage &height_map) : + HmapLandBrush(client, height_map), limitValue(0), isDown(down), limitValueUse(false), power(1) + {} + + virtual void fillParams(PropPanel2 &panel); + virtual void updateToPanel(PropPanel2 &panel); + + virtual bool brushPaintApply(int x, int y, float inc, bool rb); + virtual void saveToBlk(DataBlock &blk) const; + virtual void loadFromBlk(const DataBlock &blk); + + virtual bool updateFromPanelRef(PropPanel2 &panel, int pid); + +protected: + float limitValue; + float power; + bool isDown, limitValueUse; +}; + + +#endif //__GAIJIN_HEIGHTMAP_BRUSH__ diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlScriptBrush.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlScriptBrush.cpp new file mode 100644 index 000000000..f68d7c063 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlScriptBrush.cpp @@ -0,0 +1,41 @@ +#include "hmlScriptBrush.h" +#include "../hmlPlugin.h" +#include "../hmlCm.h" +#include + +#include + + +namespace heightmap_land +{ +HmapLandBrush *getScriptBrush(IBrushClient *client, IHmapBrushImage &height_map) { return new HmapScriptBrush(client, height_map); } +}; // namespace heightmap_land + + +void HmapScriptBrush::fillParams(PropPanel2 &panel) { panel.createEditFloat(PID_BRUSH_RADIUS, "Brush radius:", radius); } + + +void HmapScriptBrush::updateToPanel(PropPanel2 &panel) { panel.setFloat(PID_BRUSH_RADIUS, radius); } + + +void HmapScriptBrush::saveToBlk(DataBlock &blk) const { blk.addReal("radius", getRadius()); } + + +void HmapScriptBrush::loadFromBlk(const DataBlock &blk) { setRadius(blk.getReal("radius", getRadius())); } + + +bool HmapScriptBrush::updateFromPanelRef(PropPanel2 &panel, int pid) +{ + if (pid == PID_BRUSH_RADIUS) + { + const real rad = panel.getFloat(pid); + + const real sRad = setRadius(rad); + if (sRad != rad) + panel.setFloat(pid, sRad); + + return true; + } + + return false; +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlScriptBrush.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlScriptBrush.h new file mode 100644 index 000000000..074f79ec9 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlScriptBrush.h @@ -0,0 +1,27 @@ +#ifndef __GAIJIN_HEIGHTMAPLAND_SCRIPT_BRUSH__ +#define __GAIJIN_HEIGHTMAPLAND_SCRIPT_BRUSH__ + +#pragma once + +#include "hmlBrush.h" +#include "../hmlPlugin.h" + +#include + +class HmapScriptBrush : public HmapLandBrush +{ +public: + HmapScriptBrush(IBrushClient *client, IHmapBrushImage &height_map) : HmapLandBrush(client, height_map) {} + + virtual void fillParams(PropPanel2 &panel); + virtual void updateToPanel(PropPanel2 &panel); + + virtual bool brushPaintApply(int x, int y, float inc, bool rb) { return true; } + + virtual void saveToBlk(DataBlock &blk) const; + virtual void loadFromBlk(const DataBlock &blk); + + virtual bool updateFromPanelRef(PropPanel2 &panel, int pid); +}; + +#endif //__GAIJIN_HEIGHTMAPLAND_SCRIPT_BRUSH__ diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlShadowsBrush.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlShadowsBrush.cpp new file mode 100644 index 000000000..bc560331f --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlShadowsBrush.cpp @@ -0,0 +1,49 @@ +#include "hmlShadowsBrush.h" +#include "../hmlPlugin.h" +#include "../hmlCm.h" +#include + +#include + + +namespace heightmap_land +{ +HmapLandBrush *getShadowsBrush(IBrushClient *client, IHmapBrushImage &height_map) { return new HmapShadowsBrush(client, height_map); } +}; // namespace heightmap_land + + +void HmapShadowsBrush::onBrushPaintEnd(int buttons, int key_modif) +{ + HmapLandPlugin::self->calcGoodLandLightingInBox(dirtyBrushBox); + + __super::onBrushPaintEnd(buttons, key_modif); +} + + +void HmapShadowsBrush::fillParams(PropPanel2 &panel) { panel.createEditFloat(PID_BRUSH_RADIUS, "Brush radius:", radius); } + + +void HmapShadowsBrush::updateToPanel(PropPanel2 &panel) { panel.setFloat(PID_BRUSH_RADIUS, radius); } + + +void HmapShadowsBrush::saveToBlk(DataBlock &blk) const { blk.addReal("radius", getRadius()); } + + +void HmapShadowsBrush::loadFromBlk(const DataBlock &blk) { setRadius(blk.getReal("radius", getRadius())); } + + +bool HmapShadowsBrush::updateFromPanelRef(PropPanel2 &panel, int pid) +{ + if (pid == PID_BRUSH_RADIUS) + { + real rad = panel.getFloat(pid); + + const real sRad = setRadius(rad); + if (sRad != rad) + panel.setFloat(pid, sRad); + + return true; + } + + return false; +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlShadowsBrush.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlShadowsBrush.h new file mode 100644 index 000000000..4e32c196c --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlShadowsBrush.h @@ -0,0 +1,33 @@ +#ifndef __GAIJIN_HEIGHTMAPLAND_SHADOWS_BRUSH__ +#define __GAIJIN_HEIGHTMAPLAND_SHADOWS_BRUSH__ +#pragma once + + +#include "hmlBrush.h" + +class HmapShadowsBrush : public HmapLandBrush +{ +public: + HmapShadowsBrush(IBrushClient *client, IHmapBrushImage &height_map) : HmapLandBrush(client, height_map) {} + + virtual void fillParams(PropPanel2 &panel); + virtual void updateToPanel(PropPanel2 &panel); + + virtual bool brushPaintApply(int x, int y, float inc, bool rb) { return true; } + + virtual void onBrushPaintEnd(int buttons, int key_modif); + + virtual IBBox2 getDirtyBox() const + { + IBBox2 box; + return box; + } + + virtual void saveToBlk(DataBlock &blk) const; + virtual void loadFromBlk(const DataBlock &blk); + + virtual bool updateFromPanelRef(PropPanel2 &panel, int pid); +}; + + +#endif //__GAIJIN_HEIGHTMAPLAND_SHADOWS_BRUSH__ diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlSmoothBrush.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlSmoothBrush.cpp new file mode 100644 index 000000000..0a8240f46 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlSmoothBrush.cpp @@ -0,0 +1,130 @@ +#include "hmlSmoothBrush.h" +#include "../hmlPlugin.h" +#include "../hmlCm.h" +#include + + +void HmapSmoothLandBrush::fillParams(PropPanel2 &panel) +{ + HmapLandBrush::fillParams(panel); + panel.createTrackInt(PID_BRUSH_SIGMA, "Sigma", sigma * 100, 1, 100, 1); + panel.createTrackInt(PID_BRUSH_KERNEL_SIZE, "Filter Size", halfKernelSize, 1, 4, 1); + // params.addReal(PID_BRUSH_KERNEL_SIZE, "KernelSize", limitValue);*/ +} + + +void HmapSmoothLandBrush::updateToPanel(PropPanel2 &panel) +{ + __super::updateToPanel(panel); + panel.setInt(PID_BRUSH_SIGMA, sigma * 100); + panel.setInt(PID_BRUSH_KERNEL_SIZE, halfKernelSize); +} + + +bool HmapSmoothLandBrush::updateFromPanelRef(PropPanel2 &panel, int pid) +{ + switch (pid) + { + case PID_BRUSH_SIGMA: + { + sigma = panel.getInt(pid) / 100.0; + makeKernel(); + return true; + } + + case PID_BRUSH_KERNEL_SIZE: + halfKernelSize = panel.getInt(pid); + makeKernel(); + return true; + + default: return HmapLandBrush::updateFromPanelRef(panel, pid); + } + return true; // hack +} + +void HmapSmoothLandBrush::makeKernel() +{ + where.setEmpty(); + float gaussSigma2 = sigma * sigma; + int idx = 0; + float totalKrnl = 0; + clear_and_resize(gaussKernel, (halfKernelSize * 2 + 1) * (halfKernelSize * 2 + 1)); + for (int filterY = -halfKernelSize; filterY <= halfKernelSize; ++filterY) + for (int filterX = -halfKernelSize; filterX <= halfKernelSize; ++filterX, ++idx) + { + gaussKernel[idx] = expf(-(filterX * filterX + filterY * filterY) / (2 * gaussSigma2 * halfKernelSize * halfKernelSize)); + totalKrnl += gaussKernel[idx]; + } + for (int idx = 0; idx < gaussKernel.size(); ++idx) + { + gaussKernel[idx] /= totalKrnl; + } +} + +void HmapSmoothLandBrush::brushPaintApplyStart(const IBBox2 &where_apply) +{ + HmapLandBrush::brushPaintApplyStart(where_apply); + if (where != where_apply) + { + where = where_apply; + preFilteredSize = where[1] - where[0] + IPoint2(1 + 2 * halfKernelSize, 1 + 2 * halfKernelSize); + clear_and_resize(preFiltered, preFilteredSize.x * preFilteredSize.y); + } + for (int ty = 0, y = where[0].y - halfKernelSize; y <= where[1].y + halfKernelSize; ++y, ++ty) + for (int tx = 0, x = where[0].x - halfKernelSize; x <= where[1].x + halfKernelSize; ++x, ++tx) + preFiltered[ty * preFilteredSize.x + tx] = heightMap.getBrushImageData(x, y, HmapLandPlugin::self->getEditedChannel()); +} + +bool HmapSmoothLandBrush::brushPaintApply(int x, int y, float inc, bool rb) +{ + if (!(where & IPoint2(x, y))) + return false; + if (inc > 1.0f) + inc = 1.0f; + float result = 0.0f; + x -= where[0].x; + y -= where[0].y; + for (int filterY = 0; filterY < 2 * halfKernelSize + 1; ++filterY) + for (int filterX = 0; filterX < 2 * halfKernelSize + 1; ++filterX) + { + float filterWeight = gaussKernel[filterX + (filterY) * (2 * halfKernelSize + 1)]; + if (rb) + { + if (filterY == halfKernelSize && filterX == halfKernelSize) + filterWeight = 1 + (1 - filterWeight); + else + filterWeight = -filterWeight; + } + result += preFiltered[x + filterX + (y + filterY) * preFilteredSize.x] * filterWeight; + } + float prevHeight = preFiltered[x + halfKernelSize + (y + halfKernelSize) * preFilteredSize.x]; + + heightMap.setBrushImageData(where[0].x + x, where[0].y + y, result * inc + prevHeight * (1.0f - inc), + HmapLandPlugin::self->getEditedChannel()); + return true; +} + +void HmapSmoothLandBrush::saveToBlk(DataBlock &blk) const +{ + HmapLandBrush::saveToBlk(blk); + + blk.addInt("halfKernelSize", halfKernelSize); + blk.addReal("sigma", sigma); +} + +void HmapSmoothLandBrush::loadFromBlk(const DataBlock &blk) +{ + HmapLandBrush::loadFromBlk(blk); + + halfKernelSize = blk.getInt("halfKernelSize", halfKernelSize); + sigma = blk.getReal("sigma", sigma); + makeKernel(); +} + +namespace heightmap_land +{ +HmapLandBrush *getSmoothBrush(IBrushClient *client, IHmapBrushImage &height_map) +{ + return new HmapSmoothLandBrush(client, height_map); +} +}; // namespace heightmap_land diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlSmoothBrush.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlSmoothBrush.h new file mode 100644 index 000000000..e54124280 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/Brushes/hmlSmoothBrush.h @@ -0,0 +1,40 @@ +#ifndef __GAIJIN_HEIGHTMAPLAND_SMOOTH_BRUSH__ +#define __GAIJIN_HEIGHTMAPLAND_SMOOTH_BRUSH__ +#pragma once + + +#include "hmlBrush.h" + +class HmapSmoothLandBrush : public HmapLandBrush +{ +public: + HmapSmoothLandBrush(IBrushClient *client, IHmapBrushImage &height_map) : + HmapLandBrush(client, height_map), halfKernelSize(1), sigma(1) + { + makeKernel(); + } + + virtual void fillParams(PropPanel2 &panel); + virtual void updateToPanel(PropPanel2 &panel); + + virtual bool brushPaintApply(int x, int y, float inc, bool rb); + virtual void brushPaintApplyStart(const IBBox2 &where); + virtual void saveToBlk(DataBlock &blk) const; + virtual void loadFromBlk(const DataBlock &blk); + + virtual bool updateFromPanelRef(PropPanel2 &panel, int pid); + +protected: + void makeKernel(); + float sigma; + float centerWeight; + int halfKernelSize; + IBBox2 where; + IPoint2 preFilteredSize; + + SmallTab gaussKernel; + SmallTab preFiltered; +}; + + +#endif //__GAIJIN_HEIGHTMAP_BRUSH__ diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/GPUGrassDecalPID.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/GPUGrassDecalPID.h new file mode 100644 index 000000000..9d17b7add --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/GPUGrassDecalPID.h @@ -0,0 +1,14 @@ +#pragma once +#include +#include + +enum class GPUGrassDecalPID +{ + NAME, + ID, + ADD_TYPE, + REMOVE_TYPE, + TYPES_START, + TYPES_END = TYPES_START + MAX_TYPES_PER_CHANNEL, + COUNT +}; \ No newline at end of file diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/GPUGrassTypePID.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/GPUGrassTypePID.h new file mode 100644 index 000000000..ab38988c2 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/GPUGrassTypePID.h @@ -0,0 +1,31 @@ +#pragma once +enum class GPUGrassTypePID +{ + NAME, + DIFFUSE, + NORMAL, + VARIATIONS, + HEIGHT, + SIZE_LOD_MUL, + HT_RND_ADD, + HOR_SIZE, + HOR_SIZE_RND_ADD, + COLOR_MASK_R_FROM, + COLOR_MASK_R_TO, + COLOR_MASK_G_FROM, + COLOR_MASK_G_TO, + COLOR_MASK_B_FROM, + COLOR_MASK_B_TO, + HEIGHT_FROM_WEIGHT_MUL, + HEIGHT_FROM_WEIGHT_ADD, + DENSITY_FROM_WEIGHT_MUL, + DENSITY_FROM_WEIGHT_ADD, + VERTICAL_ANGLE_MUL, + VERTICAL_ANGLE_ADD, + + STIFFNESS, + HORIZONTAL_GRASS, + UNDERWATER, + + COUNT +}; \ No newline at end of file diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/buildRoad.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/buildRoad.cpp new file mode 100644 index 000000000..95a63b155 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/buildRoad.cpp @@ -0,0 +1,753 @@ +#include +#include "hmlSplineObject.h" +#include "hmlSplinePoint.h" +#include "hmlObjectsEditor.h" +#include "crossRoad.h" +#include "roadBuilderIface.h" +#include "materialMgr.h" +#include "roadUtil.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace roadbuildertool; + +typedef RoadBuilder *(*get_new_road_builder_t)(void); +typedef void (*delete_road_builder_t)(RoadBuilder *); + +static HMODULE hDll = NULL; +static get_new_road_builder_t get_new_road_builder = NULL; +static delete_road_builder_t delete_road_builder = NULL; +static RoadBuilder *road_builder = NULL; +static bool bad_road_builder = false; + +#define TRANSIENT_PART 0.1 + +static bool loadRoadBuilderDll() +{ + if (hDll) + return true; + + String fn = ::make_full_start_path("roadBuilder.dll"); + + hDll = LoadLibrary(fn); + if (!hDll) + { + DAEDITOR3.conError("Can't load road builder: %s", (char *)fn); + return false; + } + get_new_road_builder = (get_new_road_builder_t)GetProcAddress(hDll, "get_new_road_builder"); + delete_road_builder = (delete_road_builder_t)GetProcAddress(hDll, "delete_road_builder"); + if (!get_new_road_builder || !delete_road_builder) + { + DAEDITOR3.conError("Can't init road builder"); + get_new_road_builder = NULL; + delete_road_builder = NULL; + FreeLibrary(hDll); + hDll = NULL; + return false; + } + + bad_road_builder = false; + return true; +} +static bool prepareRoadBuilder() +{ + if (bad_road_builder) + return false; + + if (!road_builder) + { + road_builder = get_new_road_builder(); + if (!road_builder) + { + bad_road_builder = true; + return false; + } + if (!road_builder->checkVersion()) + { + DAEDITOR3.conError("Road builder version mismatch: has=%p needed=%p", road_builder->getVersion(), road_builder->VERSION); + road_builder = NULL; + bad_road_builder = true; + return false; + } + road_builder->init(); + } + return true; +} + +void HmapLandObjectEditor::unloadRoadBuilderDll() +{ + if (!hDll) + return; + + // if ( road_builder ) + // delete_road_builder ( road_builder ); + + road_builder = NULL; + get_new_road_builder = NULL; + delete_road_builder = NULL; + FreeLibrary(hDll); + hDll = NULL; +} + +static void addGeometryNode(StaticGeometryContainer &geom, MaterialDataList *mat, Geometry &geom_out, const char *node_name) +{ + StaticGeometryContainer *g = dagGeom->newStaticGeometryContainer(); + + Mesh *n_mesh = dagGeom->newMesh(), *n_wlMesh = dagGeom->newMesh(); + MeshData &mesh = n_mesh->getMeshData(), &wlMesh = n_wlMesh->getMeshData(); + + mesh.vert = make_span_const(geom_out.vertices, geom_out.vertCount); + mesh.tvert[0] = make_span_const(geom_out.textureCoordinates, geom_out.tcCount); + mesh.vertnorm = make_span_const(geom_out.normals, geom_out.normalCount); + + mesh.face.resize(geom_out.faceCount); + mesh.tface[0].resize(geom_out.faceCount); + mesh.facengr.resize(geom_out.faceCount); + + wlMesh.vert = make_span_const(geom_out.vertices, geom_out.vertCount); + wlMesh.tvert[0] = make_span_const(geom_out.textureCoordinates, geom_out.tcCount); + wlMesh.vertnorm = make_span_const(geom_out.normals, geom_out.normalCount); + + wlMesh.face.resize(geom_out.faceCount); + wlMesh.tface[0].resize(geom_out.faceCount); + wlMesh.facengr.resize(geom_out.faceCount); + + int fc = 0, wlfc = 0; + bool has_def_mat = false; + + for (int fi = 0; fi < geom_out.faceCount; fi++) + { + const roadbuildertool::FaceIndices &f = geom_out.geomFaces[fi]; + + if (f.v[0] == f.v[1] || f.v[0] == f.v[2] || f.v[1] == f.v[2]) + continue; + + MeshData *m; + int i; + + if (geom_out.details[fi].type == roadbuildertool::GeometryFaceDetails::TYPE_WHITELINES) + { + m = &wlMesh; + i = wlfc++; + } + else + { + m = &mesh; + i = fc++; + } + + memcpy(m->face[i].v, f.v, sizeof(int) * 3); + m->face[i].smgr = geom_out.details[fi].smoothingGroup; + + if (m->face[i].smgr == 0) + DAEDITOR3.conError("face %d, smoothing groop = 0, material: %s, class: %s", i, + (char *)mat->getSubMat(geom_out.details[fi].materialId + 1)->matName, + (char *)mat->getSubMat(geom_out.details[fi].materialId + 1)->className); + + if (geom_out.details[fi].materialId == -1) + has_def_mat = true; + m->face[i].mat = geom_out.details[fi].materialId + 1; + + memcpy(&m->facengr[i][0], geom_out.normalIndices[fi].v, sizeof(int) * 3); + memcpy(m->tface[0][i].t, geom_out.textureFaces[fi].v, sizeof(int) * 3); + } + if (has_def_mat && !mat->list[0].get()) + { + ObjLibMaterialListMgr::setDefaultMat0(*mat); + DAEDITOR3.conError("roadGeom generated with default(bad) material"); + } + + mesh.facengr.resize(fc); + mesh.tface[0].resize(fc); + mesh.face.resize(fc); + + mesh.facengr.shrink_to_fit(); + mesh.tface[0].shrink_to_fit(); + mesh.face.shrink_to_fit(); + + wlMesh.facengr.resize(wlfc); + wlMesh.tface[0].resize(wlfc); + wlMesh.face.resize(wlfc); + + wlMesh.facengr.shrink_to_fit(); + wlMesh.tface[0].shrink_to_fit(); + wlMesh.face.shrink_to_fit(); + + mesh.calc_facenorms(); + wlMesh.calc_facenorms(); + + ObjLibMaterialListMgr::complementDefaultMat0(*mat); + dagGeom->objCreator3dAddNode(node_name, n_mesh, mat, *g); + ObjLibMaterialListMgr::reclearDefaultMat0(*mat); + + for (int i = 0; i < g->nodes.size(); ++i) + { + StaticGeometryNode *node = g->nodes[i]; + + node->flags |= StaticGeometryNode::FLG_CASTSHADOWS | StaticGeometryNode::FLG_CASTSHADOWS_ON_SELF | + StaticGeometryNode::FLG_COLLIDABLE | StaticGeometryNode::FLG_NO_RECOMPUTE_NORMALS; + + dagGeom->staticGeometryNodeCalcBoundBox(*node); + dagGeom->staticGeometryNodeCalcBoundSphere(*node); + + geom.addNode(dagGeom->newStaticGeometryNode(*node, tmpmem)); + } + + dagGeom->staticGeometryContainerClear(*g); + + dagGeom->objCreator3dAddNode(String(node_name) + "_whiteline", n_wlMesh, mat, *g); + + for (int i = 0; i < g->nodes.size(); ++i) + { + StaticGeometryNode *node = g->nodes[i]; + node->flags = StaticGeometryNode::FLG_RENDERABLE | StaticGeometryNode::FLG_NO_RECOMPUTE_NORMALS; + + dagGeom->staticGeometryNodeCalcBoundBox(*node); + dagGeom->staticGeometryNodeCalcBoundSphere(*node); + + geom.addNode(dagGeom->newStaticGeometryNode(*node, tmpmem)); + } + + dagGeom->deleteStaticGeometryContainer(g); +} + +static int autoRoadNodeIdx = 0; +static int autoCrossNodeIdx = 0; +static void buildSegments(Geometry &geom_out, StaticGeometryContainer &geom, MaterialDataList *mat, + dag::Span build_links, dag::ConstSpan lamps, dag::ConstSpan build_points, + dag::ConstSpan decals) +{ + for (int i = 0; i < build_links.size(); i++) + build_links[i].lamps = &lamps[(unsigned)(uintptr_t)build_links[i].lamps]; + + Roads roads; + + roads.links = build_links.data(); + roads.linksCount = build_links.size(); + roads.points = build_points.data(); + roads.pointsCount = build_points.size(); + roads.decals = decals.data(); + roads.decalsCount = decals.size(); + roads.boundLinks = NULL; + roads.boundLinksCount = 0; + roads.transitionPart = TRANSIENT_PART; + + // build roads + // debug("roads: points = %d; links = %d", roads.pointsCount, roads.linksCount); + + // build roads + memset(&geom_out, 0, sizeof(geom_out)); + bool ret = road_builder->build(roads, geom_out); + /*debug("geom_out/roads: ret=%d faceCount=%d, vertCount=%d, tcCount=%d, normalCount=%d\n" + " lamps=%p lampsCount=%d", ret, geom_out.faceCount, geom_out.vertCount, + geom_out.tcCount, geom_out.normalCount, geom_out.lamps, geom_out.lampsCount);*/ + if (ret && geom_out.faceCount && geom_out.vertCount) + { + String name; + if (build_links.size() == 1 && build_points.size() == 2) + name.printf(1024, "road_%d", autoRoadNodeIdx++); + else + name.printf(1024, "cross_%d", autoCrossNodeIdx++); + + addGeometryNode(geom, mat, geom_out, name); + // lamp_pos.reserve(lamp_pos.size() + geom_out.lampsCount); + for (int i = 0; i < geom_out.lampsCount; ++i) + { + Quat quat; + euler_to_quat(geom_out.lamps[i].pitchYawRow.x, geom_out.lamps[i].pitchYawRow.y, geom_out.lamps[i].pitchYawRow.z, quat); + // lamp_pos.push_back(AnimV20Math::makeTM(geom_out.lamps[i].position, quat, Point3(1,1,1))); + // lamp_types.push_back(geom_out.lamps[i].typeId); + } + } + + road_builder->endBuild(geom_out); +} + +static void addInvariantPointProps(const splineclass::RoadData &road, PointProperties &props, ObjLibMaterialListMgr &mat_mgr) +{ + memset(&props, 0, sizeof(props)); + + props.linesNumber = road.linesCount; + props.lineWidth = road.lineWidth; + props.angleRadius = road.crossTurnRadius; + props.updir = Point3(0, 1, 0); + props.crossRoadMatId = mat_mgr.getMaterialId(road.mat.crossRoad); + props.crossRoadUScale = road.crossRoadUScale; + props.crossRoadVScale = road.crossRoadVScale; + props.roadFlipUV = road.flipCrossRoadUV; +} +static void addPointProps(const splineclass::RoadData &road, PointProperties &props, ObjLibMaterialListMgr &mat_mgr, + SplinePointObject *p) +{ + addInvariantPointProps(road, props, mat_mgr); + props.pos = p->getPt(); + props.inHandle = p->getBezierIn(); + props.outHandle = p->getBezierOut(); + + //! upDir assumed to be computed before while generated straight segments! + props.updir = p->tmpUpDir; +} + +static void computePointUpDir(const splineclass::RoadData *road_before, const splineclass::RoadData *road_after, + PointProperties &props, SplinePointObject *p, BezierSplineInt3d *seg_before, BezierSplineInt3d *seg_after) +{ + if (p->isCross) + props.updir = Point3(0, 1, 0); + else + { + float r1 = 0, r2 = 0; + + // calculate integral curvature characteristics of splines + if (seg_before) + for (float t = 1; t > 0; t -= 0.02) + r1 += t * seg_before->k2s(t); + + if (seg_after) + for (float t = 0; t < 1; t += 0.02) + r2 += (1 - t) * seg_after->k2s(t); + + // clamp curvature characteristics by road::maxPointR + if (road_before && fabs(r1) > road_before->maxPointR) + r1 = r1 >= 0 ? road_before->maxPointR : -road_before->maxPointR; + if (road_after && fabs(r2) > road_after->maxPointR) + r2 = r2 >= 0 ? road_after->maxPointR : -road_after->maxPointR; + + // convert curvature characteristics into upDir rotation (in radians) using multipliers of both splines + float rot = road_before ? -r1 * road_before->pointRtoUpdirRot : 0; + if (road_after) + rot -= r2 * road_after->pointRtoUpdirRot; + if (road_before && road_after) + rot *= 0.5; + + // clamp maximum upDir rotation angle + if (road_before) + { + if (rot < -road_before->maxUpdirRot) + rot = -road_before->maxUpdirRot; + else if (rot > road_before->maxUpdirRot) + rot = road_before->maxUpdirRot; + } + + if (road_after) + { + if (rot < -road_after->maxUpdirRot) + rot = -road_after->maxUpdirRot; + else if (rot > road_after->maxUpdirRot) + rot = road_after->maxUpdirRot; + } + + // if rotation angle is small engough, use vertical-up upDir + if (fabs(rot) < 1e-4) + props.updir = Point3(0, 1, 0); + else + { + // clamp minimum upDir rotation angle + if (road_before && fabs(rot) < road_before->minUpdirRot) + rot = rot >= 0 ? road_before->minUpdirRot : -road_before->minUpdirRot; + if (road_after && fabs(rot) < road_after->minUpdirRot) + rot = rot >= 0 ? road_after->minUpdirRot : -road_after->minUpdirRot; + + // finally compute upDir form upDir rotation angle + Point3 spline_dir = normalize(Point3(p->getProps().relOut.x, 0, p->getProps().relOut.z)); + props.updir = makeTM(spline_dir, rot) * Point3(0, 1, 0); + } + } + p->tmpUpDir = props.updir; +} + +static void addInvariantLinkProps(splineclass::RoadData &road, /* non const as we modify it's 'roads' member */ + const splineclass::RoadData *road_prev, const splineclass::RoadData *road_next, float seg_len, float seg_len_prev, + float seg_len_next, LinkProperties &link, Tab &lamps, ObjLibMaterialListMgr &mat_mgr) +{ +#define GET_MAT_COND(mat_name, cond) (cond) ? mat_mgr.getMaterialId(road.mat.mat_name) : -1 + + memset(link.types, 0, sizeof(link.types)); + for (int j = 0; j < splineclass::RoadData::MAX_SEP_LINES; ++j) + link.types[j] = road.sepLineType[j]; + + link.flags = 0; + if (road.hasLeftSide) + link.flags |= LinkProperties::LSIDE; + if (road.hasRightSide) + link.flags |= LinkProperties::RSIDE; + if (road.hasLeftSideBorder) + link.flags |= LinkProperties::LSIDE_BORDERS; + if (road.hasRightSideBorder) + link.flags |= LinkProperties::RSIDE_BORDERS; + if (road.hasLeftVertWall) + link.flags |= LinkProperties::LVERTICAL_WALL; + if (road.hasRightVertWall) + link.flags |= LinkProperties::RVERTICAL_WALL; + if (road.hasCenterBorder) + link.flags |= LinkProperties::CENTER_BORDER; + if (road.hasHammerSides) + link.flags |= LinkProperties::HAMMER_SIDES; + if (road.hasHammerCenter) + link.flags |= LinkProperties::HAMMER_CENTER; + if (road.hasPaintings) + link.flags |= LinkProperties::PAINTINGS; + if (road.hasStopLine) + link.flags |= LinkProperties::STOP_LINE; + if (road.isBridge) + link.flags |= LinkProperties::BRIDGE; + if (road.isBridgeSupport) + link.flags |= LinkProperties::BRIDGE_SUPPORT; + if (road.isCustomBridge) + link.flags |= LinkProperties::CUSTOM_BRIDGE; + if (road.flipRoadUV) + link.flags |= LinkProperties::FLIP_ROAD_TEX; + + link.roadMatId = mat_mgr.getMaterialId(road.mat.road); + link.sideMatId = GET_MAT_COND(sides, road.hasLeftSide | road.hasRightSide); + link.verticalWallsMatId = GET_MAT_COND(vertWalls, road.hasLeftVertWall | road.hasRightVertWall); + link.centerBorderMatId = GET_MAT_COND(centerBorder, road.hasLeftSideBorder | road.hasCenterBorder | road.hasRightSideBorder); + link.hammerSidesMatId = GET_MAT_COND(hammerSides, road.hasHammerSides); + link.hammerCenterMatId = GET_MAT_COND(hammerCenter, road.hasHammerCenter); + link.paintingsMatId = GET_MAT_COND(paintings, road.hasPaintings); + + link.sideSplineProperties.scale[1] = road.sideSlope; + link.wallSplineProperties.scale[1] = road.wallSlope; + link.sideSplineProperties.scale[0] = road.sideSlope; + link.wallSplineProperties.scale[0] = road.wallSlope; + link.sideSplineProperties.scale[2] = road.sideSlope; + link.wallSplineProperties.scale[2] = road.wallSlope; + + float len = TRANSIENT_PART * seg_len; + if (road_prev && TRANSIENT_PART > 0.001) + { + float len1 = TRANSIENT_PART * seg_len_prev; + float t = len1 / (len1 + len); + link.sideSplineProperties.scale[0] = t * road.sideSlope + (1 - t) * road_prev->sideSlope; + link.wallSplineProperties.scale[0] = t * road.wallSlope + (1 - t) * road_prev->wallSlope; + } + if (road_next && TRANSIENT_PART > 0.001) + { + float len2 = TRANSIENT_PART * seg_len_next; + float t = len / (len + len2); + link.sideSplineProperties.scale[2] = t * road_next->sideSlope + (1 - t) * road.sideSlope; + link.wallSplineProperties.scale[2] = t * road_next->wallSlope + (1 - t) * road.wallSlope; + } + + link.leftMint = 0.0; + link.leftMaxt = 1.0; + link.rightMint = 0.0; + link.rightMaxt = 1.0; + + link.curvatureStrength = road.curvatureStrength; + link.minStep = road.minStep; + link.maxStep = road.maxStep; + + + link.lamps = (LampProperties *)(uintptr_t)lamps.size(); + link.lampsCount = road.lamps.size(); + + for (int j = 0; j < road.lamps.size(); j++) + { + splineclass::RoadData::Lamp &lm = road.lamps[j]; + LampProperties &lamp = lamps.push_back(); + lamp.roadOffset = lm.roadOffset; + lamp.eachSize = lm.eachSize; + lamp.typeId = (int)(intptr_t)lm.entity; + lamp.rotateToRoad = lm.rotateToRoad; + lamp.additionalHeightOffset = lm.additionalHeightOffset; + lamp.placementType = lm.placementType; + } + + if (link.lampsCount) + link.flags |= LinkProperties::GENERATE_LAMPS; + + link.leftWallHeight = road.leftWallHeight; + link.rightWallHeight = road.rightWallHeight; + link.centerBorderHeight = road.centerBorderHeight; + link.leftBorderHeight = road.leftBorderHeight; + link.rightBorderHeight = road.rightBorderHeight; + link.leftHammerYOffs = road.leftHammerYOffs; + link.leftHammerHeight = road.leftHammerHeight; + link.rightHammerYOffs = road.rightHammerYOffs; + link.rightHammerHeight = road.rightHammerHeight; + link.centerHammerYOffs = road.centerHammerYOffs; + link.centerHammerHeight = road.centerHammerHeight; + link.bridgeRoadThickness = road.bridgeRoadThickness; + link.bridgeStandHeight = road.bridgeStandHeight; + + link.walkablePartVScale = road.walkablePartVScale; + link.walkablePartUScale = road.walkablePartUScale; + +#undef GET_MAT_COND +} +static void addLinkProps(splineclass::RoadData &road, LinkProperties &link, Tab &lamps, ObjLibMaterialListMgr &mat_mgr, + int pid1, int pid2) +{ + addInvariantLinkProps(road, NULL, NULL, 0, 0, 0, link, lamps, mat_mgr); + link.pointId1 = pid1; + link.pointId2 = pid2; +} + +static void recalcRoadsLighting(StaticGeometryContainer &geom) +{ + ISceneLightService *ltService = DAGORED2->queryEditorInterface(); + if (!ltService) + return; + + Color3 ltCol1, ltCol2, ambCol; + Point3 ltDir1, ltDir2; + Point3 normal; + + ltService->getDirectLight(ltDir1, ltCol1, ltDir2, ltCol2, ambCol); + + for (int ni = 0; ni < geom.nodes.size(); ++ni) + { + const StaticGeometryNode *node = geom.nodes[ni]; + + if (node && node->mesh) + { + Mesh &mesh = node->mesh->mesh; + + mesh.cvert.resize(mesh.face.size() * 3); + mesh.cface.resize(mesh.face.size()); + + for (int f = 0; f < mesh.face.size(); ++f) + { + for (unsigned v = 0; v < 3; ++v) + { + normal = mesh.vertnorm[mesh.facengr[f][v]]; + + const int vi = f * 3 + v; + + Color3 resColor = ambCol; + real k = normal * ltDir1; + if (k > 0) + resColor += ltCol1 * k; + k = normal * ltDir2; + if (k > 0) + resColor += ltCol2 * k; + + mesh.cvert[vi] = ::color4(resColor, 1); + mesh.cface[f].t[v] = vi; + } + } + } + } +} + +static void applyRoadShapes(const splineclass::RoadData *asset) +{ +#define SET_SHAPE(x, y) \ + if (x) \ + { \ + roadbuildertool::RoadShape shape; \ + shape.isClosed = x->isClosed; \ + shape.uScale = x->uScale; \ + shape.vScale = x->vScale; \ + shape.pointsCount = x->points.size(); \ + shape.points = (roadbuildertool::RoadShape::ShapePoint *)x->points.data(); \ + road_builder->setRoadShape(y, &shape); \ + } \ + else \ + road_builder->setRoadShape(y, NULL); + + SET_SHAPE(asset->borderShape, SHAPE_BORDER); + SET_SHAPE(asset->sideShape, SHAPE_SIDE); + SET_SHAPE(asset->roadShape, SHAPE_ROAD); + SET_SHAPE(asset->sideHammerShape, SHAPE_SIDE_HAMMER); + SET_SHAPE(asset->centerHammerShape, SHAPE_CENTER_HAMMER); + SET_SHAPE(asset->centerBorderShape, SHAPE_CENTER_BORDER); + SET_SHAPE(asset->wallShape, SHAPE_WALL); + SET_SHAPE(asset->bridgeShape, SHAPE_BRIDGE); + +#undef SET_SHAPE +} + +void SplineObject::generateRoadSegments(int start_idx, int end_idx, const splineclass::RoadData *asset_prev, + splineclass::RoadData *asset, const splineclass::RoadData *asset_next) +{ + if (!loadRoadBuilderDll()) + return; + if (!prepareRoadBuilder()) + return; + + LinkProperties link; + PointProperties pts[2]; + Tab lamps(tmpmem); + Geometry geomOut; + ObjLibMaterialListMgr matMgr; + MaterialDataList *mat = NULL; + BezierSplineInt3d *seg_cur = NULL, *seg_prev = NULL, *seg_next = NULL; + + if (asset) + { + addInvariantPointProps(*asset, pts[0], matMgr); + addInvariantPointProps(*asset, pts[1], matMgr); + addInvariantLinkProps(*asset, NULL, NULL, 0, 0, 0, link, lamps, matMgr); + mat = matMgr.buildMaterialDataList(); + applyRoadShapes(asset); + } + + for (int i = start_idx; i < end_idx; i++) + { + if (!asset || points[i]->isCross || points[i + 1]->isCross) + { + if (points[i]->getRoadGeom()) + HmapLandObjectEditor::geomBuildCntRoad++; + points[i]->removeRoadGeom(); + continue; + } + if (!points[i]->segChanged && !points[i + 1]->segChanged) + continue; + + // DAEDITOR3.conNote("build segment %p/%d", this, i); + lamps.clear(); + + seg_cur = &bezierSpline.segs[i]; + if (i > 0) + seg_prev = &bezierSpline.segs[i - 1]; + else + seg_prev = isClosed() ? &bezierSpline.segs.back() : NULL; + if (i + 1 < bezierSpline.segs.size()) + seg_next = &bezierSpline.segs[i + 1]; + else + seg_next = isClosed() ? &bezierSpline.segs[0] : NULL; + + addInvariantLinkProps(*asset, i == start_idx ? asset_prev : NULL, i + 1 == end_idx ? asset_next : NULL, seg_cur->len, + seg_prev ? seg_prev->len : 0.0, seg_next ? seg_next->len : 0.0, link, lamps, matMgr); + link.pointId1 = 0; + link.pointId2 = 1; + + pts[0].pos = points[i]->getPt(); + pts[0].inHandle = points[i]->getBezierIn(); + pts[0].outHandle = points[i]->getBezierOut(); + computePointUpDir(i == start_idx ? asset_prev : asset, asset, pts[0], points[i], seg_prev, seg_cur); + + pts[1].pos = points[i + 1]->getPt(); + pts[1].inHandle = points[i + 1]->getBezierIn(); + pts[1].outHandle = points[i + 1]->getBezierOut(); + if (i + 1 == end_idx && asset_next) + { + pts[1].linesNumber = asset_next->linesCount; + pts[1].lineWidth = asset_next->lineWidth; + } + computePointUpDir(asset, i + 1 == end_idx ? asset_next : asset, pts[1], points[i + 1], seg_cur, seg_next); + + GeomObject &roadGeom = points[i]->getClearedRoadGeom(); + + buildSegments(geomOut, *roadGeom.getGeometryContainer(), mat, make_span(&link, 1), lamps, make_span_const(pts, 2), {}); + roadGeom.setTm(TMatrix::IDENT); + + recalcRoadsLighting(*roadGeom.getGeometryContainer()); + roadGeom.notChangeVertexColors(true); + dagGeom->geomObjectRecompile(roadGeom); + roadGeom.notChangeVertexColors(false); + HmapLandObjectEditor::geomBuildCntRoad++; + points[i]->updateRoadBox(); + } + + del_it(mat); + road_builder->release(); +} + +void HmapLandObjectEditor::updateCrossRoadGeom() +{ + if (!loadRoadBuilderDll()) + return; + if (!prepareRoadBuilder()) + return; + + Tab links(tmpmem); + Tab pts(tmpmem); + Tab lamps(tmpmem); + Geometry geomOut; + ObjLibMaterialListMgr matMgr; + MaterialDataList *mat = NULL; + splineclass::RoadData *asset = NULL, *assetPrev = NULL, *central_asset = NULL; + + for (int i = 0; i < crossRoads.size(); i++) + { + if (!crossRoads[i]->changed) + continue; + // DAEDITOR3.conNote("build cross %d", i); + crossRoads[i]->changed = false; + + links.clear(); + pts.clear(); + lamps.clear(); + int idc = -1, c_rank = -1; + for (int j = crossRoads[i]->points.size() - 1; j >= 0; j--) + { + SplinePointObject *p = crossRoads[i]->points[j]; + SplineObject *s = p->spline; + + if (!getRoad(p)) + continue; + + assetPrev = asset = NULL; + for (int k = 0; k < s->points.size(); k++) + { + assetPrev = asset; + asset = getRoad(s->points[k]); + + if (s->points[k] == p && (asset || assetPrev)) + { + if (idc == -1) + { + central_asset = asset ? asset : assetPrev; + addPointProps(*central_asset, pts.push_back(), matMgr, p); + c_rank = asset ? asset->roadRankId : assetPrev->roadRankId; + idc = pts.size() - 1; + } + else if (c_rank < (asset ? asset->roadRankId : assetPrev->roadRankId)) + { + central_asset = asset ? asset : assetPrev; + addPointProps(*central_asset, pts[idc], matMgr, p); + c_rank = asset ? asset->roadRankId : assetPrev->roadRankId; + } + + if (k > 0 && assetPrev) + { + addPointProps(*assetPrev, pts.push_back(), matMgr, s->points[k - 1]); + addLinkProps(*assetPrev, links.push_back(), lamps, matMgr, pts.size() - 1, idc); + } + if (k + 1 < s->points.size() && asset) + { + asset = getRoad(s->points[k]); + if (asset) + { + addPointProps(*asset, pts.push_back(), matMgr, s->points[k + 1]); + addLinkProps(*asset, links.push_back(), lamps, matMgr, idc, pts.size() - 1); + } + } + break; + } + } + } + + if (idc == -1) + { + // not really crossroads - just cross of 2 splines + if (crossRoads[i]->getRoadGeom()) + HmapLandObjectEditor::geomBuildCntRoad++; + crossRoads[i]->removeRoadGeom(); + continue; + } + + mat = matMgr.buildMaterialDataList(); + applyRoadShapes(central_asset); + + GeomObject &roadGeom = crossRoads[i]->getClearedRoadGeom(); + buildSegments(geomOut, *roadGeom.getGeometryContainer(), mat, make_span(links), lamps, pts, {}); + roadGeom.setTm(TMatrix::IDENT); + + recalcRoadsLighting(*roadGeom.getGeometryContainer()); + roadGeom.notChangeVertexColors(true); + dagGeom->geomObjectRecompile(roadGeom); + roadGeom.notChangeVertexColors(false); + + del_it(mat); + HmapLandObjectEditor::geomBuildCntRoad++; + } +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/colorGenScriptDoc.txt b/prog/tools/sceneTools/daEditorX/HeightmapLand/colorGenScriptDoc.txt new file mode 100644 index 000000000..bb3074b35 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/colorGenScriptDoc.txt @@ -0,0 +1,304 @@ + + +*** Çàäà÷à ñêðèïòà è òåðìèíû + +Ñêðèïò èñïîëüçóåòñÿ äëÿ ãåíåðàöèè öâåòîâ ïîâåðõíîñòè è òèïîâ åå äåòàëèçàöèè ïî êàðòå âûñîò (heightmap). +Äëÿ êàæäîé òî÷êè êàðòû âûçûâàåòñÿ ôóíêöèÿ ñêðèïòà, êîòîðàÿ èñïîëüçóÿ äîñòóïíûå äàííûå +î êàðòå (âûñîòó, íàêëîí, êðèâèçíó, ìàñêè è ò.ä.) îïðåäåëÿåò â ýòîé òî÷êå öâåò è òèï äåòàëèçàöèè. + +Öâåò - öâåò ïîâåðõíîñòè, áåç îñâåùåíèÿ (diffuse), â ñêðèïòå õðàíèòñÿ êàê 24-áèòíûé öâåò, +ïî 8 áèò íà êîìïîíåíòó. + +Òèï äåòàëèçàöèè, îí æå íîìåð òåêñòóðû äåòàëèçàöèè - îïðåäåëÿåò êàêîé ôàêòóðîé áóäåò +äåòàëèçîâàòüñÿ ïîâåðõíîñòü âáëèçè. + +Öâåò è òèï äåòàëèçàöèè ïàêóþòñÿ âìåñòå â 32-áèòíîå çíà÷åíèå (int), ÷òîáû ñ íèìè áûëî +ïðîñòî è áûñòðî ðàáîòàòü.  îïèñàíèè ôóíêöèé "öâåò" óïîòðåáëÿåòñÿ â îñíîâíîì â ýòîì ñìûñëå, +êàê îáúåäèíåíèå öâåòà è òèïà äåòàëèçàöèè. +(Ôàêòè÷åñêè, äëÿ õðàíåíèÿ òèïà èñïîëüçóåòñÿ àëüôà 32-áèòíîãî öâåòà.) + + + +*** Ñòðóêòóðà è ïàðàìåòðû ñêðèïòà + + ñêðèïòå äîëæíû áûòü äâå ôóíêöèè: getParamsList è getGenerator. + + +Ïåðâàÿ âîçâðàùàåò ñïèñîê ïàðàìåòðîâ, ê ïðèìåðó: + +function getParamsList() +{ + local list= + [ + {name= "fullGrassAngle", type="real", value=30}, + {name="startGrassAngle", type="real", value=45}, + + {name="grassTexture", type="image", value="grass"}, + {name="dissolveMap", type="image", value="noise1"}, + + {name="dirtTexture", type="image", value="dirtMap"}, + ]; + return list; +} + +Ñïèñîê - ìàññèâ òàáëèö, êàæäàÿ òàáëèöà îïèñûâàåò îäèí ïàðàìåòð. + + êàæäîé òàáëèöå (êàæäîì îïèñàíèè ïàðàìåòðà) äîëæíû áûòü: +name="..." - èìÿ ïàðàìåòðà, +type="..." - òèï ïàðàìåòðà. +value - íå îáÿçàòåëüíî, ýòî çíà÷åíèå ïàðàìåòðà ïî óìîë÷àíèþ. +Äëÿ òèïà "image" value ïðåäñòàâëÿåò èç ñåáÿ òàáëèöó ñî ñëåäóþùèìè ïîëÿìè (êàæäîå èç íèõ íåîáÿçàòåëüíî): +"imageName" - string +"mappingType", "detailType" - int +"tileX", "tileY", "offsetX", "offsetY" - real +"clampU", "clampV", "flipU", "flipV", "swapUV" - bool + + +Òèïû ïàðàìåòðîâ: + +"int" èëè "integer" - öåëî÷èñëåííûé. +"real" èëè "float" - âåùåñòâåííîå ÷èñëî. +"color" - 32-áèòíûé öâåò. +"image" - èçîáðàæåíèå èëè ìàñêà. + + +Ïàðàìåòðû èç ýòîãî ñïèñêà ìîæíî íàñòðàèâàòü â ïàíåëè ðåäàêòîðà, èõ çíà÷åíèÿ ñîõðàíÿþòñÿ â ïðîåêòå. +Ïåðåä âûçîâîì ôóíêöèè getGenerator çíà÷åíèÿ ïàðàìåòðîâ âûñòàâëÿþòñÿ â ñêðèïò êàê ãëîáàëüíûå ïåðåìåííûå. + + +Âòîðàÿ ôóíêöèÿ - getGenerator - äîëæíà âîçâðàùàòü ôóíêöèþ, ãåíåðèðóþùóþ öâåòà è òèïû äåòàëèçàöèè. +Ïðèìåð: + +function getGenerator() +{ + local fullGrassCos=cos(degToRad( fullGrassAngle)); + local startGrassCos=cos(degToRad(startGrassAngle)); + + return function() : (fullGrassCos, startGrassCos) + { + local normalY=getNormalY(); + + // base 'dirt' / 'stone' + local result=sampleImage(dirtTexture); + + // add grass by angle + result=dissolveOver(result, + sampleImage(grassTexture), + smoothStep( calcBlendK(startGrassCos, fullGrassCos, normalY) ), + sampleMask(dissolveMap)); + + return result; + } +} + +Êàê âèäíî, ôóíêöèÿ getGenerator ïðåäðàñ÷èòûâàåò çíà÷åíèÿ fullGrassCos è startGrassCos, êîòîðûå +ïîòîì áóäóò èñïîëüçîâàòüñÿ â âû÷èñëåíèÿõ è ïåðåäàþòñÿ â ôóíêöèþ ãåíåðàöèè êàê "ñâîáîäíûå ïåðåìåííûå" +(free variables, êîíñòðóêöèÿ ": (...)", ñì. îïèñàíèå ÿçûêà Squirrel). +Ýòîãî ìîæíî è íå äåëàòü, âû÷èñëÿÿ èõ êàæäûé ðàç, íî òàê êîä ïîíÿòíåå è ðàáîòàåò áûñòðåå +(ñì. ðàçäåë ïðî îïòèìèçàöèþ ñêðèïòà). + +Ôóíêöèÿ ãåíåðàöèè âîçâðàùàåò 32-áèòíîå çíà÷åíèå (int), ñîäåðæàùåå öâåò è òèï äåòàëèçàöèè. + + + +*** Îïèñàíèå ôóíêöèé, äîñòóïíûõ ñêðèïòó + +Êðîìå îïèñàííûõ, äîñòóïíû òàêæå ôóíêöèè ñòàíäàðòíûõ áèáëèîòåê Squirrel (íàïðèìåð, ìàòåìàòè÷åñêèå). + + +getNormalX() +getNormalY() +getNormalZ() + +Âîçâðàùàþò ðàçëè÷íûå êîìïîíåíòû âåêòîðà íîðìàëè. +Íàèáîëåå èíòåðåñíà getNormalY(), ò.ê. ôàêòè÷åñêè ýòî êîñèíóñ óãëà íàêëîíà ïîâåðõíîñòè +îòíîñèòåëüíî ãîðèçîíòàëüíîé ïëîñêîñòè. + + + +getHeight() + +Âîçâðàùàåò àáñîëþòíóþ âûñîòó ïîâåðõíîñòè, â ìèðîâûõ êîîðäèíàòàõ. + + + +getCurvature() + +Âîçâðàùàåò êðèâèçíó ïîâåðõíîñòè. 0 - ïëîñêàÿ, ïîëîæèòåëüíûå çíà÷åíèÿ - âîãíóòàÿ, îòðèöàòåëüíûå - âûïóêëàÿ. + + + +getHeightMapX() +getHeightMapZ() + +Âîçâðàùàþò êîîðäèíàòû òåêóùåé òî÷êè (float) â ñåòêå heightmap-à. + + + +getHeightMapSizeX() +getHeightMapSizeZ() + +Âîçâðàùàþò ðàçìåðû ñåòêè heightmap-à (int). + + + +makeColor(red, green, blue, type) + red (int) - êðàñíûé, îò 0 äî 255 (çíà÷åíèÿ áîëüøå èëè ìåíüøå îáðåçàþòñÿ äî êðàéíèõ). +green (int) - çåëåíûé, îò 0 äî 255 (çíà÷åíèÿ áîëüøå èëè ìåíüøå îáðåçàþòñÿ äî êðàéíèõ). + blue (int) - ñèíèé, îò 0 äî 255 (çíà÷åíèÿ áîëüøå èëè ìåíüøå îáðåçàþòñÿ äî êðàéíèõ). + type (int) - òèï äåòàëèçàöèè, îí æå íîìåð òåêñòóðû äåòàëèçàöèè. + +Ñîáèðàåò öâåò èç êîìïîíåíò è âîçâðàùàåò åãî (êàê int). + + + +setType(color, type) +color (int) - öâåò + òèï. + type (int) - íîâîå çíà÷åíèå òèïà äåòàëèçàöèè. + +Çàìåíÿåò çíà÷åíèå òèïà íà íîâîå è âîçâðàùàåò íîâûé "öâåò + òèï" ñ ýòèì çíà÷åíèåì. + + + +getType(color) +color (int) - öâåò + òèï. + +Âîçâðàùàåò òèï äåòàëèçàöèè (int). + + + +blendColors(color1, color2, t) +color1 (int) - ïåðâûé öâåò. +color2 (int) - âòîðîé öâåò. + t (float) - ïàðàìåòð ñìåùèâàíèÿ, îò 0 (ïåðâûé öâåò) äî 1 (âòîðîé öâåò). + +Èíòåðïîëèðóåò öâåò îò ïåðâîãî äî âòîðîãî ïî óêàçàííîìó ïàðàìåòðó t. +Òèï áåðåòñÿ èç color1, åñëè t<=0.5, èíà÷å èç color2. + +Ñì. òàêæå dissolveOver. + + + +mulColors(color1, color2) +color1 (int) - ïåðâûé öâåò. +color2 (int) - âòîðîé öâåò. + +Ïåðåìíîæàåò öâåòà, âîçâðàùàåò ïîëó÷åííûé öâåò. +Òèï áåðåòñÿ èç color1. + + + +mulColors2x(color1, color2) +color1 (int) - ïåðâûé öâåò. +color2 (int) - âòîðîé öâåò. + +Ïåðåìíîæàåò öâåòà è óìíîæàåò ðåçóëüòàò íà 2, âîçâðàùàåò ïîëó÷åííûé öâåò. +Òèï áåðåòñÿ èç color1. + + + +dissolveOver(color1, color2, t, mask) +color1 (int) - ïåðâûé öâåò. +color2 (int) - âòîðîé öâåò. + t (float) - ïàðàìåòð ñìåùèâàíèÿ, îò 0 (ïåðâûé öâåò) äî 1 (âòîðîé öâåò). +mask (float) - çíà÷åíèå ìàñêè dissolve â òåêóùåé òî÷êå. + +Âûáèðàåò è âîçâðàùàåò ëèáî ïåðâûé, ëèáî âòîðîé öâåò, â çàâèñèìîñòè îò çíà÷åíèé t è mask: +Åñëè t<=0 - ïåðâûé. +Åñëè t>=1 - âòîðîé. +Åñëè t=1 âîçâðàùàåò 1. +Èíà÷å âîçâðàùàåò çíà÷åíèå îò 0 äî 1, ïî ôîðìóëå êóáè÷åñêîãî ñïëàéíà (3-2*t)*t*t. + +Îñîáåííîñòè ýòîãî ñïëàéíà: +Ïðè t==0.0 -> 0.0 +Ïðè t==0.5 -> 0.5 +Ïðè t==1.0 -> 1.0 +Ñèììåòðè÷åí îòíîñèòåëüíî 0.5, ïðîèçâîäíûå íà êîíöàõ (0 è 1) ðàâíû íóëþ. + + + +sampleImage(image) +sampleImageAt(image, u, v) +image - èçîáðàæåíèå. +u, v (float) - êîîðäèíàòû â òåêñòóðå (ìàïïèíã). + +Âîçâðàùàåò çíà÷åíèå öâåòà (è òèïà äåòàëèçàöèè) èç óêàçàííîãî èçîáðàæåíèÿ. + ñëó÷àå sampleImage èñïîëüçóåòñÿ ìàïïèíã, óêàçàííûé â íàñòðîéêàõ èçîáðàæåíèÿ. + ñëó÷àå sampleImageAt èñïîëüçóþòñÿ òîëüêî çíà÷åíèÿ íàñòðîåê flip, swapUV è clamp. + + + +sampleMask(image) +sampleMaskAt(image, u, v) +image - èçîáðàæåíèå. +u, v (float) - êîîðäèíàòû â òåêñòóðå (ìàïïèíã). + +Âîçâðàùàåò çíà÷åíèå ìàñêè (float îò 0 äî 1) èç èçîáðàæåíèÿ, èñïîëüçóÿ ÿðêîñòü öâåòà. +Ñì. sampleImage, sampleImageAt. + +sampleMaskAlpha(image) +sampleMaskRed(image) +sampleMaskGreen(image) +sampleMaskBlue(image) + +sampleMaskAlphaAt(image, u, v) +sampleMaskRedAt(image, u, v) +sampleMaskGreenAt(image, u, v) +sampleMaskBlueAt(image, u, v) + +Àíàëîãè÷íî sampleMask è sampleMaskAt, íî âîçâðàùàåò çíà÷åíèå ìàñêè â îäíîì êàíàëå + + + +*** Îïòèìèçàöèÿ ñêðèïòà + +Èñïîëüçóéòå ëîêàëüíûå ïåðåìåííûå (local) ãäå âîçìîæíî, ò.ê. îáðàùåíèå ê íèì ïðîèñõîäèò +ñóùåñòâåííî áûñòðåå, ÷åì ê ãëîáàëüíûì. + + ôóíêöèè ãåíåðàöèè çàïèøèòå âñå èñïîëüçóåìûå ãëîáàëüíûå ïåðåìåííûå è ôóíêöèè â free variables +(êîíñòðóêöèÿ function() : (ñïèñîê ñâîáîäíûõ ïåðåìåííûõ) { êîä } - ñì. îïèñàíèå ÿçûêà Squirrel). +Çíà÷åíèÿ ñâîáîäíûõ ïåðåìåííûõ (free variables) ñîõðàíÿþòñÿ îäèí ðàç ïðè ñîçäàíèè ôóíêöèè è âíóòðè +íåå îáðàùåíèÿ ê íèì òàê æå áûñòðû, êàê ê ëîêàëüíûì ïåðåìåííûì. +Ôóíêöèÿ getGenerator âîçâðàùàåò ôóíêöèþ êàê ðàç äëÿ ýòîãî, ÷òîáû ìîæíî áûëî ñîõðàíèòü çíà÷åíèÿ +ãëîáàëüíûõ ïåðåìåííûõ (ïàðàìåòðîâ ñêðèïòà ïðåæäå âñåãî) â ýòîò ìîìåíò, ïåðåä ãåíåðàöèåé êàðòû. + +Çàïèøèòå â ñâîáîäíûå ïåðåìåííûå â òîì ÷èñëå èñïîëüçóåìûå ôóíêöèè ñêðèïòà, âðîäå getNormalY èëè sampleImage. +Åñëè çàïèøèòå ëèøíåãî - íå ñòðàøíî, ñêîðîñòü ãåíåðàöèè îò ýòîãî ñêîðåå âñåãî íå èçìåíèòñÿ. +À âîò åñëè íå çàïèøèòå - áóäåò îáðàùåíèå ê ãëîáàëüíîé ïåðåìåííîé, êîòîðîå çàìåòíî ìåäëåííåé. + +Âûíîñèòå èç ôóíêöèè ãåíåðàöèè çíà÷åíèÿ, êîòîðûå êîíñòàíòíû äëÿ âñåé êàðòû, èõ ìîæíî ïðåäâû÷èñëèòü +â ôóíêöèè getGenerator (êîòîðàÿ ïðè ãåíåðàöèè âûçûâàåòñÿ òîëüêî îäèí ðàç) è ïåðåäàòü â ôóíêöèþ +ãåíåðàöèè êàê free variables. diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/common.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/common.cpp new file mode 100644 index 000000000..c2c9d7ce4 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/common.cpp @@ -0,0 +1,164 @@ +#include +#include "common.h" + +#include +#include + + +bool objectWasMoved = false, objectWasRotated = false, objectWasScaled = false; + +float triang_area(dag::ConstSpan pts) +{ + int n = pts.size(); + float a = 0.0f; + for (int p = n - 1, q = 0; q < n; p = q++) + { + a += pts[p].x * pts[q].y - pts[q].x * pts[p].y; + } + + return a * 0.5f; +} + + +bool triang_inside_triangle(float Ax, float Ay, float Bx, float By, float Cx, float Cy, float Px, float Py) +{ + float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy; + float cCROSSap, bCROSScp, aCROSSbp; + + ax = Cx - Bx; + ay = Cy - By; + + bx = Ax - Cx; + by = Ay - Cy; + + cx = Bx - Ax; + cy = By - Ay; + + apx = Px - Ax; + apy = Py - Ay; + + bpx = Px - Bx; + bpy = Py - By; + + cpx = Px - Cx; + cpy = Py - Cy; + + aCROSSbp = ax * bpy - ay * bpx; + cCROSSap = cx * apy - cy * apx; + bCROSScp = bx * cpy - by * cpx; + + return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f)); +}; + + +bool triang_snip(dag::ConstSpan pts, int u, int v, int w, int n, int *V) +{ + int p; + float Ax, Ay, Bx, By, Cx, Cy, Px, Py; + + Ax = pts[V[u]].x; + Ay = pts[V[u]].y; + + Bx = pts[V[v]].x; + By = pts[V[v]].y; + + Cx = pts[V[w]].x; + Cy = pts[V[w]].y; + + if (1e-10 > (((Bx - Ax) * (Cy - Ay)) - ((By - Ay) * (Cx - Ax)))) + return false; + + for (p = 0; p < n; p++) + { + if ((p == u) || (p == v) || (p == w)) + continue; + + Px = pts[V[p]].x; + Py = pts[V[p]].y; + + if (triang_inside_triangle(Ax, Ay, Bx, By, Cx, Cy, Px, Py)) + return false; + } + + return true; +} + +bool make_clockwise_coords(dag::Span pts) +{ + int cnt = pts.size(); + + Point2 center = Point2(0, 0); + + for (int i = 0; i < cnt; i++) + center += pts[i]; + + center /= cnt; + + Point2 p1 = center - pts[0]; + Point2 p2 = center - pts[1]; + + Point3 cross = Point3(p1.x, 0, p1.y) % Point3(p2.x, 0, p2.y); + + if (cross.y < 0) + { + Tab tmp(tmpmem_ptr()); + dag::set_allocator(tmp, tmpmem_ptr()); + tmp.resize(cnt); + + tmp = pts; + + for (int i = 0; i < cnt; i++) + pts[i] = tmp[cnt - i - 1]; + + return true; + } + + return false; +} + +bool make_clockwise_coords(dag::Span pts3) +{ + Tab pts(tmpmem); + pts.resize(pts3.size()); + for (int i = 0; i < pts3.size(); i++) + pts[i] = Point2(pts3[i].x, pts3[i].z); + + int cnt = pts.size(); + + Point2 center = Point2(0, 0); + + for (int i = 0; i < cnt; i++) + center += pts[i]; + + center /= cnt; + + Point2 p1 = center - pts[0]; + Point2 p2 = center - pts[1]; + + Point3 cross = Point3(p1.x, 0, p1.y) % Point3(p2.x, 0, p2.y); + + if (cross.y < 0) + { + Tab tmp(tmpmem_ptr()); + dag::set_allocator(tmp, tmpmem_ptr()); + tmp.resize(cnt); + + tmp = pts3; + + for (int i = 0; i < cnt; i++) + pts3[i] = tmp[cnt - i - 1]; + + return true; + } + + return false; +} + +bool lines_inters_ignore_Y(Point3 &pf1, Point3 &pf2, Point3 &ps1, Point3 &ps2) +{ + real x1 = pf1.x, z1 = pf1.z, x2 = pf2.x, z2 = pf2.z; + real x3 = ps1.x, z3 = ps1.z, x4 = ps2.x, z4 = ps2.z; + + return (((x3 - x1) * (z2 - z1) - (z3 - z1) * (x2 - x1)) * ((x4 - x1) * (z2 - z1) - (z4 - z1) * (x2 - x1)) <= 0) && + (((x1 - x3) * (z4 - z3) - (z1 - z3) * (x4 - x3)) * ((x2 - x3) * (z4 - z3) - (z2 - z3) * (x4 - x3)) <= 0); +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/common.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/common.h new file mode 100644 index 000000000..75ae70c7a --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/common.h @@ -0,0 +1,22 @@ +#ifndef __SPLINES_COMMON__ +#define __SPLINES_COMMON__ +#pragma once + + +#include +#include +#include +#include + + +extern bool objectWasMoved, objectWasRotated, objectWasScaled; + +bool triang_inside_triangle(float Ax, float Ay, float Bx, float By, float Cx, float Cy, float Px, float Py); +float triang_area(dag::ConstSpan pts); +bool triang_snip(dag::ConstSpan pts, int u, int v, int w, int n, int *V); +bool make_clockwise_coords(dag::Span pts); +bool make_clockwise_coords(dag::Span pts3); + +bool lines_inters_ignore_Y(Point3 &pf1, Point3 &pf2, Point3 &ps1, Point3 &ps2); + +#endif // __SPLINES_COMMON__ diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/crossRoad.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/crossRoad.h new file mode 100644 index 000000000..90767bc1e --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/crossRoad.h @@ -0,0 +1,30 @@ +#pragma once + + +class SplinePointObject; + +class CrossRoadData +{ +public: + PtrTab points; + GeomObject *geom; + bool changed; + + CrossRoadData(); + ~CrossRoadData(); + + bool checkCrossRoad(); + + GeomObject *getRoadGeom() { return geom; } + + GeomObject &getClearedRoadGeom(); + void removeRoadGeom(); + + int find(SplinePointObject *p) const + { + for (int i = 0; i < points.size(); i++) + if (points[i] == p) + return i; + return -1; + } +}; diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/editorLandRayTracer.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/editorLandRayTracer.h new file mode 100644 index 000000000..34495fe4b --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/editorLandRayTracer.h @@ -0,0 +1,7 @@ +#pragma once +#include +class EditorLandRayTracer : public BaseLandRayTracer +{ +public: + EditorLandRayTracer(IMemAlloc *allocator = midmem) : BaseLandRayTracer(allocator) {} +}; diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/entityCopyDlg.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/entityCopyDlg.cpp new file mode 100644 index 000000000..884abdde3 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/entityCopyDlg.cpp @@ -0,0 +1,50 @@ +#include "entityCopyDlg.h" + +#include + +enum +{ + PID_CLONE_PREFIX = 11000, + PID_CLONE_COUNT, + PID_CLONE_SEED, +}; + + +//============================================================================== +CopyDlg::CopyDlg(String &clone_name, int &clone_count, bool &clone_seed) : + cloneName(clone_name), cloneCount(clone_count), cloneSeed(clone_seed), mDialog(NULL) +{ + mDialog = DAGORED2->createDialog(hdpi::_pxScaled(290), hdpi::_pxScaled(200), "Clone object"); + + PropPanel2 &panel = *mDialog->getPanel(); + + panel.createEditBox(PID_CLONE_PREFIX, "Name of clone(s) (empty - automatic):", cloneName); + panel.createEditInt(PID_CLONE_COUNT, "Count of clones:", 1); + panel.createCheckBox(PID_CLONE_SEED, "Clone the same random seed", cloneSeed); +} + + +CopyDlg::~CopyDlg() { del_it(mDialog); } + +//================================================================================================== + +bool CopyDlg::execute() +{ + int ret = mDialog->showDialog(); + + if (ret == DIALOG_ID_OK) + { + PropPanel2 &panel = *mDialog->getPanel(); + + cloneName = panel.getText(PID_CLONE_PREFIX); + cloneCount = panel.getInt(PID_CLONE_COUNT); + cloneSeed = panel.getBool(PID_CLONE_SEED); + + if (cloneCount < 1) + cloneCount = 1; + + return true; + } + + return false; +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/entityCopyDlg.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/entityCopyDlg.h new file mode 100644 index 000000000..0f87cb128 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/entityCopyDlg.h @@ -0,0 +1,24 @@ +#ifndef __GAIJIN_PREFABS_CLONE_DLG__ +#define __GAIJIN_PREFABS_CLONE_DLG__ +#pragma once + +#include + +class CopyDlg +{ +public: + CopyDlg(String &clone_name, int &clone_count, bool &clone_seed); + ~CopyDlg(); + + bool execute(); + +private: + String &cloneName; + int &cloneCount; + bool &cloneSeed; + + CDialogWindow *mDialog; +}; + + +#endif //__GAIJIN_PREFABS_CLONE_DLG__ diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/example1.nut b/prog/tools/sceneTools/daEditorX/HeightmapLand/example1.nut new file mode 100644 index 000000000..08aac35ed --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/example1.nut @@ -0,0 +1,107 @@ +let PI = ::PI +let cos = ::cos +let makeColor = ::makeColor +let mulColors = ::mulColors +let mulColors2x = ::mulColors2x +let sampleImage = ::sampleImage +let blendColors = ::blendColors + +let degToRad = @(a) a*PI/180 + +::getParamsList <- function() +{ + local list= + [ + {name= "fullGrassAngle", type="real", value=30}, + {name="startGrassAngle", type="real", value=45}, + {name="maxGrassHeight", type="real", value=50}, + {name="grassFadeDist", type="real", value=20}, + + {name="sandCurvature", type="real", value=1}, + + {name= "fullSnowAngle", type="real", value=30}, + {name="startSnowAngle", type="real", value=45}, + {name="minSnowHeight", type="real", value=150}, + {name="snowFadeDist", type="real", value=50}, + + {name="grassTexture", type="image", value="grass"}, + {name="grassGrad", type="image", value="grassGrad"}, + {name="dissolveMap", type="image", value="noise1"}, + + {name="dirtTexture", type="image", value="dirtMap"}, + {name="dirtGradient", type="image", value="dirtGrad"}, + + {name="sandTexture", type="image", value="sand"}, + + {name="snowTexture", type="image", value="snow"}, + ]; + return list; +} + + +::getGenerator <- function() +{ + local maxGrassHeight = ::maxGrassHeight + local dirtTexture = ::dirtTexture + local dirtGradient = ::dirtGradient + local sandTexture = ::sandTexture + local grassTexture = ::grassTexture + local dissolveMap = ::dissolveMap + local grassGrad = ::grassGrad + local snowTexture = ::snowTexture + + local fullGrassCos=cos(degToRad(::fullGrassAngle)); + local startGrassCos=cos(degToRad(::startGrassAngle)); + local minGrassHeight=maxGrassHeight-::grassFadeDist; + + local sandCurv=::sandCurvature/100.0; + + local fullSnowCos=cos(degToRad( fullSnowAngle)); + local startSnowCos=cos(degToRad(startSnowAngle)); + local maxSnowHeight=minSnowHeight+snowFadeDist; + + local sampleImageAt = ::sampleImageAt + local sampleMask = ::sampleMask + local sampleMask1 = ::sampleMask1 + local sampleMask8 = ::sampleMask8 + local getHeight = ::getHeight + local getNormalY = ::getNormalY + local getCurvature = ::getCurvature + local blendColors = ::blendColors + local dissolveOver = ::dissolveOver + local calcBlendK = ::calcBlendK + local smoothStep = ::smoothStep + local noiseStrength = ::noiseStrength + + return function() + { + local normalY=getNormalY(); + local height=getHeight(); + local curvature=getCurvature(); + + // base 'dirt' / 'stone' + local res=mulColors2x(sampleImage(dirtTexture), sampleImage(dirtGradient)); + + // add 'sand' by curvature + res=blendColors(res, sampleImage(sandTexture), + calcBlendK(0.0, sandCurv, curvature) ); + + // calc coordinate for grass color gradient (by angle) + local grassG=calcBlendK(startGrassCos, 1.0, normalY); + + // add grass by angle and fade by height + res=dissolveOver(res, + mulColors2x(sampleImage(grassTexture), sampleImageAt(grassGrad, grassG, grassG)), + smoothStep( calcBlendK(startGrassCos, fullGrassCos, normalY) ) + * smoothStep( calcBlendK(maxGrassHeight, minGrassHeight, height) ), + sampleMask(dissolveMap)); + + // add snow by angle and fade by height + res=dissolveOver(res, sampleImage(snowTexture), + smoothStep( calcBlendK(startSnowCos, fullSnowCos, normalY) ) + * smoothStep( calcBlendK(minSnowHeight, maxSnowHeight, height) ), + sampleMask(dissolveMap)); + + return res; + } +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/gpuGrassPanel.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/gpuGrassPanel.cpp new file mode 100644 index 000000000..0a52ac0bf --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/gpuGrassPanel.cpp @@ -0,0 +1,617 @@ +#include "gpuGrassPanel.h" +#include "hmlCm.h" +#include "de3_gpuGrassService.h" +#include +#include "GPUGrassTypePID.h" +#include "GPUGrassDecalPID.h" +#include +#include +#include +#include +#include +#include + +using hdpi::_pxScaled; + +namespace +{ +Tab getDecalTypeNames(const GPUGrassDecal &decal) +{ + Tab types; + for (const auto &channel : decal.channels) + types.push_back(String(channel.first.c_str())); + return types; +} + +void removeDecalType(GPUGrassDecal &decal, const char *name, DataBlock *blk) +{ + if (!decal.channels.empty()) + decal.channels.erase( + eastl::remove_if(decal.channels.begin(), decal.channels.end(), [name](const auto &channel) { return channel.first == name; }), + decal.channels.end()); + + DataBlock *decalsBlk = blk->getBlockByName("decals"); + DataBlock *decalBlk = decalsBlk->getBlockByName(decal.name.c_str()); + decalBlk->removeParam(name); +} +} // namespace +void GPUGrassPanel::fillPanel(IGPUGrassService *service, DataBlock *grass_blk, PropPanel2 &panel) +{ + G_ASSERT_RETURN(service, ); + G_ASSERT_RETURN(grass_blk, ); + srv = service; + blk = grass_blk; + grassPanel = panel.createGroup(PID_GPU_GRASS_GROUP, "Grass"); + grassPanel->createCheckBox(PID_GPU_GRASS_ENABLE, "Enable grass", srv->isGrassEnabled()); + grassPanel->createButton(PID_GPU_GRASS_LOADFROM_LEVELBLK, "Load from level.blk"); + grassPanel->createFileEditBox(PID_GPU_GRASS_TYPES, "Types", blk->getStr("grass_types", "")); + grassPanel->createFileEditBox(PID_GPU_GRASS_MASKS, "Masks", blk->getStr("grass_masks", "")); + grassPanel->createTrackFloat(PID_GPU_GRASS_GRID_SIZE, "Grid size", blk->getReal("grass_grid_size"), 0.0, 1.0, 0.025); + grassPanel->createEditFloat(PID_GPU_GRASS_DISTANCE, "Distance", blk->getReal("grass_distance")); + grassPanel->createEditInt(PID_GPU_GRASS_MASK_RESOLUTION, "Mask resolution", blk->getInt("grassMaskResolution")); + grassPanel->createEditFloat(PID_GPU_GRASS_HOR_SIZE_MUL, "Horizontal size mul", blk->getReal("hor_size_mul")); + grassPanel->createStatic(0, "Type"); + grassPanel->createSeparator(0, false); + grassPanel->createButton(PID_GPU_GRASS_ADD_TYPE, "Add...", srv->getTypeCount() < GRASS_MAX_TYPES); + grassPanel->createButton(PID_GPU_GRASS_REMOVE_TYPE, "Remove...", srv->getTypeCount(), false); + grassPanel->createButton(PID_GPU_GRASS_RENAME_TYPE, "Rename...", srv->getTypeCount(), false); + + for (int i = 0; i < srv->getTypeCount(); ++i) + { + GPUGrassType &type = srv->getType(i); + if (type.name == "nograss") + continue; + int basePID = PID_GPU_GRASS_TYPE_START + i * (int)GPUGrassTypePID::COUNT; + PropertyContainerControlBase *typePanel = grassPanel->createGroup(basePID + (int)GPUGrassTypePID::NAME, type.name.c_str()); + typePanel->createFileButton(basePID + (int)GPUGrassTypePID::DIFFUSE, "Diffuse", type.diffuse.c_str()); + typePanel->createFileButton(basePID + (int)GPUGrassTypePID::NORMAL, "Normal", type.normal.c_str()); + typePanel->createEditInt(basePID + (int)GPUGrassTypePID::VARIATIONS, "Variations", type.variations); + typePanel->createTrackFloat(basePID + (int)GPUGrassTypePID::HEIGHT, "Height", type.height, 0.0f, 1.0f, 0.05f); + typePanel->createTrackFloat(basePID + (int)GPUGrassTypePID::SIZE_LOD_MUL, "Size multiplier per lod", type.size_lod_mul, 0.5f, 2.0f, + 0.01f); + typePanel->createTrackFloat(basePID + (int)GPUGrassTypePID::HT_RND_ADD, "Height random add", type.ht_rnd_add, 0.0f, 1.0f, 0.05f); + typePanel->createTrackFloat(basePID + (int)GPUGrassTypePID::HOR_SIZE, "Horizontal size", type.hor_size, 0.0f, 1.0f, 0.05f); + typePanel->createTrackFloat(basePID + (int)GPUGrassTypePID::HOR_SIZE_RND_ADD, "Horizontal size random add", type.hor_size_rnd_add, + 0.0f, 1.0f, 0.05f); + typePanel->createColorBox(basePID + (int)GPUGrassTypePID::COLOR_MASK_R_FROM, "Color mask red from", type.color_mask_r_from); + typePanel->createColorBox(basePID + (int)GPUGrassTypePID::COLOR_MASK_R_TO, "Color mask red to", type.color_mask_r_to); + typePanel->createColorBox(basePID + (int)GPUGrassTypePID::COLOR_MASK_G_FROM, "Color mask green from", type.color_mask_g_from); + typePanel->createColorBox(basePID + (int)GPUGrassTypePID::COLOR_MASK_G_TO, "Color mask green to", type.color_mask_g_to); + typePanel->createColorBox(basePID + (int)GPUGrassTypePID::COLOR_MASK_B_FROM, "Color mask blue from", type.color_mask_b_from); + typePanel->createColorBox(basePID + (int)GPUGrassTypePID::COLOR_MASK_B_TO, "Color mask blue to", type.color_mask_b_to); + typePanel->createTrackFloat(basePID + (int)GPUGrassTypePID::HEIGHT_FROM_WEIGHT_MUL, "Height from weight mul", + type.height_from_weight_mul, 0.0f, 1.0f, 0.05f); + typePanel->createTrackFloat(basePID + (int)GPUGrassTypePID::HEIGHT_FROM_WEIGHT_ADD, "Height from weight add", + type.height_from_weight_add, 0.0f, 1.0f, 0.05f); + typePanel->createTrackFloat(basePID + (int)GPUGrassTypePID::DENSITY_FROM_WEIGHT_MUL, "Density from weight mul", + type.density_from_weight_mul, 0.0f, 1.0f, 0.05f); + typePanel->createTrackFloat(basePID + (int)GPUGrassTypePID::DENSITY_FROM_WEIGHT_ADD, "Density from weight add", + type.density_from_weight_add, 0.0f, 1.0f, 0.05f); + typePanel->createTrackFloat(basePID + (int)GPUGrassTypePID::VERTICAL_ANGLE_MUL, "Vertical angle mul", type.vertical_angle_mul, + 0.0f, 1.0f, 0.05f); + typePanel->createTrackFloat(basePID + (int)GPUGrassTypePID::VERTICAL_ANGLE_ADD, "Vertical angle add", type.vertical_angle_add, -PI, + PI, 0.05f); + typePanel->createTrackFloat(basePID + (int)GPUGrassTypePID::STIFFNESS, "Stiffness", type.stiffness, 0.0f, 1.0f, 0.05f); + typePanel->createCheckBox(basePID + (int)GPUGrassTypePID::HORIZONTAL_GRASS, "Horizontal grass", type.horizontal_grass); + typePanel->createCheckBox(basePID + (int)GPUGrassTypePID::UNDERWATER, "Underwater", type.underwater); + } + + grassPanel->createStatic(0, "Decal"); + grassPanel->createSeparator(0, false); + grassPanel->createButton(PID_GPU_GRASS_ADD_DECAL, "Add...", srv->getDecalCount() < GRASS_MAX_CHANNELS); + grassPanel->createButton(PID_GPU_GRASS_REMOVE_DECAL, "Remove...", srv->getDecalCount(), false); + grassPanel->createButton(PID_GPU_GRASS_RENAME_DECAL, "Rename...", srv->getDecalCount(), false); + for (int i = 0; i < srv->getDecalCount(); ++i) + { + GPUGrassDecal &decal = srv->getDecal(i); + int basePID = PID_GPU_GRASS_DECAL_START + i * (int)GPUGrassDecalPID::COUNT; + PropertyContainerControlBase *decalPanel = grassPanel->createGroup(basePID + (int)GPUGrassDecalPID::NAME, decal.name.c_str()); + decalPanel->createEditInt(basePID + (int)GPUGrassDecalPID::ID, "Id", decal.id); + decalPanel->createButton(basePID + (int)GPUGrassDecalPID::ADD_TYPE, "Add...", decal.channels.size() < MAX_TYPES_PER_CHANNEL); + decalPanel->createButton(basePID + (int)GPUGrassDecalPID::REMOVE_TYPE, "Remove...", !decal.channels.empty(), false); + int j = 0; + for (auto &channel : decal.channels) + { + decalPanel->createEditFloat(basePID + (int)GPUGrassDecalPID::TYPES_START + j, channel.first.c_str(), channel.second, 0); + ++j; + } + } + panel.setBool(PID_GPU_GRASS_GROUP, true); +} + +bool GPUGrassPanel::isGrassValid() const +{ + if (srv->getTypeCount() == 0 || (srv->getTypeCount() == 1 && srv->getType(0).name == "nograss")) + return false; + for (int i = 0; i < srv->getDecalCount(); ++i) + { + const GPUGrassDecal &decal = srv->getDecal(i); + if (decal.channels.empty()) + continue; + for (const auto &channel : decal.channels) + { + if (channel.second < 1.0) + continue; + const GPUGrassType *type = srv->getTypeByName(channel.first.c_str()); + if (!type) + continue; + if (!type->diffuse.empty() && !type->normal.empty()) + return true; + } + } + return false; +} + +void GPUGrassPanel::reload() +{ + if (isGrassValid()) + srv->createGrass(*blk); + else + srv->closeGrass(); +} + +void GPUGrassPanel::onChange(int pcb_id, PropPanel2 *panel) +{ + switch (pcb_id) + { + case PID_GPU_GRASS_ENABLE: srv->enableGrass(panel->getBool(pcb_id)); break; + case PID_GPU_GRASS_MASKS: + case PID_GPU_GRASS_TYPES: + { + SimpleString fname = panel->getText(pcb_id); + String resName = ::get_file_name_wo_ext(fname); + panel->setText(pcb_id, resName); + blk->setStr(pcb_id == PID_GPU_GRASS_TYPES ? "grass_types" : "grass_masks", resName.c_str()); + } + break; + case PID_GPU_GRASS_GRID_SIZE: blk->setReal("grass_grid_size", panel->getFloat(PID_GPU_GRASS_GRID_SIZE)); break; + case PID_GPU_GRASS_DISTANCE: blk->setReal("grass_distance", panel->getFloat(PID_GPU_GRASS_DISTANCE)); break; + case PID_GPU_GRASS_MASK_RESOLUTION: blk->setInt("grassMaskResolution", panel->getInt(PID_GPU_GRASS_MASK_RESOLUTION)); break; + case PID_GPU_GRASS_HOR_SIZE_MUL: blk->setReal("hor_size_mul", panel->getFloat(PID_GPU_GRASS_HOR_SIZE_MUL)); break; + } + if (pcb_id > PID_GPU_GRASS_ENABLE && pcb_id <= PID_GPU_GRASS_HOR_SIZE_MUL) + reload(); + else if (pcb_id >= PID_GPU_GRASS_TYPE_START && pcb_id <= PID_GPU_GRASS_TYPE_END) + { + int basePid = pcb_id - PID_GPU_GRASS_TYPE_START; + int index = basePid / (int)GPUGrassTypePID::COUNT; + basePid -= index * (int)GPUGrassTypePID::COUNT; + G_ASSERT(index < srv->getTypeCount()); + GPUGrassType &type = srv->getType(index); + DataBlock *grassTypesBlk = blk->getBlockByName("grass_types"); + G_ASSERT_RETURN(grassTypesBlk, ); + DataBlock *typeBlk = grassTypesBlk->getBlockByName(type.name.c_str()); + G_ASSERT_RETURN(typeBlk, ); + switch (basePid) + { + case (int)GPUGrassTypePID::NORMAL: + case (int)GPUGrassTypePID::DIFFUSE: + { + SimpleString fname = panel->getText(pcb_id); + if (fname.empty()) + fname = (basePid == (int)GPUGrassTypePID::DIFFUSE) ? type.diffuse.c_str() : type.normal.c_str(); + String resName = ::get_file_name_wo_ext(fname); + for (int i = 0; i < srv->getTypeCount(); ++i) + { + if (srv->getType(i).diffuse == resName.c_str() || srv->getType(i).normal == resName.c_str()) + { + resName = (basePid == (int)GPUGrassTypePID::DIFFUSE) ? type.diffuse.c_str() : type.normal.c_str(); + wingw::message_box(wingw::MBS_EXCL, "Error", + "Currently diffuse and normal textures supposed to be unique for each grass. check grass <%s> ", + srv->getType(i).name.c_str()); + break; + } + } + panel->setText(pcb_id, resName); + typeBlk->setStr(basePid == (int)GPUGrassTypePID::DIFFUSE ? "diffuse" : "normal", resName.c_str()); + if (basePid == (int)GPUGrassTypePID::DIFFUSE) + type.diffuse = resName; + else + type.normal = resName; + } + break; + case (int)GPUGrassTypePID::VARIATIONS: typeBlk->setInt("variations", type.variations = panel->getInt(pcb_id)); break; + case (int)GPUGrassTypePID::HEIGHT: typeBlk->setReal("height", type.height = panel->getFloat(pcb_id)); break; + case (int)GPUGrassTypePID::SIZE_LOD_MUL: typeBlk->setReal("size_lod_mul", type.size_lod_mul = panel->getFloat(pcb_id)); break; + case (int)GPUGrassTypePID::HT_RND_ADD: typeBlk->setReal("ht_rnd_add", type.ht_rnd_add = panel->getFloat(pcb_id)); break; + case (int)GPUGrassTypePID::HOR_SIZE: typeBlk->setReal("hor_size", type.hor_size = panel->getFloat(pcb_id)); break; + case (int)GPUGrassTypePID::HOR_SIZE_RND_ADD: + typeBlk->setReal("hor_size_rnd_add", type.hor_size_rnd_add = panel->getFloat(pcb_id)); + break; + case (int)GPUGrassTypePID::COLOR_MASK_R_FROM: + typeBlk->setE3dcolor("color_mask_r_from", type.color_mask_r_from = panel->getColor(pcb_id)); + break; + case (int)GPUGrassTypePID::COLOR_MASK_R_TO: + typeBlk->setE3dcolor("color_mask_r_to", type.color_mask_r_to = panel->getColor(pcb_id)); + break; + case (int)GPUGrassTypePID::COLOR_MASK_G_FROM: + typeBlk->setE3dcolor("color_mask_g_from", type.color_mask_g_from = panel->getColor(pcb_id)); + break; + case (int)GPUGrassTypePID::COLOR_MASK_G_TO: + typeBlk->setE3dcolor("color_mask_g_to", type.color_mask_g_to = panel->getColor(pcb_id)); + break; + case (int)GPUGrassTypePID::COLOR_MASK_B_FROM: + typeBlk->setE3dcolor("color_mask_b_from", type.color_mask_b_from = panel->getColor(pcb_id)); + break; + case (int)GPUGrassTypePID::COLOR_MASK_B_TO: + typeBlk->setE3dcolor("color_mask_b_to", type.color_mask_b_to = panel->getColor(pcb_id)); + break; + case (int)GPUGrassTypePID::HEIGHT_FROM_WEIGHT_MUL: + typeBlk->setReal("height_from_weight_mul", type.height_from_weight_mul = panel->getFloat(pcb_id)); + break; + case (int)GPUGrassTypePID::HEIGHT_FROM_WEIGHT_ADD: + typeBlk->setReal("height_from_weight_add", type.height_from_weight_add = panel->getFloat(pcb_id)); + break; + case (int)GPUGrassTypePID::DENSITY_FROM_WEIGHT_MUL: + typeBlk->setReal("density_from_weight_mul", type.density_from_weight_mul = panel->getFloat(pcb_id)); + break; + case (int)GPUGrassTypePID::DENSITY_FROM_WEIGHT_ADD: + typeBlk->setReal("density_from_weight_add", type.density_from_weight_add = panel->getFloat(pcb_id)); + break; + case (int)GPUGrassTypePID::VERTICAL_ANGLE_MUL: + typeBlk->setE3dcolor("vertical_angle_mul", type.vertical_angle_mul = panel->getFloat(pcb_id)); + break; + case (int)GPUGrassTypePID::VERTICAL_ANGLE_ADD: + typeBlk->setReal("vertical_angle_add", type.vertical_angle_add = panel->getFloat(pcb_id)); + break; + case (int)GPUGrassTypePID::STIFFNESS: typeBlk->setReal("stiffness", type.stiffness = panel->getFloat(pcb_id)); break; + case (int)GPUGrassTypePID::HORIZONTAL_GRASS: + typeBlk->setBool("horizontal_grass", type.horizontal_grass = panel->getBool(pcb_id)); + break; + case (int)GPUGrassTypePID::UNDERWATER: typeBlk->setBool("underwater", type.underwater = panel->getBool(pcb_id)); break; + } + reload(); + } + else if (pcb_id >= PID_GPU_GRASS_DECAL_START && pcb_id <= PID_GPU_GRASS_DECAL_END) + { + int basePid = pcb_id - PID_GPU_GRASS_DECAL_START; + int index = basePid / (int)GPUGrassDecalPID::COUNT; + basePid -= index * (int)GPUGrassDecalPID::COUNT; + G_ASSERT(index < srv->getDecalCount()); + GPUGrassDecal &decal = srv->getDecal(index); + DataBlock *decalsBlk = blk->getBlockByName("decals"); + G_ASSERT_RETURN(decalsBlk, ); + DataBlock *decalBlk = decalsBlk->getBlockByName(decal.name.c_str()); + G_ASSERT_RETURN(decalBlk, ); + if (basePid == (int)GPUGrassDecalPID::ID) + { + int id = panel->getInt(pcb_id); + if (srv->findDecalId(id)) + id = decal.id; + if (id >= GRASS_MAX_CHANNELS) + id = decal.id; + panel->setInt(pcb_id, id); + decalBlk->setInt("id", id); + } + else if (basePid >= (int)GPUGrassDecalPID::TYPES_START && basePid <= (int)GPUGrassDecalPID::TYPES_END) + { + int basePid2 = basePid - (int)GPUGrassDecalPID::TYPES_START; + G_ASSERT_RETURN(basePid2 < decal.channels.size(), ); + auto &pair = decal.channels[basePid2]; + float val = panel->getFloat(pcb_id); + if (val < 1.0) + panel->setFloat(pcb_id, val = 1.0); + decalBlk->setReal(pair.first.c_str(), pair.second = val); + } + reload(); + } +} + +void GPUGrassPanel::onClick(int pcb_id, PropPanel2 *panel, const eastl::function &loadGPUGrassFromLevelBlk, + const eastl::function &fillPanel) +{ + switch (pcb_id) + { + case PID_GPU_GRASS_LOADFROM_LEVELBLK: + if (wingw::message_box(wingw::MBS_YESNO | wingw::MBS_QUEST, "Confirmation", "Overwrite grass settings?") == wingw::MB_ID_YES) + loadGPUGrassFromLevelBlk(); + break; + case PID_GPU_GRASS_ADD_TYPE: + { + eastl::string name; + if (showNameDialog("Add type", name, [this](const char *name) { return !!srv->getTypeByName(name); })) + { + GPUGrassType &type = srv->addType(name.c_str()); + addGrassType(type); + fillPanel(); + } + } + break; + case PID_GPU_GRASS_REMOVE_TYPE: + { + Tab types = getGrassTypeNames(); + Tab result; + if (showMultiListDialog("Remove type", types, result)) + if (!result.empty() && + wingw::message_box(wingw::MBS_YESNO | wingw::MBS_QUEST, "Confirmation", "Remove grass type(s)?") == wingw::MB_ID_YES) + { + for (int i = 0; i < result.size(); ++i) + { + const char *name = types[result[i]].c_str(); + srv->removeType(name); + DataBlock *typesBlk = blk->getBlockByName("grass_types"); + typesBlk->removeBlock(name); + for (int j = 0; j < srv->getDecalCount(); ++j) + removeDecalType(srv->getDecal(j), name, blk); + } + fillPanel(); + reload(); + } + } + break; + case PID_GPU_GRASS_RENAME_TYPE: + { + Tab types = getGrassTypeNames(); + int result; + if (showListDialog("Rename type", types, result)) + { + eastl::string name = types[result].c_str(); + if (showNameDialog("Rename type", name, [this](const char *name) { return !!srv->getTypeByName(name); })) + { + GPUGrassType &type = srv->getType(result); + for (int i = 0; i < srv->getDecalCount(); ++i) + { + GPUGrassDecal &decal = srv->getDecal(i); + for (auto &channel : decal.channels) + if (channel.first == type.name) + channel.first = name.c_str(); + } + DataBlock *decals = blk->getBlockByName("decals"); + int i = 0; + while (DataBlock *decal = decals->getBlock(i)) + { + int j = 0; + while (const char *typeName = decal->getParamName(j)) + { + if (type.name == typeName) + { + float val = decal->getReal(typeName); + decal->removeParam(j); + decal->addReal(name.c_str(), val); + break; + } + else + ++j; + } + ++i; + } + DataBlock *types = blk->getBlockByName("grass_types"); + types->removeBlock(type.name.c_str()); + type.name = name; + addGrassType(type); + fillPanel(); + } + } + } + break; + case PID_GPU_GRASS_ADD_DECAL: + { + eastl::string name; + if (showNameDialog("Add decal", name, [this](const char *name) { return !!srv->getDecalByName(name); })) + { + GPUGrassDecal &decal = srv->addDecal(name.c_str()); + addGrassDecal(decal); + fillPanel(); + reload(); + } + } + break; + case PID_GPU_GRASS_REMOVE_DECAL: + { + Tab decals = getGrassDecalNames(); + Tab result; + if (showMultiListDialog("Remove decal", decals, result)) + if (!result.empty() && + wingw::message_box(wingw::MBS_YESNO | wingw::MBS_QUEST, "Confirmation", "Remove grass decal(s)?") == wingw::MB_ID_YES) + { + for (int i = 0; i < result.size(); ++i) + { + const char *name = decals[result[i]].c_str(); + srv->removeDecal(name); + DataBlock *decalBlks = blk->getBlockByName("decals"); + decalBlks->removeBlock(name); + } + fillPanel(); + reload(); + } + } + break; + case PID_GPU_GRASS_RENAME_DECAL: + { + Tab decals = getGrassDecalNames(); + int result; + if (showListDialog("Rename decal", decals, result)) + { + eastl::string name = decals[result].c_str(); + if (showNameDialog("Rename decal", name, [this](const char *name) { return !!srv->getDecalByName(name); })) + { + GPUGrassDecal &decal = srv->getDecal(result); + DataBlock *decals = blk->getBlockByName("decals"); + decals->removeBlock(decal.name.c_str()); + decal.name = name; + addGrassDecal(decal); + fillPanel(); + } + } + } + break; + } + int basePid = pcb_id - PID_GPU_GRASS_DECAL_START; + int index = basePid / (int)GPUGrassDecalPID::COUNT; + basePid -= index * (int)GPUGrassDecalPID::COUNT; + if (basePid >= (int)GPUGrassDecalPID::ADD_TYPE && basePid <= (int)GPUGrassDecalPID::REMOVE_TYPE) + { + GPUGrassDecal &decal = srv->getDecal(index); + switch (basePid) + { + case (int)GPUGrassDecalPID::ADD_TYPE: + { + Tab types = getGrassTypeNames(); + types.push_back(String("nograss")); + for (const auto &channel : decal.channels) + { + intptr_t ptr = find_value_idx(types, String{channel.first.c_str()}); + if (ptr >= 0) + erase_items(types, ptr, 1); + } + int result; + if (showListDialog("Add type", types, result)) + { + const float defVal = 1.0; + decal.channels.emplace_back(eastl::string{types[result].c_str()}, defVal); + DataBlock *decalsBlk = blk->getBlockByName("decals"); + DataBlock *decalBlk = decalsBlk->getBlockByName(decal.name.c_str()); + decalBlk->addReal(types[result].c_str(), defVal); + fillPanel(); + reload(); + } + } + break; + case (int)GPUGrassDecalPID::REMOVE_TYPE: + { + Tab types = getDecalTypeNames(decal); + Tab result; + if (showMultiListDialog("Remove type", types, result)) + if (!result.empty() && + wingw::message_box(wingw::MBS_YESNO | wingw::MBS_QUEST, "Confirmation", "Remove grass type(s)?") == wingw::MB_ID_YES) + { + for (int i = 0; i < result.size(); ++i) + removeDecalType(decal, types[result[i]].c_str(), blk); + fillPanel(); + reload(); + } + } + break; + } + } +} + +Tab GPUGrassPanel::getGrassTypeNames() const +{ + Tab types; + for (int i = 0; i < srv->getTypeCount(); ++i) + { + if (srv->getType(i).name == "nograss") + continue; + types.push_back(String(srv->getType(i).name.c_str())); + } + return types; +} + +Tab GPUGrassPanel::getGrassDecalNames() const +{ + Tab decals; + for (int i = 0; i < srv->getDecalCount(); ++i) + decals.push_back(String(srv->getDecal(i).name.c_str())); + return decals; +} + +void GPUGrassPanel::addGrassType(const GPUGrassType &type) +{ + DataBlock *types = blk->getBlockByName("grass_types"); + G_ASSERT_RETURN(types, ); + DataBlock *typeBlk = types->addBlock(type.name.c_str()); + typeBlk->addStr("diffuse", type.diffuse.c_str()); + typeBlk->addStr("normal", type.normal.c_str()); + typeBlk->addInt("variations", type.variations); + typeBlk->addReal("height", type.height); + typeBlk->addReal("size_lod_mul", type.size_lod_mul); + typeBlk->addReal("ht_rnd_add", type.ht_rnd_add); + typeBlk->addReal("hor_size", type.hor_size); + typeBlk->addReal("hor_size_rnd_add", type.hor_size_rnd_add); + typeBlk->addE3dcolor("color_mask_r_from", type.color_mask_r_from); + typeBlk->addE3dcolor("color_mask_r_to", type.color_mask_r_to); + typeBlk->addE3dcolor("color_mask_g_from", type.color_mask_g_from); + typeBlk->addE3dcolor("color_mask_g_to", type.color_mask_g_to); + typeBlk->addE3dcolor("color_mask_b_from", type.color_mask_b_from); + typeBlk->addE3dcolor("color_mask_b_to", type.color_mask_b_to); + typeBlk->addReal("height_from_weight_mul", type.height_from_weight_mul); + typeBlk->addReal("height_from_weight_add", type.height_from_weight_add); + typeBlk->addReal("density_from_weight_mul", type.density_from_weight_mul); + typeBlk->addReal("density_from_weight_add", type.density_from_weight_add); + typeBlk->addReal("vertical_angle_add", type.vertical_angle_add); + typeBlk->addReal("vertical_angle_mul", type.vertical_angle_mul); + + typeBlk->addReal("stiffness", type.stiffness); + typeBlk->addBool("horizontal_grass", type.horizontal_grass); + typeBlk->addBool("underwater", type.underwater); +} + +void GPUGrassPanel::addGrassDecal(const GPUGrassDecal &decal) +{ + DataBlock *decals = blk->getBlockByName("decals"); + G_ASSERT_RETURN(decals, ); + DataBlock *decalBlk = decals->addBlock(decal.name.c_str()); + decalBlk->addInt("id", decal.id); + for (const auto &channel : decal.channels) + decalBlk->addReal(channel.first.c_str(), channel.second); +} + +bool GPUGrassPanel::showNameDialog(const char *title, eastl::string &res, const eastl::function &findName) +{ + eastl::unique_ptr dialog(DAGORED2->createDialog(_pxScaled(250), _pxScaled(120), title)); + PropPanel2 *dlgPanel = dialog->getPanel(); + enum + { + PCB_EDIT, + }; + dlgPanel->createEditBox(PCB_EDIT, "Name"); + dlgPanel->setText(PCB_EDIT, res.c_str()); + dlgPanel->setFocusById(PCB_EDIT); + while (true) + { + int ret = dialog->showDialog(); + if (ret == DIALOG_ID_OK) + { + SimpleString name = dlgPanel->getText(PCB_EDIT); + if (name.empty()) + continue; + if (findName(name.c_str())) + wingw::message_box(wingw::MBS_EXCL, "Error", "Name already exists"); + else + { + res = name; + return true; + } + } + else + break; + } + return false; +} + +bool GPUGrassPanel::showMultiListDialog(const char *title, const Tab &entries, Tab &res) +{ + eastl::unique_ptr dialog(DAGORED2->createDialog(_pxScaled(250), _pxScaled(620), title)); + PropPanel2 *dlgPanel = dialog->getPanel(); + enum + { + PCB_LIST, + }; + clear_and_shrink(res); + dlgPanel->createMultiSelectList(PCB_LIST, entries, _pxScaled(600)); + if (dialog->showDialog() == DIALOG_ID_OK) + { + dlgPanel->getSelection(PCB_LIST, res); + return true; + } + return false; +} + +bool GPUGrassPanel::showListDialog(const char *title, const Tab &entries, int &res) +{ + eastl::unique_ptr dialog(DAGORED2->createDialog(_pxScaled(250), _pxScaled(200), title)); + PropPanel2 *dlgPanel = dialog->getPanel(); + enum + { + PCB_LIST, + }; + res = -1; + dlgPanel->createList(PCB_LIST, "Name", entries, 0); + if (dialog->showDialog() == DIALOG_ID_OK) + { + res = dlgPanel->getInt(PCB_LIST); + return true; + } + return false; +} \ No newline at end of file diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/gpuGrassPanel.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/gpuGrassPanel.h new file mode 100644 index 000000000..b3ac03a17 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/gpuGrassPanel.h @@ -0,0 +1,29 @@ +#pragma once +#include +#include + +class IGPUGrassService; +class DataBlock; +struct GPUGrassType; +struct GPUGrassDecal; +class GPUGrassPanel +{ + PropertyContainerControlBase *grassPanel = nullptr; + IGPUGrassService *srv = nullptr; + DataBlock *blk = nullptr; + bool showNameDialog(const char *title, eastl::string &res, const eastl::function &findName); + bool showMultiListDialog(const char *title, const Tab &entries, Tab &res); + bool showListDialog(const char *title, const Tab &entries, int &res); + void addGrassType(const GPUGrassType &type); + void addGrassDecal(const GPUGrassDecal &decal); + Tab getGrassTypeNames() const; + Tab getGrassDecalNames() const; + void reload(); + +public: + void fillPanel(IGPUGrassService *service, DataBlock *grass_blk, PropPanel2 &panel); + void onChange(int pcb_id, PropPanel2 *panel); + void onClick(int pcb_id, PropPanel2 *panel, const eastl::function &loadGPUGrassFromLevelBlk, + const eastl::function &fillPanel); + bool isGrassValid() const; +}; diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlClipping.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlClipping.cpp new file mode 100644 index 000000000..8818e6ec1 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlClipping.cpp @@ -0,0 +1,214 @@ +#include +#include +#include "hmlPlugin.h" + +#include +#include +#include +#include + + +#define CHECK_DET_VERT_TRACE(PT, NORM, MAXT) \ + if (detDivisor && (detRect & Point2(PT.x, PT.z))) \ + { \ + HMDetTR det_hm; \ + if (get_height_midpoint_heightmap(det_hm, Point2(PT.x, PT.z), y, NORM)) \ + { \ + float t = PT.y - y; \ + if (t >= 0 && t < MAXT) \ + { \ + MAXT = t; \ + return true; \ + } \ + } \ + return false; \ + } + +bool HmapLandPlugin::isColliderVisible() const +{ + if (exportType == EXPORT_PSEUDO_PLANE) + return false; + + int st_mask = DAEDITOR3.getEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_COLLISION); + return getVisible() && (st_mask & (hmapSubtypeMask | lmeshSubtypeMask)); +} + +bool HmapLandPlugin::traceRayPrivate(const Point3 &p, const Point3 &dir, real &maxt, Point3 *norm) +{ + HMDetTR det_hm_tr; + if (exportType == EXPORT_PSEUDO_PLANE) + { + if (EDITORCORE->traceRay(p, dir, maxt, NULL)) + return true; + + if (!heightMap.isFileOpened()) + return false; + + if (dir.y < -0.999) + { + real y; + CHECK_DET_VERT_TRACE(p, norm, maxt); + if (get_height_midpoint_heightmap(*genHmap, Point2(p.x, p.z), y, norm)) + { + float t = p.y - y; + if (t >= 0 && t < maxt) + { + maxt = t; + return true; + } + } + return false; + } + + bool ret = detDivisor ? ::trace_ray_midpoint_heightmap(det_hm_tr, p, dir, maxt, norm) : false; + return ::trace_ray_midpoint_heightmap(*genHmap, p, dir, maxt, norm) || ret; + } + + if (noTraceNow || !heightMap.isFileOpened()) + return false; + + int st_mask = DAEDITOR3.getEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_RENDER); + if (exportType == EXPORT_LANDMESH && !landMeshMap.isEmpty() && (st_mask & lmeshSubtypeMask) && !(st_mask & hmapSubtypeMask)) + { + bool ret = detDivisor ? ::trace_ray_midpoint_heightmap(det_hm_tr, p, dir, maxt, norm) : false; + return landMeshMap.traceRay(p, dir, maxt, norm) || ret; + } + + applyHmModifiers(false); + + if (dir.y < -0.999) + { + real y; + CHECK_DET_VERT_TRACE(p, norm, maxt); + if (get_height_midpoint_heightmap(*this, Point2(p.x, p.z), y, norm)) + { + float t = p.y - y; + if (t >= 0 && t < maxt) + { + maxt = t; + return true; + } + } + return false; + } + + bool ret = detDivisor ? ::trace_ray_midpoint_heightmap(det_hm_tr, p, dir, maxt, norm) : false; + return ::trace_ray_midpoint_heightmap(*this, p, dir, maxt, norm) || ret; +} + +bool HmapLandPlugin::traceRay(const Point3 &pt, const Point3 &dir, real &maxt, Point3 *norm) +{ + if (!heightMap.isFileOpened() || noTraceNow || exportType == EXPORT_PSEUDO_PLANE) + return false; + + int st_mask = DAEDITOR3.getEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_COLLISION); + if (!(st_mask & (hmapSubtypeMask | lmeshSubtypeMask))) + return false; + + HMDetTR det_hm_tr; + if (exportType == EXPORT_LANDMESH && !landMeshMap.isEmpty()) + { + bool ret = detDivisor ? ::trace_ray_midpoint_heightmap(det_hm_tr, pt, dir, maxt, norm) : false; + return landMeshMap.traceRay(pt, dir, maxt, norm) || ret; + } + + applyHmModifiers(false); + + if (dir.y < -0.999) + { + real y; + CHECK_DET_VERT_TRACE(pt, norm, maxt); + if (get_height_midpoint_heightmap(*this, Point2(pt.x, pt.z), y, norm)) + { + float t = pt.y - y; + if (t >= 0 && t < maxt) + { + maxt = t; + return true; + } + } + return false; + } + + bool ret = detDivisor ? ::trace_ray_midpoint_heightmap(det_hm_tr, pt, dir, maxt, norm) : false; + return ::trace_ray_midpoint_heightmap(*this, pt, dir, maxt, norm) || ret; +} + +bool HmapLandPlugin::shadowRayHitTest(const Point3 &pt, const Point3 &dir, real maxt) +{ + if (!heightMap.isFileOpened() || !isVisible || exportType == EXPORT_PSEUDO_PLANE || calculating_shadows) + return false; + + applyHmModifiers(false); + return ray_hit_midpoint_heightmap_approximate(*this, pt, dir, maxt); +} + + +bool HmapLandPlugin::getHeightmapCell5Pt(const IPoint2 &cell, real &h0, real &hx, real &hy, real &hxy, real &hmid) const +{ + if (exportType == EXPORT_PSEUDO_PLANE) + return false; + + //== TODO: check holes? + if (detDivisor && insideDetRectC(cell * detDivisor)) + return false; + if (cell.x < 0 || cell.y < 0 || cell.x + 1 >= heightMap.getMapSizeX() || cell.y + 1 >= heightMap.getMapSizeY()) + return false; + + h0 = heightMap.getFinalData(cell.x, cell.y); + hx = heightMap.getFinalData(cell.x + 1, cell.y); + hy = heightMap.getFinalData(cell.x, cell.y + 1); + hxy = heightMap.getFinalData(cell.x + 1, cell.y + 1); + + hmid = (h0 + hx + hy + hxy) * 0.25f; + + return true; +} + +bool HmapLandPlugin::getHeightmapHeight(const IPoint2 &cell, real &ht) const +{ + if (exportType == EXPORT_PSEUDO_PLANE) + return false; + + //== TODO: check holes? + if (detDivisor && insideDetRectC(cell * detDivisor)) + return false; + if (cell.x < 0 || cell.y < 0 || cell.x >= heightMap.getMapSizeX() || cell.y >= heightMap.getMapSizeY()) + return false; + + ht = heightMap.getFinalData(cell.x, cell.y); + + return true; +} + + +bool HmapLandPlugin::getHeightmapPointHt(Point3 &inout_p, Point3 *out_norm) const +{ + if (exportType == EXPORT_PSEUDO_PLANE) + return false; + + if (detDivisor && (detRect & Point2::xz(inout_p))) + { + HMDetTR det_hm; + return get_height_midpoint_heightmap(det_hm, Point2::xz(inout_p), inout_p.y, out_norm); + } + if (exportType == EXPORT_LANDMESH && !landMeshMap.isEmpty()) + { + return landMeshMap.getHeight(Point2::xz(inout_p), inout_p.y, out_norm); + } + + return get_height_midpoint_heightmap(*this, Point2(inout_p.x, inout_p.z), inout_p.y, out_norm); +} + +bool HmapLandPlugin::getHeightmapOnlyPointHt(Point3 &inout_p, Point3 *out_norm) const +{ + if (exportType == EXPORT_PSEUDO_PLANE) + return false; + + if (detDivisor && (detRect & Point2::xz(inout_p))) + { + HMDetTR det_hm; + return get_height_midpoint_heightmap(det_hm, Point2::xz(inout_p), inout_p.y, out_norm); + } + return get_height_midpoint_heightmap(*this, Point2(inout_p.x, inout_p.z), inout_p.y, out_norm); +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlCm.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlCm.h new file mode 100644 index 000000000..ceaee5ebe --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlCm.h @@ -0,0 +1,491 @@ +#ifndef __GAIJIN_HEIGHTMAPLAND_CM__ +#define __GAIJIN_HEIGHTMAPLAND_CM__ +#pragma once + + +#include +#include "GPUGrassTypePID.h" +#include "GPUGrassDecalPID.h" + +// commands +enum +{ + PROPBAR_EDITOR_WTYPE = 133, + PROPBAR_WIDTH = 280, + + CM_SHOW_PANEL = CM_PLUGIN_BASE + 1, + CM_CREATE_HEIGHTMAP, + CM_ERASE_HEIGHTMAP, + CM_IMPORT_HEIGHTMAP, + CM_REIMPORT, + CM_EXPORT_HEIGHTMAP, + CM_IMPORT_WATER_DET_HMAP, + CM_IMPORT_WATER_MAIN_HMAP, + CM_ERASE_WATER_HEIGHTMAPS, + CM_EXPORT_COLORMAP, + CM_REBUILD, + CM_BUILD_COLORMAP, + CM_BUILD_LIGHTMAP, + CM_EXPORT_AS_COMPOSIT, + CM_EXPORT_LAND_TO_GAME, + CM_EXPORT_LOFT_MASKS, + CM_RESCALE_HMAP, + CM_REBUILD_RIVERS, + + CM_SHOW_LAND_OBJECTS, + CM_HIDE_SPLINES, + CM_CREATE_HOLEBOX_MODE, + CM_HILL_UP, + CM_HILL_DOWN, + CM_SMOOTH, + CM_ALIGN, + CM_SHADOWS, + CM_SCRIPT, + + CM_CREATE_POLYGON, + CM_CREATE_LT, + CM_CREATE_SNOW_SOURCE, + + CM_SELECT_SPLINES, + CM_SELECT_PT, + CM_SELECT_ENT, + CM_SELECT_SPL_ENT, + CM_SELECT_LT, + CM_SELECT_SNOW, + + CM_RESTORE_HM_BACKUP, + CM_COMMIT_HM_CHANGES, + + CM_CREATE_SPLINE, + CM_REFINE_SPLINE, + CM_SPLINE_EXPORT_TO_DAG, + CM_SPLINE_IMPORT_FROM_DAG, + + CM_CREATE_ENTITY, + CM_ROTATION_NONE, + CM_ROTATION_X = CM_ROTATION_NONE + 1, + CM_ROTATION_Y = CM_ROTATION_NONE + 2, + CM_ROTATION_Z = CM_ROTATION_NONE + 3, + + CM_SPLIT_SPLINE, + CM_REVERSE_SPLINE, + CM_CLOSE_SPLINE, + CM_OPEN_SPLINE, + CM_SPLIT_POLY, + + CM_EXPORT_LAYERS, + CM_MANUAL_SPLINE_REGEN_MODE, + CM_SPLINE_REGEN, + CM_SET_PT_VIS_DIST, + + CM_COLLAPSE_MODIFIERS, + CM_UNIFY_OBJ_NAMES, + CM_AUTO_ATACH, + CM_REBUILD_SPLINES_BITMASK, + CM_MAKE_BOTTOM_SPLINES, + CM_MOVE_OBJECTS, + CM_SPLIT_COMPOSIT, + CM_INSTANTIATE_GENOBJ_INTO_ENTITIES, + CM_MAKE_SPLINES_CROSSES, + CM_HIDE_UNSELECTED_SPLINES, + CM_UNHIDE_ALL_SPLINES, + + CM_LAYERS_DLG, +}; + + +#define MAX_DETAIL_TEXTURES 100 + +#define MAX_UI_NAVMESHES 2 + +// Navmesh properties +enum +{ + NM_PARAM_GRP, + NM_PARAM_EXP, + NM_PARAM_KIND, + NM_PARAM_AREATYPE, + NM_PARAM_AREATYPE_MAIN, + NM_PARAM_AREATYPE_DET, + NM_PARAM_AREATYPE_RECT, + NM_PARAM_AREATYPE_RECT0, + NM_PARAM_AREATYPE_RECT1, + NM_PARAM_CELL_DXZ, + NM_PARAM_CELL_DY, + NM_PARAM_CELL_A_HT, + NM_PARAM_CELL_A_RAD, + NM_PARAM_CELL_A_SLOPE, + NM_PARAM_CELL_A_CLIMB, + NM_PARAM_CELL_EDGE_MAX_LEN, + NM_PARAM_CELL_EDGE_MAX_ERR, + NM_PARAM_CELL_REG_MIN_SZ, + NM_PARAM_CELL_REG_MERGE_SZ, + NM_PARAM_CELL_VERTS_PER_POLY, + NM_PARAM_CELL_DET_SAMPLE, + NM_PARAM_CELL_DET_MAX_ERR, + NM_PARAM_WATER, + NM_PARAM_WATER_LEV, + NM_PARAM_DROP_RESULT_ON_COLLISION, + NM_PARAM_DROP_RESULT_ON_COLLISION_TRACE_OFFSET, + NM_PARAM_DROP_RESULT_ON_COLLISION_TRACE_LEN, + NM_PARAM_TYPE, + NM_PARAM_TILE_SZ, + NM_PARAM_BUCKET_SZ, + NM_PARAM_PREFAB_COLLISION, + NM_PARAM_TRACE_STEP, + NM_PARAM_CROSSING_WATER_DEPTH, + + NM_PARAM_JLK_AND_CVRS_GRP, + NM_PARAM_JLK_CVRS_EXTRA_CELLS, + NM_PARAM_EMRG_ENABLED, + NM_PARAM_EMRG_WALK_PRECISION, + NM_PARAM_EMRG_EXTRUDE_MISTAKE, + NM_PARAM_EMRG_EXTRUDE_LIMIT, + NM_PARAM_EMRG_SAFE_CUT_LIMIT, + NM_PARAM_EMRG_UNSAFE_CUT_LIMIT, + NM_PARAM_EMRG_UNSAFE_MAX_CUT_SPACE, + NM_PARAM_JLK_ENABLED, + NM_PARAM_JLK_JUMP_OVER_HEIGHT, + NM_PARAM_JLK_JUMP_LENGTH, + NM_PARAM_JLK_MIN_WIDTH, + NM_PARAM_JLK_DH_THRESHOLD, + NM_PARAM_JLK_MERGE_ANGLE, + NM_PARAM_JLK_MERGE_DIST, + NM_PARAM_JLK_CPLX_THRESHOLD, + NM_PARAM_JLK_CROSS_OBSTACLES_WITH_JUMPLINKS, + NM_PARAM_CVRS_ENABLED, + NM_PARAM_CVRS_TYPEGEN, + NM_PARAM_CVRS_MAX_HEIGHT, + NM_PARAM_CVRS_MIN_HEIGHT, + NM_PARAM_CVRS_MIN_WIDTH, + NM_PARAM_CVRS_MIN_DEPTH, + NM_PARAM_CVRS_SHOOT_WINDOW_HEIGHT, + NM_PARAM_CVRS_COLLISION_TARNSP_THRESHOLD, + NM_PARAM_CVRS_MERGE_DIST, + NM_PARAM_CVRS_DH_THRESHOLD, + NM_PARAM_CVRS_SHOOT_DEPTH_CHECK, + NM_PARAM_CVRS_SHOOT_HEIGHT, + NM_PARAM_CVRS_OPENING_TRESHOLD, + NM_PARAM_CVRS_BOX_OFFSET, + NM_PARAM_CVRS_TEST_X, + NM_PARAM_CVRS_TEST_Y, + NM_PARAM_CVRS_TEST_Z, + + NM_PARAM_EXPORT_TYPE, + NM_PARAM_EXPORT_TYPE_WATER, + NM_PARAM_EXPORT_TYPE_SPLINES, + NM_PARAM_EXPORT_TYPE_HEIGHT_FROM_ABOVE, + NM_PARAM_EXPORT_TYPE_GEOMETRY, + NM_PARAM_EXPORT_TYPE_WATER_AND_GEOMETRY, + + NM_PARAM_COMPRESS_RATIO, + NM_PARAMS_COUNT +}; + + +// Property Panel pids +enum +{ + PID_BRUSH_GRP = 1, + PID_BRUSH_RADIUS, + PID_BRUSH_OPACITY, + PID_BRUSH_HARDNESS, + PID_BRUSH_SPACING, + PID_BRUSH_AUTOREPEAT, + PID_BRUSH_LIMIT_VALUE, + PID_BRUSH_LIMIT_USE, + PID_BRUSH_KERNEL_SIZE, + PID_BRUSH_SIGMA, + PID_BRUSH_CONTINUOS, + PID_BRUSH_TRAIL, + PID_BRUSH_POWER, + PID_BRUSH_MASK, + PID_BRUSH_APPLY_ONCE, + PID_BRUSH_AUTO_ANGLE, + PID_BRUSH_ANGLE, + PID_BRUSH_ALIGN_OFFSET, + PID_BRUSH_ALIGN_SGEOMETRY, + PID_BRUSH_ALIGN_TOP, + PID_BRUSHES_PIDS, + + PID_HMAP_PARAMS_GRP, + PID_GRID_CELL_SIZE, + PID_HEIGHT_SCALE, + PID_HEIGHT_OFFSET, + PID_HEIGHTMAP_OFFSET, + PID_HEIGHTMAP_AUTOCENTER, + PID_HM_COLLISION_OFFSET, + PID_HM_COLLISION_SIZE, + PID_HM_COLLISION_SHOW, + + PID_GRID_H2_CELL_SIZE, + PID_GRID_H2_BBOX_OFS, + PID_GRID_H2_BBOX_SZ, + PID_GRID_H2_APPLY, + + PID_HM_EXPORT_GRP, + PID_HM_EXPORT_TYPE, + PID_HM_LOFT_BELOW_ALL, + + PID_HM_SIZE_METERS, + PID_HM_SIZE_PIXELS, + + PID_RENDERER_GRP, + PID_RENDER_GRID_STEP, + PID_RENDER_RADIUS_ELEMS, + PID_RENDER_RING_ELEMS, + PID_RENDER_NUM_LODS, + PID_RENDER_MAX_DETAIL_LOD, + PID_RENDER_DETAIL_TILE, + PID_RENDER_CANYON_HOR_TILE, + PID_RENDER_CANYON_VERT_TILE, + PID_RENDER_ELEM_SIZE, + PID_RENDER_RADIOGROUP_HM, + PID_RENDER_INITIAL_HM, + PID_RENDER_FINAL_HM, + PID_RENDER_DEBUG_LINES, + PID_RENDER_ALL_SPLINES_ALWAYS, + PID_RENDER_SEL_SPLINES_ALWAYS, + PID_RENDER_HM2_YBASE_FOR_LOD, + PID_HM2_DISPLACEMENT_Q, + + PID_LIGHTING_GRP, + PID_SUN_LIGHT_COLOR, + PID_SKY_LIGHT_COLOR, + PID_SUN_LIGHT_POWER, + PID_SKY_LIGHT_POWER, + PID_SPECULAR_COLOR, + PID_SPECULAR_MUL, + PID_SPECULAR_POWER, + PID_SUN_DIRECTION, + PID_SUN_AZIMUTH, + PID_SUN_ZENITH, + PID_GET_SUN_SETTINGS, + PID_GET_SUN_SETTINGS_AUTOMAT, + PID_GET_SUN_DIR_SETTINGS_AUTOMAT, + PID_CALC_FAST_LIGHTING, + PID_CALC_GOOD_LIGHTING, + PID_SAVE_LIGHTING_PC, + PID_SAVE_LIGHTING_X360, + PID_SAVE_LIGHTING_PS3, + PID_SAVE_LIGHTING_PS4, + PID_SAVE_LIGHTING_iOS, + PID_SAVE_LIGHTING_AND, + PID_SAVE_LIGHTING_DDS, + PID_SHADOW_GRP, + PID_SHADOW_BIAS, + PID_SHADOW_TRACE_DIST, + PID_SHADOW_DENSITY, + PID_SHADOW_CASTERS_GRP, + PID_SHADOW_CASTER_FIRST, + PID_SHADOW_CASTER_LAST = PID_SHADOW_CASTER_FIRST + 200, + + PID_BOX_SIZE_X, + PID_BOX_SIZE_Y, + PID_BOX_SIZE_Z, + + PID_LAND_TEXTURES_OPTIONS_GRP, + + PID_DETAIL_TEX_LIST_GRP, + + PID_DETAIL_TEX_0, + PID_DETAIL_TEX_LAST = PID_DETAIL_TEX_0 + MAX_DETAIL_TEXTURES - 1, + + PID_DETAIL_NMAP_0, + PID_DETAIL_NMAP_LAST = PID_DETAIL_NMAP_0 + MAX_DETAIL_TEXTURES - 1, + + PID_DETAIL_SIDE_TEX_0, + PID_DETAIL_SIDE_TEX_LAST = PID_DETAIL_SIDE_TEX_0 + MAX_DETAIL_TEXTURES - 1, + + PID_DETAIL_SIDE_NMAP_0, + PID_DETAIL_SIDE_NMAP_LAST = PID_DETAIL_SIDE_NMAP_0 + MAX_DETAIL_TEXTURES - 1, + + PID_DETAIL_TEX_TILE_0, + PID_DETAIL_TEX_TILE_LAST = PID_DETAIL_TEX_TILE_0 + MAX_DETAIL_TEXTURES - 1, + + PID_DETAIL_TEX_OFFSET_0, + PID_DETAIL_TEX_OFFSET_LAST = PID_DETAIL_TEX_OFFSET_0 + MAX_DETAIL_TEXTURES - 1, + + PID_SET_NUM_DETAIL_TEXS, + PID_CANYON_ANGLE, + PID_CANYON_FADE_ANGLE, + + PID_SCRIPT_PARAMS_GRP, + PID_SCRIPT_FILE, + PID_RESET_SCRIPT, + PID_RELOAD_SCRIPT, + PID_GENERATE_COLORMAP, + PID_IMPORT_SCRIPT_IMAGE, + PID_CREATE_MASK, + PID_TILE_OFFSET_GRP, + + PID_SCRIPT_PARAM_START, + PID_LAST_SCRIPT_PARAM = PID_SCRIPT_PARAM_START + 2048, + + PID_GRASS_LAYER_GRP, + PID_GRASS_PARAM_START = PID_GRASS_LAYER_GRP + 128, + PID_LAST_GRASS_PARAM = PID_GRASS_PARAM_START + 2048, + PID_ENABLE_GRASS, + PID_GRASS_LOADFROM_LEVELBLK, + PID_GRASS_ADDLAYER, + PID_GRASS_MASK_START, + PID_GRASS_MASK_END = PID_GRASS_MASK_START + 10, + PID_GRASS_DEFAULT_MIN_DENSITY, + PID_GRASS_DEFAULT_MAX_DENSITY, + PID_GRASS_MAX_RADIUS, + PID_GRASS_TEX_SIZE, + + PID_GRASS_SOW_PER_LIN_FREQ, + PID_GRASS_FADE_DELTA, + PID_GRASS_LOD_FADE_DELTA, + PID_GRASS_BLEND_TO_LAND_DELTA, + + PID_GRASS_NOISE_FIRST_RND, + PID_GRASS_NOISE_FIRST_VAL_MUL, + PID_GRASS_NOISE_FIRST_VAL_ADD, + + PID_GRASS_NOISE_SECOND_RND, + PID_GRASS_NOISE_SECOND_VAL_MUL, + PID_GRASS_NOISE_SECOND_VAL_ADD, + + PID_GRASS_DIRECT_WIND_MUL, + PID_GRASS_NOISE_WIND_MUL, + PID_GRASS_WIND_PER_LIN_FREQ, + PID_GRASS_DIRECT_WIND_FREQ, + PID_GRASS_DIRECT_WIND_MODULATION_FREQ, + PID_GRASS_WIND_WAVE_LENGTH, + PID_GRASS_WIND_TO_COLOR, + PID_GRASS_HELICOPTER_HOR_MUL, + PID_GRASS_HELICOPTER_VER_MUL, + PID_GRASS_HELICOPTER_TO_DIRECT_WIND_MUL, + PID_GRASS_HELICOPTER_FALLOFF, + + PID_SHOWMASK, + PID_ADDLAYER, + + + PID_HORIZONTAL_TEX_GRP, + PID_HORIZONTAL_TEX_NAME, + PID_HORIZONTAL_DET_TEX_NAME, + PID_HORIZONTAL_TILE_SIZE_X, + PID_HORIZONTAL_TILE_SIZE_Y, + PID_HORIZONTAL_OFFSET_X, + PID_HORIZONTAL_OFFSET_Y, + PID_HORIZONTAL_DETAIL_TILE_SIZE_X, + PID_HORIZONTAL_DETAIL_TILE_SIZE_Y, + PID_USE_HORIZONTAL_TEX, + + PID_LAND_MODULATE_TEX_TEX_GRP, + PID_LAND_MODULATE_TEX_NAME, + PID_LAND_MODULATE_EDGE0_X, + PID_LAND_MODULATE_EDGE1_X, + PID_USE_LAND_MODULATE_TEX, + + PID_RENDIST_DETAIL2_COLOR_GRP, + PID_USE_RENDIST_DETAIL2_COLOR, + PID_RENDIST_DETAIL2_COLOR_FROM, + PID_RENDIST_DETAIL2_COLOR_TO, + + PID_TILE_TEX_GRP, + PID_TILE_SIZE_X, + PID_TILE_SIZE_Y, + PID_TILE_TEX, + + PID_VERT_TEX_GRP, + PID_VERT_TEX_USE, + PID_VERT_TEX_USE_HMAP, + PID_VERT_TEX_NAME, + PID_VERT_TEX_TILE_XZ, + PID_VERT_TEX_TILE_Y, + PID_VERT_TEX_ANG0, + PID_VERT_TEX_ANG1, + PID_VERT_TEX_HBLEND, + PID_VERT_NM_TEX_NAME, + PID_VERT_TEX_Y_OFS, + PID_VERT_DET_TEX_NAME, + PID_VERT_DET_TEX_TILE_XZ, + PID_VERT_DET_TEX_TILE_Y, + PID_VERT_DET_TEX_Y_OFS, + + PID_LIGHTING_SUBDIV, + PID_LIGHTING_1, + PID_LIGHTING_2, + PID_LIGHTING_4, + + PID_LCMAP_SUBDIV, + PID_LCMAP_1, + PID_LCMAP_2, + PID_LCMAP_4, + + PID_MESH_GRP, + PID_MESH_PREVIEW, + PID_MESH_PREVIEW_DISTANCE, + PID_REBUILD_MESH, + // PID_MESH_CELL_SIZE, + PID_MESH_CELLS, + PID_MESH_ERROR_THRESHOLD, + PID_NUM_MESH_VERTICES, + PID_LOD1_DENSITY, + PID_IMPORTANCE_MASK_SCALE, + PID_WATER_SURF, + PID_WATER_SURF_LEV, + PID_MIN_UNDERWATER_BOTOM_DEPTH, + PID_WATER_SURF_REBUILD, + PID_WATER_OCEAN, + PID_WATER_OCEAN_EXPAND, + PID_WATER_OCEAN_SL_TOL, + PID_WATER_SET_MAT, + PID_DEBUG_CELLS, + PID_MONOLAND, + PID_MONOLAND_COL, + PID_GROUND_OBJECTS_COL, + PID_HTLEVELS, + PID_HTLEVELS_STEP, + PID_HTLEVELS_OFS, + PID_HTLEVELS_THICK, + PID_HTLEVELS_DARK, + + PID_SNOW_GRP, + PID_SNOW_PREVIEW, + PID_SNOW_SPHERE_PREVIEW, + PID_DYN_SNOW, + PID_COPY_SNOW, + PID_AMB_SNOW, + + PID_NAVMESH_COMMON_GRP, + PID_NAVMESH_EXPORT_START, + PID_NAVMESH_EXPORT_END = PID_NAVMESH_EXPORT_START + MAX_UI_NAVMESHES - 1, + PID_NAVMESH_SHOWN_NAVMESH, + PID_NAVMESH_EXP_SHOW, + PID_NAVMESH_COVERS_SHOW, + PID_NAVMESH_CONTOURS_SHOW, + PID_NAVMESH_OBSTACLES_SHOW, + PID_NAVMESH_DISABLE_ZTEST, + PID_NAVMESH_BUILD, + + PID_NAVMESH_START, + PID_NAVMESH_END = PID_NAVMESH_START + NM_PARAMS_COUNT * MAX_UI_NAVMESHES - 1, + + PID_GPU_GRASS_GROUP, + PID_GPU_GRASS_ENABLE, + PID_GPU_GRASS_LOADFROM_LEVELBLK, + PID_GPU_GRASS_TYPES, + PID_GPU_GRASS_MASKS, + PID_GPU_GRASS_GRID_SIZE, + PID_GPU_GRASS_DISTANCE, + PID_GPU_GRASS_MASK_RESOLUTION, + PID_GPU_GRASS_HOR_SIZE_MUL, + PID_GPU_GRASS_ADD_TYPE, + PID_GPU_GRASS_REMOVE_TYPE, + PID_GPU_GRASS_RENAME_TYPE, + PID_GPU_GRASS_TYPE_START, + PID_GPU_GRASS_TYPE_END = PID_GPU_GRASS_TYPE_START + GRASS_MAX_TYPES * (int)GPUGrassTypePID::COUNT, + PID_GPU_GRASS_ADD_DECAL, + PID_GPU_GRASS_REMOVE_DECAL, + PID_GPU_GRASS_RENAME_DECAL, + PID_GPU_GRASS_DECAL_START, + PID_GPU_GRASS_DECAL_END = PID_GPU_GRASS_DECAL_START + GRASS_MAX_CHANNELS * (int)GPUGrassDecalPID::COUNT +}; + + +#endif //__GAIJIN_GRASS_CM__ diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlEditorEH.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlEditorEH.cpp new file mode 100644 index 000000000..c36f1ecd6 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlEditorEH.cpp @@ -0,0 +1,1543 @@ +#include "hmlObjectsEditor.h" +#include "hmlPlugin.h" +#include "hmlSplineObject.h" +#include "hmlSplinePoint.h" +#include "hmlHoleObject.h" +#include "hmlSplineUndoRedo.h" +#include "hmlCm.h" +#include "common.h" +#include "hmlEntity.h" +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include + +using hdpi::_pxScaled; + +#define MAX_TRACE_DIST 10000 + +static Ptr startPt = NULL, dispPt = NULL; +static SplineObject *refSpline = NULL, *splPoly = NULL; +static int pointsCnt = 0; +static bool splittingPolyFirstPoint = true; +static int splittingFirstPointId, splittingSecondPointId; + +inline bool is_creating_entity_mode(int m) { return m == CM_CREATE_ENTITY; } + + +SplineObject *HmapLandObjectEditor::findSplineAndDirection(IGenViewportWnd *wnd, SplinePointObject *p, bool &dirs_equal, + SplineObject *excl) +{ + for (int i = 0; i < splines.size(); i++) + { + if (!splines[i]->points.size() || splines[i] == excl || splines[i]->isPoly() || splines[i]->isClosed()) + continue; + + real screenDist = screenDistBetweenPoints(wnd, p, splines[i]->points[0]); + if (screenDist >= 0 && screenDist <= 25) + { + dirs_equal = true; + return splines[i]; + } + else + { + screenDist = screenDistBetweenPoints(wnd, p, splines[i]->points[splines[i]->points.size() - 1]); + if (screenDist >= 0 && screenDist <= 25) + { + dirs_equal = false; + return splines[i]; + } + } + } + + return NULL; +} + + +void HmapLandObjectEditor::handleKeyPress(IGenViewportWnd *wnd, int vk, int modif) +{ + if (is_creating_entity_mode(getEditMode()) && wingw::is_key_pressed(wingw::V_ALT)) + { + newObj->setPlaceOnCollision(true); + wnd->invalidateCache(); + return; + } + + if (wingw::is_key_pressed(wingw::V_F1)) + { + onClick(CM_SPLINE_REGEN, NULL); + return; + } + + if (wingw::is_key_pressed(wingw::V_F2)) + { + onClick(CM_REBUILD_SPLINES_BITMASK, NULL); + return; + } + + if (wingw::is_key_pressed(wingw::V_CONTROL)) + switch (vk) + { + case '1': onClick(CM_SELECT_PT, NULL); return; + case '2': onClick(CM_SELECT_SPLINES, NULL); return; + case '3': onClick(CM_SELECT_ENT, NULL); return; + case '4': onClick(CM_SELECT_LT, NULL); return; + case '5': onClick(CM_SELECT_SNOW, NULL); return; + case '6': setSelectMode(-1); return; + case '7': onClick(CM_SELECT_SPL_ENT, NULL); return; + case '0': onClick(CM_HIDE_SPLINES, NULL); return; + } + return __super::handleKeyPress(wnd, vk, modif); +} + +void HmapLandObjectEditor::handleKeyRelease(IGenViewportWnd *wnd, int vk, int modif) +{ + if (is_creating_entity_mode(getEditMode()) && !wingw::is_key_pressed(wingw::V_ALT)) + { + newObj->setPlaceOnCollision(false); + wnd->invalidateCache(); + return; + } + return __super::handleKeyRelease(wnd, vk, modif); +} + +bool HmapLandObjectEditor::handleMouseMove(IGenViewportWnd *wnd, int x, int y, bool inside, int buttons, int key_modif) +{ + if (objCreator) + return objCreator->handleMouseMove(wnd, x, y, inside, buttons, key_modif, false); + + if (inside) + { + Point3 pos; + if (getEditMode() == CM_CREATE_SPLINE || getEditMode() == CM_CREATE_POLYGON) + { + const bool placeOnRiCollision = static_cast(wingw::get_modif() & wingw::M_SHIFT); + if (curPt && findTargetPos(wnd, x, y, pos, placeOnRiCollision)) + { + if (DAGORED2->getGrid().getMoveSnap()) + pos = DAGORED2->snapToGrid(pos); + + curPt->setPos(pos); + + bool is = false; + if (wingw::is_key_pressed(wingw::V_CONTROL)) + for (int i = 0; i < splines.size(); i++) + { + for (int j = 0; j < splines[i]->points.size(); j++) + { + if (curPt == splines[i]->points[j]) + continue; + + real ddist = screenDistBetweenPoints(wnd, curPt, splines[i]->points[j]); + if (ddist <= 9 && ddist > 0) + { + is = true; + curPt->setPos(splines[i]->points[j]->getPos()); + break; + } + } + if (is) + break; + } + } + + if (getEditMode() == CM_CREATE_SPLINE) + { + recalcCatmul(); + if (curSpline) + curSpline->pointChanged(curSpline->points.size() - 1); + } + } + else if (getEditMode() == CM_SPLIT_SPLINE) + { + bool is = false; + for (int i = 0; i < splines.size(); i++) + { + if (!splines[i]->points.size() || splines[i]->isPoly() || splines[i]->isClosed()) + continue; + + for (int j = 0; j < splines[i]->points.size(); j++) + { + if (splines[i]->points[j]->arrId <= 0 || splines[i]->points[j]->arrId + 1 >= splines[i]->points.size()) + continue; + + real dist = screenDistBetweenCursorAndPoint(wnd, x, y, splines[i]->points[j]); + if (dist > 0 && dist <= 20) + { + curPt->setPos(splines[i]->points[j]->getPt()); + curPt->visible = true; + dispPt = splines[i]->points[j]; + is = true; + break; + } + } + + if (is) + break; + } + + if (!is) + { + curPt->visible = false; + dispPt = NULL; + } + } + else if (getEditMode() == CM_REFINE_SPLINE) + { + bool is = false; + for (int i = 0; i < splines.size(); i++) + { + Point3 p; + real refT; + int segId; + + bool hasTarget = splines[i]->getPosOnSpline(wnd, x, y, 4, &segId, &refT, &p); + + if (hasTarget && segId >= 0) + { + curPt->visible = true; + refSpline = splines[i]; + curPt->setPos(p); + curPt->arrId = segId + 1; + is = true; + + break; + } + } + if (!is) + { + curPt->visible = false; + refSpline = NULL; + } + } + else if (is_creating_entity_mode(getEditMode())) + { + newObj->setPlaceOnCollision(wingw::is_key_pressed(wingw::V_ALT)); + return __super::handleMouseMove(wnd, x, y, inside, buttons, key_modif); + } + else if (getEditMode() == CM_SPLIT_POLY) + { + bool is = false; + for (int i = 0; i < splines.size(); i++) + { + if (!splines[i]->points.size() || !splines[i]->isPoly()) + continue; + + for (int j = 0; j < splines[i]->points.size(); j++) + { + if (!splittingPolyFirstPoint) + { + int nextIdx = (splittingFirstPointId + 1) % splines[i]->points.size(); + int prevIdx = (splittingFirstPointId == 0 ? splines[i]->points.size() - 1 : splittingFirstPointId - 1); + if (j == splittingFirstPointId || j == nextIdx || j == prevIdx) + continue; + } + + real dist = screenDistBetweenCursorAndPoint(wnd, x, y, splines[i]->points[j]); + if (dist > 0 && dist <= 20) + { + Point3 p = splines[i]->points[j]->getPt(); + curPt->visible = true; + splPoly = splines[i]; + curPt->setPos(p); + if (!splittingPolyFirstPoint && debugP2) + *debugP2 = p; + is = true; + + break; + } + } + + if (is) + break; + } + + if (!is) + { + curPt->visible = false; + splPoly = NULL; + + if (debugP2) + { + Point3 dir, p0; + wnd->clientToWorld(Point2(x, y), p0, dir); + real dist = MAX_TRACE_DIST; + if (IEditorCoreEngine::get()->traceRay(p0, dir, dist, NULL)) + *debugP2 = p0 + dir * dist; + } + } + } + else + return false; + + updateGizmo(); + wnd->invalidateCache(); + } + return __super::handleMouseMove(wnd, x, y, inside, buttons, key_modif); +} + +bool HmapLandObjectEditor::usesRendinstPlacement() const +{ + if (!selection.size()) + return false; + for (int i = 0; i < selection.size(); i++) + { + LandscapeEntityObject *leo = RTTI_cast(selection[0]); + if (!leo || !leo->usesRendinstPlacement()) + return false; + } + return true; +} + +bool HmapLandObjectEditor::handleMouseLBPress(IGenViewportWnd *wnd, int x, int y, bool inside, int buttons, int key_modif) +{ + if (objCreator) + return objCreator->handleMouseLBPress(wnd, x, y, inside, buttons, key_modif); + + if (inside && wnd->isActive()) + { + wnd->invalidateCache(); + + if (getEditMode() == CM_CREATE_SPLINE || getEditMode() == CM_CREATE_POLYGON) + { + Ptr newPt = new SplinePointObject; + bool needReverse = false, wasResumed = false; + ; + newPt->setPos(curPt->getPos()); + + if (!startPt) + { + if (getEditMode() == CM_CREATE_SPLINE) + { + bool dirsEqual; + SplineObject *resumeS = findSplineAndDirection(wnd, newPt, dirsEqual); + if (resumeS) + { + if (wingw::message_box(wingw::MBS_YESNO | wingw::MBS_QUEST, "Confirmation", "Continue spline \"%s\"?", + resumeS->getName()) == wingw::MB_ID_YES) + { + pointsCnt = resumeS->points.size(); + if (dirsEqual) + needReverse = true; + + curSpline = resumeS; + wasResumed = true; + } + else + { + curSpline = NULL; + } + } + } + + if (!curSpline) + { + pointsCnt = 1; + curSpline = new SplineObject(getEditMode() == CM_CREATE_POLYGON); + curSpline->setEditLayerIdx(EditLayerProps::activeLayerIdx[curSpline->lpIndex()]); + if (wingw::is_key_pressed(wingw::V_SHIFT)) + curSpline->setCornerType(-1); + curSpline->selectObject(); + splines.push_back(curSpline); + } + + if (curSpline) + { + getUndoSystem()->begin(); + + if (needReverse) + { + curSpline->reverse(); + + Tab spls(tmpmem); + spls.resize(1); + spls[0] = curSpline; + + getUndoSystem()->put(new UndoReverse(spls)); + } + + if (!curSplineAsset.empty()) + { + String objname(128, "%s_001", curSplineAsset.str()); + setUniqName(curSpline, objname); + } + addObject(curSpline); + + curPt->arrId = curSpline->points.size(); + curPt->spline = curSpline; + + curSpline->addPoint(curPt); + if (curSpline->points.size() == 1) + curSpline->changeAsset(curSplineAsset, false); + } + + startPt = newPt; + } + else + { + if (getEditMode() == CM_CREATE_SPLINE) + { + bool dirsEqual; + SplineObject *att = findSplineAndDirection(wnd, newPt, dirsEqual, curSpline); + + if (att) + { + if (wingw::message_box(wingw::MBS_YESNO | wingw::MBS_QUEST, "Confirmation", "Attach spline to\"%s\"?", att->getName()) == + wingw::MB_ID_YES) + { + if (!dirsEqual) + { + att->reverse(); + + Tab spls(tmpmem); + spls.resize(1); + spls[0] = att; + + getUndoSystem()->put(new UndoReverse(spls)); + } + + pointsCnt += att->points.size(); + int pt_idx = curSpline->points.size() - 2; + att->attachTo(curSpline, curSpline->points.size() - 1); + + memset(catmul, 0, sizeof(catmul)); + prepareCatmul(curSpline->points[pt_idx], curPt); + + curSpline->pointChanged(-1); + curSpline->getSpline(); + + handleMouseRBPress(wnd, x, y, inside, buttons, key_modif); + return true; + } + } + } + + pointsCnt++; + } + + if (curSpline) + { + if (!wasResumed) + { + if (curSpline->points.size() > 2) + { + real scrDist = screenDistBetweenPoints(wnd, newPt, curSpline->points[0]); + if (scrDist >= 0 && scrDist <= 25 && + wingw::message_box(wingw::MBS_YESNO | wingw::MBS_QUEST, "Confirmation", + curSpline->isPoly() ? "Close polygon?" : "Close spline?") == wingw::MB_ID_YES) + { + for (int i = 0; i < curSpline->points.size(); i++) + if (curSpline->points[i] == curPt) + { + curSpline->onPointRemove(i); + break; + } + + if (getEditMode() == CM_CREATE_SPLINE) + { + getUndoSystem()->put(curSpline->makePointListUndo()); + curSpline->points.push_back(curSpline->points[0]); + curSpline->pointChanged(curSpline->points.size() - 1); + } + + getUndoSystem()->accept(curSpline->isPoly() ? "Create polygon" : "Create spline"); + + memset(catmul, 0, sizeof(catmul)); + + if (curSpline) + curSpline->onCreated(); + + startPt = NULL; + setEditMode(CM_OBJED_MODE_SELECT); + + return true; + } + } + + newPt->spline = curSpline; + newPt->arrId = curSpline->points.size() - 1; + + addObject(newPt); + + if (getEditMode() == CM_CREATE_SPLINE) + prepareCatmul(newPt, curPt); + } + + if (newPt) + newPt->markChanged(); + if (curPt) + curPt->markChanged(); + } + + return true; + } + else if (getEditMode() == CM_SPLIT_SPLINE) + { + if (curPt && curPt->visible && dispPt) + { + SplineObject *s = dispPt->spline; + if (s) + s->split(dispPt->arrId); + } + } + else if (getEditMode() == CM_REFINE_SPLINE) + { + if (curPt->visible && refSpline) + { + real refT; + int segId; + Point3 p; + refSpline->getPosOnSpline(wnd, x, y, 4, &segId, &refT, &p); + + refSpline->refine(segId, refT, p); + } + } + else if (getEditMode() == CM_SPLIT_POLY) + { + if (curPt->visible && splPoly) + { + for (int j = 0; j < splPoly->points.size(); j++) + { + real dist = screenDistBetweenCursorAndPoint(wnd, x, y, splPoly->points[j]); + if (dist > 0 && dist <= 20) + { + if (splittingPolyFirstPoint) + { + splittingPolyFirstPoint = false; + + debugP1 = new Point3; + debugP2 = new Point3; + + splittingFirstPointId = j; + + *debugP1 = splPoly->points[splittingFirstPointId]->getPt(); + *debugP2 = splPoly->points[splittingFirstPointId]->getPt(); + } + else + { + splittingSecondPointId = j; + + int nextIdx = (j + 1) % splPoly->points.size(); + int prevIdx = (j == 0 ? splPoly->points.size() - 1 : j - 1); + + if (splittingFirstPointId != splittingSecondPointId && splittingFirstPointId != nextIdx && + splittingFirstPointId != prevIdx) + { + splPoly->splitOnTwoPolys(splittingFirstPointId, splittingSecondPointId); + + splittingPolyFirstPoint = true; + setEditMode(CM_OBJED_MODE_SELECT); + + del_it(debugP1); + del_it(debugP2); + } + } + } + } + } + } + else + __super::handleMouseLBPress(wnd, x, y, inside, buttons, key_modif); + } + else + __super::handleMouseLBPress(wnd, x, y, inside, buttons, key_modif); + + updateGizmo(); + return true; +} + +bool HmapLandObjectEditor::handleMouseRBPress(IGenViewportWnd *wnd, int x, int y, bool inside, int buttons, int key_modif) +{ + if (objCreator) + return objCreator->handleMouseRBPress(wnd, x, y, inside, buttons, key_modif); + + bool l_result = false; + + if (getEditMode() == CM_CREATE_SPLINE || getEditMode() == CM_CREATE_POLYGON) + { + if (pointsCnt > 0) + { + if ((getEditMode() == CM_CREATE_POLYGON && pointsCnt < 3) || (getEditMode() == CM_CREATE_SPLINE && pointsCnt < 2)) + { + getUndoSystem()->cancel(); + curSpline = NULL; + } + else if (startPt && curSpline) + { + for (int i = 0; i < curSpline->points.size(); i++) + if (curSpline->points[i] == curPt) + { + curSpline->onPointRemove(i); + break; + } + + getUndoSystem()->accept(curSpline->isPoly() ? "Create polygon" : "Create spline"); + } + } + + memset(catmul, 0, sizeof(catmul)); + curPt->spline = NULL; + + if (curSpline) + curSpline->onCreated(); + + startPt = NULL; + + setEditMode(CM_OBJED_MODE_SELECT); + + setButton(CM_CREATE_SPLINE, false); + setButton(CM_CREATE_POLYGON, false); + wnd->invalidateCache(); + + l_result = true; + } + else if (getEditMode() == CM_SPLIT_SPLINE) + { + setEditMode(CM_OBJED_MODE_SELECT); + } + else if (is_creating_entity_mode(getEditMode())) + { + if (buttons & 1) + return __super::handleMouseRBPress(wnd, x, y, inside, buttons, key_modif); + setCreateBySampleMode(NULL); + selectNewObjEntity(NULL); + setEditMode(CM_OBJED_MODE_SELECT); + + l_result = true; + } + else if (getEditMode() == CM_SPLIT_POLY) + { + if (!splittingPolyFirstPoint) + { + splittingPolyFirstPoint = true; + setEditMode(CM_OBJED_MODE_SELECT); + } + } + + del_it(debugP1); + del_it(debugP2); + + setEditMode(CM_OBJED_MODE_SELECT); + return (l_result) ? true : __super::handleMouseRBPress(wnd, x, y, inside, buttons, key_modif); +} + + +bool HmapLandObjectEditor::handleMouseLBRelease(IGenViewportWnd *wnd, int x, int y, bool inside, int buttons, int key_modif) +{ + if (objCreator) + return objCreator->handleMouseLBRelease(wnd, x, y, inside, buttons, key_modif); + + if (inside && wnd->isActive()) + wnd->invalidateCache(); + + bool needResetRenderer = false; + + if (objectWasMoved || objectWasRotated || objectWasScaled) + { + Tab transfSplines(tmpmem); + Tab transfPoints(tmpmem); + + for (int i = 0; i < selection.size(); i++) + { + SplineObject *s = RTTI_cast(selection[i]); + if (s) + { + bool is = false; + for (int j = 0; j < transfSplines.size(); j++) + if (transfSplines[j] == s) + { + is = true; + break; + } + + if (!is) + transfSplines.push_back(s); + } + else if (objectWasMoved) + { + SplinePointObject *p = RTTI_cast(selection[i]); + + if (p) + { + bool is = false; + for (int j = 0; j < transfSplines.size(); j++) + if (transfSplines[j] == p->spline) + { + is = true; + break; + } + + if (!is) + transfPoints.push_back(p); + } + } + + HmapLandHoleObject *ho = RTTI_cast(selection[i]); + if (ho && objectWasScaled) + needResetRenderer = true; + } + + if (needResetRenderer) + { + invalidateObjectProps(); + HmapLandPlugin::self->resetRenderer(); + } + + Tab modifSplines(tmpmem); + for (int i = 0; i < transfSplines.size(); i++) + { + SplineObject *s = transfSplines[i]; + if (s->isAffectingHmap()) + modifSplines.push_back(s); + } + + for (int i = 0; i < transfPoints.size(); i++) + { + SplinePointObject *p = transfPoints[i]; + if (p->spline->isAffectingHmap()) + { + bool is = false; + for (int j = 0; j < modifSplines.size(); j++) + if (p->spline == modifSplines[i]) + { + is = true; + break; + } + + if (!is) + modifSplines.push_back(p->spline); + } + } + + for (int i = 0; i < transfPoints.size(); i++) + transfPoints[i]->spline->pointChanged(transfPoints[i]->arrId); + + if (modifSplines.size()) + { + for (int i = 0; i < modifSplines.size(); i++) + modifSplines[i]->markModifChanged(); + HmapLandPlugin::self->applyHmModifiers(); + } + + for (int i = 0; i < transfSplines.size(); i++) + transfSplines[i]->pointChanged(-1); + } + + objectWasMoved = objectWasRotated = objectWasScaled = false; + + return __super::handleMouseLBRelease(wnd, x, y, inside, buttons, key_modif); +} + +HmapLandObjectEditor::PlacementRotation HmapLandObjectEditor::buttonIdToPlacementRotation(int id) +{ + G_ASSERT(id >= CM_ROTATION_NONE && id <= CM_ROTATION_Z); + return static_cast(id - CM_ROTATION_X); +} + +void HmapLandObjectEditor::onClick(int pcb_id, PropPanel2 *panel) +{ + bool ctrl_pressed = wingw::is_key_pressed(wingw::V_CONTROL); + switch (pcb_id) + { + case CM_OBJED_MODE_SELECT: + case CM_OBJED_MODE_MOVE: + case CM_OBJED_MODE_SURF_MOVE: + case CM_OBJED_MODE_ROTATE: + case CM_OBJED_MODE_SCALE: + if (getEditMode() == CM_CREATE_SPLINE || getEditMode() == CM_CREATE_POLYGON) + return; + setEditMode(pcb_id); + updateGizmo(); + break; + + case CM_SHOW_PANEL: HmapLandPlugin::self->onPluginMenuClick(pcb_id); break; + + case CM_SHOW_LAND_OBJECTS: + areLandHoleBoxesVisible = !areLandHoleBoxesVisible; + updateToolbarButtons(); + DAGORED2->repaint(); + break; + case CM_HIDE_SPLINES: + hideSplines = !hideSplines; + updateToolbarButtons(); + DAGORED2->repaint(); + break; + + case CM_HILL_UP: + case CM_HILL_DOWN: + case CM_ALIGN: + case CM_SMOOTH: + case CM_SHADOWS: + case CM_SCRIPT: HmapLandPlugin::self->onPluginMenuClick(pcb_id); break; + + case CM_CREATE_HOLEBOX_MODE: + case CM_CREATE_LT: + case CM_CREATE_SNOW_SOURCE: setEditMode(pcb_id); break; + + case CM_CREATE_ENTITY: + setEditMode(pcb_id); + if (!newObj.get()) + { + newObj = new LandscapeEntityObject(NULL); + newObj->setEditLayerIdx(EditLayerProps::activeLayerIdx[newObj->lpIndex()]); + newObj->setCollisionIgnored(); + } + setCreateBySampleMode(newObj); + DAEDITOR3.showAssetWindow(true, "Select entity to create", this, DAEDITOR3.getGenObjAssetTypes()); + break; + + case CM_ROTATION_NONE: + case CM_ROTATION_X: + case CM_ROTATION_Y: + case CM_ROTATION_Z: selectedPlacementRotation = buttonIdToPlacementRotation(pcb_id); break; + + case CM_CREATE_SPLINE: + case CM_CREATE_POLYGON: + pointsCnt = 0; + setEditMode(pcb_id); + curPt = new SplinePointObject; + unselectAll(); + + { + int t = DAEDITOR3.getAssetTypeId(pcb_id == CM_CREATE_SPLINE ? "spline" : "land"); + + DAEDITOR3.showAssetWindow(true, pcb_id == CM_CREATE_SPLINE ? "Assign asset to spline" : "Assign asset to polygon", this, + make_span_const(&t, 1)); + } + break; + + case CM_REFINE_SPLINE: + setEditMode(pcb_id); + curPt = new SplinePointObject; + curPt->visible = false; + break; + + case CM_SPLIT_SPLINE: + if (selection.size() == 1 && RTTI_cast(selection[0])) + { + SplinePointObject *p = RTTI_cast(selection[0]); + if (p->spline->isClosed()) + onClick(CM_OPEN_SPLINE, panel); + else + p->spline->split(p->arrId); + break; + } + DAEDITOR3.conWarning("invalid selection for split command:" + " must be selected exactly one point to split at"); + + // setEditMode(cmd); + // curPt = new SplinePointObject; + // curPt->visible = false; + break; + + case CM_SPLIT_POLY: + setEditMode(pcb_id); + curPt = new SplinePointObject; + curPt->visible = false; + break; + + case CM_REVERSE_SPLINE: + { + setEditMode(CM_OBJED_MODE_SELECT); + Tab spl(tmpmem); + + for (int i = 0; i < selection.size(); i++) + { + if (SplineObject *s = RTTI_cast(selection[i])) + { + bool is = false; + for (int j = 0; j < spl.size(); j++) + if (spl[j] == s) + { + is = true; + break; + } + + if (!is) + spl.push_back(s); + } + else if (SplinePointObject *p = RTTI_cast(selection[i])) + { + bool is = false; + for (int j = 0; j < spl.size(); j++) + if (spl[j] == p->spline) + { + is = true; + break; + } + + if (!is) + spl.push_back(p->spline); + } + } + + if (!spl.size()) + break; + + getUndoSystem()->begin(); + + for (int i = 0; i < spl.size(); i++) + spl[i]->reverse(); + + getUndoSystem()->put(new UndoReverse(spl)); + getUndoSystem()->accept("Reverse spline(s)"); + } + break; + + case CM_CLOSE_SPLINE: + { + setEditMode(CM_OBJED_MODE_SELECT); + Tab spl(tmpmem); + + for (int i = 0; i < selection.size(); i++) + { + SplineObject *s = RTTI_cast(selection[i]); + if (s && !s->isPoly() && !s->isClosed()) + spl.push_back(s); + } + + if (!spl.size()) + { + DAEDITOR3.conWarning("No splines selected to be closed"); + break; + } + + getUndoSystem()->begin(); + + for (int i = 0; i < spl.size(); i++) + { + getUndoSystem()->put(spl[i]->makePointListUndo()); + spl[i]->points.push_back(spl[i]->points[0]); + spl[i]->pointChanged(spl[i]->points.size() - 1); + } + + getUndoSystem()->accept("Close spline(s)"); + } + break; + + case CM_OPEN_SPLINE: + { + setEditMode(CM_OBJED_MODE_SELECT); + Tab pt(tmpmem); + + for (int i = 0; i < selection.size(); i++) + { + SplinePointObject *p = RTTI_cast(selection[i]); + + if (p && !p->spline->isPoly() && p->spline->isClosed()) + pt.push_back(p); + } + + if (!pt.size()) + { + DAEDITOR3.conWarning("No points selected for splines to be open"); + break; + } + + getUndoSystem()->begin(); + + for (int i = 0; i < pt.size(); i++) + { + if (!pt[i]->spline->isClosed()) + continue; + + SplineObject &s = *pt[i]->spline; + getUndoSystem()->put(s.makePointListUndo()); + + PtrTab spt(midmem); + s.points.pop_back(); + + spt.reserve(s.points.size() + 1); + + SplinePointObject::Props s_props = s.points[pt[i]->arrId]->getProps(); + for (int j = pt[i]->arrId; j < s.points.size(); j++) + { + s.points[j]->arrId = spt.size(); + spt.push_back(s.points[j]); + } + for (int j = 0; s.points[j] != pt[i]; j++) + { + s.points[j]->arrId = spt.size(); + spt.push_back(s.points[j]); + } + + SplinePointObject *p = new SplinePointObject; + p->setProps(s_props); + p->setPos(s_props.pt); + p->arrId = spt.size(); + spt.push_back(p); + p->spline = &s; + addObject(p); + + s.points = spt; + pt[i]->markChanged(); + + spt.clear(); + } + + getUndoSystem()->accept("Open spline(s)"); + } + break; + + case CM_SELECT_PT: + case CM_SELECT_SPLINES: + case CM_SELECT_ENT: + case CM_SELECT_SPL_ENT: + case CM_SELECT_LT: + case CM_SELECT_SNOW: + setEditMode(CM_OBJED_MODE_SELECT); + setSelectMode(selectMode == pcb_id ? -1 : pcb_id); + return; + + case CM_OBJED_DROP: + { + setEditMode(CM_OBJED_MODE_SELECT); + Tab pts(tmpmem); + + for (int i = 0; i < selection.size(); i++) + { + SplinePointObject *p = RTTI_cast(selection[i]); + if (p) + { + bool is = false; + for (int j = 0; j < pts.size(); j++) + if (pts[j] == p) + { + is = true; + break; + } + + if (!is) + pts.push_back(p); + } + else + { + SplineObject *s = RTTI_cast(selection[i]); + if (s) + { + for (int j = 0; j < s->points.size(); j++) + { + bool is = false; + for (int k = 0; k < pts.size(); k++) + if (s->points[j] == pts[k]) + { + is = true; + break; + } + + if (!is) + pts.push_back(s->points[j]); + } + } + } + } + + if (!pts.size()) + break; + + getUndoSystem()->begin(); + + const Point3 dir = Point3(0, -1, 0); + + for (int i = 0; i < pts.size(); i++) + { + float dist = 2.f * DAGORED2->getMaxTraceDistance(); +#if defined(USE_HMAP_ACES) + const Point3 pos = pts[i]->getPos() + Point3(0, dist / 2, 0); +#else + const Point3 pos = pts[i]->getPos() + Point3(0, 0.2, 0); +#endif + + if (IEditorCoreEngine::get()->traceRay(pos, dir, dist)) + { + pts[i]->putMoveUndo(); + pts[i]->setPos(pos + dir * dist); + } + } + + getUndoSystem()->accept("Drop object(s)"); + + updateGizmo(); + DAGORED2->repaint(); + updateToolbarButtons(); + + return; + } + + case CM_SPLINE_EXPORT_TO_DAG: + setEditMode(CM_OBJED_MODE_SELECT); + exportToDag(); + break; + + case CM_EXPORT_AS_COMPOSIT: + setEditMode(CM_OBJED_MODE_SELECT); + exportAsComposit(); + break; + + case CM_SPLIT_COMPOSIT: + setEditMode(CM_OBJED_MODE_SELECT); + splitComposits(); + break; + + case CM_INSTANTIATE_GENOBJ_INTO_ENTITIES: + setEditMode(CM_OBJED_MODE_SELECT); + instantiateGenToEntities(); + break; + + case CM_SPLINE_IMPORT_FROM_DAG: + setEditMode(CM_OBJED_MODE_SELECT); + importFromDag(); + break; + + case CM_HIDE_UNSELECTED_SPLINES: + splines.clear(); + for (int i = 0; i < objects.size(); i++) + if (SplineObject *s = RTTI_cast(objects[i])) + { + bool used = s->isSelected(); + if (!used) + for (int j = 0; j < selection.size(); ++j) + if (SplinePointObject *o = RTTI_cast(selection[j])) + if (o->spline == s) + { + used = true; + break; + } + s->splineInactive = !used; + if (!s->splineInactive) + splines.push_back(s); + } + break; + case CM_UNHIDE_ALL_SPLINES: + splines.clear(); + for (int i = 0; i < objects.size(); i++) + if (SplineObject *s = RTTI_cast(objects[i])) + { + if (s->splineInactive) + { + s->splineInactive = false; + s->modifChanged = true; + s->splineChanged = true; + splinesChanged = true; + DAGORED2->invalidateViewportCache(); + HmapLandPlugin::hmlService->invalidateClipmap(true); + } + splines.push_back(s); + } + break; + + case CM_COLLAPSE_MODIFIERS: + { + setEditMode(CM_OBJED_MODE_SELECT); + Tab spls(tmpmem); + for (int i = 0; i < selection.size(); ++i) + { + SplineObject *o = RTTI_cast(selection[i]); + if (!o) + continue; + + if (o->isAffectingHmap()) + spls.push_back(o); + } + + if (spls.size()) + { + HmapLandPlugin::self->collapseModifiers(spls); + invalidateObjectProps(); + } + else if (!selection.size()) + { + if (wingw::message_box(wingw::MBS_YESNO, "Confirmation", "No objects selected, copy all HMAP final to initial?") == + wingw::MB_ID_YES) + HmapLandPlugin::self->copyFinalHmapToInitial(); + } + else + wingw::message_box(wingw::MBS_EXCL, "Warning", "No splines selected for collapse!"); + + break; + } + + case CM_MAKE_SPLINES_CROSSES: + { + setEditMode(CM_OBJED_MODE_SELECT); + Tab spls(tmpmem); + for (int i = 0; i < selection.size(); ++i) + { + SplineObject *o = RTTI_cast(selection[i]); + if (!o) + continue; + + if (!o->isPoly()) + spls.push_back(o); + } + + if (!spls.size()) + wingw::message_box(wingw::MBS_EXCL, "Warning", "No splines selected for collapse!"); + else + { + int num = SplineObject::makeSplinesCrosses(spls); + invalidateObjectProps(); + wingw::message_box(wingw::MBS_INFO, "Results", "Added %d new point(s) at detected crosses of %d spline(s)", num, spls.size()); + } + break; + } + + case CM_UNIFY_OBJ_NAMES: + { + Tab spl(tmpmem); + Tab ent(tmpmem); + + if (!selection.size()) + { + if ( + wingw::message_box(wingw::MBS_YESNO, "Confirmation", "No objects selected, unify names for ALL object?") != wingw::MB_ID_YES) + break; + for (int i = 0; i < objects.size(); ++i) + if (SplineObject *o = RTTI_cast(objects[i])) + spl.push_back(o); + else if (LandscapeEntityObject *o = RTTI_cast(objects[i])) + ent.push_back(o); + } + else + for (int i = 0; i < selection.size(); ++i) + if (SplineObject *o = RTTI_cast(selection[i])) + spl.push_back(o); + else if (LandscapeEntityObject *o = RTTI_cast(selection[i])) + ent.push_back(o); + + if (spl.size() + ent.size()) + { + if (selection.size() && wingw::message_box(wingw::MBS_YESNO, "Confirmation", + "Unify names for %d selected splines and %d entities?", spl.size(), ent.size()) != wingw::MB_ID_YES) + break; + } + else + { + wingw::message_box(wingw::MBS_EXCL, "Warning", "No objects selected for names unification!"); + break; + } + + // clear names + for (int i = 0; i < spl.size(); ++i) + spl[i]->setName(""); + for (int i = 0; i < ent.size(); ++i) + ent[i]->setName(""); + + // build enumerated names + setSuffixDigitsCount(3); + for (int i = 0; i < spl.size(); ++i) + setUniqName(spl[i], + String(0, "%s_%03d", spl[i]->getProps().blkGenName.empty() ? "spline" : spl[i]->getProps().blkGenName.str(), i)); + for (int i = 0; i < ent.size(); ++i) + setUniqName(ent[i], + String(0, "%s_%03d", ent[i]->getProps().entityName.empty() ? "entity" : ent[i]->getProps().entityName.str(), i)); + + wingw::message_box(wingw::MBS_INFO, "Success", "Names of %d objects unified!", spl.size() + ent.size()); + break; + } + + case CM_MANUAL_SPLINE_REGEN_MODE: + autoUpdateSpline = !autoUpdateSpline; + updateToolbarButtons(); + DAGORED2->repaint(); + break; + + case CM_LAYERS_DLG: + if (layersDlg.isVisible()) + layersDlg.hide(); + else + layersDlg.show(); + break; + + case CM_SPLINE_REGEN: + if (ctrl_pressed) + { + int s_num = 0, p_num = 0; + for (int i = 0; i < selection.size(); i++) + if (RTTI_cast(selection[i])) + { + RTTI_cast(selection[i])->pointChanged(-1); + s_num++; + } + else if (RTTI_cast(selection[i])) + { + RTTI_cast(selection[i])->markChanged(); + p_num++; + } + if (s_num + p_num) + DAEDITOR3.conNote("Invalidated %d spline(s), %d point(s)", s_num, p_num); + } + + updateSplinesGeom(); + + if (ctrl_pressed) + for (int i = 0; i < selection.size(); i++) + if (LandscapeEntityObject *o = RTTI_cast(selection[i])) + o->updateEntityPosition(true); + + DAGORED2->invalidateViewportCache(); + break; + + case CM_REBUILD_SPLINES_BITMASK: + HmapLandPlugin::self->rebuildSplinesBitmask(); + DAGORED2->invalidateViewportCache(); + break; + + case CM_MOVE_OBJECTS: + if (objects.size()) + { + CDialogWindow *dlg = DAGORED2->createDialog(_pxScaled(250), _pxScaled(190), "Move multiple objects..."); + PropPanel2 &panel = *dlg->getPanel(); + if (selection.size()) + panel.createStatic(-1, String(0, "Move %d object(s)", selection.size())); + else + panel.createStatic(-1, String(0, "No selection, move all (%d) objects", objects.size())); + panel.createEditFloat(1, "Move X", 0); + panel.createEditFloat(2, "Move Y", 0); + panel.createEditFloat(3, "Move Z", 0); + + if (dlg->showDialog() == DIALOG_ID_OK) + { + getUndoSystem()->begin(); + moveObjects(selection.size() ? selection : objects, Point3(panel.getFloat(1), panel.getFloat(2), panel.getFloat(3)), + IEditorCoreEngine::BASIS_World); + getUndoSystem()->accept("Move objects"); + DAGORED2->invalidateViewportCache(); + } + del_it(dlg); + } + break; + } + + updateGizmo(); + updateToolbarButtons(); + + __super::onClick(pcb_id, panel); +} + + +void HmapLandObjectEditor::autoAttachSplines() +{ + enum + { + FLOAT_EDIT_ID = 100, + }; + + CDialogWindow *dialog = DAGORED2->createDialog(_pxScaled(250), _pxScaled(100), "Attach points maximum distance"); + PropPanel2 *panel = dialog->getPanel(); + panel->createEditFloat(FLOAT_EDIT_ID, "Attach distance:", 0.3); + + if (dialog->showDialog() == DIALOG_ID_OK) + { + double value = panel->getFloat(FLOAT_EDIT_ID); + + getUndoSystem()->begin(); + + for (int i = splines.size() - 1; i >= 0; i--) + { + if (!splines[i]->points.size() || splines[i]->isPoly() || splines[i]->isClosed()) + continue; + + for (int j = splines.size() - 1; j >= 0; j--) + { + if (splines[i] == splines[j]) + continue; + + if (!splines[j]->points.size() || splines[j]->isPoly() || splines[j]->isClosed()) + continue; + + bool needReverse = false; + + Point3 diff = splines[i]->points[splines[i]->points.size() - 1]->getPt() - splines[j]->points[0]->getPt(); // *------ *------ + if (diff.length() < value) + { + removeObject(splines[i]->points[splines[i]->points.size() - 1]); + splines[j]->attachTo(splines[i]); + } + else + { + diff = splines[i]->points[0]->getPt() - splines[j]->points[0]->getPt(); // ------* *------ + if (diff.length() < value) + { + splines[i]->reverse(); + Tab spls(tmpmem); + spls.resize(1); + spls[0] = splines[i]; + getUndoSystem()->put(new UndoReverse(spls)); + + removeObject(splines[i]->points[splines[i]->points.size() - 1]); + splines[j]->attachTo(splines[i]); + } + else + { + diff = splines[i]->points[splines[i]->points.size() - 1]->getPt() - + splines[j]->points[splines[j]->points.size() - 1]->getPt(); // *------ ------* + if (diff.length() <= value) + { + splines[j]->reverse(); + Tab spls(tmpmem); + spls.resize(1); + spls[0] = splines[j]; + getUndoSystem()->put(new UndoReverse(spls)); + + removeObject(splines[i]->points[splines[i]->points.size() - 1]); + splines[j]->attachTo(splines[i]); + } + } + } + } + + splines[i]->pointChanged(-1); + splines[i]->getSpline(); + } + + getUndoSystem()->accept("Auto attach splines"); + DAGORED2->invalidateViewportCache(); + } + + DAGORED2->deleteDialog(dialog); + + updateGizmo(); + DAGORED2->repaint(); + updateToolbarButtons(); +} + +void HmapLandObjectEditor::makeBottomSplines() +{ + Tab poly(tmpmem); + + for (int i = 0; i < selection.size(); i++) + { + SplineObject *s = RTTI_cast(selection[i]); + if (s && s->isPoly()) + poly.push_back(s); + } + if (!poly.size()) + { + wingw::message_box(wingw::MBS_OK, "No polygons selected", "To build bottom lines select one or more polygons"); + return; + } + + CDialogWindow *dialog = DAGORED2->createDialog(_pxScaled(250), _pxScaled(180), "Bottom splines properties"); + PropPanel2 *panel = dialog->getPanel(); + panel->createStatic(-1, String(128, "%d polygons selected", poly.size())); + panel->createEditFloat(1, "Border width:", 40); + panel->createEditFloat(2, "Underwater depth:", 4); + panel->createEditFloat(3, "Line tolerance", 0.5); + + if (dialog->showDialog() == DIALOG_ID_OK) + { + double border_w = panel->getFloat(1); + double bottom_y = HmapLandPlugin::self->getWaterSurfLevel() - panel->getFloat(2); + double tolerance = panel->getFloat(3); + + getUndoSystem()->begin(); + for (int j = 0; j < poly.size(); j++) + { + Tab pts(tmpmem); + poly[j]->buildInnerSpline(pts, border_w, bottom_y, tolerance); + if (pts.size()) + { + SplineObject *so = new SplineObject(false); + so->setEditLayerIdx(EditLayerProps::activeLayerIdx[so->lpIndex()]); + so->setName(String(128, "%s_bottom", poly[j]->getName())); + addObject(so); + + for (int i = 0; i < pts.size(); ++i) + { + SplinePointObject *p = new SplinePointObject; + p->setPos(pts[i]); + p->arrId = i; + p->spline = so; + + addObject(p); + } + so->applyCatmull(true, true); + so->onCreated(false); + } + } + getUndoSystem()->accept("Make bottom splines"); + DAGORED2->invalidateViewportCache(); + } + DAGORED2->deleteDialog(dialog); + + updateGizmo(); + DAGORED2->repaint(); + updateToolbarButtons(); +} + +void HmapLandObjectEditor::selectNewObjEntity(const char *name) +{ + if (!newObj.get()) + return; + + LandscapeEntityObject::Props p; + p.entityName = name; + p.placeType = p.PT_coll; + if (DagorAsset *a = DAEDITOR3.getGenObjAssetByName(name)) + if (IObjEntity *entity = DAEDITOR3.createEntity(*a)) + { + if (ICompositObj *ico = entity->queryInterface()) + { + int defPlaceTypeOverride = ico->getCompositPlaceTypeOverride(); + if (defPlaceTypeOverride >= 0) + { + p.placeType = defPlaceTypeOverride; + p.overridePlaceTypeForComposit = true; + } + } + destroy_it(entity); + } + newObj->setProps(p); + if (newObj->getEntity()) + newObj->getEntity()->setSubtype(IObjEntity::ST_NOT_COLLIDABLE); + + if (!name && !is_creating_entity_mode(getEditMode())) + newObj = NULL; +} + +void HmapLandObjectEditor::createObjectBySample(RenderableEditableObject *sample) +{ + LandscapeEntityObject *o = RTTI_cast(sample); + G_ASSERT(o); + + IObjEntity *e = o->getEntity(); + if (!e) + return; + + IRandomSeedHolder *irsh = e->queryInterface(); + int rndSeed = 0; + if (irsh) + { + rndSeed = irsh->getSeed(); + irsh->setSeed(grnd()); + } + + LandscapeEntityObject *no = new LandscapeEntityObject(NULL, rndSeed); + no->setEditLayerIdx(EditLayerProps::activeLayerIdx[no->lpIndex()]); + + TMatrix tm; + e->getTm(tm); + + no->setProps(o->getProps()); + no->setSavedPlacementNormal(sample->getSavedPlacementNormal()); + no->setWtm(tm); + getUndoSystem()->begin(); + addObject(no); + unselectAll(); + no->selectObject(); + getUndoSystem()->accept("Add Entity"); + + DAEDITOR3.addAssetToRecentlyUsed(o->getProps().entityName); +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlEntity.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlEntity.cpp new file mode 100644 index 000000000..1d2c737ba --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlEntity.cpp @@ -0,0 +1,1195 @@ +#include "hmlEntity.h" +#include "hmlPlugin.h" +#include "hmlObjectsEditor.h" +#include "hmlSplineObject.h" +#include "hmlSplinePoint.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "objectParam.h" + + +static ObjectParam objParam; + + +LandscapeEntityObject::CollidersData LandscapeEntityObject::colliders; +static int default_place_type = ICompositObj::Props::PT_coll; + +enum +{ + PID_PLACE_TYPE = 100, + PID_PLACE_TYPE_OVERRIDE, + + PID_ENTITY_COLLISION, + PID_ENTITY_NOTES, + PID_ENTITY_CASTER_GRP, + PID_ENTITY_CASTER_FIRST, + PID_ENTITY_CASTER_LAST = PID_ENTITY_CASTER_FIRST + 200, + + PID_ENTITY_USE_FILTER, + PID_ENTITY_FILTER_GRP, + PID_ENTITY_FILTER_FIRST, + PID_ENTITY_FILTER_LAST = PID_ENTITY_FILTER_FIRST + 200, + PID_DEF_PLACE_TYPE, + + PID_TRACEOFFSET, + + PID_ENTITYNAME, + + PID_GENERATE_PERINST_SEED, + PID_GENERATE_EQUAL_PERINST_SEED, + PID_PERINST_SEED, + + PID_GENERATE_SEED, + PID_GENERATE_EQUAL_SEED, + PID_SEED, +}; + +LandscapeEntityObject::LandscapeEntityObject(const char *ent_name, int rnd_seed) +{ + props.entityName = ent_name; + entity = NULL; + rndSeed = rnd_seed; + perInstSeed = 0; + isCollidable = true; +} +LandscapeEntityObject::~LandscapeEntityObject() { destroy_it(entity); } + +void LandscapeEntityObject::renderBox() +{ + if (EditLayerProps::layerProps[getEditLayerIdx()].hide) + return; + if (EditLayerProps::layerProps[getEditLayerIdx()].lock) + return; + + if (!entity || isSelected()) + { +#define BOUND_BOX_LEN_DIV 4 +#define BOUND_BOX_INDENT_MUL 0.03 + BBox3 box = entity ? entity->getBbox() : BBox3(Point3(-0.2, -0.2, -0.2), Point3(0.2, 0.2, 0.2)); + + const real deltaX = box[1].x - box[0].x; + const real deltaY = box[1].y - box[0].y; + const real deltaZ = box[1].z - box[0].z; + + const real dx = deltaX / BOUND_BOX_LEN_DIV; + const real dy = deltaY / BOUND_BOX_LEN_DIV; + const real dz = deltaZ / BOUND_BOX_LEN_DIV; + + const E3DCOLOR c = isSelected() ? E3DCOLOR(0xff, 0, 0) : E3DCOLOR(0xff, 0xff, 0xff); + + if (entity) + { + TMatrix tm; + entity->getTm(tm); + dagRender->setLinesTm(tm); + } + else + dagRender->setLinesTm(getWtm()); + + dagRender->renderLine(box[0], box[0] + Point3(dx, 0, 0), c); + dagRender->renderLine(box[0], box[0] + Point3(0, dy, 0), c); + dagRender->renderLine(box[0], box[0] + Point3(0, 0, dz), c); + + dagRender->renderLine(box[0] + Point3(deltaX, 0, 0), box[0] + Point3(deltaX - dx, 0, 0), c); + dagRender->renderLine(box[0] + Point3(deltaX, 0, 0), box[0] + Point3(deltaX, dy, 0), c); + dagRender->renderLine(box[0] + Point3(deltaX, 0, 0), box[0] + Point3(deltaX, 0, dz), c); + + dagRender->renderLine(box[0] + Point3(deltaX, 0, deltaZ), box[0] + Point3(deltaX - dx, 0, deltaZ), c); + dagRender->renderLine(box[0] + Point3(deltaX, 0, deltaZ), box[0] + Point3(deltaX, dy, deltaZ), c); + dagRender->renderLine(box[0] + Point3(deltaX, 0, deltaZ), box[0] + Point3(deltaX, 0, deltaZ - dz), c); + + dagRender->renderLine(box[0] + Point3(0, 0, deltaZ), box[0] + Point3(dx, 0, deltaZ), c); + dagRender->renderLine(box[0] + Point3(0, 0, deltaZ), box[0] + Point3(0, dy, deltaZ), c); + dagRender->renderLine(box[0] + Point3(0, 0, deltaZ), box[0] + Point3(0, 0, deltaZ - dz), c); + + + dagRender->renderLine(box[1], box[1] - Point3(dx, 0, 0), c); + dagRender->renderLine(box[1], box[1] - Point3(0, dy, 0), c); + dagRender->renderLine(box[1], box[1] - Point3(0, 0, dz), c); + + dagRender->renderLine(box[1] - Point3(deltaX, 0, 0), box[1] - Point3(deltaX - dx, 0, 0), c); + dagRender->renderLine(box[1] - Point3(deltaX, 0, 0), box[1] - Point3(deltaX, dy, 0), c); + dagRender->renderLine(box[1] - Point3(deltaX, 0, 0), box[1] - Point3(deltaX, 0, dz), c); + + dagRender->renderLine(box[1] - Point3(deltaX, 0, deltaZ), box[1] - Point3(deltaX - dx, 0, deltaZ), c); + dagRender->renderLine(box[1] - Point3(deltaX, 0, deltaZ), box[1] - Point3(deltaX, dy, deltaZ), c); + dagRender->renderLine(box[1] - Point3(deltaX, 0, deltaZ), box[1] - Point3(deltaX, 0, deltaZ - dz), c); + + dagRender->renderLine(box[1] - Point3(0, 0, deltaZ), box[1] - Point3(dx, 0, deltaZ), c); + dagRender->renderLine(box[1] - Point3(0, 0, deltaZ), box[1] - Point3(0, dy, deltaZ), c); + dagRender->renderLine(box[1] - Point3(0, 0, deltaZ), box[1] - Point3(0, 0, deltaZ - dz), c); + +#undef BOUND_BOX_LEN_DIV +#undef BOUND_BOX_INDENT_MUL + } +} + +bool LandscapeEntityObject::isSelectedByRectangle(IGenViewportWnd *vp, const EcRect &rect) const +{ + if (EditLayerProps::layerProps[getEditLayerIdx()].hide) + return false; + if (!entity) + { + Point2 p; + if (!vp->worldToClient(matrix.getcol(3), p, NULL)) + return false; + return p.x >= rect.l && p.y >= rect.t && p.x <= rect.r && p.y <= rect.b; + } + + Point2 cp[8]; + BBox3 box = entity->getBbox(); + BBox2 box2; + real z; + bool in_frustum = false; + + TMatrix tm; + entity->getTm(tm); +#define TEST_POINT(i, P) \ + in_frustum |= vp->worldToClient(tm * P, cp[i], &z) && z > 0; \ + if (z > 0 && rect.l <= cp[i].x && rect.t <= cp[i].y && cp[i].x <= rect.r && cp[i].y <= rect.b) \ + return true; \ + else \ + box2 += cp[i]; + +#define TEST_SEGMENT(i, j) \ + if (::isect_line_segment_box(cp[i], cp[j], rbox)) \ + return true + + for (int i = 0; i < 8; i++) + { + TEST_POINT(i, box.point(i)); + } + + if (!in_frustum) + return false; + BBox2 rbox(Point2(rect.l, rect.t), Point2(rect.r, rect.b)); + if (!(box2 & rbox)) + return false; + + TEST_SEGMENT(0, 4); + TEST_SEGMENT(4, 5); + TEST_SEGMENT(5, 1); + TEST_SEGMENT(1, 0); + TEST_SEGMENT(2, 6); + TEST_SEGMENT(6, 7); + TEST_SEGMENT(7, 3); + TEST_SEGMENT(3, 2); + TEST_SEGMENT(0, 2); + TEST_SEGMENT(1, 3); + TEST_SEGMENT(4, 6); + TEST_SEGMENT(5, 7); + +#undef TEST_POINT +#undef TEST_SEGMENT + + return isSelectedByPointClick(vp, rect.l, rect.t); +} +bool LandscapeEntityObject::isSelectedByPointClick(IGenViewportWnd *vp, int x, int y) const +{ + if (EditLayerProps::layerProps[getEditLayerIdx()].hide) + return false; + if (!entity) + { + Point2 p; + if (!vp->worldToClient(matrix.getcol(3), p, NULL)) + return false; + return p.x >= x - 3 && p.y >= y - 3 && p.x <= x + 3 && p.y <= y + 3; + } + + Point3 dir, p0; + float out_t; + + vp->clientToWorld(Point2(x, y), p0, dir); + TMatrix tm; + entity->getTm(tm); + return ray_intersect_box(p0, dir, entity->getBbox(), tm, out_t); +} +bool LandscapeEntityObject::getWorldBox(BBox3 &box) const +{ + box = matrix * (entity ? entity->getBsph() : BSphere3(Point3(0, 0, 0), 0.5)); + return true; +} + +bool LandscapeEntityObject::isColliderEnabled(const IDagorEdCustomCollider *collider) +{ + for (int i = colliders.col.size() - 1; i >= 0; i--) + if (colliders.col[i] == collider) + return true; + + return false; +} + +void LandscapeEntityObject::fillProps(PropPanel2 &panel, DClassID for_class_id, dag::ConstSpan objects) +{ + bool one_type = true; + int one_layer = -1; + + for (int i = 0; i < objects.size(); ++i) + if (LandscapeEntityObject *o = RTTI_cast(objects[i])) + { + if (one_layer == -1) + one_layer = o->getEditLayerIdx(); + else if (one_layer != o->getEditLayerIdx()) + one_layer = -2; + } + else + { + one_layer = -2; + one_type = false; + break; + } + + if (one_layer < 0) + panel.createStatic(-1, "Edit layer: --multiple selected--"); + else + panel.createStatic(-1, String(0, "Edit layer: %s", EditLayerProps::layerProps[one_layer].name())); + + if (one_type) + { + int plColl = props.placeType; + String entName(props.entityName); + String entNotes(props.notes); + + for (int i = 0; i < objects.size(); ++i) + { + LandscapeEntityObject *o = RTTI_cast(objects[i]); + if (!o) + continue; + + if (o->props.placeType != props.placeType) + plColl = -1; + if (strcmp(o->props.entityName, props.entityName) != 0) + entName = ""; + if (o->props.notes != entNotes) + entNotes = ""; + } + + panel.createEditBox(PID_ENTITY_NOTES, "Notes", entNotes); + + PropertyContainerControlBase &placeGrp = *panel.createRadioGroup(PID_PLACE_TYPE, "Place on collision"); + if (plColl < 0) + placeGrp.createRadio(-1, "-- (mixed) --"); + placeGrp.createRadio(props.PT_none, "-- no --"); + placeGrp.createRadio(props.PT_coll, "Place pivot"); + placeGrp.createRadio(props.PT_collNorm, "Place pivot and use normal"); + placeGrp.createRadio(props.PT_3pod, "Place 3-point (bbox)"); + placeGrp.createRadio(props.PT_fnd, "Place foundation (bbox)"); + placeGrp.createRadio(props.PT_flt, "Place on water (floatable)"); + placeGrp.createRadio(props.PT_riColl, "Place pivot with rendinst collision"); + panel.setInt(PID_PLACE_TYPE, plColl); + panel.createCheckBox(PID_PLACE_TYPE_OVERRIDE, "Override placement type for composit", props.overridePlaceTypeForComposit); + panel.createSeparator(); + + if (entity) + { + IEntityCollisionState *ecs = entity->queryInterface(); + if (ecs) + panel.createCheckBox(PID_ENTITY_COLLISION, "Has collision", isCollidable); + } + + panel.createIndent(); + panel.createButton(PID_ENTITYNAME, entName); + + panel.createIndent(); + panel.createButton(PID_GENERATE_PERINST_SEED, "Generate individual per-inst-seed"); + panel.createButton(PID_GENERATE_EQUAL_PERINST_SEED, "Generate equal per-inst-seed"); + if (entity && objects.size() == 1) + if (IRandomSeedHolder *irsh = entity->queryInterface()) + panel.createTrackInt(PID_PERINST_SEED, "Per-instance seed", irsh->getPerInstanceSeed() & 0x7FFF, 0, 32767, 1); + + panel.createIndent(); + panel.createButton(PID_GENERATE_SEED, "Generate individual seed"); + panel.createButton(PID_GENERATE_EQUAL_SEED, "Generate equal seed"); + if (entity && objects.size() == 1) + if (IRandomSeedHolder *irsh = entity->queryInterface()) + if (irsh->isSeedSetSupported()) + panel.createTrackInt(PID_SEED, "Random seed", irsh->getSeed() & 0x7FFF, 0, 32767, 1); + + panel.createIndent(); + objParam.fillParams(panel, objects); + + panel.createIndent(); + + PropertyContainerControlBase *subGrp = panel.createGroup(PID_ENTITY_CASTER_GRP, "Entity casters"); + + Tab def_place_type_nm(tmpmem); + def_place_type_nm.resize(props.PT_riColl + 1); + def_place_type_nm[props.PT_none] = "-- no --"; + def_place_type_nm[props.PT_coll] = "Place pivot"; + def_place_type_nm[props.PT_collNorm] = "Place pivot and use normal"; + def_place_type_nm[props.PT_3pod] = "Place 3-point (bbox)"; + def_place_type_nm[props.PT_fnd] = "Place foundation (bbox)"; + def_place_type_nm[props.PT_flt] = "Place on water (floatable)"; + def_place_type_nm[props.PT_riColl] = "Place pivot with rendinst collision"; + subGrp->createCombo(PID_DEF_PLACE_TYPE, "Def. place type:", def_place_type_nm, default_place_type, true); + + subGrp->createEditFloat(PID_TRACEOFFSET, "Tracert up offset", colliders.tracertUpOffset); + subGrp->createIndent(); + + const int colCnt = DAGORED2->getCustomCollidersCount(); + G_ASSERT(colCnt < PID_ENTITY_CASTER_LAST - PID_ENTITY_CASTER_FIRST); + + for (int i = 0; i < colCnt; ++i) + { + const IDagorEdCustomCollider *collider = DAGORED2->getCustomCollider(i); + + if (collider) + { + subGrp->createCheckBox(PID_ENTITY_CASTER_FIRST + i, collider->getColliderName(), isColliderEnabled(collider)); + } + } + + panel.createIndent(); + panel.createCheckBox(PID_ENTITY_USE_FILTER, "Apply Filters", colliders.useFilters); + + if (colliders.useFilters) + { + subGrp = panel.createGroup(PID_ENTITY_FILTER_GRP, "Entity filters"); + + unsigned old_mask = 0; + + old_mask = DAEDITOR3.getEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_COLLISION); + DAEDITOR3.setEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_COLLISION, colliders.filter); + + const int plgCnt = DAGORED2->getPluginCount(); + for (int i = 0; i < plgCnt; i++) + { + IGenEditorPlugin *plugin = DAGORED2->getPlugin(i); + IObjEntityFilter *filter = plugin->queryInterface(); + + if (filter && filter->allowFiltering(IObjEntityFilter::STMASK_TYPE_COLLISION)) + { + const bool val = filter->isFilteringActive(IObjEntityFilter::STMASK_TYPE_COLLISION); + subGrp->createCheckBox(PID_ENTITY_FILTER_FIRST + i, plugin->getMenuCommandName(), val); + } + } + + DAEDITOR3.setEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_COLLISION, old_mask); + } + } +} + +void LandscapeEntityObject::rePlaceAllEntities() +{ + HmapLandObjectEditor *ed = (HmapLandObjectEditor *)getObjEditor(); + if (!ed) + return; + + DAGORED2->setColliders(colliders.col, colliders.getFilter()); + for (int i = ed->objectCount() - 1; i >= 0; i--) + { + LandscapeEntityObject *o = RTTI_cast(ed->getObject(i)); + if (o) + o->updateEntityPosition(); + } + + DAGORED2->restoreEditorColliders(); + DAGORED2->invalidateViewportCache(); +} + +void LandscapeEntityObject::rePlaceAllEntitiesOnCollision(HmapLandObjectEditor &objEd, bool loft_changed, bool polygeom_changed, + bool roads_chanded, BBox3 changed_region) +{ + bool need_work = false; + for (int i = 0; i < colliders.col.size(); i++) + if ((loft_changed && colliders.col[i] == &objEd.loftGeomCollider) || + (polygeom_changed && colliders.col[i] == &objEd.polyGeomCollider) || (roads_chanded && colliders.col[i] == &objEd)) + { + need_work = true; + break; + } + if (!need_work) + return; + + DAGORED2->setColliders(colliders.col, colliders.getFilter()); + for (int i = objEd.objectCount() - 1; i >= 0; i--) + { + LandscapeEntityObject *o = RTTI_cast(objEd.getObject(i)); + if (o && o->props.placeType && o->entity && (o->matrix * o->entity->getBsph() & changed_region)) + o->updateEntityPosition(); + } + + DAGORED2->restoreEditorColliders(); + DAGORED2->invalidateViewportCache(); +} + +void LandscapeEntityObject::updateEntityPosition(bool apply_collision) +{ + if (!entity) + return; + + if (props.placeType == props.PT_riColl) + { + apply_collision = false; + DAGORED2->restoreEditorColliders(); + } + + if (apply_collision) + DAGORED2->setColliders(colliders.col, colliders.getFilter()); + if (!props.placeType) + entity->setTm(matrix); + else + setPosOnCollision(matrix.getcol(3)); + if (apply_collision) + DAGORED2->restoreEditorColliders(); +} + +void LandscapeEntityObject::onPPChange(int pid, bool edit_finished, PropPanel2 &panel, + dag::ConstSpan objects) +{ + if (objParam.onPPChange(panel, pid, objects)) + return; + +#define CHANGE_VAL(type, pname, getfunc) \ + { \ + type val = panel.getfunc(pid); \ + for (int i = 0; i < objects.size(); ++i) \ + { \ + LandscapeEntityObject *o = RTTI_cast(objects[i]); \ + if (!o || o->pname == val) \ + continue; \ + getObjEditor()->getUndoSystem()->put(new UndoPropsChange(o)); \ + o->pname = val; \ + o->propsChanged(); \ + } \ + } + + if (pid == PID_ENTITY_NOTES) + { + for (int i = 0; i < objects.size(); ++i) + { + LandscapeEntityObject *o = RTTI_cast(objects[i]); + if (o) + o->props.notes = panel.getText(PID_ENTITY_NOTES); + } + DAGORED2->invalidateViewportCache(); + } + else if ((pid == PID_PLACE_TYPE && panel.getInt(pid) >= 0) || pid == PID_PLACE_TYPE_OVERRIDE) + { + getObjEditor()->getUndoSystem()->begin(); + if (pid == PID_PLACE_TYPE) + CHANGE_VAL(int, props.placeType, getInt) + else // if (pid == PID_PLACE_TYPE_OVERRIDE) + CHANGE_VAL(bool, props.overridePlaceTypeForComposit, getBool) + getObjEditor()->getUndoSystem()->accept("Change props"); + + DAGORED2->setColliders(colliders.col, colliders.getFilter()); + for (int i = objects.size() - 1; i >= 0; i--) + { + LandscapeEntityObject *o = RTTI_cast(objects[i]); + if (o) + o->updateEntityPosition(); + } + + DAGORED2->restoreEditorColliders(); + DAGORED2->invalidateViewportCache(); + } + else if (pid == PID_DEF_PLACE_TYPE) + default_place_type = panel.getInt(pid); + else if (pid == PID_ENTITY_COLLISION) + { + getObjEditor()->getUndoSystem()->begin(); + CHANGE_VAL(bool, isCollidable, getBool) + getObjEditor()->getUndoSystem()->accept("Change props"); + } + else if (pid == PID_TRACEOFFSET) + { + float ofs = panel.getFloat(PID_TRACEOFFSET); + + if (float_nonzero(colliders.tracertUpOffset - ofs)) + { + colliders.tracertUpOffset = ofs; + rePlaceAllEntities(); + } + } + else if (pid >= PID_ENTITY_CASTER_FIRST && pid < PID_ENTITY_CASTER_LAST) + { + getObjEditor()->getUndoSystem()->begin(); + getObjEditor()->getUndoSystem()->put(new UndoStaticPropsChange()); + getObjEditor()->getUndoSystem()->accept("Change entity colliders"); + + colliders.col.clear(); + for (int i = DAGORED2->getCustomCollidersCount() - 1; i >= 0; i--) + { + IDagorEdCustomCollider *collider = DAGORED2->getCustomCollider(i); + if (panel.getBool(PID_ENTITY_CASTER_FIRST + i)) + colliders.col.push_back(collider); + } + + rePlaceAllEntities(); + } + else if (pid == PID_ENTITY_USE_FILTER) + { + getObjEditor()->getUndoSystem()->begin(); + getObjEditor()->getUndoSystem()->put(new UndoStaticPropsChange()); + getObjEditor()->getUndoSystem()->accept("Change entity filtering"); + + colliders.useFilters = panel.getBool(PID_ENTITY_USE_FILTER); + + getObjEditor()->invalidateObjectProps(); + rePlaceAllEntities(); + } + else if (pid >= PID_ENTITY_FILTER_FIRST && pid < PID_ENTITY_FILTER_LAST) + { + if (panel.getBool(PID_ENTITY_USE_FILTER)) + { + const int id = pid - PID_ENTITY_FILTER_FIRST; + if (id >= DAGORED2->getPluginCount()) + return; + + getObjEditor()->getUndoSystem()->begin(); + getObjEditor()->getUndoSystem()->put(new UndoStaticPropsChange()); + getObjEditor()->getUndoSystem()->accept("Change entity filtering"); + + IGenEditorPlugin *plugin = DAGORED2->getPlugin(pid - PID_ENTITY_FILTER_FIRST); + IObjEntityFilter *filter = plugin->queryInterface(); + G_ASSERT(filter && filter->allowFiltering(IObjEntityFilter::STMASK_TYPE_COLLISION)); + + unsigned old_mask = DAEDITOR3.getEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_COLLISION); + + DAEDITOR3.setEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_COLLISION, colliders.filter); + filter->applyFiltering(IObjEntityFilter::STMASK_TYPE_COLLISION, panel.getBool(pid)); + colliders.filter = DAEDITOR3.getEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_COLLISION); + + DAEDITOR3.setEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_COLLISION, old_mask); + + rePlaceAllEntities(); + } + } + else if (pid == PID_SEED && objects.size() == 1) + { + if (LandscapeEntityObject *p = RTTI_cast(objects[0])) + p->setRndSeed(panel.getInt(pid)); + } + else if (pid == PID_PERINST_SEED && objects.size() == 1) + { + if (LandscapeEntityObject *p = RTTI_cast(objects[0])) + p->setPerInstSeed(panel.getInt(pid)); + } + +#undef CHANGE_VAL +} + +void LandscapeEntityObject::onPPBtnPressed(int pid, PropPanel2 &panel, dag::ConstSpan objects) +{ + if (pid == PID_ENTITYNAME) + { + const char *asset = DAEDITOR3.selectAsset(props.entityName, "Select entity", DAEDITOR3.getGenObjAssetTypes()); + if (!asset) + return; + + getObjEditor()->getUndoSystem()->begin(); + for (int i = 0; i < objects.size(); i++) + { + LandscapeEntityObject *p = RTTI_cast(objects[i]); + if (p) + { + getObjEditor()->getUndoSystem()->put(new UndoPropsChange(p)); + p->props.entityName = asset; + p->propsChanged(); + } + } + getObjEditor()->getUndoSystem()->accept("Change entity"); + DAGORED2->repaint(); + } + else if (pid == PID_GENERATE_SEED || pid == PID_GENERATE_PERINST_SEED) + { + bool gen_rnd_seed = (pid == PID_GENERATE_SEED); + for (int i = objects.size() - 1; i >= 0; i--) + { + LandscapeEntityObject *p = RTTI_cast(objects[i]); + + gen_rnd_seed ? p->setRndSeed(grnd()) : p->setPerInstSeed(grnd()); + if (objects.size() == 1) + panel.setInt(gen_rnd_seed ? PID_SEED : PID_PERINST_SEED, gen_rnd_seed ? p->rndSeed : p->perInstSeed); + } + + DAGORED2->invalidateViewportCache(); + } + else if (pid == PID_GENERATE_EQUAL_SEED || pid == PID_GENERATE_EQUAL_PERINST_SEED) + { + bool gen_rnd_seed = (pid == PID_GENERATE_EQUAL_SEED); + const int seed = grnd(); + + for (int i = objects.size() - 1; i >= 0; i--) + { + LandscapeEntityObject *p = RTTI_cast(objects[i]); + + gen_rnd_seed ? p->setRndSeed(seed) : p->setPerInstSeed(seed); + } + if (objects.size() == 1) + panel.setInt(gen_rnd_seed ? PID_SEED : PID_PERINST_SEED, seed); + + DAGORED2->invalidateViewportCache(); + } + + getObjEditor()->invalidateObjectProps(); +} + +void LandscapeEntityObject::saveColliders(DataBlock &blk) +{ + DataBlock *colBlk = blk.addBlock("entity_colliders"); + + colBlk->addReal("tracertUpOffset", colliders.tracertUpOffset); + + DAGORED2->saveColliders(*colBlk, colliders.col, colliders.filter, colliders.useFilters); +} + +void LandscapeEntityObject::loadColliders(const DataBlock &blk) +{ + const DataBlock *colBlk = blk.getBlockByName("entity_colliders"); + if (colBlk) + { + colliders.col = DAGORED2->loadColliders(blk, colliders.filter, "entity_colliders"); + colliders.useFilters = colBlk->getBool("applyFilters", false); + colliders.tracertUpOffset = colBlk->getReal("tracertUpOffset", 1.0); + } + else + { + colliders.useFilters = false; + colliders.tracertUpOffset = 1.0; + + for (int i = DAGORED2->getCustomCollidersCount() - 1; i >= 0; i--) + { + IDagorEdCustomCollider *collider = DAGORED2->getCustomCollider(i); + if (collider) + colliders.col.push_back(collider); + } + } +} + +void LandscapeEntityObject::save(DataBlock &blk) +{ + blk.setStr("name", getName()); + blk.setStr("notes", props.notes); + blk.setStr("entName", props.entityName); + blk.setInt("place_type", props.placeType); + if (props.overridePlaceTypeForComposit) + blk.setBool("force_cmp_place_type", props.overridePlaceTypeForComposit); + + blk.setTm("tm", matrix); + + // fx + DataBlock *sblk = NULL; + if (fxProps.maxRadius != 10.f) + { + sblk = blk.addBlock("fx"); + sblk->setReal("maxRadius", fxProps.maxRadius); + } + if (fxProps.updateWhenInvisible) + { + if (!sblk) + sblk = blk.addBlock("fx"); + sblk->setBool("updateWhenInvisible", fxProps.updateWhenInvisible); + } + + // physObj + sblk = NULL; + if (physObjProps.active) + { + sblk = blk.addBlock("physObj"); + sblk->setBool("physActive", physObjProps.active); + } + if (physObjProps.scriptClass.length()) + { + if (!sblk) + sblk = blk.addBlock("physObj"); + sblk->setStr("scriptClass", physObjProps.scriptClass); + } + + if (entity) + { + IRandomSeedHolder *irsh = entity->queryInterface(); + if (irsh && (rndSeed != -1)) + blk.addInt("entSeed", rndSeed); + if (irsh && perInstSeed) + blk.addInt("entPerInstSeed", perInstSeed); + + if (!isCollidable) + blk.addBool("isCollidable", isCollidable); + } +} +void LandscapeEntityObject::load(const DataBlock &blk) +{ + getObjEditor()->setUniqName(this, blk.getStr("name", "")); + props.notes = blk.getStr("notes", ""); + props.entityName = blk.getStr("entName", NULL); + if (!blk.getBool("place_on_collision", true)) + props.placeType = props.PT_none; + else if (blk.getBool("use_collision_norm", false)) + props.placeType = props.PT_collNorm; + else + props.placeType = props.PT_coll; + props.placeType = blk.getInt("place_type", props.placeType); + props.overridePlaceTypeForComposit = blk.getBool("force_cmp_place_type", false); + TMatrix _tm = blk.getTm("tm", TMatrix::IDENT); + if (check_nan(_tm)) + { + DAEDITOR3.conError("entity <%s> (%s) has invalid TM=%@", getName(), props.entityName, _tm); + if (d3d::is_stub_driver()) + { + DAEDITOR3.conError("entity <%s> with invalid TM removed!", getName()); + getObjEditor()->removeObject(this, false); + return; + } + else + { + if (check_nan(_tm.getcol(3))) + _tm = TMatrix::IDENT; + else + { + _tm.setcol(0, TMatrix::IDENT.getcol(0)); + _tm.setcol(1, TMatrix::IDENT.getcol(1)); + _tm.setcol(2, TMatrix::IDENT.getcol(2)); + } + DAEDITOR3.conWarning("entity <%s>: replaced invalid TM with %@", getName(), _tm); + } + } + setWtm(_tm); + + // fx + const DataBlock *sblk = blk.getBlockByName("fx"); + fxProps.maxRadius = sblk ? sblk->getReal("maxRadius", fxProps.maxRadius) : fxProps.maxRadius; + fxProps.updateWhenInvisible = sblk ? sblk->getBool("updateWhenInvisible", false) : false; + + // physObj + sblk = blk.getBlockByName("physObj"); + physObjProps.active = sblk ? sblk->getBool("physActive", false) : false; + physObjProps.scriptClass = sblk ? sblk->getStr("scriptClass", "") : ""; + + rndSeed = blk.getInt("entSeed", -1); + perInstSeed = blk.getInt("entPerInstSeed", 0); + isCollidable = blk.getBool("isCollidable", true); + propsChanged(true); // gizmoTranformMode will be reset later in HmapLandPlugin::beforeMainLoop() +} + +void LandscapeEntityObject::setRndSeed(int seed) +{ + rndSeed = seed; + if (!entity) + return; + + IRandomSeedHolder *irsh = entity->queryInterface(); + if (irsh) + irsh->setSeed(rndSeed); +} + +void LandscapeEntityObject::setPerInstSeed(int seed) +{ + perInstSeed = seed; + if (!entity) + return; + + IRandomSeedHolder *irsh = entity->queryInterface(); + if (irsh) + irsh->setPerInstanceSeed(perInstSeed); +} + +void LandscapeEntityObject::setWtm(const TMatrix &wtm) +{ + __super::setWtm(wtm); + if (entity) + updateEntityPosition(true); +} + +void LandscapeEntityObject::setGizmoTranformMode(bool enable) +{ + if (gizmoEnabled == enable) + return; + if (entity) + { + entity->setGizmoTranformMode(enable); + if (gizmoEnabled && !enable) + updateEntityPosition(true); + } + gizmoEnabled = enable; +} + +void LandscapeEntityObject::onRemove(ObjectEditor *) { destroy_it(entity); } +void LandscapeEntityObject::onAdd(ObjectEditor *objEditor) +{ + propsChanged(); + + if (name.empty()) + { + String fn(dd_get_fname(props.entityName)); + objEditor->setUniqName(this, fn); + } +} + +void LandscapeEntityObject::setPosOnCollision(Point3 pos) +{ + int stype = entity->getSubtype(); + entity->setSubtype(entity->ST_NOT_COLLIDABLE); + + TMatrix etm = matrix; + if (props.placeType == props.PT_collNorm) + { + Point3 norm(0, 1, 0); + objgenerator::place_on_ground(pos, norm, colliders.tracertUpOffset); + if (fabs(matrix.getcol(0) * norm) < 0.999) + { + etm.setcol(1, norm); + etm.setcol(2, normalize(etm.getcol(0) % norm)); + etm.setcol(0, normalize(norm % etm.getcol(2))); + } + else + { + etm.setcol(1, norm); + etm.setcol(0, normalize(norm % etm.getcol(2))); + etm.setcol(2, normalize(etm.getcol(0) % norm)); + } + } + else if (props.placeType == props.PT_coll) + objgenerator::place_on_ground(pos, colliders.tracertUpOffset); + else if (props.placeType == props.PT_3pod && entity) + { + MpPlacementRec mppRec; + mppRec.mpOrientType = mppRec.MP_ORIENT_3POINT; + mppRec.makePointsFromBox(entity->getBbox()); + mppRec.computePivotBc(); + + etm.setcol(3, ZERO()); + objgenerator::place_multipoint(mppRec, pos, etm, colliders.tracertUpOffset); + objgenerator::rotate_multipoint(etm, mppRec); + } + else if (props.placeType == props.PT_fnd && entity) + { + BBox3 box = entity->getBbox(); + float dh; + box[0].y = 0; + dh = objgenerator::dist_to_ground(matrix * box.point(0), colliders.tracertUpOffset); + inplace_max(dh, objgenerator::dist_to_ground(matrix * box.point(1), colliders.tracertUpOffset)); + inplace_max(dh, objgenerator::dist_to_ground(matrix * box.point(4), colliders.tracertUpOffset)); + inplace_max(dh, objgenerator::dist_to_ground(matrix * box.point(5), colliders.tracertUpOffset)); + pos.y -= dh; + } + else if (props.placeType == props.PT_flt && entity) + { + if (IWaterService *waterService = EDITORCORE->queryEditorInterface()) + pos.y = waterService->get_level(); + } + else if (props.placeType == props.PT_riColl && entity) + { + setCollisionIgnored(); + EDITORCORE->setupColliderParams(1, BBox3()); + objgenerator::place_on_plane(pos, savedPlacementNormal, colliders.tracertUpOffset); + EDITORCORE->setupColliderParams(0, BBox3()); + resetCollisionIgnored(); + } + + etm.setcol(3, pos); + entity->setSubtype(stype); + entity->setTm(etm); +} + +bool LandscapeEntityObject::setPos(const Point3 &p) +{ + if (!__super::setPos(p)) + return false; + + if (entity) + updateEntityPosition(true); + + return true; +} + +void LandscapeEntityObject::setPlaceOnCollision(bool place_on_rendinst) +{ + if (!props.overridePlaceTypeForComposit) + props.placeType = place_on_rendinst ? props.PT_riColl : default_place_type; + setWtm(matrix); +} +void LandscapeEntityObject::objectPropsChanged() +{ + if (!entity) + return; + + IObjEntityUserDataHolder *oeud = entity->queryInterface(); + if (!oeud) + return; + + static int fxId = IDaEditor3Engine::get().getAssetTypeId("fx"); + static int physObjId = IDaEditor3Engine::get().getAssetTypeId("physObj"); + + int id = entity->getAssetTypeId(); + + DataBlock *blk = oeud->getUserDataBlock(true); + G_ASSERT(blk); + + if (id == fxId) + { + blk->setReal("maxRadius", fxProps.maxRadius); + blk->setBool("updateWhenInvisible", fxProps.updateWhenInvisible); + } + else if (id == physObjId) + { + blk->setStr("name", getName()); + blk->setBool("physActive", physObjProps.active); + blk->setStr("scriptClass", physObjProps.scriptClass); + } +} +void LandscapeEntityObject::setEditLayerIdx(int idx) +{ + editLayerIdx = idx; + if (entity) + entity->setEditLayerIdx(editLayerIdx); +} +void LandscapeEntityObject::propsChanged(bool prevent_gen) +{ + destroy_it(entity); + DagorAsset *a = DAEDITOR3.getGenObjAssetByName(props.entityName); + if (!a && !props.entityName.empty()) + DAEDITOR3.conError("cannot find entity asset: <%s>", props.entityName.str()); + entity = a ? DAEDITOR3.createEntity(*a) : NULL; + if (entity) + { + if (prevent_gen) + setGizmoTranformMode(true); // will be reset later in HmapLandPlugin::beforeMainLoop() + + entity->setSubtype(IDaEditor3Engine::get().registerEntitySubTypeId("single_ent")); + entity->setEditLayerIdx(editLayerIdx); + + IRandomSeedHolder *irsh = entity->queryInterface(); + if (irsh) + { + irsh->setSeed(rndSeed); + irsh->setPerInstanceSeed(perInstSeed); + } + if (ICompositObj *ico = entity->queryInterface()) + ico->setCompositPlaceTypeOverride(props.overridePlaceTypeForComposit ? props.placeType : -1); + + IEntityCollisionState *ecs = entity->queryInterface(); + if (ecs) + ecs->setCollisionFlag(isCollidable); + + DAGORED2->setColliders(colliders.col, colliders.getFilter()); + entity->setTm(matrix); + DAGORED2->restoreEditorColliders(); + objectPropsChanged(); + } +} + +LandscapeEntityObject *LandscapeEntityObject::clone() +{ + LandscapeEntityObject *obj = new LandscapeEntityObject(props.entityName); + obj->setEditLayerIdx(EditLayerProps::activeLayerIdx[lpIndex()]); + + getObjEditor()->setUniqName(obj, getName()); + + Props pr = obj->getProps(); + pr.placeType = props.placeType; + obj->setProps(pr); + + TMatrix tm = getWtm(); + obj->setWtm(tm); + + return obj; +} + +void LandscapeEntityObject::putMoveUndo() +{ + HmapLandObjectEditor *ed = (HmapLandObjectEditor *)getObjEditor(); + if (!ed->isCloneMode()) + __super::putMoveUndo(); +} + +void HmapLandObjectEditor::splitComposits() +{ + Tab otherObj; + Tab compObj, decompObj; + + for (int i = 0; i < selection.size(); ++i) + { + LandscapeEntityObject *o = RTTI_cast(selection[i]); + if (o && o->getEntity() && o->getEntity()->queryInterface()) + compObj.push_back(o); + else + otherObj.push_back(o); + } + if (!compObj.size()) + { + wingw::message_box(wingw::MBS_INFO, "Cannot split composits", "Selected %d objects do not contain any composits", + selection.size()); + return; + } + + DataBlock splitSplinesBlk; + getUndoSystem()->begin(); + for (int i = 0; i < compObj.size(); i++) + { + ICompositObj *co = compObj[i]->getEntity()->queryInterface(); + for (int j = 0, je = co->getCompositSubEntityCount(); j < je; j++) + if (IObjEntity *e = co->getCompositSubEntity(j)) + { + if (ISplineEntity *se = e->queryInterface()) + { + DataBlock splineBlk; + if (se->saveSplineTo(splineBlk) && splineBlk.blockCount() == 1) + { + splineBlk.getBlock(0)->setStr("name", + String(0, "%s_%s", compObj[i]->getName(), splineBlk.getBlock(0)->getStr("blkGenName", ""))); + splitSplinesBlk.addNewBlock(splineBlk.getBlock(0)); + } + continue; + } + + if (!e->getObjAssetName()) + continue; + String nm(e->getObjAssetName()); + int seed = 0; + if (IRandomSeedHolder *irsh = e->queryInterface()) + seed = irsh->getSeed(); + else if (IRandomSeedHolder *irsh = compObj[i]->getEntity()->queryInterface()) + seed = irsh->getSeed(); + + LandscapeEntityObject *obj = new LandscapeEntityObject(nm, seed); + obj->setEditLayerIdx(EditLayerProps::activeLayerIdx[obj->lpIndex()]); + const ICompositObj::Props &p = co->getCompositSubEntityProps(j); + + if (char *p = strrchr(nm, ':')) + *p = 0; + setUniqName(obj, String(0, "%s_%s", compObj[i]->getName(), nm)); + + LandscapeEntityObject::Props pr = obj->getProps(); + pr.placeType = p.placeType; + obj->setProps(pr); + TMatrix tm(TMatrix::IDENT); + e->getTm(tm); + obj->setWtm(tm); + decompObj.push_back(obj); + } + } + removeObjects((RenderableEditableObject **)compObj.data(), compObj.size(), true); + addObjects((RenderableEditableObject **)decompObj.data(), decompObj.size(), true); + + String tmpName; + for (int i = 0; i < decompObj.size(); i++) + { + tmpName = decompObj[i]->getName(); + decompObj[i]->setName(""); + setUniqName(decompObj[i], tmpName); + decompObj[i]->selectObject(); + decompObj[i]->propsChanged(); + } + for (int i = 0; i < splitSplinesBlk.blockCount(); i++) + { + const DataBlock &b = *splitSplinesBlk.getBlock(i); + SplineObject *s = new SplineObject(strcmp(b.getBlockName(), "polygon") == 0); + s->setEditLayerIdx(EditLayerProps::activeLayerIdx[s->lpIndex()]); + addObject(s, true); + s->load(b, true); + setUniqName(s, b.getStr("name")); + s->onCreated(false); + s->selectObject(); + } + updateSelection(); + + getUndoSystem()->accept(String(0, "Decomposit %d objects", compObj.size())); + + wingw::message_box(wingw::MBS_INFO, "Composits are splitted", "%d composit objects are splitted into %d subobjects and %d splines", + compObj.size(), decompObj.size(), splitSplinesBlk.blockCount()); +} + +void HmapLandObjectEditor::instantiateGenToEntities() +{ + Tab genObj; + PtrTab decompObj; + + for (int i = 0; i < selection.size(); ++i) + if (SplineObject *o = RTTI_cast(selection[i])) + genObj.push_back(o); + if (!genObj.size()) + { + wingw::message_box(wingw::MBS_INFO, "Cannot split generated", "Selected %d objects do not contain any splines", selection.size()); + return; + } + + auto make_entities = [&decompObj, this](const char *parent_obj_nm, dag::ConstSpan entities) { + for (auto *e : entities) + { + if (!e->getObjAssetName()) + continue; + String nm(e->getObjAssetName()); + int seed = 0; + if (IRandomSeedHolder *irsh = e->queryInterface()) + seed = irsh->getSeed(); + + LandscapeEntityObject *obj = new LandscapeEntityObject(nm, seed); + obj->setEditLayerIdx(EditLayerProps::activeLayerIdx[obj->lpIndex()]); + + if (char *p = strrchr(nm, ':')) + *p = 0; + setUniqName(obj, String(0, "%s_%s", parent_obj_nm, nm)); + TMatrix tm(TMatrix::IDENT); + e->getTm(tm); + obj->setWtm(tm); + decompObj.push_back(obj); + } + }; + + for (auto *spl : genObj) + { + if (spl->points.size() < 2) + continue; + if (spl->isPoly() && spl->getLandClass()) + { + for (auto &p : spl->getLandClass()->poolTiled) + make_entities(spl->getName(), make_span_const(p.entUsed ? p.entPool.data() : nullptr, p.entUsed)); + for (auto &p : spl->getLandClass()->poolPlanted) + make_entities(spl->getName(), make_span_const(p.entUsed ? p.entPool.data() : nullptr, p.entUsed)); + } + for (auto sp : spl->points) + if (ISplineGenObj *gen = sp->getSplineGen()) + for (auto &p : gen->entPools) + make_entities(spl->getName(), make_span_const(p.entUsed ? p.entPool.data() : nullptr, p.entUsed)); + } + if (wingw::message_box(wingw::MBS_QUEST | wingw::MBS_YESNO, "Instantiate generated objects", + String(0, "Split generated objects of %d splines into %d distinct entities and reset spline class?", genObj.size(), + decompObj.size())) != wingw::MB_ID_YES) + return; + + getUndoSystem()->begin(); + for (auto *spl : genObj) + { + if (spl->points.size() < 2) + continue; + for (auto sp : spl->points) + sp->setEffectiveAsset("", true, 0); + spl->points[0]->setBlkGenName(""); + spl->selectObject(false); + } + addObjects((RenderableEditableObject **)decompObj.data(), decompObj.size(), true); + String tmpName; + for (int i = 0; i < decompObj.size(); i++) + { + tmpName = decompObj[i]->getName(); + decompObj[i]->setName(""); + setUniqName(decompObj[i], tmpName); + decompObj[i]->selectObject(); + decompObj[i]->propsChanged(); + } + updateSelection(); + getUndoSystem()->accept(String(0, "Split %d splines into %d entities", genObj.size(), decompObj.size())); + + wingw::message_box(wingw::MBS_INFO, "Generated objects instantiated", + "Generated objects of %d splines are splitted into %d entities", genObj.size(), decompObj.size()); +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlEntity.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlEntity.h new file mode 100644 index 000000000..89ec2e322 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlEntity.h @@ -0,0 +1,232 @@ +#pragma once + +#include +#include +#include +#include "hmlLayers.h" + +class IObjEntity; +class IDagorEdCustomCollider; +class HmapLandObjectEditor; + +static constexpr unsigned CID_LandscapeEntityObject = 0xE79DC1EDu; // LandscapeEntityObject + +// +// Entity object placed on landscape +// +class LandscapeEntityObject : public RenderableEditableObject +{ +public: + LandscapeEntityObject(const char *ent_name, int rnd_seed = 0); + + virtual void update(float) {} + virtual void beforeRender() {} + virtual void render() {} + virtual void renderTrans() {} + + virtual bool isSelectedByRectangle(IGenViewportWnd *vp, const EcRect &rect) const; + virtual bool isSelectedByPointClick(IGenViewportWnd *vp, int x, int y) const; + virtual bool getWorldBox(BBox3 &box) const; + + virtual void fillProps(PropPanel2 &panel, DClassID for_class_id, dag::ConstSpan objects); + + virtual void onPPChange(int pid, bool edit_finished, PropPanel2 &panel, dag::ConstSpan objects); + + virtual void onPPBtnPressed(int pid, PropPanel2 &panel, dag::ConstSpan objects); + + virtual void save(DataBlock &blk); + virtual void load(const DataBlock &blk); + + virtual bool mayRename() { return true; } + virtual bool mayDelete() { return true; } + virtual void setWtm(const TMatrix &wtm); + + virtual void onRemove(ObjectEditor *); + virtual void onAdd(ObjectEditor *objEditor); + + virtual bool setPos(const Point3 &p); + + virtual void putMoveUndo(); + + virtual void onObjectNameChange(RenderableEditableObject *obj, const char *old_name, const char *new_name) { objectPropsChanged(); } + + EO_IMPLEMENT_RTTI(CID_LandscapeEntityObject) + + UndoRedoObject *makePropsUndoObj() { return new UndoPropsChange(this); } + void renderBox(); + LandscapeEntityObject *clone(); + + void setRndSeed(int seed); + int getRndSeed() { return rndSeed; } + void setPerInstSeed(int seed); + int getPerInstSeed() { return perInstSeed; } + void setPlaceOnCollision(bool on_collison); + + void updateEntityPosition(bool apply_collision = false); + + void setEditLayerIdx(int idx); + int getEditLayerIdx() const { return editLayerIdx; } + int lpIndex() const { return EditLayerProps::ENT; }; + + struct Props + { + enum + { + PT_none = ICompositObj::Props::PT_none, + PT_coll = ICompositObj::Props::PT_coll, + PT_collNorm = ICompositObj::Props::PT_collNorm, + PT_3pod = ICompositObj::Props::PT_3pod, + PT_fnd = ICompositObj::Props::PT_fnd, + PT_flt = ICompositObj::Props::PT_flt, + PT_riColl = ICompositObj::Props::PT_riColl + }; + SimpleString entityName; + int placeType = PT_coll; + bool overridePlaceTypeForComposit = false; + + String notes; + }; + + const Props &getProps() const { return props; } + void setProps(const Props &p) + { + props = p; + propsChanged(); + } + + void propsChanged(bool prevent_gen = false); + void objectPropsChanged(); + IObjEntity *getEntity() { return entity; } + + bool usesRendinstPlacement() const override { return props.placeType == props.PT_riColl; } + void setCollisionIgnored() override + { + oldPerInstSeed = perInstSeed; + setPerInstSeed(0xBAD); + } + void resetCollisionIgnored() override { setPerInstSeed(oldPerInstSeed); } + + struct FxProps + { + real maxRadius; + bool updateWhenInvisible; + + FxProps() : maxRadius(10.f), updateWhenInvisible(false) {} + }; + + struct PhysObjProps + { + String scriptClass; + bool active; + + PhysObjProps() : active(false) {} + }; + + FxProps fxProps; + PhysObjProps physObjProps; + +public: + static void saveColliders(DataBlock &blk); + static void loadColliders(const DataBlock &blk); + static void rePlaceAllEntitiesOnCollision(HmapLandObjectEditor &objEd, bool loft_changed, bool polygeom_changed, bool roads_chanded, + BBox3 changed_region); + + void setGizmoTranformMode(bool enable); + +protected: + struct CollidersData + { + CollidersData(const CollidersData &cl_data) : col(midmem) { copyData(cl_data); } + CollidersData() : col(midmem) + { + filter = 0x7FFFFFFF; + useFilters = false; + tracertUpOffset = 1.0; + } + + ~CollidersData() { col.clear(); } + + inline void operator=(const CollidersData &cl_data) { copyData(cl_data); } + + inline unsigned getFilter() { return useFilters ? filter : 0x7FFFFFFF; } + + public: + Tab col; + real tracertUpOffset; + unsigned filter; + bool useFilters; + + protected: + inline void copyData(const CollidersData &cl_data) + { + col.clear(); + col = cl_data.col; + filter = cl_data.filter; + useFilters = cl_data.useFilters; + tracertUpOffset = cl_data.tracertUpOffset; + } + }; + + Props props; + IObjEntity *entity; + int rndSeed; + int perInstSeed = 0; + int oldPerInstSeed = 0; + bool isCollidable; + int editLayerIdx = 0; + bool gizmoEnabled = false; + + static CollidersData colliders; + + ~LandscapeEntityObject(); + + static bool isColliderEnabled(const IDagorEdCustomCollider *collider); + + void setPosOnCollision(Point3 pos); + + void rePlaceAllEntities(); + + class UndoStaticPropsChange : public UndoRedoObject + { + LandscapeEntityObject::CollidersData oldData, redoData; + + public: + UndoStaticPropsChange() : redoData(LandscapeEntityObject::colliders), oldData(LandscapeEntityObject::colliders) {} + + virtual void restore(bool save_redo) + { + if (save_redo) + redoData = LandscapeEntityObject::colliders; + + LandscapeEntityObject::colliders = oldData; + } + + virtual void redo() { LandscapeEntityObject::colliders = redoData; } + + virtual size_t size() { return sizeof(*this); } + virtual void accepted() {} + virtual void get_description(String &s) { s = "UndoEntityStaticPropsChange"; } + }; + + class UndoPropsChange : public UndoRedoObject + { + Ptr obj; + LandscapeEntityObject::Props oldProps, redoProps; + + public: + UndoPropsChange(LandscapeEntityObject *o) : obj(o) { oldProps = redoProps = obj->props; } + + virtual void restore(bool save_redo) + { + if (save_redo) + redoProps = obj->props; + obj->setProps(oldProps); + } + + virtual void redo() { obj->setProps(redoProps); } + + virtual size_t size() { return sizeof(*this); } + virtual void accepted() {} + virtual void get_description(String &s) { s = "UndoEntityPropsChange"; } + }; +}; diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlEventHandler.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlEventHandler.cpp new file mode 100644 index 000000000..6a864bb57 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlEventHandler.cpp @@ -0,0 +1,685 @@ +#include "hmlPanel.h" +#include "hmlCm.h" +#include "hmlHoleObject.h" + +#include + +#include +#include + +#include + +#include +#include +#include + +#include + +using hdpi::_pxScaled; + +struct HmapBitLayerDesc; +class IHmapService; + + +struct BrushIncrementer +{ + real lim, value; +}; + +static BrushIncrementer brushIncTable[] = {{0, 1}, {10, 5}, {50, 10}, {100, 25}, {200, 50}, {300, 100}}; + + +class ExportLayeesDlg : public ControlEventHandler +{ +public: + static const int PID_LAYER = 1; + + ExportLayeesDlg(HmapLandPlugin *p_, Tab &enabled_) : p(p_), enabled(enabled_) + { + mDialog = DAGORED2->createDialog(_pxScaled(250), _pxScaled(300), "Export landClass layers"); + PropPanel2 &panel = *mDialog->getPanel(); + + dag::ConstSpan landClsLayer = p->hmlService->getBitLayersList(p->getLayersHandle()); + for (int i = 0; i < landClsLayer.size(); i++) + { + panel.createCheckBox(PID_LAYER + i, p->hmlService->getBitLayerName(p->getLayersHandle(), i), true); + } + } + + ~ExportLayeesDlg() { del_it(mDialog); } + + + bool execute() + { + int ret = mDialog->showDialog(); + + if (ret == DIALOG_ID_OK) + { + PropPanel2 &panel = *mDialog->getPanel(); + + dag::ConstSpan landClsLayer = p->hmlService->getBitLayersList(p->getLayersHandle()); + for (int i = 0; i < landClsLayer.size(); i++) + { + if (panel.getBool(PID_LAYER + i)) + enabled.push_back(i); + } + + return true; + } + + return false; + } + +private: + HmapLandPlugin *p; + Tab &enabled; + CDialogWindow *mDialog; +}; + + +//============================================================================== + +void HmapLandPlugin::refillBrush() +{ + if (propPanel) + propPanel->fillPanel(); +} + + +bool HmapLandPlugin::onPluginMenuClick(unsigned id) +{ + switch (id) + { + case CM_SHOW_PANEL: + propPanel->showPropPanel(!propPanel->isVisible()); + objEd.setButton(CM_SHOW_PANEL, propPanel->isVisible()); + EDITORCORE->managePropPanels(); + return true; + + case CM_CREATE_HEIGHTMAP: createHeightmap(); return true; + + case CM_IMPORT_HEIGHTMAP: importHeightmap(); break; + + case CM_REIMPORT: reimportHeightmap(); break; + + case CM_ERASE_HEIGHTMAP: eraseHeightmap(); break; + + case CM_EXPORT_HEIGHTMAP: exportHeightmap(); break; + + case CM_RESCALE_HMAP: + { + applyHmModifiers(false, true, false); + + CDialogWindow *dlg = DAGORED2->createDialog(_pxScaled(300), _pxScaled(400), "Rescale heightmap"); + PropPanel2 &panel = *dlg->getPanel(); + float mMin = 0, mMax = 0, dMin = 0, dMax = 0; + + mMin = mMax = heightMap.getInitialData(0, 0); + for (int y = 0, ye = heightMap.getMapSizeY(); y < ye; y++) + for (int x = 0, xe = heightMap.getMapSizeX(); x < xe; x++) + { + float v = heightMap.getInitialData(x, y); + inplace_min(mMin, v); + inplace_max(mMax, v); + } + + if (detDivisor) + { + dMin = dMax = heightMapDet.getInitialData(detRectC[0].x, detRectC[0].y); + for (int y = detRectC[0].y; y < detRectC[1].y; y++) + for (int x = detRectC[0].x; x < detRectC[1].x; x++) + { + float v = heightMapDet.getInitialData(x, y); + inplace_min(dMin, v); + inplace_max(dMax, v); + } + } + else + dMin = mMin, dMax = mMax; + + panel.createStatic(-1, String(0, "Main HMAP min: %.2f m", mMin)); + panel.createStatic(-1, String(0, "Main HMAP max: %.2f m", mMax)); + if (detDivisor) + { + panel.createStatic(-1, String(0, "Detailed HMAP min: %.2f m", dMin)); + panel.createStatic(-1, String(0, "Detailed HMAP max: %.2f m", dMax)); + } + panel.createEditFloat(1, "New min height", min(mMin, dMin)); + panel.createEditFloat(2, "New max height", max(mMax, dMax)); + panel.createCheckBox(3, "Rescale main HMAP", true); + if (detDivisor) + panel.createCheckBox(4, "Rescale detailed HMAP", true); + panel.createCheckBox(5, "Normalize main HMAP", false); + // panel.createCheckBox(6, "Absolutize main HMAP", false); + + if (dlg->showDialog() == DIALOG_ID_OK) + { + float nMin = panel.getFloat(1), nMax = panel.getFloat(2); + bool rescale_main = panel.getBool(3), rescale_det = panel.getBool(4), norm_main = panel.getBool(5); + if (rescale_main || rescale_det) + { + float oMin = (rescale_main && rescale_det) ? min(mMin, dMin) : (rescale_main ? mMin : (rescale_det ? dMin : 0)); + float oMax = (rescale_main && rescale_det) ? max(mMax, dMax) : (rescale_main ? mMax : (rescale_det ? dMax : 0)); + bool good_range = oMax > oMin; + + if (rescale_det) + for (int y = detRectC[0].y; y < detRectC[1].y; y++) + for (int x = detRectC[0].x; x < detRectC[1].x; x++) + heightMapDet.setInitialData(x, y, + good_range ? (heightMapDet.getInitialData(x, y) - oMin) / (oMax - oMin) * (nMax - nMin) + nMin : nMin); + + if (rescale_main) + { + if (good_range) + { + heightMap.heightScale *= (nMax - nMin) / (oMax - oMin); + heightMap.heightOffset = nMin + (heightMap.heightOffset - oMin) * (nMax - nMin) / (oMax - oMin); + } + else + heightMap.heightOffset += nMin - oMin; + } + } + if (norm_main && nMax > nMin) + { + if (!rescale_main) + nMin = mMin, nMax = mMax; + float s = heightMap.heightScale, o = heightMap.heightOffset; + heightMap.heightScale = nMax - nMin; + heightMap.heightOffset = nMin; + for (int y = 0, ye = heightMap.getMapSizeY(); y < ye; y++) + for (int x = 0, xe = heightMap.getMapSizeX(); x < xe; x++) + heightMap.setInitialData(x, y, heightMap.getInitialMap().getData(x, y) * s + o); + } + + if (rescale_main || rescale_det || norm_main) + { + if (rescale_main || norm_main) + refillPanel(); + heightMap.resetFinal(); + heightMapDet.resetFinal(); + applyHmModifiers(true, true, true); + updateHeightMapTex(false); + updateHeightMapTex(true); + DAGORED2->invalidateViewportCache(); + invalidateDistanceField(); + } + } + del_it(dlg); + } + break; + + case CM_IMPORT_WATER_DET_HMAP: importWaterHeightmap(true); break; + case CM_IMPORT_WATER_MAIN_HMAP: importWaterHeightmap(false); break; + case CM_ERASE_WATER_HEIGHTMAPS: eraseWaterHeightmap(); break; + + case CM_EXPORT_COLORMAP: exportColormap(); break; + + case CM_HILL_UP: + case CM_HILL_DOWN: + case CM_ALIGN: + case CM_SMOOTH: + case CM_SHADOWS: + case CM_SCRIPT: + if (id == CM_SHADOWS && !hasLightmapTex) + break; + + objEd.setEditMode(id); + objEd.updateToolbarButtons(); + DAGORED2->setBrush((Brush *)brushes[currentBrushId = (id - CM_HILL_UP)]); + refillBrush(); + DAGORED2->beginBrushPaint(); + DAGORED2->repaint(); + break; + + case CM_REBUILD: + generateLandColors(); + calcFastLandLighting(); + resetRenderer(); + break; + + case CM_REBUILD_RIVERS: rebuildRivers(); break; + + case CM_BUILD_COLORMAP: + generateLandColors(); + resetRenderer(); + break; + + case CM_BUILD_LIGHTMAP: + calcFastLandLighting(); + resetRenderer(); + break; + + case CM_EXPORT_LAND_TO_GAME: exportLand(); break; + + case CM_EXPORT_LOFT_MASKS: + { + CDialogWindow *dlg = DAGORED2->createDialog(_pxScaled(350), _pxScaled(704), "Loft mask export props"); + PropPanel2 &panel = *dlg->getPanel(); + panel.createCheckBox(11, "Build main HMAP loft masks", lastExpLoftMain); + panel.createEditInt(12, "Main HMAP masks tex size", lastExpLoftMainSz); + panel.createCheckBox(13, "Use main HMAP area", lastExpLoftUseRect[0]); + panel.createPoint2(14, "Main Area origin:", lastExpLoftRect[0][0]); + panel.createPoint2(15, "Main Area Size:", lastExpLoftRect[0].width()); + if (detDivisor) + { + panel.createSeparator(0); + panel.createCheckBox(21, "Build det HMAP loft masks", lastExpLoftDet); + panel.createEditInt(22, "Det HMAP masks tex size", lastExpLoftDetSz); + panel.createCheckBox(23, "Use det HMAP area", lastExpLoftUseRect[1]); + panel.createPoint2(24, "Det Area origin:", lastExpLoftRect[1][0]); + panel.createPoint2(25, "Det Area Size:", lastExpLoftRect[1].width()); + } + + panel.createSeparator(0); + float hmin = 0, hmax = 8192; + if (lastMinHeight[0] < MAX_REAL / 2 && lastHeightRange[0] < MAX_REAL / 2) + hmin = lastMinHeight[0], hmax = lastMinHeight[0] + lastHeightRange[0]; + if (detDivisor) + { + float hmin_det = 0, hmax_det = 8192; + if (lastMinHeight[1] < MAX_REAL / 2 && lastHeightRange[1] < MAX_REAL / 2) + hmin_det = lastMinHeight[1], hmax_det = lastMinHeight[1] + lastHeightRange[1]; + inplace_min(hmin, hmin_det); + inplace_max(hmax, hmax_det); + } + panel.createEditFloat(31, "Minimal height", hmin); + panel.createEditFloat(32, "Height range", hmax - hmin); + + panel.createSeparator(0); + panel.createCheckBox(51, "Use prefabs to build masks", true); + panel.createEditInt(52, "Prefabs layer index", 0); + + panel.createSeparator(0); + panel.createCheckBox(61, "Honour layers' \"to mask\" properties", true); + + String prj; + DAGORED2->getProjectFolderPath(prj); + panel.createSeparator(0); + panel.createFileEditBox(41, "Out dir", lastExpLoftFolder.empty() ? prj : lastExpLoftFolder); + panel.setBool(41, true); + panel.createCheckBox(42, "Create subfolders when areas used", lastExpLoftCreateAreaSubfolders); + if (dlg->showDialog() == DIALOG_ID_OK) + { + lastExpLoftFolder = panel.getText(41); + lastExpLoftCreateAreaSubfolders = panel.getBool(42); + lastExpLoftMain = panel.getBool(11); + lastExpLoftMainSz = panel.getInt(12); + lastExpLoftDet = panel.getBool(21); + lastExpLoftDetSz = panel.getInt(22); + lastExpLoftUseRect[0] = panel.getBool(13); + lastExpLoftRect[0][0] = panel.getPoint2(14); + lastExpLoftRect[0][1] = lastExpLoftRect[0][0] + panel.getPoint2(15); + lastExpLoftUseRect[1] = panel.getBool(23); + lastExpLoftRect[1][0] = panel.getPoint2(24); + lastExpLoftRect[1][1] = lastExpLoftRect[1][0] + panel.getPoint2(25); + + G_STATIC_ASSERT(EditLayerProps::MAX_LAYERS <= 64); + uint64_t prev_layers_hide_mask = DAEDITOR3.getEntityLayerHiddenMask(); + bool honor_layer_props = panel.getBool(61); + if (!honor_layer_props) + DAEDITOR3.conNote("%s: ignoring layers' \"to mask\" property", "Loft mask export"); + else + { + uint64_t layers_hide_mask = 0; + for (unsigned i = 0; i < EditLayerProps::layerProps.size(); i++) + { + if (!EditLayerProps::layerProps[i].renderToMask) + layers_hide_mask |= uint64_t(1) << i; + if (EditLayerProps::layerProps[i].hide && EditLayerProps::layerProps[i].renderToMask) + DAEDITOR3.conNote("%s: unhiding layer '%s' due to \"to mask\" is ON", "Loft mask export", EditLayerProps::layerName(i)); + else if (!EditLayerProps::layerProps[i].hide && !EditLayerProps::layerProps[i].renderToMask) + DAEDITOR3.conNote("%s: hiding layer '%s' due to \"to mask\" is OFF", "Loft mask export", EditLayerProps::layerName(i)); + } + DAEDITOR3.setEntityLayerHiddenMask(layers_hide_mask); + } + + exportLoftMasks(lastExpLoftFolder, lastExpLoftMain ? lastExpLoftMainSz : 0, lastExpLoftDet ? lastExpLoftDetSz : 0, + panel.getFloat(31), panel.getFloat(31) + panel.getFloat(32), panel.getBool(51) ? panel.getInt(52) : -1); + + DAEDITOR3.setEntityLayerHiddenMask(prev_layers_hide_mask); + } + del_it(dlg); + } + break; + + case CM_RESTORE_HM_BACKUP: + if (hmBackupCanBeRestored()) + { + if (wingw::message_box(wingw::MBS_YESNO | wingw::MBS_QUEST, "Confirmation", + "Do you really want to revert changes\n" + "(restore backup copy of heightmap)?") == wingw::MB_ID_YES) + restoreBackup(); + } + else + { + wingw::message_box(wingw::MBS_INFO, "Cannot revert changes", "No backup created yet (maybe nothing changed?)"); + } + break; + + case CM_COMMIT_HM_CHANGES: hmCommitChanges(); break; + + case CM_EXPORT_LAYERS: + { + Tab enabledLayers(tmpmem); + ExportLayeesDlg dlg(this, enabledLayers); + if (!dlg.execute()) + break; + + int mapSizeX = landClsMap.getMapSizeX(); + int mapSizeY = landClsMap.getMapSizeY(); + + for (int i = 0; i < enabledLayers.size(); i++) + { + int idx = enabledLayers[i]; + const char *lname = hmlService->getBitLayerName(landClsLayersHandle, idx); + HmapBitLayerDesc layer = landClsLayer[idx]; + + int bpp = layer.bitCount; + if (bpp == 1 || bpp == 2) + ; // leave as is + else if (bpp <= 4) + bpp = 4; + else if (bpp <= 8) + bpp = 8; + else + bpp = 32; + + IBitMaskImageMgr::BitmapMask img; + if (bpp == 32) + bitMaskImgMgr->createImage32(img, mapSizeX, mapSizeY); + else + bitMaskImgMgr->createBitMask(img, mapSizeX, mapSizeY, bpp); + +#define BUILD_MAP(SET, SH) \ + for (int y = 0; y < mapSizeY; y++) \ + for (int x = 0; x < mapSizeX; x++) \ + img.SET(x, y, layer.getLayerData(landClsMap.getData(x, y)) << SH); + switch (bpp) + { + case 1: BUILD_MAP(setMaskPixel1, 7); break; + case 2: BUILD_MAP(setMaskPixel2, 6); break; + case 4: BUILD_MAP(setMaskPixel4, 4); break; + case 8: BUILD_MAP(setMaskPixel8, 0); break; + case 32: BUILD_MAP(setImagePixel, 0); break; + } + bitMaskImgMgr->saveImage(img, ".", lname); + bitMaskImgMgr->destroyImage(img); +#undef BUILD_MAP + + DAEDITOR3.conNote("landclass layer %s exported to %%LEVEL%%/%s.tif", lname, lname); + + if (idx == detLayerIdx && detTexIdxMap) + { + bool hasDet[256]; + memset(hasDet, 0, sizeof(hasDet)); + for (int y = 0; y < mapSizeY; y++) + for (int x = 0; x < mapSizeX; x++) + { + uint64_t idx = detTexIdxMap->getData(x, y); + uint64_t wt = detTexWtMap->getData(x, y); + while (wt) + { + if (!hasDet[idx & 0xFF] && (wt & 0xFF)) + hasDet[idx & 0xFF] = true; + idx >>= 8; + wt >>= 8; + } + } + + bitMaskImgMgr->createBitMask(img, mapSizeX, mapSizeY, 8); + + for (int dt = 0; dt < 256; dt++) + { + if (!hasDet[dt]) + continue; + for (int y = 0; y < mapSizeY; y++) + for (int x = 0; x < mapSizeX; x++) + { + uint64_t idx = detTexIdxMap->getData(x, y); + uint64_t wt = detTexWtMap->getData(x, y); + while (wt) + { + if ((idx & 0xFF) == dt) + { + int w = wt & 0xFF; + if (w) + img.setMaskPixel8(x, y, w); + break; + } + idx >>= 8; + wt >>= 8; + } + } + + String fn(128, "%s_%d_%s", lname, dt, dd_get_fname(detailTexBlkName[dt].str())); + bitMaskImgMgr->saveImage(img, ".", fn); + DAEDITOR3.conNote("landclass layer %s:slot%d exported to %%LEVEL%%/%s.tif", lname, dt, fn.str()); + bitMaskImgMgr->clearBitMask(img); + } + + bitMaskImgMgr->destroyImage(img); + } + } + DAEDITOR3.conShow(true); + break; + } + + case CM_EXPORT_AS_COMPOSIT: + case CM_SPLIT_COMPOSIT: + case CM_INSTANTIATE_GENOBJ_INTO_ENTITIES: + case CM_SPLINE_IMPORT_FROM_DAG: + case CM_SPLINE_EXPORT_TO_DAG: + case CM_COLLAPSE_MODIFIERS: + case CM_MAKE_SPLINES_CROSSES: + case CM_MOVE_OBJECTS: + case CM_UNIFY_OBJ_NAMES: + case CM_HIDE_UNSELECTED_SPLINES: + case CM_UNHIDE_ALL_SPLINES: objEd.onClick(id, 0); break; + + case CM_SET_PT_VIS_DIST: + { + CDialogWindow *dlg = DAGORED2->createDialog(_pxScaled(250), _pxScaled(100), "Set visibility range for points"); + PropPanel2 &panel = *dlg->getPanel(); + panel.createEditFloat(1, "Visibility range", objEd.maxPointVisDist); + int ret = dlg->showDialog(); + + if (ret == DIALOG_ID_OK) + { + objEd.maxPointVisDist = panel.getFloat(1); + DAGORED2->invalidateViewportCache(); + } + + del_it(dlg); + + break; + } + + case CM_AUTO_ATACH: + { + objEd.autoAttachSplines(); + break; + } + + case CM_MAKE_BOTTOM_SPLINES: objEd.makeBottomSplines(); break; + + case CM_TAB_PRESS: + { + IGenViewportWnd *_vp = DAGORED2->getCurrentViewport(); + + if (!brushDlg->isVisible() && _vp && _vp->isActive()) + if (currentBrushId >= 0 && currentBrushId < brushes.size()) + { + PropertyContainerControlBase *_panel = brushDlg->getPanel(); + _panel->clear(); + brushes[currentBrushId]->fillParams(*_panel); + int _x = 0, _y = 0; + wingw::get_mouse_pos(_x, _y); + brushDlg->autoSize(); + int _x_offset = brushDlg->getPanel()->getWidth() / 2; + int _y_offset = brushDlg->getPanel()->getHeight() / 2; + brushDlg->moveWindow(_x - _x_offset, _y - _y_offset); + brushDlg->show(); + return true; + } + } + break; + + case CM_TAB_RELEASE: + { + if (brushDlg->isVisible()) + brushDlg->hide(); + + IGenViewportWnd *_vp = DAGORED2->getCurrentViewport(); + if (_vp) + _vp->activate(); + } + break; + } + + return false; +} + +//============================================================================== + +void HmapLandPlugin::handleKeyPress(IGenViewportWnd *wnd, int vk, int modif) +{ + if (vk == 'P') + { + EDITORCORE->skipManagePropPanels(true); + objEd.handleKeyPress(wnd, vk, modif); + EDITORCORE->skipManagePropPanels(false); + onPluginMenuClick(CM_SHOW_PANEL); + return; + } + + objEd.handleKeyPress(wnd, vk, modif); + + switch (vk) + { + case 'G': + if (wingw::is_key_pressed(wingw::V_CONTROL)) + onPluginMenuClick(CM_BUILD_COLORMAP); + return; + + case 'H': + if (wingw::is_key_pressed(wingw::V_CONTROL) && wingw::is_key_pressed(wingw::V_ALT)) + onPluginMenuClick(CM_RESTORE_HM_BACKUP); + else if (wingw::is_key_pressed(wingw::V_CONTROL)) + onPluginMenuClick(CM_COMMIT_HM_CHANGES); + return; + + case 'E': + if (wingw::is_key_pressed(wingw::V_CONTROL) && wingw::is_key_pressed(wingw::V_SHIFT)) + onPluginMenuClick(CM_UNHIDE_ALL_SPLINES); + else if (wingw::is_key_pressed(wingw::V_CONTROL)) + onPluginMenuClick(CM_HIDE_UNSELECTED_SPLINES); + return; + + case 'M': + if (wingw::is_key_pressed(wingw::V_CONTROL)) + onPluginMenuClick(CM_COLLAPSE_MODIFIERS); + return; + + case 'R': + if (wingw::is_key_pressed(wingw::V_CONTROL)) + onPluginMenuClick(CM_REBUILD); + return; + + case '1': + if (!wingw::is_special_pressed()) + onPluginMenuClick(CM_HILL_UP); + return; + + case '2': + if (!wingw::is_special_pressed()) + onPluginMenuClick(CM_HILL_DOWN); + return; + + case '3': + if (!wingw::is_special_pressed()) + onPluginMenuClick(CM_ALIGN); + return; + + case '4': + if (!wingw::is_special_pressed()) + onPluginMenuClick(CM_SMOOTH); + return; + + case '5': + if (!wingw::is_special_pressed()) + onPluginMenuClick(CM_SHADOWS); + return; + + case '6': + if (!wingw::is_special_pressed()) + onPluginMenuClick(CM_SCRIPT); + return; + + case wingw::V_BRACKET_O: + if (DAGORED2->isBrushPainting() && DAGORED2->getBrush()) + { + int cnt = sizeof(brushIncTable) / sizeof(BrushIncrementer); + G_ASSERT(cnt > 0); + + real radius = DAGORED2->getBrush()->getRadius(), incr = 0; + + real cellSz = (real)HmapLandPlugin::self->getHeightmapCellSize() * (real)HmapLandPlugin::self->getHeightmapSizeX() / + (real)HmapLandPlugin::self->getlandClassMap().getMapSizeX(); + + if (cellSz < 1e-3) + return; + + real landClsMapRadius = radius / cellSz; + + for (int i = cnt - 1; i >= 0; i--) + { + if (landClsMapRadius > brushIncTable[i].lim) + { + incr = brushIncTable[i].value; + break; + } + } + + landClsMapRadius = floor(landClsMapRadius - incr); + + DAGORED2->getBrush()->setRadius(landClsMapRadius * cellSz); + if (propPanel->getPanelWindow()) + DAGORED2->getBrush()->updateToPanel(*propPanel->getPanelWindow()); // refillBrush(); + DAGORED2->invalidateViewportCache(); + } + return; + + case wingw::V_BRACKET_C: + if (DAGORED2->isBrushPainting() && DAGORED2->getBrush()) + { + int cnt = sizeof(brushIncTable) / sizeof(BrushIncrementer); + G_ASSERT(cnt > 0); + + real radius = DAGORED2->getBrush()->getRadius(), incr = 0; + + real cellSz = (real)HmapLandPlugin::self->getHeightmapCellSize() * (real)HmapLandPlugin::self->getHeightmapSizeX() / + (real)HmapLandPlugin::self->getlandClassMap().getMapSizeX(); + + if (cellSz < 1e-3) + return; + + real landClsMapRadius = radius / cellSz; + + for (int i = 0; i < cnt; i++) + { + if (landClsMapRadius >= brushIncTable[i].lim) + incr = brushIncTable[i].value; + } + + landClsMapRadius = floor(landClsMapRadius + incr); + + DAGORED2->getBrush()->setRadius(landClsMapRadius * cellSz); + if (propPanel->getPanelWindow()) + DAGORED2->getBrush()->updateToPanel(*propPanel->getPanelWindow()); // refillBrush(); + DAGORED2->invalidateViewportCache(); + } + return; + } +} + +void HmapLandPlugin::handleKeyRelease(IGenViewportWnd *wnd, int vk, int modif) { objEd.handleKeyRelease(wnd, vk, modif); } diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlExport.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlExport.cpp new file mode 100644 index 000000000..9689a184c --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlExport.cpp @@ -0,0 +1,864 @@ +#include "hmlPlugin.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +// the 3d/ddsFormat.h included by mokeDDS.h indirectly includes wingdi.h which defines ERROR with a macro +#undef ERROR + +bool game_res_sys_v2 = false; +int exportImageAsDds(mkbindump::BinDumpSaveCB &cb, TexPixel32 *image, int size, int format, int mipmap_count, bool gamma1); +static int exportDdsAsDDsX(mkbindump::BinDumpSaveCB &cb, void *data, int size, bool gamma1); + + +static void makeFilter(float *wt, int size) +{ + double sum = 0; + + float *ptr = wt; + for (int y = -size; y <= size; ++y) + { + float yk = size - abs(y); + + for (int x = -size; x <= size; ++x, ++ptr) + { + float w = (size - abs(x)) * yk; + *ptr = w; + sum += w; + } + } + + ptr = wt; + for (int y = -size; y <= size; ++y) + for (int x = -size; x <= size; ++x, ++ptr) + *ptr /= sum; +} + + +static float filterHeight(float *data, int size, int stride, float *wt) +{ + float res = 0; + + for (int y = size; y; --y, data += stride) + for (int x = 0; x < size; ++x, ++wt) + res += data[x] * (*wt); + + return res; +} + + +struct HeightMapExportLodMap +{ + int sizeX, sizeY; + SmallTab offsets; + + int tableOffset; + + + void resize(int x, int y) + { + sizeX = x; + sizeY = y; + clear_and_resize(offsets, x * y); + mem_set_0(offsets); + } + + void saveTable(mkbindump::BinDumpSaveCB &cb) + { + tableOffset = cb.tell(); + cb.writeTabData32ex(offsets); + } + + void makeOfsRelative(int base_ofs) + { + for (int i = 0; i < offsets.size(); i++) + offsets[i] -= base_ofs; + } + + void save(mkbindump::BinDumpSaveCB &cb) + { + cb.writeInt32e(sizeX); + cb.writeInt32e(sizeY); + + saveTable(cb); + } +}; + + +static int packHeightAs16Bit(float h, float min_val, float scale) +{ + int v = real2int((h - min_val) * scale + 0.5f); + if (v <= 0) + return 0; + if (v >= (1 << 16) - 1) + return (1 << 16) - 1; + return v; +} + + +static void writeHeightmapElem(mkbindump::BinDumpSaveCB &cb, float *data_ptr, int elem_size, int data_x, int data_stride) +{ + G_ASSERT(data_x > 0); + + if (data_x > elem_size) + data_x = elem_size; + + float minVal, maxVal; + minVal = maxVal = *data_ptr; + + float *ptr = data_ptr; + for (int y = 0; y < elem_size; ++y, ptr += data_stride) + for (int x = 0; x < data_x; ++x) + { + float v = ptr[x]; + if (v < minVal) + minVal = v; + else if (v > maxVal) + maxVal = v; + } + + cb.writeReal(minVal); + cb.writeReal(maxVal); + + float scale = maxVal - minVal; + if (float_nonzero(scale)) + scale = ((1 << 16) - 1) / scale; + + for (int y = 0; y < elem_size; ++y, data_ptr += data_stride) + { + for (int x = 0; x < data_x; ++x) + cb.writeInt16e(packHeightAs16Bit(data_ptr[x], minVal, scale)); + + int v = packHeightAs16Bit(data_ptr[data_x - 1], minVal, scale); + for (int x = data_x; x < elem_size; ++x) + cb.writeInt16e(v); + } +} + + +static void exportHeightmapToGame(mkbindump::BinDumpSaveCB &cb, HeightMapStorage &heightmap, int gridStep, int elemSize, int numLods, + int base_ofs) +{ + CoolConsole &con = DAGORED2->getConsole(); + + int mapSizeX = heightmap.getMapSizeX(); + int mapSizeY = heightmap.getMapSizeY(); + + int farCellSize = 1 << numLods; + int farElemSize = elemSize << numLods; + + Tab lodMaps(tmpmem); + lodMaps.resize(numLods + 1); + + for (int i = 0; i < lodMaps.size(); ++i) + { + int esize = (elemSize * gridStep) << i; + + lodMaps[i].resize((mapSizeX + esize - 1) / esize, (mapSizeY + esize - 1) / esize); + + lodMaps[i].save(cb); + } + + con.startProgress(); + con.setActionDesc("exporting heightmap..."); + con.setTotal(mapSizeY); + + int dataW = mapSizeX / gridStep + farCellSize * 2; + + SmallTab data, buffer, filterWt; + clear_and_resize(data, dataW * ((elemSize + 2) << numLods)); + + int bufferW = (dataW + 1) * gridStep + 1; + clear_and_resize(buffer, bufferW * (gridStep * 2 + 1)); + + clear_and_resize(filterWt, (gridStep * 2 + 1) * (gridStep * 2 + 1)); + makeFilter(&filterWt[0], gridStep); + + for (int mapY = 0; mapY < mapSizeY; mapY += farElemSize * gridStep) + { + // get data from heightmap (downsample if necessary) + int hmY = mapY - farCellSize * gridStep; + + float *ptr = &buffer[0]; + for (int y = 0; y <= gridStep; ++y) + for (int x = 0; x < bufferW; ++x, ++ptr) + *ptr = heightmap.getFinalData(x - gridStep - farCellSize * gridStep, hmY + y - gridStep); + + float *dataPtr = &data[0]; + for (int dataY = -farCellSize; dataY < farElemSize + farCellSize; ++dataY) + { + hmY = mapY + dataY * gridStep; + + ptr = &buffer[bufferW * (gridStep + 1)]; + for (int y = 1; y <= gridStep; ++y) + for (int x = 0; x < bufferW; ++x, ++ptr) + *ptr = heightmap.getFinalData(x - gridStep - farCellSize * gridStep, hmY + y); + + // downsample buffer to data line + ptr = &buffer[0]; + for (int x = 0; x < dataW; ++x, ++dataPtr, ptr += gridStep) + *dataPtr = filterHeight(ptr, gridStep * 2 + 1, bufferW, &filterWt[0]); + + // move buffer data + memmove(&buffer[0], &buffer[gridStep * bufferW], bufferW * (gridStep + 1) * elem_size(buffer)); + } + + // save lods heightmap data + for (int lodi = 0; lodi < lodMaps.size(); ++lodi) + { + int elemY = mapY / ((elemSize * gridStep) << lodi); + int ofsi = elemY * lodMaps[lodi].sizeX; + + int numY = 1 << (numLods - lodi); + + if (numY + elemY > lodMaps[lodi].sizeY) + numY = lodMaps[lodi].sizeY - elemY; + + int width = dataW >> lodi; + + int dataOfs = (farCellSize >> lodi) * (width + 1); + + for (int ey = 0; ey < numY; ++ey, ofsi += lodMaps[lodi].sizeX) + { + dataPtr = &data[width * elemSize * ey + dataOfs]; + + for (int ex = 0; ex < lodMaps[lodi].sizeX; ++ex, dataPtr += elemSize) + { + lodMaps[lodi].offsets[ofsi + ex] = cb.tell(); + + writeHeightmapElem(cb, dataPtr, elemSize, width - ex * elemSize, width); + } + } + + if (lodi == lodMaps.size() - 1) + break; + + // downsample data for lower LOD + dataPtr = &data[width * 2]; + float *dest = &data[width >> 1]; + + numY = (elemSize + 2) << (numLods - lodi); + + for (int y = 2; y < numY - 1; y += 2, dataPtr += width * 2, dest += (width >> 1)) + for (int x = 2; x < width - 1; x += 2) + dest[x >> 1] = dataPtr[x] * 0.25f + (dataPtr[x - 1] + dataPtr[x + 1] + dataPtr[x - width] + dataPtr[x + width]) * 0.125f + + (dataPtr[x - width - 1] + dataPtr[x - width + 1] + dataPtr[x + width - 1] + dataPtr[x + width + 1]) * 0.0625f; + } + + heightmap.unloadUnchangedData(mapY + 1); + + con.incDone(farElemSize * gridStep); + } + + // write tables + int ofs = cb.tell(); + + for (int i = 0; i < lodMaps.size(); ++i) + { + cb.seekto(lodMaps[i].tableOffset); + lodMaps[i].makeOfsRelative(base_ofs); + lodMaps[i].saveTable(cb); + } + + cb.seekto(ofs); + + con.endProgress(); +} + + +// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ// + + +void buildColorTexture(TexPixel32 *image, MapStorage &colormap, int tex_data_sizex, int tex_data_sizey, int stride, + int map_x, int map_y) +{ + for (int y = 0; y < tex_data_sizey; ++y, ++map_y, image += stride) + for (int x = 0; x < tex_data_sizex; ++x) + image[x].c = colormap.getData(map_x + x, map_y); +} + + +void buildLightTexture(TexPixel32 *image, MapStorage &lightmap, int tex_data_sizex, int tex_data_sizey, int stride, + int map_x, int map_y, bool use_normal_map) +{ + for (int y = 0; y < tex_data_sizey; ++y, ++map_y, image += stride) + for (int x = 0; x < tex_data_sizex; ++x) + { + unsigned lt = lightmap.getData(map_x + x, map_y); + + if (use_normal_map) + { + unsigned nx = (lt >> 16) & 0xFF; + unsigned nz = (lt >> 24) & 0xFF; + + image[x].c = E3DCOLOR(0, nx, 0, nz); + } + else + { + unsigned sunLight = (lt >> 0) & 0xFF; + unsigned skyLight = (lt >> 8) & 0xFF; + + image[x].c = E3DCOLOR(skyLight, skyLight, skyLight, sunLight); + } + } +} + + +static void expandImageBorder(TexPixel32 *image, int size, int data_size) +{ + int y; + for (y = 0; y < data_size; ++y, image += size) + { + TexPixel32 p = image[data_size - 1]; + for (int x = data_size; x < size; ++x) + image[x] = p; + } + + TexPixel32 *lastLine = image - size; + for (; y < size; ++y, image += size) + memcpy(image, lastLine, size * sizeof(*image)); +} + + +static void exportColorAndLightMaps(mkbindump::BinDumpSaveCB &cb, MapStorage &colormap, MapStorage &lightmap, + int elem_size, int num_lods, int lightmapScaleFactor, int base_ofs, bool use_normal_map) +{ + CoolConsole &con = DAGORED2->getConsole(); + bool exp_ltmap = lightmapScaleFactor > 0; + if (!exp_ltmap) + lightmapScaleFactor = 1; + + int mapSizeX = colormap.getMapSizeX(); + int mapSizeY = colormap.getMapSizeY(); + + int texElemSize = elem_size << num_lods; + + int texSize; + for (texSize = 1; texSize < texElemSize; texSize <<= 1) + ; + + int texDataSize = texElemSize; + if (texDataSize < texSize) + texDataSize++; + + int numElemsX = (mapSizeX + texElemSize - 1) / texElemSize; + int numElemsY = (mapSizeY + texElemSize - 1) / texElemSize; + + con.startProgress(); + con.setActionDesc(exp_ltmap ? "exporting color and light maps..." : "exporting color maps..."); + con.setTotal(numElemsX * numElemsY); + + cb.writeInt32e(numElemsX); + cb.writeInt32e(numElemsY); + cb.writeInt32e(texSize); + cb.writeInt32e(exp_ltmap ? texSize * lightmapScaleFactor : 0); + cb.writeInt32e(texElemSize); + + SmallTab offsets; + + clear_and_resize(offsets, numElemsX * numElemsY); + mem_set_0(offsets); + + int tableOffset = cb.tell(); + cb.writeTabDataRaw(offsets); // reserve space with zeroes here + + SmallTab image; + clear_and_resize(image, texSize * texSize * lightmapScaleFactor * lightmapScaleFactor); + + for (int ey = 0, mapY = 0, index = 0; ey < numElemsY; ++ey, mapY += texElemSize) + { + for (int ex = 0, mapX = 0; ex < numElemsX; ++ex, mapX += texElemSize, ++index) + { + offsets[index] = cb.tell(); + int colorTexSz = 0, lightTexSz = 0; + + cb.writeInt32e(0); + cb.writeInt32e(0); + + buildColorTexture(&image[0], colormap, texDataSize, texDataSize, texSize, mapX, mapY); + expandImageBorder(&image[0], texSize, texDataSize); + + ddstexture::Converter::Format fmt = ddstexture::Converter::fmtDXT1; + if (cb.getTarget() == _MAKE4C('iOS')) + fmt = ddstexture::Converter::fmtASTC8; + colorTexSz = exportImageAsDds(cb, &image[0], texSize, fmt, ddstexture::Converter::AllMipMaps, false); + + if (exp_ltmap) + { + buildLightTexture(&image[0], lightmap, texDataSize * lightmapScaleFactor, texDataSize * lightmapScaleFactor, + texSize * lightmapScaleFactor, mapX * lightmapScaleFactor, mapY * lightmapScaleFactor, use_normal_map); + expandImageBorder(&image[0], texSize * lightmapScaleFactor, texDataSize * lightmapScaleFactor); + + ddstexture::Converter::Format fmt = ddstexture::Converter::fmtDXT5; + if (cb.getTarget() == _MAKE4C('iOS')) + fmt = ddstexture::Converter::fmtASTC4; + lightTexSz = exportImageAsDds(cb, &image[0], texSize * lightmapScaleFactor, fmt, ddstexture::Converter::AllMipMaps, true); + } + int endOfs = cb.tell(); + + cb.seekto(offsets[index]); + cb.writeInt32e(colorTexSz); + cb.writeInt32e(lightTexSz); + + cb.seekto(endOfs); + + con.incDone(); + } + colormap.unloadUnchangedData(mapY + 1); + lightmap.unloadUnchangedData(mapY + 1); + } + + int ofs = cb.tell(); + + cb.seekto(tableOffset); + + for (int i = 0; i < offsets.size(); i++) + offsets[i] -= base_ofs; + cb.writeTabData32ex(offsets); + + cb.seekto(ofs); + + con.endProgress(); +} + +int exportImageAsDds(mkbindump::BinDumpSaveCB &cb, TexPixel32 *image, int size, int format, int mipmap_count, bool gamma1) +{ + ddstexture::Converter cnv; + cnv.format = (ddstexture::Converter::Format)format; + cnv.mipmapType = ddstexture::Converter::mipmapGenerate; + cnv.mipmapCount = mipmap_count; + + DynamicMemGeneralSaveCB memcwr(tmpmem, 0, size * size * (4 * 3 / 2)); + if (!dagTools->ddsConvertImage(cnv, memcwr, image, size, size, size * sizeof(*image))) + throw IGenSave::SaveException("Error converting image to DDS", cb.tell()); + + return exportDdsAsDDsX(cb, memcwr.data(), memcwr.size(), gamma1); +} + +static int exportDdsAsDDsX(mkbindump::BinDumpSaveCB &cb, void *data, int size, bool gamma1) +{ + ddsx::Buffer b; + ddsx::ConvertParams cp; + cp.allowNonPow2 = false; + cp.packSzThres = 8 << 10; + if (gamma1) + cp.imgGamma = 1.0; + cp.addrU = ddsx::ConvertParams::ADDR_CLAMP; + cp.addrV = ddsx::ConvertParams::ADDR_CLAMP; + cp.mipOrdRev = HmapLandPlugin::defMipOrdRev; + + if (!dagTools->ddsxConvertDds(cb.getTarget(), b, data, size, cp)) + { + CoolConsole &con = DAGORED2->getConsole(); + con.startLog(); + con.addMessage(ILogWriter::ERROR, "Can't export image: %s", dagTools->ddsxGetLastErrorText()); + con.endLog(); + return 0; + } + cb.writeRaw(b.ptr, b.len); + // debug("DDS(%d)->DDSx(%d)= %+d b rev=%d", size, b.len, b.len-size, cp.mipOrdRev); + int ret = b.len; + dagTools->ddsxFreeBuffer(b); + return ret; +} + +// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ// + + +int hmap_export_dds_as_ddsx_raw(mkbindump::BinDumpSaveCB &cb, char *data, int size, int w, int h, int bpp, int levels, int fmt, + bool gamma1) +{ + Tab dds_data; + char buf[1024]; + if (!create_dds_header(buf, sizeof(buf), w, h, bpp, levels, fmt, cb.getTarget() == _MAKE4C('iOS'))) + { + CoolConsole &con = DAGORED2->getConsole(); + con.startLog(); + con.addMessage(ILogWriter::ERROR, "Can't convert to DDS - unknown format %08X", fmt); + con.endLog(); + return 0; + } + + dds_data.resize(::dds_header_size() + size); + memcpy(&dds_data[0], buf, ::dds_header_size()); + memcpy(&dds_data[::dds_header_size()], data, size); + return exportDdsAsDDsX(cb, dds_data.data(), data_size(dds_data), gamma1); +} + + +// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ// + +static bool validate_texture_name(String &name) +{ + DagorAsset *a = DAEDITOR3.getAssetByName(name, DAEDITOR3.getAssetTypeId("tex")); + if (!a) + return false; + name.printf(128, "%s*", a->getName()); + strlwr(name); + return true; +} + +bool hmap_export_tex(mkbindump::BinDumpSaveCB &cb, const char *tex_name, const char *fname, bool clamp, bool gamma1) +{ + String name(128, "%s", tex_name); + if (!validate_texture_name(name)) + { + cb.writeDwString(""); + return false; + } + cb.writeDwString(name); + return true; +} + + +static bool validate_blk_texture_name(DataBlock &blk, const char *param_name) +{ + if (!blk.getStr(param_name, NULL)) + return false; + String texture_name(128, "%s", blk.getStr(param_name)); + validate_texture_name(texture_name); + blk.setStr(param_name, texture_name); + return true; +} + +bool hmap_export_land(mkbindump::BinDumpSaveCB &cb, const char *land_name, int editorId) +{ + DagorAsset *a = DAEDITOR3.getAssetByName(land_name, DAEDITOR3.getAssetTypeId("land")); + String ref(128, "%s", a ? a->getName() : ""); + strlwr(ref); + cb.beginBlock(); + cb.writeDwString(ref); + // saves for now only! + DataBlock *blk = a ? a->props.getBlockByName("detail") : NULL; + if (!a || !blk) + { + cb.endBlock(); + if (a) + DAGORED2->getConsole().addMessage(ILogWriter::WARNING, "Land class <%s> - has no detail block", land_name); + else + DAGORED2->getConsole().addMessage(ILogWriter::WARNING, "No land class <%s>", land_name); + return false; + } + + if (!blk->getStr("texture", NULL)) + DAGORED2->getConsole().addMessage(ILogWriter::WARNING, "Land class <%s> - has no texture in detail block", land_name); + DataBlock saveBlk = *blk; + validate_blk_texture_name(saveBlk, "texture"); + saveBlk.setInt("editorId", editorId); + saveBlk.saveToStream(cb.getRawWriter()); + cb.endBlock(); + return true; +} + +#if defined(USE_HMAP_ACES) +__forceinline uint8_t convert_4bit_to8bit(unsigned a) +{ + a &= 0xF; + return (a << 4) | a; +} +bool aces_export_detail_maps(mkbindump::BinDumpSaveCB &cb, int mapSizeX, int mapSizeY, int tex_elem_size, + const Tab &land_class_names, int base_ofs, bool optimize_size = true, bool tools_internal = false) +{ + static const int MAX_DET_TEX_NUM = HmapLandPlugin::HMAX_DET_TEX_NUM; + CoolConsole &con = DAGORED2->getConsole(); + + int texElemSize = tex_elem_size; + + int texSize; + for (texSize = 1; texSize < texElemSize; texSize <<= 1) + ; + + int texDataSize = texElemSize; + if (texDataSize < texSize) + texDataSize++; + + int numElemsX = (mapSizeX + texElemSize - 1) / texElemSize; + int numElemsY = (mapSizeY + texElemSize - 1) / texElemSize; + + int numDetTex = HmapLandPlugin::self->getNumDetailTextures(); + SmallTab detTexRemap; + if (true) + { + SmallTab usedDetTex; + clear_and_resize(usedDetTex, numDetTex); + mem_set_0(usedDetTex); + + SmallTab typeRemap; + clear_and_resize(typeRemap, 256); + uint8_t detIds[MAX_DET_TEX_NUM]; + int texDataSize = min(texElemSize + 4, texSize); + for (int ey = 0, mapY = 0, index = 0; ey < numElemsY; ++ey, mapY += texElemSize) + for (int ex = 0, mapX = 0; ex < numElemsX; ++ex, mapX += texElemSize, ++index) + { + mem_set_ff(typeRemap); + memset(detIds, 0, MAX_DET_TEX_NUM); + int cnt = + HmapLandPlugin::self->getMostUsedDetTex(mapX, mapY, texDataSize, detIds, typeRemap.data(), HmapLandPlugin::LMAX_DET_TEX_NUM); + for (int di = 0; di < MAX_DET_TEX_NUM; di++) + if (detIds[di] != 0xFFU && detIds[di] < usedDetTex.size() && !usedDetTex[detIds[di]]) + usedDetTex[detIds[di]] = true; + } + + clear_and_resize(detTexRemap, numDetTex); + mem_set_ff(detTexRemap); + int ord = 0; + for (int i = 0; i < numDetTex; ++i) + { + if (usedDetTex[i]) + detTexRemap[i] = ord++; + debug("detTex[%d] %s is %s, remapped to %d", i, i < land_class_names.size() ? land_class_names[i].str() : NULL, + usedDetTex[i] ? "used" : "UNUSED", detTexRemap[i]); + } + debug("used %d detTex of %d", ord, numDetTex); + numDetTex = ord; + } + else + { + clear_and_resize(detTexRemap, numDetTex); + for (int i = 0; i < numDetTex; ++i) + detTexRemap[i] = i; + } + + int time0 = dagTools->getTimeMsec(); + + con.startProgress(); + con.setActionDesc("exporting detail textures..."); + con.setTotal(numDetTex); + + cb.beginBlock(); + + cb.writeInt32e(numDetTex); + + for (int i = 0, ie = HmapLandPlugin::self->getNumDetailTextures(); i < ie; ++i) + { + if (detTexRemap[i] < 0) + continue; + ::hmap_export_land(cb, i < land_class_names.size() ? land_class_names[i].str() : NULL, i); + con.incDone(); + } + debug("exported %d detail tex", numDetTex); + + con.endProgress(); + con.addMessage(ILogWriter::REMARK, " in %g seconds", (dagTools->getTimeMsec() - time0) / 1000.0f); + time0 = dagTools->getTimeMsec(); + + /*for (int i=0; i < numDetTex; ++i) + { + cb.writeReal(i < det_tex_offset.size() ? det_tex_offset[i].x : 0.f); + cb.writeReal(i < det_tex_offset.size() ? det_tex_offset[i].y : 0.f); + }*/ + + cb.endBlock(); + + con.endProgress(); + con.addMessage(ILogWriter::REMARK, " in %g seconds", (dagTools->getTimeMsec() - time0) / 1000.0f); + time0 = dagTools->getTimeMsec(); + + con.startProgress(); + con.setActionDesc("exporting %d detail maps: %dx%d (texSize=%d)...", numElemsX * numElemsY, numElemsX, numElemsY, texSize); + con.setTotal(numElemsX * numElemsY); + + cb.writeInt32e(numElemsX); + cb.writeInt32e(numElemsY); + cb.writeInt32e(texSize); + cb.writeInt32e(texElemSize); + + SmallTab offsets; + + clear_and_resize(offsets, numElemsX * numElemsY); + mem_set_0(offsets); + + int tableOffset = cb.tell(); + cb.writeTabDataRaw(offsets); // reserve space with zeroes here + + SmallTab image1; + clear_and_resize(image1, texSize * texSize); + mem_set_0(image1); + + SmallTab image2; + clear_and_resize(image2, texSize * texSize / 2); + mem_set_0(image2); + int optimizedSize = 0; + + for (int ey = 0, mapY = 0, index = 0; ey < numElemsY; ++ey, mapY += texElemSize) + { + for (int ex = 0, mapX = 0; ex < numElemsX; ++ex, mapX += texElemSize, ++index) + { + offsets[index] = cb.tell(); + if (tools_internal) + { + cb.writeZeroes(MAX_DET_TEX_NUM); + cb.writeInt32e(0); + cb.writeInt32e(0); + continue; + } + carray detIds; + mem_set_0(detIds); + + bool doneMark; + int cnt = HmapLandPlugin::self->loadLandDetailTexture(cb.getTarget(), ex, ey, (char *)image1.data(), texSize * 2, + (char *)image2.data(), texSize * 2, detIds, &doneMark, texSize, texElemSize, false, false); + for (int di = 0; di < MAX_DET_TEX_NUM; di++) + if (detIds[di] != 0xFFU) + { + DagorAsset *a = detIds[di] >= 0 && detIds[di] < land_class_names.size() + ? DAEDITOR3.getAssetByName(land_class_names[detIds[di]], DAEDITOR3.getAssetTypeId("land")) + : NULL; + if (!a) + DAEDITOR3.conError("cannot export with unresolved reference to landclass <%s>, id=%d [%d]", + detIds[di] >= 0 && detIds[di] < land_class_names.size() ? land_class_names[detIds[di]] : "", detIds[di], di); + else if (!a->props.getBlockByName("detail")) + DAEDITOR3.conError("Land class <%s> - has no detail block", land_class_names[detIds[di]]); + else if (!a->props.getBlockByName("detail")->getStr("texture", NULL)) + DAEDITOR3.conError("Land class <%s> - has no texture in detail block", land_class_names[detIds[di]]); + else if (detIds[di] >= detTexRemap.size() || detTexRemap[detIds[di]] < 0) + DAEDITOR3.conError("Internal error: unexpected detIds[%d]=%d detTexRemap.count=%d", di, detIds[di], detTexRemap.size()); + else + { + detIds[di] = detTexRemap[detIds[di]]; + continue; + } + return false; + } + + cb.writeRaw(detIds.data(), MAX_DET_TEX_NUM); + cb.writeInt32e(0); + cb.writeInt32e(0); + + int texOfs = cb.tell(); + + // exportImageAsDds(cb, image2.data(), texSize, + // ddstexture::Converter::fmtDXT1a, 1); + if (!optimize_size || cnt > 1) + { + unsigned fmt = + ((!optimize_size || cnt > 4) && cb.getTarget() != _MAKE4C('iOS')) ? TEXFMT_A4R4G4B4 : (cnt > 3 ? TEXFMT_DXT5 : TEXFMT_DXT1); + char *srcData = (char *)image1.data(); + int srcDataSize = data_size(image1); + SmallTab cnvData; + if (fmt != TEXFMT_A4R4G4B4) + { + ddstexture::Converter cnv; + cnv.format = (fmt == TEXFMT_DXT5) ? ddstexture::Converter::fmtDXT5 : ddstexture::Converter::fmtDXT1; + if (cb.getTarget() == _MAKE4C('iOS')) + cnv.format = (fmt == TEXFMT_DXT5) ? ddstexture::Converter::fmtASTC4 : ddstexture::Converter::fmtASTC8; + cnv.mipmapType = ddstexture::Converter::mipmapNone; + cnv.mipmapCount = 0; + clear_and_resize(cnvData, texSize * texSize * 4); + uint16_t *srcPix = (uint16_t *)srcData; + TexPixel32 *pixel = (TexPixel32 *)cnvData.data(); + for (int i = 0; i < texSize * texSize; ++i, srcPix++, pixel++) + { + pixel->a = pixel->r = pixel->g = pixel->b = 0; + pixel->a = convert_4bit_to8bit((*srcPix) >> 12); + pixel->r = convert_4bit_to8bit(((*srcPix) >> 8)); + pixel->g = convert_4bit_to8bit(((*srcPix) >> 4)); + pixel->b = convert_4bit_to8bit(((*srcPix) >> 0)); + if (cnt == 3 || cnt == 4) + pixel->b = 0; + else if (cnt == 2) + pixel->r = 0; + } + DynamicMemGeneralSaveCB cwr(tmpmem, data_size(cnvData) + 256, 64 << 10); + if (!dagTools->ddsConvertImage(cnv, cwr, (TexPixel32 *)cnvData.data(), texSize, texSize, texSize * 4)) + { + DAEDITOR3.conError("cannot convert %dx%d image at (%d,%d)", texSize, texSize, ex, ey); + fmt = TEXFMT_A4R4G4B4; + } + else + { + srcDataSize = (fmt == TEXFMT_DXT5) ? (texSize * texSize) : (texSize / 4) * (texSize * 2); + if (cb.getTarget() == _MAKE4C('iOS')) + srcDataSize = (fmt == TEXFMT_DXT5) ? srcDataSize : srcDataSize / 2; + clear_and_resize(cnvData, srcDataSize); + memcpy(cnvData.data(), cwr.data() + 128, srcDataSize); + srcData = (char *)cnvData.data(); + } + } + if (!hmap_export_dds_as_ddsx_raw(cb, srcData, srcDataSize, texSize, texSize, + (fmt == TEXFMT_A4R4G4B4) ? 16 : ((fmt == TEXFMT_DXT5) ? 8 : 4), 1, fmt, true)) + { + con.addMessage(ILogWriter::ERROR, "Can't write DDSX"); + } + optimizedSize += texSize * texSize * 2 - srcDataSize; + } + else + { + if (optimize_size) + optimizedSize += texSize * texSize * 2; + } + int endOfs1 = cb.tell(); + if (!optimize_size || cnt > 5) + { + hmap_export_dds_as_ddsx_raw(cb, (char *)image2.data(), data_size(image2), texSize, texSize, 4, 1, TEXFMT_DXT1, true); + } + { + if (optimize_size) + optimizedSize += texSize * texSize / 2; + } + int endOfs2 = cb.tell(); + + cb.seekto(offsets[index] + MAX_DET_TEX_NUM); + cb.writeInt32e(endOfs2 - texOfs); + cb.writeInt32e(endOfs1 - texOfs); + + cb.seekto(endOfs2); + + con.incDone(); + } + } + + int ofs = cb.tell(); + + cb.seekto(tableOffset); + + for (int i = 0; i < offsets.size(); i++) + offsets[i] -= base_ofs; + cb.writeTabData32ex(offsets); + + cb.seekto(ofs); + con.addMessage(ILogWriter::REMARK, " in %g seconds, optimizedSize=%dbytes", (dagTools->getTimeMsec() - time0) / 1000.0f, + optimizedSize); + time0 = dagTools->getTimeMsec(); + + con.endProgress(); + return true; +} +#else +bool aces_export_detail_maps(mkbindump::BinDumpSaveCB &cb, int mapSizeX, int mapSizeY, int tex_elem_size, + const Tab &land_class_names, int base_ofs, bool optimize_size = true, bool tools_internal = false) +{ + return false; +} +#endif + + +// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ// + + +// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ// + +bool HmapLandPlugin::exportLand(mkbindump::BinDumpSaveCB &cb) { return true; } + +bool HmapLandPlugin::exportLand(String &filename) +{ + CoolConsole &con = DAGORED2->getConsole(); + con.addMessage(ILogWriter::NOTE, "Exporting heightmap is no longer supported..."); + return true; +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlExportHmap.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlExportHmap.cpp new file mode 100644 index 000000000..51b9f8e3e --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlExportHmap.cpp @@ -0,0 +1,320 @@ +#include "hmlPlugin.h" + +#include + +#include +#include +#include +#include + + +class HeightmapExporter +{ +public: + virtual ~HeightmapExporter() {} + virtual bool exportHeightmap(const char *filename, HeightMapStorage &heightmap, real min_height, real height_range, CoolConsole &con, + int x0, int y0, int x1, int y1) = 0; +}; + + +class Raw32fHeightmapExporter : public HeightmapExporter +{ +#pragma pack(push) +#pragma pack(1) + struct Header + { + int w, h; + }; +#pragma pack(pop) + bool writeHeader; + +public: + Raw32fHeightmapExporter(bool write_header) : writeHeader(write_header) {} + virtual bool exportHeightmap(const char *filename, HeightMapStorage &heightmap, real, real, CoolConsole &con, int x0, int y0, int x1, + int y1) + { + file_ptr_t handle = ::df_open(filename, DF_WRITE | DF_CREATE); + + if (!handle) + { + con.addMessage(ILogWriter::ERROR, "Can't create file '%s'", filename); + return false; + } + + if (writeHeader) + { + Header header; + header.w = x1 - x0; + header.h = y1 - y0; + if (::df_write(handle, &header, sizeof(header)) != sizeof(header)) + { + con.addMessage(ILogWriter::ERROR, "Error writing file '%s'", filename); + ::df_close(handle); + return false; + } + } + + SmallTab buf; + clear_and_resize(buf, x1 - x0); + + con.startProgress(); + con.setActionDesc("exporting heightmap..."); + con.setTotal(y1 - y0); + + for (int y = y1 - 1, cnt = 0; y >= y0; --y) + { + for (int x = x0; x < x1; ++x) + buf[x - x0] = heightmap.getFinalData(x, y); + + if (::df_write(handle, buf.data(), data_size(buf)) != data_size(buf)) + { + con.addMessage(ILogWriter::ERROR, "Error writing file '%s'", filename); + ::df_close(handle); + return false; + } + + con.incDone(); + } + + heightmap.unloadAllUnchangedData(); + + con.endProgress(); + + ::df_close(handle); + + return true; + } +}; + + +class Raw16HeightmapExporter : public HeightmapExporter +{ +public: + virtual bool exportHeightmap(const char *filename, HeightMapStorage &heightmap, real min_height, real height_range, CoolConsole &con, + int x0, int y0, int x1, int y1) + { + file_ptr_t handle = ::df_open(filename, DF_WRITE | DF_CREATE); + + if (!handle) + { + con.addMessage(ILogWriter::ERROR, "Can't create file '%s'", filename); + return false; + } + + SmallTab buf; + clear_and_resize(buf, x1 - x0); + + con.startProgress(); + con.setActionDesc("exporting heightmap..."); + con.setTotal((y1 - y0) * 2); + + float minH = min_height; + float maxH = min_height + height_range; + + heightmap.unloadAllUnchangedData(); + + float scale = maxH - minH; + if (float_nonzero(scale)) + scale = ((1 << 16) - 1) / scale; + + for (int y = y1 - 1, cnt = 0; y >= y0; --y) + { + for (int x = x0; x < x1; ++x) + { + int h = real2int((heightmap.getFinalData(x, y) - minH) * scale + 0.5); + + if (h < 0) + h = 0; + else if (h >= (1 << 16)) + h = (1 << 16) - 1; + + buf[x - x0] = h; + } + + if (::df_write(handle, buf.data(), data_size(buf)) != data_size(buf)) + { + con.addMessage(ILogWriter::ERROR, "Error writing file '%s'", filename); + ::df_close(handle); + return false; + } + + con.incDone(); + } + + heightmap.unloadAllUnchangedData(); + + con.endProgress(); + + ::df_close(handle); + + return true; + } +}; + + +class TgaHeightmapExporter : public HeightmapExporter +{ +public: + virtual bool exportHeightmap(const char *filename, HeightMapStorage &heightmap, real min_height, real height_range, CoolConsole &con, + int x0, int y0, int x1, int y1) + { + file_ptr_t handle = ::df_open(filename, DF_WRITE | DF_CREATE); + + if (!handle) + { + con.addMessage(ILogWriter::ERROR, "Can't create file '%s'", filename); + return false; + } + + int mapSizeX = x1 - x0; + int mapSizeY = y1 - y0; + + SmallTab buf; + clear_and_resize(buf, mapSizeX); + + con.startProgress(); + con.setActionDesc("exporting heightmap..."); + con.setTotal(mapSizeY * 2); + + ::df_write(handle, "\0\0\2\0\0\0\0\0\0\0\0\0", 12); + ::df_write(handle, &mapSizeX, 2); + ::df_write(handle, &mapSizeY, 2); + ::df_write(handle, "\x20\x08", 2); + + float minH = min_height; + float maxH = min_height + height_range; + + heightmap.unloadAllUnchangedData(); + + float scale = maxH - minH; + if (float_nonzero(scale)) + scale = ((1 << 8) - 1) / scale; + + for (int y = y0, cnt = 0; y < y1; ++y) + { + for (int x = x0; x < x1; ++x) + { + int h = real2int((heightmap.getFinalData(x, y) - minH) * scale); + + if (h < 0) + h = 0; + else if (h >= (1 << 8)) + h = (1 << 8) - 1; + + buf[x - x0] = E3DCOLOR(h, h, h); + } + + if (::df_write(handle, buf.data(), data_size(buf)) != data_size(buf)) + { + con.addMessage(ILogWriter::ERROR, "Error writing file '%s'", filename); + ::df_close(handle); + return false; + } + + heightmap.unloadUnchangedData(y + 1); + + con.incDone(); + } + + heightmap.unloadAllUnchangedData(); + + con.endProgress(); + + ::df_close(handle); + + return true; + } +}; + + +class TiffHeightmapExporter : public HeightmapExporter +{ +public: + virtual bool exportHeightmap(const char *filename, HeightMapStorage &heightmap, real min_height, real height_range, CoolConsole &con, + int x0, int y0, int x1, int y1) + { + int mapSizeX = x1 - x0; + int mapSizeY = y1 - y0; + IBitMaskImageMgr::BitmapMask img; + static const int MAX_VAL = 0xFFFF; + HmapLandPlugin::bitMaskImgMgr->createBitMask(img, mapSizeX, mapSizeX, 16); + + con.startProgress(); + con.setActionDesc("exporting heightmap..."); + con.setTotal(mapSizeY * 2); + + float minH = min_height; + float maxH = min_height + height_range; + + heightmap.unloadAllUnchangedData(); + + float scale = maxH - minH; + if (float_nonzero(scale)) + scale = MAX_VAL / scale; + + for (int y = y0, cnt = 0; y < y1; ++y) + { + for (int x = x0; x < x1; ++x) + { + int h = clamp(int((heightmap.getFinalData(x, y) - minH) * scale), 0, int(MAX_VAL)); + img.setMaskPixel16(x - x0, y1 - 1 - y, h); + } + heightmap.unloadUnchangedData(y + 1); + con.incDone(); + } + + heightmap.unloadAllUnchangedData(); + + bool ret = HmapLandPlugin::bitMaskImgMgr->saveImage(img, NULL, filename); + HmapLandPlugin::bitMaskImgMgr->destroyImage(img); + + con.endProgress(); + + if (!ret) + con.addMessage(ILogWriter::ERROR, "Can't write file '%s'", filename); + + return ret; + } +}; + + +bool HmapLandPlugin::exportHeightmap(String &filename, real min_height, real height_range, bool exp_det_hmap) +{ + const char *ext = dd_get_fname_ext(filename); + if (!ext) + return false; + + CoolConsole &con = DAGORED2->getConsole(); + con.startLog(); + + HeightmapExporter *exporter = NULL; + + if (stricmp(ext, ".r32") == 0) + exporter = new Raw32fHeightmapExporter(false); + else if (stricmp(ext, ".height") == 0) + exporter = new Raw32fHeightmapExporter(true); + else if (stricmp(ext, ".r16") == 0 || stricmp(ext, ".raw") == 0) + exporter = new Raw16HeightmapExporter; + else if (stricmp(ext, ".tif") == 0 || stricmp(ext, ".tiff") == 0) + exporter = new TiffHeightmapExporter; + else + exporter = new TgaHeightmapExporter; + + applyHmModifiers(false); + + if (!exporter->exportHeightmap(filename, exp_det_hmap ? heightMapDet : heightMap, min_height, height_range, con, + exp_det_hmap ? detRectC[0].x : 0, exp_det_hmap ? detRectC[0].y : 0, exp_det_hmap ? detRectC[1].x : heightMap.getMapSizeX(), + exp_det_hmap ? detRectC[1].y : heightMap.getMapSizeY())) + { + con.endLog(); + delete exporter; + return false; + } + + con.addMessage(ILogWriter::NOTE, "Exported heightmap to '%s'", (const char *)filename); + + con.endLog(); + + delete exporter; + return true; +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlExportSizeDlg.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlExportSizeDlg.cpp new file mode 100644 index 000000000..7bfb3103d --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlExportSizeDlg.cpp @@ -0,0 +1,62 @@ +#include "hmlExportSizeDlg.h" + +#include + +enum +{ + ID_MIN_HEIGHT = 1, + ID_HEIGHT_RANGE, + ID_GET_FROM_HEIGHTMAP +}; + + +//================================================================================================== +HmapExportSizeDlg::HmapExportSizeDlg(float &min_height, float &height_range, float min_height_hm, float height_range_hm) : + minHeight(min_height), heightRange(height_range), minHeightHm(min_height_hm), heightRangeHm(height_range_hm), mDialog(NULL) +{ + mDialog = DAGORED2->createDialog(hdpi::_pxScaled(240), hdpi::_pxScaled(170), "HeightMap dimensions"); + + PropPanel2 &panel = *mDialog->getPanel(); + panel.setEventHandler(this); + + panel.createEditFloat(ID_MIN_HEIGHT, "Minimal height:", minHeight); + panel.createEditFloat(ID_HEIGHT_RANGE, "Height range:", heightRange); + panel.createButton(ID_GET_FROM_HEIGHTMAP, "Get dimensions from HeightMap"); +} + + +HmapExportSizeDlg::~HmapExportSizeDlg() { del_it(mDialog); } + + +//================================================================================================== + +void HmapExportSizeDlg::onClick(int pcb_id, PropPanel2 *panel) +{ + if (pcb_id == ID_GET_FROM_HEIGHTMAP) + { + minHeight = minHeightHm; + heightRange = heightRangeHm; + + panel->setFloat(ID_MIN_HEIGHT, minHeight); + panel->setFloat(ID_HEIGHT_RANGE, heightRange); + } +} + + +//================================================================================================== + +bool HmapExportSizeDlg::execute() +{ + int ret = mDialog->showDialog(); + + if (ret == DIALOG_ID_OK) + { + PropPanel2 &panel = *mDialog->getPanel(); + minHeight = panel.getFloat(ID_MIN_HEIGHT); + heightRange = panel.getFloat(ID_HEIGHT_RANGE); + + return true; + } + + return false; +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlExportSizeDlg.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlExportSizeDlg.h new file mode 100644 index 000000000..e6a6f098e --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlExportSizeDlg.h @@ -0,0 +1,28 @@ +#ifndef __GAIJIN_HMAP_EXPORT_SIZE_DLG__ +#define __GAIJIN_HMAP_EXPORT_SIZE_DLG__ +#pragma once + +#include + +class HmapExportSizeDlg : public ControlEventHandler +{ +public: + HmapExportSizeDlg(float &min_height, float &height_range, float min_height_hm, float height_range_hm); + + ~HmapExportSizeDlg(); + + virtual bool execute(); + virtual void onClick(int pcb_id, PropPanel2 *panel); + +private: + float &minHeight; + float &heightRange; + + float minHeightHm; + float heightRangeHm; + + CDialogWindow *mDialog; +}; + + +#endif //__GAIJIN_HMAP_EXPORT_SIZE_DLG__ diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlExportSplines.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlExportSplines.cpp new file mode 100644 index 000000000..82bcdac74 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlExportSplines.cpp @@ -0,0 +1,789 @@ +#include "hmlPlugin.h" + +#include +#include + +#include +#include +#include "hmlSplineObject.h" +#include "hmlSplinePoint.h" +#include +#include + +// Grid spline point. +struct SplineGridPoint +{ + uint16_t splineId; + uint16_t pointId; + + SplineGridPoint(uint16_t spl, uint16_t pnt) : splineId(spl), pointId(pnt) {} +}; + +struct SplinesGrid +{ + uint16_t width; + uint16_t height; + Point2 offset; + Point2 cellSize; + Tab **grid; + +public: + SplinesGrid() : width(0), height(0), grid(NULL) {} + + ~SplinesGrid() + { + for (int i = 0; i != width * height; ++i) + delete grid[i]; + + delete[] grid; + } + + void write(mkbindump::BinDumpSaveCB &cwr) + { + bool packed = dagor_target_code_store_packed(cwr.getTarget()); + cwr.beginTaggedBlock(packed ? (HmapLandPlugin::preferZstdPacking ? _MAKE4C('spgz') : _MAKE4C('spgZ')) : _MAKE4C('splg')); + if (packed) + { + mkbindump::BinDumpSaveCB cwr_t(2 << 10, cwr.getTarget(), cwr.WRITE_BE); + writeData(cwr_t); + + MemoryLoadCB mcrd(cwr_t.getMem(), false); + if (HmapLandPlugin::preferZstdPacking) + zstd_compress_data(cwr.getRawWriter(), mcrd, cwr_t.getSize()); + else + lzma_compress_data(cwr.getRawWriter(), 9, mcrd, cwr_t.getSize()); + } + else + writeData(cwr); + cwr.align8(); + cwr.endBlock(); + } + void writeData(mkbindump::BinDumpSaveCB &cwr) + { + int recVal = 0; + Point4 offsetMul(offset.x, offset.y, 1.f / cellSize.x, 1.f / cellSize.y); + + cwr.writeInt32e(width); + cwr.writeInt32e(height); + cwr.write32ex(&offsetMul, sizeof(Point4)); + + for (uint16_t i = 0; i < width; ++i) + { + for (uint16_t j = 0; j < height; ++j) + { + cwr.writeInt32e(recVal); + recVal += grid[j * width + i]->size(); + } + } + + cwr.writeInt32e(recVal); + for (uint16_t i = 0; i != width; ++i) + for (uint16_t j = 0; j != height; ++j) + for (uint16_t num = 0; num != grid[j * width + i]->size(); ++num) + cwr.write16ex(&grid[j * width + i]->operator[](num), sizeof(SplineGridPoint)); + } + + void init(int w, int h, const Point2 &offs, const Point2 &cellSz) + { + width = w; + height = h; + offset = offs; + cellSize = cellSz; + + grid = new Tab *[width * height]; + for (int i = 0; i != width * height; ++i) + grid[i] = new Tab(tmpmem); + } + + void addPoint(const Point3 &pos, uint16_t splineId, uint16_t pointId) + { + Point2 nrmPt = (Point2::xz(pos) - offset); + int x = clamp(int(nrmPt.x / cellSize.x), 0, int(width - 1)); + int y = clamp(int(nrmPt.y / cellSize.y), 0, int(height - 1)); + grid[y * width + x]->push_back(SplineGridPoint(splineId, pointId)); + } +}; + +// Spline point for path (represents accurate position). +struct IntersectionSplinePoint +{ + uint16_t splineId; + float pos; + + IntersectionSplinePoint(uint16_t splId, float p) : splineId(splId), pos(p) {} +}; + +struct IntersectionEdge +{ + uint16_t interId; + uint8_t pointId; + float distance; + uint8_t fromPointId; +}; + +struct PathFinderInfo +{ + IntersectionEdge prevEdge; + bool navigated; + float distToDst; + + void reset() + { + prevEdge.distance = FLT_MAX; + prevEdge.interId = 0xffff; + prevEdge.pointId = 0xff; + navigated = false; + } +}; + +// Spline intersection point. Tab of accurate spline positions, and connections. +struct SplineIntersection +{ + Tab points; + Point2 position; + Tab edges; + PathFinderInfo pfInfo; + + SplineIntersection() : points(tmpmem), edges(tmpmem) {} + + void addEdge(uint16_t interId, uint8_t pointId, float dist, uint8_t from) + { + IntersectionEdge &edge = edges.push_back(); + edge.interId = interId; + edge.pointId = pointId; + edge.distance = dist; + edge.fromPointId = from; + } + + void resetPathFinder(const Point2 &dest) + { + pfInfo.reset(); + pfInfo.distToDst = (dest - position).length(); + } +}; + +// Represents exact point in intersection. +struct IntersectionNodePoint +{ + uint16_t nodeId; + uint8_t nodePointId; + + IntersectionNodePoint() : nodeId(0xffff), nodePointId(0xff) {} + IntersectionNodePoint(uint16_t nId, uint8_t nPt) : nodeId(nId), nodePointId(nPt) {} + + bool isValid() const { return nodeId != 0xffff && nodePointId != 0xff; } + + bool operator==(const IntersectionNodePoint &rhs) const { return rhs.nodeId == nodeId && rhs.nodePointId == nodePointId; } + + bool operator!=(const IntersectionNodePoint &rhs) const { return !(*this == rhs); } +}; + +// Point in intersection to which we should proceed and distance to this point. +struct IntersectionTableRecord +{ + IntersectionNodePoint nextPoint; + float dist; +}; + +// Exact position and spline parametric position of this point. +struct SplineSegmentPoint +{ + Point3 in; + Point3 pos; + Point3 out; + float splinePos; + + SplineSegmentPoint(SplinePointObject *p, float splPos) : + in(p->getBezierIn()), pos(p->getPt()), out(p->getBezierOut()), splinePos(splPos) + {} +}; + +// All spline segments, used to find intersections. +struct SplineSegments +{ + Tab points; + bool haveIntersections; + + SplineSegments() : points(tmpmem), haveIntersections(false) {} +}; + +// IntersectionNodePoint and intersection which is represented by it. +struct SplineIntersectionNode +{ + IntersectionNodePoint point; + SplineIntersection *inter = nullptr; + SplineIntersectionNode() = default; + + SplineIntersectionNode(const IntersectionNodePoint &pt, SplineIntersection *intr) : point(pt), inter(intr) {} +}; + +struct SplineData +{ + String name; + SplineSegments segments; + Tab pathNodePoints; + BBox2 box; + + SplineData() : pathNodePoints(tmpmem) {} +}; + +float sqr(float a) { return a * a; } + +class SplineExporter +{ + Tab splineData; + SplinesGrid grid; + float distBetween; + Tab intersections; + + void fillSplineData(const Tab &splines); + void findIntersections(); + void addNodePoint(const IntersectionNodePoint &pt); + void makeConnections(); + + bool findWay(uint16_t from, uint16_t to); + + void savePaths(mkbindump::BinDumpSaveCB &cwr); + +public: + SplineExporter() : splineData(tmpmem), distBetween(20.f), intersections(tmpmem) {} + + void exportSplines(mkbindump::BinDumpSaveCB &cwr, const Tab &splines, const HeightMapStorage &heightMap, + float gridCellSize, const Point2 &heightMapOffset); +}; + + +void SplineExporter::fillSplineData(const Tab &splines) +{ + if (splines.empty()) + { + clear_and_shrink(splineData); + return; + } + else + { + splineData.resize(splines.size()); + Point2 offset = Point2(1.f, 1.f) * distBetween; + for (int i = 0; i < splines.size(); ++i) + { + SplineData &splData = splineData[i]; + SplineObject *o = splines[i]; + BBox3 box = o->getSplineBox(); + splData.name = o->getName(); + splData.box = BBox2(Point2::xz(box.lim[0]) - offset, Point2::xz(box.lim[1]) + offset); + const BezierSpline3d &bezSpl = o->getBezierSpline(); + float len = 0.f; + int pointId = 0; + for (int j = 0; j < o->points.size(); ++j) + { + SplinePointObject *p = o->points[j]; + if (p) + { + splData.segments.points.push_back(SplineSegmentPoint(p, len)); + grid.addPoint(p->getPt(), uint16_t(i), uint16_t(pointId)); + pointId++; + } + if (j != o->points.size() - 1) + len += bezSpl.segs[j].len; + } + } + } +} + +void SplineExporter::findIntersections() +{ + CoolConsole &con = DAGORED2->getConsole(); + con.startLog(); + + con.addMessage(ILogWriter::REMARK, "[SPL] Generating intersections."); + + int startIntersections = dagTools->getTimeMsec(); + for (uint16_t i = 0; i < splineData.size(); ++i) + { + SplineData &splSrc = splineData[i]; + for (uint16_t j = i; j < splineData.size(); ++j) // start at i because we want self intersections as well + { + SplineData &splDst = splineData[j]; + if (!(splSrc.box & splDst.box)) + continue; // No intersections... NEXT + for (int k = 0; k < (int)splSrc.segments.points.size() - 1; ++k) + { + const SplineSegmentPoint &pnt0 = splSrc.segments.points[k]; + const SplineSegmentPoint &pnt1 = splSrc.segments.points[k + 1]; + Point3 p0 = pnt0.pos; + Point3 p1 = pnt1.pos; + + for (int l = 0; l < (int)splDst.segments.points.size() - 1; ++l) + { + const SplineSegmentPoint &pnt2 = splDst.segments.points[l]; + const SplineSegmentPoint &pnt3 = splDst.segments.points[l + 1]; + Point3 p2 = pnt2.pos; + Point3 p3 = pnt3.pos; + + if (i == j && (pnt2.splinePos - pnt1.splinePos) < 2.f * distBetween) + continue; // Skip all points on same spline, when they are too close to each other. + + float mua, mub; + lineLineIntersect(p0, p1, p2, p3, mua, mub); + mua = clamp(mua, 0.f, 1.f); + mub = clamp(mub, 0.f, 1.f); + Point3 p10 = p1 - p0; + Point3 p32 = p3 - p2; + Point3 pOnFirst = p0 + p10 * mua; + Point3 pOnSecond = p2 + p32 * mub; + + float firstPos = pnt0.splinePos + (pnt1.splinePos - pnt0.splinePos) * mua; + float secondPos = pnt2.splinePos + (pnt3.splinePos - pnt2.splinePos) * mub; + + Point2 ptMid = Point2::xz(pOnFirst + pOnSecond) * 0.5f; + + if (lengthSq(pOnFirst - pOnSecond) >= sqr(distBetween)) + continue; + bool haveIntersections = false; + for (int m = 0; m < intersections.size(); ++m) + { + Point2 pt = intersections[m].position; + if (lengthSq(pt - ptMid) >= sqr(distBetween)) + continue; + bool foundFirst = false; + bool foundSecond = false; + for (int n = 0; n < intersections[m].points.size(); ++n) + { + const IntersectionSplinePoint &splinePoint = intersections[m].points[n]; + if (splinePoint.splineId == i && rabs(splinePoint.pos - firstPos) < distBetween) + foundFirst = true; + if (splinePoint.splineId == j && rabs(splinePoint.pos - secondPos) < distBetween) + foundSecond = true; + if (foundFirst && foundSecond) + break; + } + if (!foundFirst) + intersections[m].points.push_back(IntersectionSplinePoint(i, firstPos)); + if (!foundSecond) + intersections[m].points.push_back(IntersectionSplinePoint(j, secondPos)); + haveIntersections = true; + } + if (!haveIntersections) + { + SplineIntersection &intersection = intersections.push_back(); + intersection.points.push_back(IntersectionSplinePoint(i, firstPos)); + intersection.points.push_back(IntersectionSplinePoint(j, secondPos)); + intersection.position = ptMid; + } + splSrc.segments.haveIntersections = splDst.segments.haveIntersections = true; + } // second spline segments + } // first spline segments + } // for second splines + } // for first splines + + // First and last points on each spline which have intersections. + for (int i = 0; i < splineData.size(); ++i) + { + const SplineData &splData = splineData[i]; + const SplineSegments &splSeg = splData.segments; + if (!splSeg.haveIntersections || splSeg.points.empty()) + continue; + bool firstPoint = false; + bool lastPoint = false; + float lastPos = splSeg.points.back().splinePos; + for (int j = 0; j < intersections.size(); ++j) + { + SplineIntersection &intersection = intersections[j]; + for (int k = 0; k < intersection.points.size(); ++k) + { + if (intersection.points[k].splineId != i) + continue; + if (intersection.points[k].pos < distBetween) + { + firstPoint = true; + intersection.points[k].pos = 0.f; + } + if (intersection.points[k].pos > lastPos - distBetween) + { + lastPoint = true; + intersection.points[k].pos = lastPos; + } + if (firstPoint && lastPoint) + break; + } + if (firstPoint && lastPoint) + break; + } + + if (!firstPoint) + { + SplineIntersection &intersection = intersections.push_back(); + intersection.points.push_back(IntersectionSplinePoint(i, 0.f)); + intersection.position = Point2::xz(splSeg.points[0].pos); + } + if (!lastPoint) + { + SplineIntersection &intersection = intersections.push_back(); + intersection.points.push_back(IntersectionSplinePoint(i, lastPos)); + intersection.position = Point2::xz(splSeg.points.back().pos); + } + } + + // For each spline fill list of intersections on it. + for (int i = 0; i < intersections.size(); ++i) + { + const SplineIntersection &inter = intersections[i]; + for (int j = 0; j < inter.points.size(); ++j) + addNodePoint(IntersectionNodePoint(i, j)); + } + + con.addMessage(ILogWriter::REMARK, "[SPL] Found %d intersections in %g seconds.", intersections.size(), + (dagTools->getTimeMsec() - startIntersections) / 1000.f); + con.endLog(); +} + +void SplineExporter::addNodePoint(const IntersectionNodePoint &pt) +{ + SplineIntersection &inter = intersections[pt.nodeId]; + const IntersectionSplinePoint &pathSplPt = inter.points[pt.nodePointId]; + int splineId = inter.points[pt.nodePointId].splineId; + SplineData &splData = splineData[splineId]; + + int i; + for (i = 0; i < splData.pathNodePoints.size(); ++i) + { + const IntersectionNodePoint &point = splData.pathNodePoints[i].point; + if (point == pt) + { + G_ASSERT(false); + return; + } + const IntersectionSplinePoint &curPathSplPt = intersections[point.nodeId].points[point.nodePointId]; + if (pathSplPt.pos < curPathSplPt.pos) + break; + } + SplineIntersectionNode initWith = SplineIntersectionNode(pt, &inter); + insert_items(splData.pathNodePoints, i, 1, &initWith); +} + +void SplineExporter::makeConnections() +{ + CoolConsole &con = DAGORED2->getConsole(); + con.startLog(); + + con.addMessage(ILogWriter::REMARK, "[SPL] Generating connections."); + int startConnections = dagTools->getTimeMsec(); + + for (int i = 0; i < splineData.size(); ++i) + { + SplineData &splData = splineData[i]; + for (int j = 0; j < (int)splData.pathNodePoints.size() - 1; ++j) + { + const SplineIntersectionNode &splPathNodeSrc = splData.pathNodePoints[j]; + const IntersectionNodePoint &srcPt = splPathNodeSrc.point; + SplineIntersection *interSrc = splPathNodeSrc.inter; + const IntersectionSplinePoint &splPtSrc = interSrc->points[srcPt.nodePointId]; + for (int k = j + 1; k < splData.pathNodePoints.size(); ++k) + { + const SplineIntersectionNode &splPathNodeDst = splData.pathNodePoints[k]; + const IntersectionNodePoint &dstPt = splPathNodeDst.point; + SplineIntersection *interDst = splPathNodeDst.inter; + const IntersectionSplinePoint &splPtDst = interDst->points[dstPt.nodePointId]; + G_ASSERT(splPtSrc.splineId == splPtDst.splineId); + float dist = rabs(splPtSrc.pos - splPtDst.pos); + + interSrc->addEdge(dstPt.nodeId, dstPt.nodePointId, dist, srcPt.nodePointId); + interDst->addEdge(srcPt.nodeId, srcPt.nodePointId, dist, dstPt.nodePointId); + } + } + } + + con.addMessage(ILogWriter::REMARK, "[SPL] Generated connections in %g seconds.", + (dagTools->getTimeMsec() - startConnections) / 1000.f); + con.endLog(); +} + +bool SplineExporter::findWay(uint16_t from, uint16_t to) +{ + // Init. + for (int i = 0; i < intersections.size(); ++i) + intersections[i].resetPathFinder(intersections[to].position); + SplineIntersection &frm = intersections[from]; + + frm.pfInfo.navigated = true; + frm.pfInfo.prevEdge.distance = 0.f; + frm.pfInfo.prevEdge.interId = from; + frm.pfInfo.prevEdge.pointId = 0; + + Tab openNodes(tmpmem); + openNodes.push_back(from); + while (!openNodes.empty()) + { + int shortest = -1; + float minDist = FLT_MAX; + for (int i = 0; i < openNodes.size(); ++i) + { + uint16_t nodeId = openNodes[i]; + G_ASSERT(nodeId < intersections.size()); + SplineIntersection &node = intersections[nodeId]; + float dist = node.pfInfo.distToDst + node.pfInfo.prevEdge.distance; + if (dist < minDist) + { + shortest = i; + minDist = dist; + } + } + uint16_t nodeId = openNodes[shortest]; + if (nodeId == to) + return true; + erase_items(openNodes, shortest, 1); + SplineIntersection &node = intersections[nodeId]; + node.pfInfo.navigated = true; + for (int i = 0; i < node.edges.size(); ++i) + { + const IntersectionEdge &edge = node.edges[i]; + G_ASSERT(edge.interId < intersections.size()); + SplineIntersection &nextNode = intersections[edge.interId]; + if (nextNode.pfInfo.navigated) + continue; + IntersectionEdge &pfEdge = nextNode.pfInfo.prevEdge; + float distance = node.pfInfo.prevEdge.distance + edge.distance; + bool proceedToNode = false; + if (find_value_idx(openNodes, edge.interId) < 0) + { + openNodes.push_back(edge.interId); + proceedToNode = true; + } + else + proceedToNode = distance < pfEdge.distance; + + if (proceedToNode) + { + pfEdge.interId = nodeId; + pfEdge.pointId = edge.fromPointId; + pfEdge.distance = distance; + pfEdge.fromPointId = edge.pointId; + } + } + } + return false; +} + +void SplineExporter::savePaths(mkbindump::BinDumpSaveCB &cwr) +{ + CoolConsole &con = DAGORED2->getConsole(); + con.startLog(); + + int startTable = dagTools->getTimeMsec(); + + int size = intersections.size(); + + cwr.beginTaggedBlock(_MAKE4C('stbl')); + + cwr.writeInt32e(size); + for (int i = 0; i < size; ++i) + { + const SplineIntersection &inter = intersections[i]; + cwr.writeInt32e(inter.points.size()); + for (int j = 0; j < inter.points.size(); ++j) + { + cwr.writeReal(inter.points[j].pos); + cwr.writeInt16e(inter.points[j].splineId); + cwr.writeInt16e(0); + } + } + + SmallTab table; + if (size < 360) // Less than 1 mb + { + con.addMessage(ILogWriter::REMARK, "[SPL] Calculating path table."); + clear_and_resize(table, size * size); + for (int i = 0; i < size; ++i) + for (int j = 0; j < size; ++j) + table[i + j * size] = IntersectionTableRecord(); + + for (int i = 0; i < size; ++i) + for (int j = 0; j < size; ++j) + G_ASSERT(!table[i + j * size].nextPoint.isValid()); + + for (int i = 0; i < size; ++i) + { + const SplineIntersection &firstInter = intersections[i]; + for (int j = 0; j < size; ++j) + { + if (i == j) + { + table[i + j * size].dist = FLT_MAX; + continue; + } + const SplineIntersection &secondInter = intersections[j]; + if (!findWay(i, j)) + { + table[i + j * size].dist = FLT_MAX; + continue; + } + float totalDist = secondInter.pfInfo.prevEdge.distance; + int nodeId = j; + int step = 0; + while (nodeId != i) + { + const SplineIntersection &inter = intersections[nodeId]; + const IntersectionEdge &edge = inter.pfInfo.prevEdge; + const IntersectionEdge &prevEdge = intersections[edge.interId].pfInfo.prevEdge; + IntersectionTableRecord &rec = table[edge.interId + j * size]; + bool overwrite = true; + if (rec.nextPoint.isValid()) + { + if (rec.nextPoint.nodeId != nodeId) + { + const PathFinderInfo &pfInfo = intersections[rec.nextPoint.nodeId].pfInfo; + if (pfInfo.navigated && rec.dist < totalDist - intersections[pfInfo.prevEdge.interId].pfInfo.prevEdge.distance) + { + nodeId = rec.nextPoint.nodeId; + step++; + continue; + } + } + } + if (overwrite) + { + rec.dist = totalDist - prevEdge.distance; + rec.nextPoint.nodeId = nodeId; + rec.nextPoint.nodePointId = edge.fromPointId; + } + nodeId = edge.interId; + step++; + } + } + } + cwr.beginTaggedBlock(_MAKE4C('tabl')); + cwr.writeInt32e(table.size()); + for (int i = 0; i < table.size(); ++i) + { + const IntersectionTableRecord &rec = table[i]; + cwr.writeInt32e(rec.dist); + cwr.writeInt16e(rec.nextPoint.nodeId); + cwr.writeInt8e(rec.nextPoint.nodePointId); + cwr.writeInt8e(0); + } + con.addMessage(ILogWriter::REMARK, "[SPL] Filled table in %g seconds.", (dagTools->getTimeMsec() - startTable) / 1000.f); + } + else + { + cwr.beginTaggedBlock(_MAKE4C('ncon')); + for (int i = 0; i < size; ++i) + { + const SplineIntersection &inter = intersections[i]; + int edgesCount = inter.edges.size(); + cwr.write32ex(&inter.position, sizeof(Point2)); + cwr.writeInt32e(edgesCount); + for (int j = 0; j < edgesCount; ++j) + { + const IntersectionEdge &edge = inter.edges[j]; + cwr.writeReal(edge.distance); + cwr.writeInt16e(edge.interId); + cwr.writeInt8e(edge.pointId); + cwr.writeInt8e(0); + cwr.writeInt8e(edge.fromPointId); + cwr.writeInt8e(0); + cwr.writeInt8e(0); + cwr.writeInt8e(0); + } + } + } + cwr.align8(); + cwr.endBlock(); + + + for (int i = 0; i < splineData.size(); ++i) + { + const SplineData &splData = splineData[i]; + cwr.writeInt32e(splData.pathNodePoints.size()); + for (int j = 0; j < splData.pathNodePoints.size(); ++j) + { + const IntersectionNodePoint &pathNodePt = splData.pathNodePoints[j].point; + cwr.writeInt16e(pathNodePt.nodeId); + cwr.writeInt8e(pathNodePt.nodePointId); + cwr.writeInt8e(0); + } + } + + cwr.align8(); + cwr.endBlock(); + + con.endLog(); +} + +void SplineExporter::exportSplines(mkbindump::BinDumpSaveCB &cwr, const Tab &splines, + const HeightMapStorage &heightMap, float gridCellSize, const Point2 &heightMapOffset) +{ + if (splines.empty()) + return; + + CoolConsole &con = DAGORED2->getConsole(); + con.startLog(); + + const uint16_t width = clamp(heightMap.getMapSizeX() * gridCellSize / 128.f, 0.f, 512.f); + const uint16_t height = clamp(heightMap.getMapSizeY() * gridCellSize / 128.f, 0.f, 512.f); + Point2 cellSize(heightMap.getMapSizeX() * gridCellSize / float(width), heightMap.getMapSizeY() * gridCellSize / float(height)); + con.addMessage(ILogWriter::REMARK, "[SPL] width = %d, height = %d, cellSize = (%f, %f)", width, height, cellSize.x, cellSize.y); + + grid.init(width, height, heightMapOffset, cellSize); + fillSplineData(splines); + + // Splines themselves. + cwr.beginTaggedBlock(_MAKE4C('hspl')); + cwr.writeInt32e(splineData.size()); + + int splineId = 0; + for (int i = 0; i < splineData.size(); ++i) + { + const SplineData &splData = splineData[i]; + cwr.writeDwString(splData.name.str()); + + int numPoints = splData.segments.points.size(); + cwr.writeInt32e(numPoints); + for (int j = 0; j < numPoints; ++j) + { + const SplineSegmentPoint &pt = splData.segments.points[j]; + cwr.write32ex(&pt.in, sizeof(Point3)); + cwr.write32ex(&pt.pos, sizeof(Point3)); + cwr.write32ex(&pt.out, sizeof(Point3)); + } + } + cwr.align8(); + cwr.endBlock(); + + // Splines grid. + grid.write(cwr); + + // Pathfinding info + { + con.addMessage(ILogWriter::REMARK, "[SPL] Generating pathfinding info."); + int startPathFinding = dagTools->getTimeMsec(); + + findIntersections(); + makeConnections(); + savePaths(cwr); + + con.addMessage(ILogWriter::REMARK, "[SPL] Generated pathfinding info in %g seconds.", + (dagTools->getTimeMsec() - startPathFinding) / 1000.f); + } + + con.endLog(); +} + + +void HmapLandPlugin::exportSplines(mkbindump::BinDumpSaveCB &cwr) +{ + Tab splines(tmpmem); + for (int i = 0; i < objEd.objectCount(); i++) + { + SplineObject *o = RTTI_cast(objEd.getObject(i)); + if (o && o->getProps().exportable && !o->points.empty()) + splines.push_back(o); + } + + CoolConsole &con = DAGORED2->getConsole(); + con.startLog(); + con.addMessage(ILogWriter::REMARK, "[SPL] spline objects %d", splines.size()); + con.endLog(); + + SplineExporter exporter; + exporter.exportSplines(cwr, splines, heightMap, gridCellSize, heightMapOffset); +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlGenColorMap.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlGenColorMap.cpp new file mode 100644 index 000000000..966076464 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlGenColorMap.cpp @@ -0,0 +1,3929 @@ +#include "hmlPlugin.h" +#include "landClassSlotsMgr.h" + +#include +#include +#include +#include +#include +#include <3d/dag_drv3d.h> + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#undef ERROR + +using hdpi::_pxScaled; + +// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ// +const int PID_STATIC_OFFSET = 10000; + + +static char defScript[] = "\r\n" + "let function degToRad(a)\r\n" + "{\r\n" + " return a*PI/180;\r\n" + "}\r\n" + "\r\n" + "\r\n" + "::getParamsList <- function getParamsList()\r\n" + "{\r\n" + " local list=\r\n" + " [\r\n" + " {name= \"fullGrassAngle\", type=\"real\", value=20},\r\n" + " {name=\"startGrassAngle\", type=\"real\", value=40},\r\n" + "\r\n" + " {name=\"sandCurvature\", type=\"real\", value=50},\r\n" + "\r\n" + " {name=\"dirtColor\" , type=\"color\", value=makeColor(120, 90, 40, 0)},\r\n" + " {name=\"sandColor\" , type=\"color\", value=makeColor(160, 150, 120, 0)},\r\n" + " {name=\"grassColor\", type=\"color\", value=makeColor(120, 120, 30, 1)},\r\n" + " ];\r\n" + " return list;\r\n" + "}\r\n" + "\r\n" + "\r\n" + "::getGenerator <- function getGenerator()\r\n" + "{\r\n" + " local fullGrassCos=cos(degToRad( fullGrassAngle));\r\n" + " local startGrassCos=cos(degToRad(startGrassAngle));\r\n" + "\r\n" + " local sandCurv=sandCurvature/100.0;\r\n" + "\r\n" + " return function(lcMap)\r\n" + " : (\r\n" + " getNormalY,\r\n" + " getHeight,\r\n" + " getCurvature,\r\n" + " sampleImage,\r\n" + " sampleImageAt,\r\n" + " sampleMask,\r\n" + " sampleMaskAlpha,\r\n" + " sampleMaskRed,\r\n" + " sampleMaskGreen,\r\n" + " sampleMaskBlue,\r\n" + " sampleMaskAt,\r\n" + " sampleMaskAlphaAt,\r\n" + " sampleMaskRedAt,\r\n" + " sampleMaskGreenAt,\r\n" + " sampleMaskBlueAt,\r\n" + " setMask,\r\n" + " mulColors,\r\n" + " mulColors2x,\r\n" + " blendColors,\r\n" + " dissolveOver,\r\n" + " calcBlendK,\r\n" + " smoothStep,\r\n" + "\r\n" + " fullGrassCos,\r\n" + " startGrassCos,\r\n" + " sandCurv,\r\n" + "\r\n" + " dirtColor,\r\n" + " sandColor,\r\n" + " grassColor\r\n" + " )\r\n" + " {\r\n" + " local normalY=getNormalY();\r\n" + " local height=getHeight();\r\n" + " local curvature=getCurvature();\r\n" + "\r\n" + " // base 'dirt' / 'stone'\r\n" + " local res=dirtColor;\r\n" + "\r\n" + " // add 'sand' by curvature\r\n" + " res=blendColors(res, sandColor, calcBlendK(0.0, sandCurv, curvature));\r\n" + "\r\n" + " // add 'grass' by angle\r\n" + " res=blendColors(res, grassColor,\r\n" + " smoothStep(calcBlendK(startGrassCos, fullGrassCos, normalY)));\r\n" + "\r\n" + " lcMap[0] = getType(res);\r\n" + " return res;\r\n" + " }\r\n" + "}\r\n"; + + +// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ// + + +class ScriptParamInt : public HmapLandPlugin::ScriptParam +{ +public: + int value; + int paramPid; + + ScriptParamInt(const char *name, int val) : ScriptParam(name), value(val), paramPid(-1) {} + + virtual void fillParams(PropPanel2 &panel, int &pid) + { + paramPid = pid++; + panel.createEditInt(paramPid, paramName, value); + } + + virtual void onPPChange(int pid, PropPanel2 &panel) + { + if (pid != paramPid) + return; + value = panel.getInt(pid); + } + + virtual void save(DataBlock &blk) { blk.setInt(paramName, value); } + + virtual void load(const DataBlock &blk) { value = blk.getInt(paramName, value); } + + virtual void setToScript(HSQUIRRELVM vm) + { + sq_pushroottable(vm); + sq_pushstring(vm, paramName, -1); + sq_pushinteger(vm, value); + sq_newslot(vm, -3, false); + sq_pop(vm, 1); + } +}; + + +class ScriptParamReal : public HmapLandPlugin::ScriptParam +{ +public: + real value; + int paramPid; + + ScriptParamReal(const char *name, real val) : ScriptParam(name), value(val), paramPid(-1) {} + + virtual void fillParams(PropPanel2 &panel, int &pid) + { + paramPid = pid++; + panel.createEditFloat(paramPid, paramName, value); + } + + virtual void onPPChange(int pid, PropPanel2 &panel) + { + if (pid != paramPid) + return; + value = panel.getFloat(pid); + } + + virtual void save(DataBlock &blk) { blk.setReal(paramName, value); } + + virtual void load(const DataBlock &blk) { value = blk.getReal(paramName, value); } + + virtual void setToScript(HSQUIRRELVM vm) + { + sq_pushroottable(vm); + sq_pushstring(vm, paramName, -1); + sq_pushfloat(vm, value); + sq_newslot(vm, -3, false); + sq_pop(vm, 1); + } +}; + + +class ScriptParamColor : public HmapLandPlugin::ScriptParam +{ +public: + E3DCOLOR value; + int paramPid; + + ScriptParamColor(const char *name, E3DCOLOR val) : ScriptParam(name), value(val), paramPid(-1) {} + + virtual void fillParams(PropPanel2 &panel, int &pid) + { + paramPid = pid++; + panel.createColorBox(paramPid, paramName, value); + } + + virtual void onPPChange(int pid, PropPanel2 &panel) + { + if (pid != paramPid) + return; + value = panel.getColor(pid); + } + + virtual void save(DataBlock &blk) { blk.setE3dcolor(paramName, value); } + + virtual void load(const DataBlock &blk) { value = blk.getE3dcolor(paramName, value); } + + virtual void setToScript(HSQUIRRELVM vm) + { + sq_pushroottable(vm); + sq_pushstring(vm, paramName, -1); + sq_pushinteger(vm, value); + sq_newslot(vm, -3, false); + sq_pop(vm, 1); + } +}; + + +// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ// + + +class ScriptParamMask : public HmapLandPlugin::ScriptParam +{ +public: + int imageIndex, bitsPerPixel; + + int buttonPid, editButtonPid; + bool detailed; + int divisor; + + + ScriptParamMask(const char *name, int bpp, bool det, int div = 1) : + ScriptParam(name), buttonPid(-1), imageIndex(-1), bitsPerPixel(bpp), detailed(det), divisor(div) + { + imageIndex = HmapLandPlugin::self->getScriptImage(paramName, divisor, bpp); // preload image + } + + virtual void *get_interface(int id) { return id == 'Mask' ? this : NULL; } + + virtual void fillParams(PropPanel2 &panel, int &pid) + { + bool isEditImage = HmapLandPlugin::self->getEditedScriptImage() == this; + buttonPid = pid++; + editButtonPid = pid++; + panel.createIndent(); + panel.createSeparator(0); + panel.createStatic(pid + PID_STATIC_OFFSET, String(64, "%s, %d bpp", (char *)paramName, bitsPerPixel)); + panel.setBool(pid + PID_STATIC_OFFSET, true); + panel.createButton(buttonPid, "Import from...", false); + panel.createButton(editButtonPid, isEditImage ? "Done" : "Edit", true, false); + } + + virtual void onPPChange(int pid, PropPanel2 &panel) {} + + virtual void onPPBtnPressed(int pid, PropPanel2 &panel) + { + if (pid == buttonPid) + { + //== import mask here + } + else if (pid == editButtonPid) + { + ScriptParamMask *curEd = (ScriptParamMask *)HmapLandPlugin::self->getEditedScriptImage(); + if (curEd) + curEd->finishEdit(panel); + + HmapLandPlugin::self->editScriptImage(this); + bool isEditImage = HmapLandPlugin::self->getEditedScriptImage() == this; + panel.setCaption(pid, isEditImage ? "Done" : "Edit"); + HmapLandPlugin::self->setShowBlueWhiteMask(); + + if (!isEditImage) + HmapLandPlugin::self->setSelectMode(); + } + } + + virtual void save(DataBlock &main_blk) {} + + virtual void load(const DataBlock &main_blk) {} + + virtual void setToScript(HSQUIRRELVM vm) + { + sq_pushroottable(vm); + sq_pushstring(vm, paramName, -1); + sq_pushuserpointer(vm, this); + sq_newslot(vm, -3, false); + sq_pop(vm, 1); + } + + virtual void finishEdit(PropPanel2 &panel) { panel.setCaption(editButtonPid, "Edit"); } + + float sampleMask1(); + float sampleMask8(); + float sampleMask1Pixel(); + float sampleMask8Pixel(); + void setMask1(bool c); + void setMask8(char c); + + static inline ScriptParamMask *cast(ScriptParam *es) + { + if (es && es->get_interface('Mask')) + return static_cast(es); + return NULL; + } +}; + + +class ScriptParamImage : public ScriptParamMask +{ +public: + SimpleString imageName; + int mappingType; + Point2 tile, offset; + bool clampU, clampV, flipU, flipV, swapUV, showMask; + int detailType; + IHmapBrushImage::Channel channel; + + int mappingTypePid, tilePid, offsetPid, clampUPid, clampVPid, showMaskPid, flipUPid, flipVPid, swapUVPid, detailTypePid, + channelsComboPid; + + + enum + { + MAPPING_HMAP, + MAPPING_HMAP_PERCENT, + MAPPING_WORLD, + MAPPING_VERT_U, + MAPPING_VERT_V, + }; + + struct DefParams + { + SimpleString imageName; + int mappingType, detailType; + Point2 tile, offset; + bool clampU, clampV, flipU, flipV, swapUV; + + DefParams() : + mappingType(MAPPING_HMAP), + tile(100, 100), + offset(0, 0), + clampU(false), + clampV(false), + flipU(false), + flipV(false), + swapUV(false), + detailType(0) + {} + }; + + + ScriptParamImage(const char *name, const DefParams &def) : + ScriptParamMask(name, 32, false, 1), + imageName(def.imageName), + mappingType(def.mappingType), + tile(def.tile), + offset(def.offset), + clampU(def.clampU), + clampV(def.clampV), + flipU(def.flipU), + flipV(def.flipV), + swapUV(def.swapUV), + detailType(def.detailType), + channel(IHmapBrushImage::CHANNEL_RGB) + {} + + virtual void *get_interface(int id) { return (id == 'Mask' || id == 'Img') ? this : NULL; } + + virtual void fillParams(PropPanel2 &panel, int &pid) + { + + PropertyContainerControlBase *op = panel.createGroup(pid++, paramName); + + bool isEditImage = HmapLandPlugin::self->getEditedScriptImage() == this; + buttonPid = pid++; + editButtonPid = pid++; + op->createButton(buttonPid, imageName); + op->createButton(editButtonPid, isEditImage ? "Done" : "Edit", true, false); + + Tab channels(tmpmem); + channels.resize(IHmapBrushImage::CHANNELS_COUNT); + channels[IHmapBrushImage::CHANNEL_RGB] = "RGB"; + channels[IHmapBrushImage::CHANNEL_R] = "Red"; + channels[IHmapBrushImage::CHANNEL_G] = "Green"; + channels[IHmapBrushImage::CHANNEL_B] = "Blue"; + channels[IHmapBrushImage::CHANNEL_A] = "Alpha"; + + channelsComboPid = pid++; + op->createCombo(channelsComboPid, "Edit channel:", channels, channel, !isEditImage); + + showMaskPid = pid++; + op->createCheckBox(showMaskPid, "Show blue-white mask", showMask); + + detailTypePid = pid++; + op->createEditInt(detailTypePid, "Detail type", detailType); + + mappingTypePid = pid++; + PropertyContainerControlBase *rg = op->createRadioGroup(mappingTypePid, "Mapping type", mappingType); + rg->createRadio(pid++, "match heightmap"); + rg->createRadio(pid++, "heightmap percent"); + rg->createRadio(pid++, "world units"); + rg->createRadio(pid++, "vertical U"); + rg->createRadio(pid++, "vertical V"); + op->setInt(mappingTypePid, mappingTypePid + 1 + mappingType); + + tilePid = pid++; + offsetPid = pid++; + op->createPoint2(tilePid, "Tile", tile); + op->createPoint2(offsetPid, "Offset", offset); + + op->createCheckBox(clampUPid = pid++, "Clamp U", clampU); + op->createCheckBox(clampVPid = pid++, "Clamp V", clampV); + + op->createCheckBox(swapUVPid = pid++, "Swap UV", swapUV); + + op->createCheckBox(flipUPid = pid++, "Flip U", flipU); + op->createCheckBox(flipVPid = pid++, "Flip V", flipV); + + op->setBoolValue(true); + } + + virtual void onPPChange(int pid, PropPanel2 &panel) + { + if (pid == detailTypePid) + detailType = panel.getInt(detailTypePid); + else if (pid == mappingTypePid) + mappingType = panel.getInt(mappingTypePid) - mappingTypePid - 1; + else if (pid == tilePid) + tile = panel.getPoint2(tilePid); + else if (pid == offsetPid) + offset = panel.getPoint2(offsetPid); + else if (pid == clampUPid) + clampU = panel.getBool(pid); + else if (pid == clampVPid) + clampV = panel.getBool(pid); + else if (pid == flipUPid) + flipU = panel.getBool(pid); + else if (pid == flipVPid) + flipV = panel.getBool(pid); + else if (pid == swapUVPid) + swapUV = panel.getBool(pid); + else if (pid == channelsComboPid) + channel = (IHmapBrushImage::Channel)panel.getInt(pid); + else if (pid == showMaskPid) + showMask = panel.getBool(pid); + } + + virtual void onPPBtnPressed(int pid, PropPanel2 &panel) + { + if (pid == buttonPid) + { + const char *name = HmapLandPlugin::self->pickScriptImage(imageName, 32); + if (name) + { + imageName = name; + panel.setCaption(pid, (char *)imageName); + } + } + else if (pid == editButtonPid) + { + ScriptParamMask *curEd = (ScriptParamMask *)HmapLandPlugin::self->getEditedScriptImage(); + if (curEd) + curEd->finishEdit(panel); + + HmapLandPlugin::self->editScriptImage(this); + bool isEditImage = HmapLandPlugin::self->getEditedScriptImage() == this; + panel.setCaption(pid, isEditImage ? "Done" : "Edit"); + panel.setEnabledById(channelsComboPid, !isEditImage); + } + } + + virtual void save(DataBlock &main_blk) + { + DataBlock &blk = *main_blk.addBlock(paramName); + + blk.setStr("name", imageName); + blk.setInt("detailType", detailType); + blk.setInt("mappingType", mappingType); + blk.setPoint2("tile", tile); + blk.setPoint2("offset", offset); + blk.setBool("clampU", clampU); + blk.setBool("clampV", clampV); + blk.setBool("flipU", flipU); + blk.setBool("flipV", flipV); + blk.setBool("swapUV", swapUV); + blk.setInt("channel", channel); + blk.setBool("showMask", showMask); + } + + virtual void load(const DataBlock &main_blk) + { + const DataBlock &blk = *main_blk.getBlockByNameEx(paramName); + const char *name = blk.getStr("name", NULL); + if (name) + imageName = name; + detailType = blk.getInt("detailType", detailType); + mappingType = blk.getInt("mappingType", mappingType); + tile = blk.getPoint2("tile", tile); + offset = blk.getPoint2("offset", offset); + clampU = blk.getBool("clampU", clampU); + clampV = blk.getBool("clampV", clampV); + flipU = blk.getBool("flipU", flipU); + flipV = blk.getBool("flipV", flipV); + swapUV = blk.getBool("swapUV", swapUV); + channel = (IHmapBrushImage::Channel)blk.getInt("channel", channel); + showMask = blk.getBool("showMask", true); + } + + virtual void setToScript(HSQUIRRELVM vm) + { + sq_pushroottable(vm); + sq_pushstring(vm, paramName, -1); + sq_pushuserpointer(vm, this); + sq_newslot(vm, -3, false); + sq_pop(vm, 1); + } + + virtual void finishEdit(PropPanel2 &panel) + { + panel.setCaption(editButtonPid, "Edit"); + panel.setEnabledById(channelsComboPid, true); + } + + void flipAndSwapUV(real &u, real &v) + { + if (swapUV) + { + real a = u; + u = v; + v = a; + } + + if (flipU) + u = 1 - u; + if (flipV) + v = 1 - v; + } + + void calcMapping(real x, real z, Point2 &p); + + E3DCOLOR sampleImage(); + float sampleImage1(); + float sampleImage8(); + void setImage(E3DCOLOR); + + E3DCOLOR sampleImagePixel(); + E3DCOLOR sampleImagePixelTrueAlpha(); + void paintImage(E3DCOLOR color); + + E3DCOLOR ScriptParamImage::sampleImageAt(real u, real v) + { + flipAndSwapUV(u, v); + + E3DCOLOR c = HmapLandPlugin::self->sampleScriptImageUV(imageIndex, u, v, clampU, clampV); + c.a = detailType; + return c; + } + bool saveImage(); +}; + + +class ScriptParamLandClass : public HmapLandPlugin::ScriptParam, public IAssetUpdateNotify +{ +public: + SimpleString asset; + SmallTab perLayerAssetIdx; + PtrTab images; + int detailIdx; + landclass::AssetData *assetData; + + int buttonPid; + + struct DefParams + { + SimpleString asset; + SmallTab layerIdx; + int detailIdx; + + DefParams() : detailIdx(-1) {} + }; + + + ScriptParamLandClass(const char *name, const DefParams &def) : ScriptParam(name), asset(def.asset), buttonPid(-1), images(midmem) + { + perLayerAssetIdx = def.layerIdx; + detailIdx = def.detailIdx; + assetData = NULL; + registerAsset(); + LandClassSlotsManager::subscribeLandClassUpdateNotify(this); + } + ~ScriptParamLandClass() + { + unregisterAsset(); + LandClassSlotsManager::unsubscribeLandClassUpdateNotify(this); + } + + virtual void fillParams(PropPanel2 &panel, int &pid) + { + buttonPid = pid; + panel.createIndent(); + panel.createSeparator(0); + panel.createStatic(pid + PID_STATIC_OFFSET, paramName); + panel.setBool(pid + PID_STATIC_OFFSET, true); + panel.createButton(buttonPid, ::dd_get_fname(asset)); + // panel.createButton(buttonPid+1, "X"); + pid += 2; + } + + virtual void onPPChange(int pid, PropPanel2 &panel) {} + + virtual void onPPBtnPressed(int pid, PropPanel2 &panel) + { + if (pid == buttonPid) + { + const char *lc_asset = DAEDITOR3.selectAssetX(asset, "Select landclass", "land"); + + if (lc_asset) + { + asset = lc_asset; + panel.setCaption(pid, lc_asset); + registerAsset(); + + HmapLandPlugin::self->getLandClassMgr().regenerateObjects(HmapLandPlugin::self->getlandClassMap()); + } + } + else if (pid == buttonPid + 1) + { + // asset=NULL; + // panel.setCaption(pid-1, (char*)asset); + // unregisterAsset(); + } + } + + virtual void save(DataBlock &main_blk) + { + DataBlock &blk = *main_blk.addBlock(paramName); + + blk.setStr("asset", asset); + } + + virtual void load(const DataBlock &main_blk) + { + const DataBlock &blk = *main_blk.getBlockByNameEx(paramName); + const char *name = blk.getStr("asset", NULL); + if (name) + asset = name; + registerAsset(); + } + + virtual void setToScript(HSQUIRRELVM vm) + { + int det_layer_id = HmapLandPlugin::self->getDetLayerIdx(); + sq_pushroottable(vm); + sq_pushstring(vm, paramName, -1); + sq_newarray(vm, perLayerAssetIdx.size()); + for (int i = 0; i < perLayerAssetIdx.size(); i++) + { + sq_pushinteger(vm, i); + sq_pushinteger(vm, (i == det_layer_id) ? detailIdx : perLayerAssetIdx[i]); + sq_rawset(vm, -3); + } + sq_newslot(vm, -3, false); + sq_pop(vm, 1); + + for (int i = 0; i < images.size(); i++) + images[i]->setToScript(vm); + } + + void registerAsset() + { + if (!asset.length()) + return unregisterAsset(); + + for (int i = 0; i < perLayerAssetIdx.size(); i++) + if (perLayerAssetIdx[i] >= 0) + HmapLandPlugin::self->getLandClassMgr().setLandClass(i, perLayerAssetIdx[i], asset); + + regetAsset(); + int det_layer_id = HmapLandPlugin::self->getDetLayerIdx(); + if (det_layer_id >= 0 && detailIdx >= 0 && assetData) + HmapLandPlugin::self->setDetailTexSlot(detailIdx, asset); + images.clear(); + if (assetData && assetData->colorImages) + { + images.resize(assetData->colorImages->images.size()); + for (int i = 0; i < images.size(); i++) + { + landclass::ColorImagesData::Image &img = assetData->colorImages->images[i]; + ScriptParamImage::DefParams def; + def.imageName = img.fname; + def.mappingType = img.mappingType; + def.tile = img.tile; + def.offset = img.offset; + def.clampU = img.clampU; + def.clampV = img.clampV; + def.flipU = img.flipU; + def.flipV = img.flipV; + def.swapUV = img.swapUV; + + images[i] = new ScriptParamImage(String(64, "%s_%s", (char *)paramName, (char *)img.name), def); + HmapLandPlugin::self->getScriptImage(images[i]->imageName, 1, 32); + } + } + } + + void unregisterAsset() + { + LandClassSlotsManager::releaseAsset(assetData); + assetData = NULL; + + for (int i = 0; i < perLayerAssetIdx.size(); i++) + if (perLayerAssetIdx[i] >= 0) + HmapLandPlugin::self->getLandClassMgr().setLandClass(i, perLayerAssetIdx[i], NULL); + + int det_layer_id = HmapLandPlugin::self->getDetLayerIdx(); + if (det_layer_id >= 0 && detailIdx >= 0) + HmapLandPlugin::self->setDetailTexSlot(detailIdx, NULL); + images.clear(); + } + + void regetAsset() + { + landclass::AssetData *a = assetData; + assetData = LandClassSlotsManager::getAsset(asset); + LandClassSlotsManager::releaseAsset(a); + } + + // IAssetUpdateNotify interface + virtual void onLandClassAssetChanged(landclass::AssetData *data) + { + if (assetData == data) + { + unregisterAsset(); + registerAsset(); + HmapLandPlugin::self->getLandClassMgr().regenerateObjects(HmapLandPlugin::self->getlandClassMap()); + } + } + virtual void onLandClassAssetTexturesChanged(landclass::AssetData *data) override {} + virtual void onSplineClassAssetChanged(splineclass::AssetData *data) {} +}; + + +class ScriptParamDetailTex : public HmapLandPlugin::ScriptParam +{ +public: + enum + { + IPID_LANDCLASS, + IPID__NUM + }; + struct DefParams + { + int detailSlot; + // Point2 offset; + SimpleString blkName; + + DefParams() : detailSlot(-1), blkName("") {} //, tile(1.0), offset(0.f, 0.f) + }; + DefParams p; + int basePid; + + ScriptParamDetailTex(const char *name, const DefParams &def) : ScriptParam(name), p(def), basePid(-1) { registerDetTex(); } + ~ScriptParamDetailTex() { unregisterDetTex(); } + + static bool prepareName(String &out, const char *in) + { + if (!in || !in[0]) + { + out = NULL; + return false; + } + + out = DagorAsset::fpath2asset(in); + DagorAsset *a = DAEDITOR3.getAssetByName(out, DAEDITOR3.getAssetTypeId("land")); + + if (a) + return ::dd_file_exist(a->getTargetFilePath()); + + DAEDITOR3.conError("cant find det land asset: %s", out); + return ::dd_file_exist(in); + } + + virtual void fillParams(PropPanel2 &panel, int &pid) + { + String btn_name; + PropertyContainerControlBase *op = panel.createGroup(pid++, String(64, "%s: slot %d", (char *)paramName, p.detailSlot)); + + basePid = pid; + pid += IPID__NUM; + + // detail tex + if (!prepareName(btn_name, p.blkName)) + btn_name = "---"; + op->createButton(basePid + IPID_LANDCLASS, btn_name); + op->setBoolValue(true); + } + + virtual void onPPChange(int pid, PropPanel2 &panel) {} + + virtual void onPPBtnPressed(int pid, PropPanel2 &panel) + { + if (pid >= basePid + IPID_LANDCLASS && pid < basePid + IPID__NUM) + { + const char *asset; + + switch (pid - basePid) + { + case IPID_LANDCLASS: asset = p.blkName; break; + default: G_ASSERT(0 && "unknown tex!"); + } + asset = DAEDITOR3.selectAssetX(asset, "Select landclass", "land"); + + if (!asset) + return; + + String btn_name; + switch (pid - basePid) + { + case IPID_LANDCLASS: + p.blkName = asset; + if (!prepareName(btn_name, asset)) + btn_name = "---"; + panel.setCaption(pid, btn_name.str()); + break; + } + registerDetTex(); + } + } + + virtual void save(DataBlock &main_blk) + { + DataBlock &blk = *main_blk.addBlock(paramName); + blk.setStr("asset", p.blkName); + } + + virtual void load(const DataBlock &main_blk) + { + const DataBlock &blk = *main_blk.getBlockByNameEx(paramName); + const char *asset = blk.getStr("asset", NULL); + + if (asset) + p.blkName = asset; + registerDetTex(); + } + + virtual void setToScript(HSQUIRRELVM vm) + { + sq_pushroottable(vm); + sq_pushstring(vm, paramName, -1); + sq_pushinteger(vm, p.detailSlot); + sq_newslot(vm, -3, false); + sq_pop(vm, 1); + } + + void registerDetTex() + { + int det_layer_id = HmapLandPlugin::self->getDetLayerIdx(); + if (det_layer_id >= 0 && p.detailSlot >= 0) + HmapLandPlugin::self->setDetailTexSlot(p.detailSlot, p.blkName); + } + void unregisterDetTex() + { + int det_layer_id = HmapLandPlugin::self->getDetLayerIdx(); + if (det_layer_id >= 0 && p.detailSlot >= 0) + HmapLandPlugin::self->setDetailTexSlot(p.detailSlot, NULL); + } +}; + + +class PostScriptParamLandLayer : public HmapLandPlugin::ScriptParam, public IAssetUpdateNotify +{ +public: + enum + { + PID_LAYER_CAPTION, + PID_LAYER_ENABLED, + PID_EDIT_PROPS, + PID_SEL_LC1, + PID_SEL_LC2, + PID_SEL_MASK, + PID_EDIT_MASK, + PID_SEL_GRASS_MASK, + PID_ELC_EDIT_MASK_BASE, + PID_ELC_EDIT_MASK_LAST = PID_ELC_EDIT_MASK_BASE + 10, + PID__COUNT + }; + struct WtRange + { + enum + { + WMT_one, + WMT_asIs, + WMT_smoothStep, + WMT_zero + }; + float v0, dv; + int conv; + }; + + int slotIdx, pidBase, landIdx; + int detIdx; + bool enabled; + bool sumWeights; + bool badDetTex; + + enum + { + AREA_main, + AREA_det, + AREA_both + }; + int areaSelect; + + // landclass 1 + struct LandClassRec + { + SimpleString asset; + landclass::AssetData *assetData; + } lc1, lc2; + + // mask + SimpleString maskName; + int imageIndex, imageBpp; + int maskConv; + bool detRectMappedMask; + + WtRange ht, ang, curv; + bool writeDetTex, writeLand1, writeLand2, writeImportance; + float writeDetTexThres, writeLand1Thres, writeLand2Thres; + bool editableLandClass; + + struct PropsDlg : public ControlEventHandler + { + enum + { + PID_LAYER_CAPTION, + PID_LAYER_WEIGHTCALC, + PID_LAYER_OUTPUT, + PID_LAYER_SUMWT, + PID_WTR_AREA, + PID_WTR_MASK_CONV, + PID_MASK_REFSYS, + PID_SEL_MASK, + PID_WTR_HT_V0, + PID_WTR_HT_DV, + PID_WTR_HT_CONV, + PID_WTR_ANG_V0, + PID_WTR_ANG_DV, + PID_WTR_ANG_CONV, + PID_WTR_CURV_V0, + PID_WTR_CURV_DV, + PID_WTR_CURV_CONV, + PID_WRITE_LC1, + PID_WRITE_LC1_THRES, + PID_WRITE_LC2, + PID_WRITE_LC2_THRES, + PID_WRITE_DET, + PID_WRITE_DET_THRES, + PID_WRITE_IM, + PID_LAYER_ELC_ADD, + PID_BASE, + }; + enum + { + PID_ELC_GRP, + PID_ELC_PRESET, + PID_ELC_SEL_MASK, + PID_ELC_OUT_COLORMAP, + PID_ELC_OUT_SPLATTINGMAP, + PID_ELC_PARAM_BASE, + PID_ELC_PARAM_LAST = PID_ELC_PARAM_BASE + 10, + PID_ELC__CNT + }; + + public: + PropsDlg(PostScriptParamLandLayer &_gl) : gl(_gl) + { + dlg = EDITORCORE->createDialog(_pxScaled(290), _pxScaled(460), + String(0, gl.paramName.empty() ? "Layer #%d" : "Layer #%d: %s", gl.slotIdx + 1, gl.paramName)); + ::GetWindowRect((HWND)dlg->getHandle(), &wr); + dlg->setCloseHandler(this); + dlg->showButtonPanel(false); + } + ~PropsDlg() + { + EDITORCORE->deleteDialog(dlg); + dlg = NULL; + } + + bool isVisible() const { return dlg->isVisible(); } + void show() + { + ::SetWindowPos((HWND)dlg->getHandle(), NULL, wr.left, wr.top, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE); + dlg->show(); + PropertyContainerControlBase &panel = *dlg->getPanel(); + panel.setEventHandler(this); + + Tab wtConv(tmpmem); + wtConv.push_back() = "1"; + wtConv.push_back() = "As is"; + wtConv.push_back() = "Smooth step"; + wtConv.push_back() = "0"; + Tab areaConv(tmpmem); + areaConv.push_back() = "Main only"; + areaConv.push_back() = "Detailed only"; + areaConv.push_back() = "Main and detailed"; + + panel.createStatic(-1, "Apply to land region"); + panel.createCombo(PID_WTR_AREA, "", areaConv, gl.areaSelect, true, false); + panel.setEnabledById(PID_WTR_AREA, HmapLandPlugin::self->hasDetaledRect()); + + PropertyContainerControlBase &pCalc = *panel.createGroup(PID_LAYER_WEIGHTCALC, "Weight formula"); + PropertyContainerControlBase &pOut = *panel.createGroup(PID_LAYER_OUTPUT, "Output and thresholds"); + + pCalc.createCheckBox(PID_LAYER_SUMWT, "Sum weights (instead of multiply)", gl.sumWeights); + pCalc.createSeparator(0); + + pCalc.createStatic(-1, "Mask weight conv"); + pCalc.createCombo(PID_WTR_MASK_CONV, "", wtConv, gl.maskConv, true, false); + pCalc.createCheckBox(PID_MASK_REFSYS, "Mapped to detailed area", gl.detRectMappedMask); + pCalc.setEnabledById(PID_MASK_REFSYS, HmapLandPlugin::self->hasDetaledRect() && gl.maskConv); + pCalc.createButton(PID_SEL_MASK, gl.maskName.empty() ? "-- no mask --" : gl.maskName, gl.maskConv); + pCalc.createSeparator(0); + + pCalc.createStatic(-1, "Height weight conv"); + pCalc.createCombo(PID_WTR_HT_CONV, "", wtConv, gl.ht.conv, true, false); + pCalc.createEditFloat(PID_WTR_HT_V0, "base", gl.ht.v0, 2, gl.ht.conv); + pCalc.createEditFloat(PID_WTR_HT_DV, "delta", gl.ht.dv, 2, gl.ht.conv, false); + + pCalc.createStatic(-1, "Angle weight conv"); + pCalc.createCombo(PID_WTR_ANG_CONV, "", wtConv, gl.ang.conv, true, false); + pCalc.createEditFloat(PID_WTR_ANG_V0, "base", gl.ang.v0, 2, gl.ang.conv); + pCalc.createEditFloat(PID_WTR_ANG_DV, "delta", gl.ang.dv, 2, gl.ang.conv, false); + + pCalc.createStatic(-1, "Curv. weight conv"); + pCalc.createCombo(PID_WTR_CURV_CONV, "", wtConv, gl.curv.conv, true, false); + pCalc.createEditFloat(PID_WTR_CURV_V0, "base", gl.curv.v0, 2, gl.ht.conv); + pCalc.createEditFloat(PID_WTR_CURV_DV, "delta", gl.curv.dv, 2, gl.ht.conv, false); + + pOut.createCheckBox(PID_WRITE_DET, "Write weight to DetTex", gl.writeDetTex); + pOut.createEditFloat(PID_WRITE_DET_THRES, "DetTex weight threshold", gl.writeDetTexThres, 2, gl.writeDetTex); + + pOut.createCheckBox(PID_WRITE_IM, "Write weight to importance mask", gl.writeImportance); + + pOut.createCheckBox(PID_WRITE_LC1, "Write weight to Land#1", gl.writeLand1); + pOut.createEditFloat(PID_WRITE_LC1_THRES, "Land#1 weight threshold", gl.writeLand1Thres, 2, gl.writeLand1); + + pOut.createCheckBox(PID_WRITE_LC2, "Write weight to Land#2", gl.writeLand2); + pOut.createEditFloat(PID_WRITE_LC2_THRES, "Land#2 weight threshold", gl.writeLand2Thres, 2, gl.writeLand2); + + if (gl.editableLandClass) + { + dag::Span dlp = HmapLandPlugin::hmlService->getDetLayerClassList(); + Tab clsList(tmpmem); + for (int i = 0; i < dlp.size(); i++) + clsList.push_back() = dlp[i].name; + + pCalc.createSeparator(0); + for (int i = 0; i < gl.elcLayers.blockCount(); i++) + { + const DataBlock &b = *gl.elcLayers.getBlock(i); + int base = PID_BASE + i * PID_ELC__CNT; + int idx = HmapLandPlugin::hmlService->resolveDetLayerClassName(b.getStr("lName", "")); + + PropertyContainerControlBase &pElc = *panel.createExtGroup(base + PID_ELC_GRP, String(0, "Land detail layer #%d", i + 1)); + panel.setInt(base + PID_ELC_GRP, (1 << EXT_BUTTON_INSERT) | (1 << EXT_BUTTON_REMOVE) | (i > 0 ? (1 << EXT_BUTTON_UP) : 0) | + (i + 1 < gl.elcLayers.blockCount() ? (1 << EXT_BUTTON_DOWN) : 0)); + + pElc.createStatic(-1, "Detail class"); + pElc.createCombo(base + PID_ELC_PRESET, "", clsList, b.getStr("lName", ""), true, false); + if (idx >= 0) + { + if (dlp[idx].needsMask) + pElc.createButton(base + PID_ELC_SEL_MASK, *b.getStr("lMask", "") ? b.getStr("lMask") : "-- no mask --"); + pElc.createCheckBox(base + PID_ELC_OUT_COLORMAP, "Output colormap", b.getBool("lOutCmap", true)); + if (dlp[idx].canOutSplatting) + pElc.createCheckBox(base + PID_ELC_OUT_SPLATTINGMAP, "Output splatting mask", b.getBool("lOutSmap", true)); + for (int j = 0; j < dlp[idx].param.size() && PID_ELC_PARAM_BASE + j <= PID_ELC_PARAM_LAST; j++) + switch (dlp[idx].param[j].type) + { + case HmapDetLayerProps::Param::PT_int: + pElc.createEditInt(base + PID_ELC_PARAM_BASE + j, dlp[idx].param[j].name, + b.getInt(dlp[idx].param[j].name, dlp[idx].param[j].defValI[0])); + pElc.setMinMaxStep(base + PID_ELC_PARAM_BASE + j, dlp[idx].param[j].pmin, dlp[idx].param[j].pmax, 1); + break; + case HmapDetLayerProps::Param::PT_bool: + pElc.createCheckBox(base + PID_ELC_PARAM_BASE + j, dlp[idx].param[j].name, + b.getBool(dlp[idx].param[j].name, dlp[idx].param[j].defValI[0])); + break; + case HmapDetLayerProps::Param::PT_float: + pElc.createEditFloat(base + PID_ELC_PARAM_BASE + j, dlp[idx].param[j].name, + b.getReal(dlp[idx].param[j].name, dlp[idx].param[j].defValF[0])); + pElc.setMinMaxStep(base + PID_ELC_PARAM_BASE + j, dlp[idx].param[j].pmin, dlp[idx].param[j].pmax, 0.1); + break; + case HmapDetLayerProps::Param::PT_float2: + pElc.createPoint2(base + PID_ELC_PARAM_BASE + j, dlp[idx].param[j].name, + b.getPoint2(dlp[idx].param[j].name, Point2(dlp[idx].param[j].defValF[0], dlp[idx].param[j].defValF[1]))); + pElc.setMinMaxStep(base + PID_ELC_PARAM_BASE + j, dlp[idx].param[j].pmin, dlp[idx].param[j].pmax, 0.1); + break; + case HmapDetLayerProps::Param::PT_tex: + pElc.createButton(base + PID_ELC_PARAM_BASE + j, + String(0, "%s: %s", dlp[idx].param[j].name, + *b.getStr(dlp[idx].param[j].name, "") ? b.getStr(dlp[idx].param[j].name) : "-- no tex --")); + break; + case HmapDetLayerProps::Param::PT_color: + pElc.createSimpleColor(base + PID_ELC_PARAM_BASE + j, dlp[idx].param[j].name, + b.getE3dcolor(dlp[idx].param[j].name, 0xFFFFFFFF)); + break; + } + } + } + panel.createButton(PID_LAYER_ELC_ADD, "Add layer", dlp.size() > 0); + } + dlg->getPanel()->loadState(panelState); + dlg->setScrollPos(panelState.getInt("pOffset", 0)); + } + void hide() + { + if (dlg->getPanel()->getChildCount()) + { + panelState.reset(); + dlg->getPanel()->saveState(panelState); + panelState.setInt("pOffset", dlg->getScrollPos()); + dlg->getPanel()->clear(); + } + dlg->hide(); + } + void refillPanel() + { + if (dlg->isVisible()) + { + panelState.reset(); + dlg->getPanel()->saveState(panelState); + panelState.setInt("pOffset", dlg->getScrollPos()); + + dlg->getPanel()->clear(); + show(); + } + } + void updateTitle() + { + ::SetWindowText((HWND)dlg->getHandle(), + String(0, gl.paramName.empty() ? "Layer #%d" : "Layer #%d: %s", gl.slotIdx + 1, gl.paramName)); + } + + virtual void onChange(int pid, PropertyContainerControlBase *panel) + { + if (pid == PID_LAYER_SUMWT) + gl.sumWeights = panel->getBool(pid); + else if (pid == PID_MASK_REFSYS) + gl.detRectMappedMask = panel->getBool(pid); + else if (pid == PID_WTR_AREA) + { + gl.areaSelect = panel->getInt(pid); + } + else if (pid == PID_WTR_MASK_CONV) + { + gl.maskConv = panel->getInt(pid); + panel->setEnabledById(PID_MASK_REFSYS, HmapLandPlugin::self->hasDetaledRect() && gl.maskConv); + panel->setEnabledById(PID_SEL_MASK, gl.maskConv); + if (PropPanel2 *pp = HmapLandPlugin::self->getPropPanel()) + { + pp->setEnabledById(gl.pidBase + gl.PID_SEL_MASK, true); + pp->setEnabledById(gl.pidBase + gl.PID_EDIT_MASK, gl.maskConv); + } + } + else if (pid == PID_WTR_HT_CONV) + { + gl.ht.conv = panel->getInt(pid); + panel->setEnabledById(PID_WTR_HT_V0, gl.ht.conv); + panel->setEnabledById(PID_WTR_HT_DV, gl.ht.conv); + } + else if (pid == PID_WTR_HT_V0) + gl.ht.v0 = panel->getFloat(pid); + else if (pid == PID_WTR_HT_DV) + gl.ht.dv = panel->getFloat(pid); + else if (pid == PID_WTR_ANG_CONV) + { + gl.ang.conv = panel->getInt(pid); + panel->setEnabledById(PID_WTR_ANG_V0, gl.ang.conv); + panel->setEnabledById(PID_WTR_ANG_DV, gl.ang.conv); + } + else if (pid == PID_WTR_ANG_V0) + gl.ang.v0 = panel->getFloat(pid); + else if (pid == PID_WTR_ANG_DV) + gl.ang.dv = panel->getFloat(pid); + else if (pid == PID_WTR_CURV_CONV) + { + gl.curv.conv = panel->getInt(pid); + panel->setEnabledById(PID_WTR_CURV_V0, gl.curv.conv); + panel->setEnabledById(PID_WTR_CURV_DV, gl.curv.conv); + } + else if (pid == PID_WTR_CURV_V0) + gl.curv.v0 = panel->getFloat(pid); + else if (pid == PID_WTR_CURV_DV) + gl.curv.dv = panel->getFloat(pid); + else if (pid == PID_WRITE_LC1) + { + gl.writeLand1 = panel->getBool(pid); + panel->setEnabledById(PID_WRITE_LC1_THRES, gl.writeLand1); + } + else if (pid == PID_WRITE_LC1_THRES) + gl.writeLand1Thres = panel->getFloat(pid); + else if (pid == PID_WRITE_LC2) + { + gl.writeLand2 = panel->getBool(pid); + panel->setEnabledById(PID_WRITE_LC2_THRES, gl.writeLand2); + } + else if (pid == PID_WRITE_LC2_THRES) + gl.writeLand2Thres = panel->getFloat(pid); + else if (pid == PID_WRITE_DET) + { + gl.writeDetTex = panel->getBool(pid); + panel->setEnabledById(PID_WRITE_DET_THRES, gl.writeDetTex); + } + else if (pid == PID_WRITE_DET_THRES) + gl.writeDetTexThres = panel->getFloat(pid); + else if (pid == PID_WRITE_IM) + gl.writeImportance = panel->getBool(pid); + else if (pid >= PID_BASE && pid < PID_BASE + PID_ELC__CNT * gl.elcLayers.blockCount()) + { + dag::Span dlp = HmapLandPlugin::hmlService->getDetLayerClassList(); + int lidx = (pid - PID_BASE) / PID_ELC__CNT; + int lpid = (pid - PID_BASE) % PID_ELC__CNT; + DataBlock &b = *gl.elcLayers.getBlock(lidx); + + if (lpid == PID_ELC_PRESET) + { + if (strcmp(b.getStr("lName", ""), dlp[panel->getInt(pid)].name) != 0) + { + b.setStr("lName", dlp[panel->getInt(pid)].name); + panel->setPostEvent(1); + return; + } + } + else if (lpid == PID_ELC_OUT_COLORMAP) + b.setBool("lOutCmap", panel->getBool(pid)); + else if (lpid == PID_ELC_OUT_SPLATTINGMAP) + b.setBool("lOutSmap", panel->getBool(pid)); + else + { + int idx = HmapLandPlugin::hmlService->resolveDetLayerClassName(b.getStr("lName", "")); + if (idx < 0) + return; + int pidx = lpid - PID_ELC_PARAM_BASE; + switch (dlp[idx].param[pidx].type) + { + case HmapDetLayerProps::Param::PT_int: b.setInt(dlp[idx].param[pidx].name, panel->getInt(pid)); break; + case HmapDetLayerProps::Param::PT_bool: b.setBool(dlp[idx].param[pidx].name, panel->getBool(pid)); break; + case HmapDetLayerProps::Param::PT_float: b.setReal(dlp[idx].param[pidx].name, panel->getFloat(pid)); break; + case HmapDetLayerProps::Param::PT_float2: b.setPoint2(dlp[idx].param[pidx].name, panel->getPoint2(pid)); break; + case HmapDetLayerProps::Param::PT_color: b.setE3dcolor(dlp[idx].param[pidx].name, panel->getColor(pid)); break; + } + } + if (gl.drdHandle) + { + HmapLandPlugin::hmlService->updateDetailRenderData(gl.drdHandle, gl.elcLayers); + HmapLandPlugin::hmlService->invalidateClipmap(false); + } + } + } + virtual void onClick(int pid, PropertyContainerControlBase *panel) + { + if (pid == -DIALOG_ID_CLOSE) + { + ::GetWindowRect((HWND)dlg->getHandle(), &wr); + if (PropPanel2 *pp = HmapLandPlugin::self->getPropPanel()) + gl.onPPBtnPressed(pid, *pp); + if (dlg->getPanel()->getChildCount()) + { + panelState.reset(); + dlg->getPanel()->saveState(panelState); + panelState.setInt("pOffset", dlg->getScrollPos()); + dlg->getPanel()->clear(); + } + } + else if (pid == PID_SEL_MASK) + { + if (HmapLandPlugin::self->getEditedScriptImage() == &gl) + { + gl.finishEdit(*panel); + HmapLandPlugin::self->editScriptImage(&gl); + HmapLandPlugin::self->setShowBlueWhiteMask(); + } + const char *name = HmapLandPlugin::self->pickScriptImage(gl.maskName, 8); + if (name) + { + gl.maskName = name; + if (*name && gl.maskConv == WtRange::WMT_one) + gl.maskConv = WtRange::WMT_asIs; + else if (!*name && gl.maskConv != WtRange::WMT_one) + gl.maskConv = WtRange::WMT_one; + + panel->setInt(PID_WTR_MASK_CONV, gl.maskConv); + panel->setEnabledById(PID_MASK_REFSYS, HmapLandPlugin::self->hasDetaledRect() && gl.maskConv); + panel->setEnabledById(PID_SEL_MASK, gl.maskConv); + panel->setCaption(pid, *name ? name : "-- no mask --"); + if (PropPanel2 *pp = HmapLandPlugin::self->getPropPanel()) + { + pp->setCaption(gl.pidBase + gl.PID_SEL_MASK, *name ? name : "-- no mask --"); + pp->setEnabledById(gl.pidBase + gl.PID_SEL_MASK, true); + pp->setEnabledById(gl.pidBase + gl.PID_EDIT_MASK, gl.maskConv); + } + gl.imageIndex = HmapLandPlugin::self->getScriptImage(gl.maskName, 1, -1); + gl.imageBpp = HmapLandPlugin::self->getScriptImageBpp(gl.imageIndex); + } + } + else if (pid == PID_LAYER_ELC_ADD) + { + DataBlock &b = *gl.elcLayers.addNewBlock("elc_layer"); + HmapDetLayerProps &lp = HmapLandPlugin::hmlService->getDetLayerClassList()[0]; + b.setStr("lName", lp.name); + for (int i = 0; i < lp.param.size(); i++) + switch (lp.param[i].type) + { + case HmapDetLayerProps::Param::PT_int: b.setInt(lp.param[i].name, lp.param[i].defValI[0]); break; + case HmapDetLayerProps::Param::PT_float: b.setReal(lp.param[i].name, lp.param[i].defValF[0]); break; + case HmapDetLayerProps::Param::PT_bool: b.setBool(lp.param[i].name, lp.param[i].defValI[0]); break; + case HmapDetLayerProps::Param::PT_float2: + b.setPoint2(lp.param[i].name, Point2(lp.param[i].defValF[0], lp.param[i].defValF[1])); + break; + case HmapDetLayerProps::Param::PT_tex: b.setStr(lp.param[i].name, ""); break; + case HmapDetLayerProps::Param::PT_color: b.setE3dcolor(lp.param[i].name, e3dcolor(Color4(lp.param[i].defValF))); break; + } + if (lp.needsMask) + b.setStr("lMask", ""); + panel->setPostEvent(1); + gl.reinitDrdHandle(); + gl.updateElcMasks(); + } + else if (((pid - PID_BASE) % PID_ELC__CNT) == PID_ELC_GRP) + { + dag::Span dlp = HmapLandPlugin::hmlService->getDetLayerClassList(); + DataBlock bc; + int lidx = (pid - PID_BASE) / PID_ELC__CNT; + + switch (panel->getInt(pid)) + { + case EXT_BUTTON_REMOVE: + if (wingw::message_box(wingw::MBS_YESNO | wingw::MBS_QUEST, "Confirmation", + "Do you really want to delete land detail layer #%d (%s)?", lidx + 1, + gl.elcLayers.getBlock(lidx)->getStr("lName")) != wingw::MB_ID_YES) + return; + gl.elcLayers.removeBlock(lidx); + break; + + case EXT_BUTTON_INSERT: + for (int i = 0; i < gl.elcLayers.blockCount(); i++) + { + if (i == lidx) + { + DataBlock &b = *bc.addNewBlock("elc_layer"); + int i; + b.setStr("lName", dlp[0].name); + for (int i = 0; i < dlp[0].param.size(); i++) + switch (dlp[0].param[i].type) + { + case HmapDetLayerProps::Param::PT_int: b.setInt(dlp[0].param[i].name, dlp[0].param[i].defValI[0]); break; + case HmapDetLayerProps::Param::PT_bool: b.setBool(dlp[0].param[i].name, dlp[0].param[i].defValI[0]); break; + case HmapDetLayerProps::Param::PT_float2: + b.setPoint2(dlp[0].param[i].name, Point2(dlp[0].param[i].defValF[0], dlp[0].param[i].defValF[1])); + break; + case HmapDetLayerProps::Param::PT_float: b.setReal(dlp[0].param[i].name, dlp[0].param[i].defValF[0]); break; + case HmapDetLayerProps::Param::PT_tex: b.setStr(dlp[0].param[i].name, ""); break; + case HmapDetLayerProps::Param::PT_color: + b.setE3dcolor(dlp[0].param[i].name, e3dcolor(Color4(dlp[0].param[i].defValF))); + break; + } + if (dlp[0].needsMask) + b.setStr("lMask", ""); + } + bc.addNewBlock(gl.elcLayers.getBlock(i)); + } + gl.elcLayers = bc; + break; + + case EXT_BUTTON_UP: + for (int i = 0; i < gl.elcLayers.blockCount(); i++) + { + if (i == lidx - 1) + bc.addNewBlock(gl.elcLayers.getBlock(i + 1)); + else if (i == lidx) + bc.addNewBlock(gl.elcLayers.getBlock(i - 1)); + else + bc.addNewBlock(gl.elcLayers.getBlock(i)); + } + gl.elcLayers = bc; + break; + + case EXT_BUTTON_DOWN: + for (int i = 0; i < gl.elcLayers.blockCount(); i++) + { + if (i == lidx) + bc.addNewBlock(gl.elcLayers.getBlock(i + 1)); + else if (i == lidx + 1) + bc.addNewBlock(gl.elcLayers.getBlock(i - 1)); + else + bc.addNewBlock(gl.elcLayers.getBlock(i)); + } + gl.elcLayers = bc; + break; + } + panel->setPostEvent(1); + gl.reinitDrdHandle(); + gl.updateElcMasks(); + } + else if (pid >= PID_BASE && pid < PID_BASE + PID_ELC__CNT * gl.elcLayers.blockCount()) + { + dag::Span dlp = HmapLandPlugin::hmlService->getDetLayerClassList(); + int lidx = (pid - PID_BASE) / PID_ELC__CNT; + int lpid = (pid - PID_BASE) % PID_ELC__CNT; + DataBlock &b = *gl.elcLayers.getBlock(lidx); + int idx = HmapLandPlugin::hmlService->resolveDetLayerClassName(b.getStr("lName", "")); + + if (lpid == PID_ELC_SEL_MASK) + { + if (HmapLandPlugin::self->getEditedScriptImage()) + { + HmapLandPlugin::self->editScriptImage(NULL); + HmapLandPlugin::self->setShowBlueWhiteMask(); + HmapLandPlugin::self->refillPanel(); + panel->setPostEvent(1); + } + const char *name = HmapLandPlugin::self->pickScriptImage(b.getStr("lMask"), 8); + if (name) + { + b.setStr("lMask", name); + panel->setCaption(pid, *name ? name : "-- no mask --"); + gl.updateElcMasks(); + if (gl.drdHandle) + { + HmapLandPlugin::hmlService->updateDetailRenderData(gl.drdHandle, gl.elcLayers); + HmapLandPlugin::hmlService->invalidateClipmap(false); + } + } + } + else if (idx >= 0 && lpid >= PID_ELC_PARAM_BASE) + { + int pidx = lpid - PID_ELC_PARAM_BASE; + if (dlp[idx].param[pidx].type == HmapDetLayerProps::Param::PT_tex) + if (const char *tex = DAEDITOR3.selectAssetX(b.getStr(dlp[idx].param[pidx].name, ""), "Select texture", "tex")) + { + b.setStr(dlp[idx].param[pidx].name, tex); + panel->setCaption(pid, String(0, "%s: %s", dlp[idx].param[pidx].name, tex)); + HmapLandPlugin::hmlService->updateDetailRenderData(gl.drdHandle, gl.elcLayers); + HmapLandPlugin::hmlService->invalidateClipmap(false); + } + } + } + } + virtual void onDoubleClick(int pid, PropertyContainerControlBase *panel) {} + virtual void onPostEvent(int pid, PropPanel2 *panel) + { + if (pid == 1) + refillPanel(); + } + + PostScriptParamLandLayer ≷ + CDialogWindow *dlg; + RECT wr; + DataBlock panelState; + }; + PropsDlg *dlg; + DataBlock elcLayers; + NameMap elcMaskList; + int elcMaskCurIdx, elcMaskImageIndex, elcMaskImageBpp; + + void *drdHandle; + + + PostScriptParamLandLayer(int slot_idx, int land_idx, const char *nm) : + ScriptParam(nm), slotIdx(slot_idx), pidBase(-1), imageIndex(-1), imageBpp(-1), enabled(true), landIdx(land_idx), maskConv(0) + { + memset(&lc1, 0, sizeof(lc1)); + memset(&lc2, 0, sizeof(lc2)); + memset(&ht, 0, sizeof(ht)); + memset(&ang, 0, sizeof(ang)); + memset(&curv, 0, sizeof(curv)); + sumWeights = false; + badDetTex = false; + detIdx = slotIdx; + detRectMappedMask = false; + editableLandClass = false; + drdHandle = NULL; + elcMaskCurIdx = elcMaskImageIndex = elcMaskImageBpp = -1; + areaSelect = 0; + writeDetTex = writeLand1 = writeLand2 = writeImportance = false; + writeDetTexThres = writeLand1Thres = writeLand2Thres = 1e-3; + LandClassSlotsManager::subscribeLandClassUpdateNotify(this); + dlg = new PropsDlg(*this); + } + ~PostScriptParamLandLayer() + { + HmapLandPlugin::hmlService->destroyDetailRenderData(drdHandle); + unregisterAsset(lc1); + unregisterAsset(lc2); + LandClassSlotsManager::unsubscribeLandClassUpdateNotify(this); + del_it(dlg); + } + virtual void *get_interface(int id) { return id == 'Layr' ? this : NULL; } + + virtual void fillParams(PropPanel2 &_panel, int &pid) + { + pidBase = pid; + PropertyContainerControlBase &panel = *_panel.createExtGroup(pidBase + PID_LAYER_CAPTION, + String(0, paramName.empty() ? "Layer #%d" : "Layer #%d: %s", slotIdx + 1, paramName)); + _panel.setInt(pidBase + PID_LAYER_CAPTION, + (1 << EXT_BUTTON_INSERT) | (1 << EXT_BUTTON_REMOVE) | (1 << EXT_BUTTON_RENAME) | (1 << EXT_BUTTON_UP) | (1 << EXT_BUTTON_DOWN)); + + panel.createCheckBox(pidBase + PID_LAYER_ENABLED, "Layer enabled", enabled); + panel.createButton(pidBase + PID_EDIT_PROPS, "Props...", true, false); + panel.createButton(pidBase + PID_SEL_LC1, lc1.asset.empty() ? "-- no land#1 --" : ::dd_get_fname(lc1.asset)); + panel.createButton(pidBase + PID_SEL_LC2, lc2.asset.empty() ? "-- no land#2 --" : ::dd_get_fname(lc2.asset)); + + // mask + bool isEditImage = HmapLandPlugin::self->getEditedScriptImage() == this && elcMaskCurIdx < 0; + panel.createSeparator(0); + panel.createButton(pidBase + PID_SEL_MASK, maskName.empty() ? "-- no mask --" : maskName); + panel.createButton(pidBase + PID_EDIT_MASK, isEditImage ? "Done" : "Edit", !maskName.empty(), false); + // panel.setEnabledById(pidBase+PID_SEL_MASK, maskConv); + panel.setEnabledById(pidBase + PID_EDIT_MASK, maskConv); + + // grass mask + /*int landclassId = HmapLandPlugin::self->getLandclassIndex(lc1.asset); + String grassMaskName("-- grass mask --"); + if (landclassId != -1) + grassMaskName = HmapLandPlugin::self->landClassInfo[landclassId].grassMaskName; + panel.createButton(pidBase + PID_SEL_GRASS_MASK, grassMaskName.str());*/ + + // editable land class masks + elcMaskList.reset(); + if (editableLandClass) + { + dag::Span dlp = HmapLandPlugin::hmlService->getDetLayerClassList(); + for (int i = 0; i < elcLayers.blockCount(); i++) + { + const DataBlock &b = *elcLayers.getBlock(i); + int idx = HmapLandPlugin::hmlService->resolveDetLayerClassName(b.getStr("lName", "")); + + if (idx >= 0 && dlp[idx].needsMask && *b.getStr("lMask", "")) + elcMaskList.addNameId(b.getStr("lMask")); + } + + if (elcMaskList.nameCount()) + { + panel.createSeparator(0); + for (int i = 0; i < elcMaskList.nameCount() && PID_ELC_EDIT_MASK_BASE + i <= PID_ELC_EDIT_MASK_LAST; i++) + { + bool edit = HmapLandPlugin::self->getEditedScriptImage() == this && elcMaskCurIdx == i; + panel.createButton(pidBase + PID_ELC_EDIT_MASK_BASE + i, + String(0, edit ? "%s - Done!" : "elcMask: %s", elcMaskList.getName(i))); + } + } + } + + pid += PID__COUNT; + prepareDrdHandle(); + } + void updateElcMasks() + { + NameMap list; + bool missing = false; + if (editableLandClass) + { + dag::Span dlp = HmapLandPlugin::hmlService->getDetLayerClassList(); + for (int i = 0; i < elcLayers.blockCount(); i++) + { + const DataBlock &b = *elcLayers.getBlock(i); + int idx = HmapLandPlugin::hmlService->resolveDetLayerClassName(b.getStr("lName", "")); + + if (idx >= 0 && dlp[idx].needsMask && *b.getStr("lMask", "")) + { + if (elcMaskList.getNameId(b.getStr("lMask")) == -1) + { + missing = true; + break; + } + else + list.addNameId(b.getStr("lMask")); + } + } + } + if (missing || list.nameCount() != elcMaskList.nameCount()) + { + HmapLandPlugin::hmlService->destroyDetailRenderData(drdHandle); + drdHandle = NULL; + HmapLandPlugin::self->refillPanel(); + } + } + void prepareDrdHandle() {} + void reinitDrdHandle() {} + void updateDrdTex() {} + + + virtual void onPPChange(int pid, PropPanel2 &panel) + { + if (pid == pidBase + PID_LAYER_ENABLED) + enabled = panel.getBool(pid); + } + + virtual void onPPBtnPressed(int pid, PropPanel2 &panel) + { + if (pid == pidBase + PID_SEL_LC1) + { + const char *lc_asset = DAEDITOR3.selectAssetX(lc1.asset, "Select primary landclass", "land"); + + if (lc_asset) + { + lc1.asset = lc_asset; + panel.setCaption(pid, lc_asset); + registerAsset(lc1); + updateEditableLandClassFlag(); + + HmapLandPlugin::self->getLandClassMgr().regenerateObjects(HmapLandPlugin::self->getlandClassMap()); + HmapLandPlugin::hmlService->invalidateClipmap(true); + } + } + else if (pid == pidBase + PID_SEL_LC2) + { + const char *lc_asset = DAEDITOR3.selectAssetX(lc2.asset, "Select secondary landclass", "land"); + + if (lc_asset) + { + lc2.asset = lc_asset; + panel.setCaption(pid, lc_asset); + registerAsset(lc2); + + HmapLandPlugin::self->getLandClassMgr().regenerateObjects(HmapLandPlugin::self->getlandClassMap()); + HmapLandPlugin::hmlService->invalidateClipmap(true); + } + } + else if (pid == pidBase + PID_EDIT_PROPS) + { + if (dlg->isVisible()) + { + panel.setCaption(pid, "Props..."); + dlg->hide(); + } + else + { + panel.setCaption(pid, "-hide-"); + dlg->show(); + } + } + else if (pid == -DIALOG_ID_CLOSE) + { + panel.setCaption(pidBase + PID_EDIT_PROPS, "Props..."); + } + else if (pid == pidBase + PID_SEL_MASK) + { + if (HmapLandPlugin::self->getEditedScriptImage() == this) + { + finishEdit(panel); + HmapLandPlugin::self->editScriptImage(this); + HmapLandPlugin::self->setShowBlueWhiteMask(); + } + const char *name = HmapLandPlugin::self->pickScriptImage(maskName, 8); + if (name) + { + if (*name && maskConv == WtRange::WMT_one) + maskConv = WtRange::WMT_asIs; + else if (!*name && maskConv != WtRange::WMT_one) + maskConv = WtRange::WMT_one; + + maskName = name; + panel.setCaption(pid, *name ? name : "-- no mask --"); + dlg->dlg->getPanel()->setCaption(dlg->PID_SEL_MASK, *name ? name : "-- no mask --"); + dlg->dlg->getPanel()->setInt(dlg->PID_WTR_MASK_CONV, maskConv); + dlg->dlg->getPanel()->setEnabledById(dlg->PID_MASK_REFSYS, HmapLandPlugin::self->hasDetaledRect() && maskConv); + dlg->dlg->getPanel()->setEnabledById(dlg->PID_SEL_MASK, maskConv); + panel.setEnabledById(pidBase + PID_EDIT_MASK, maskConv); + imageIndex = HmapLandPlugin::self->getScriptImage(maskName, 1, -1); + imageBpp = HmapLandPlugin::self->getScriptImageBpp(imageIndex); + } + } + else if (pid == pidBase + PID_EDIT_MASK) + { + ScriptParam *curEd = HmapLandPlugin::self->getEditedScriptImage(); + if (PostScriptParamLandLayer *gl = PostScriptParamLandLayer::cast(curEd)) + gl->finishEdit(panel); + else if (ScriptParamMask *sm = ScriptParamMask::cast(curEd)) + sm->finishEdit(panel); + + if (imageIndex < 0) + return; + + HmapLandPlugin::self->editScriptImage(this); + bool isEditImage = HmapLandPlugin::self->getEditedScriptImage() == this; + panel.setCaption(pid, isEditImage ? "Done" : "Edit"); + HmapLandPlugin::self->setShowBlueWhiteMask(); + + if (!isEditImage) + HmapLandPlugin::self->setSelectMode(); + } + else if (pid == pidBase + PID_SEL_GRASS_MASK) + { + /*String fname = wingw::file_open_dlg(NULL, "Select grass mask", + "tex (*.tga)|*.tga|All files (*.*)|*.*", "tga"); + + if (!fname.length()) + return; + + String grassMaskName = ::get_file_name_wo_ext(fname) + "*"; + panel.setCaption(pid, grassMaskName.isEmpty() ? "-- grass mask --" : grassMaskName); + + //replace grass_mask for all landclasses with given name (lc1.asset) + if (lc1.asset != NULL) + { + int landclassId = HmapLandPlugin::self->getLandclassIndex(lc1.asset); + if (landclassId != -1) + { + HmapLandPlugin::self->replaceGrassMask(HmapLandPlugin::self->landClasses[landclassId].colormapId, grassMaskName.str()); + HmapLandPlugin::self->hmlService->invalidateClipmap(true); + } + }*/ + } + else if (pid == pidBase + PID_LAYER_CAPTION) + { + switch (panel.getInt(pid)) + { + case EXT_BUTTON_REMOVE: + if (wingw::message_box(wingw::MBS_YESNO | wingw::MBS_QUEST, "Confirmation", + "Do you really want to delete generation layer #%d %s?", slotIdx + 1, paramName) == wingw::MB_ID_YES) + if (HmapLandPlugin::self->delGenLayer(this)) + { + if (wingw::message_box(wingw::MBS_YESNO | wingw::MBS_QUEST, "Confirmation", + "Generation layers changed.\nRegenerate all?\n(generation may be started manually with Ctrl-G later)") == + wingw::MB_ID_YES) + HmapLandPlugin::self->refillPanel(true); + else + HmapLandPlugin::self->refillPanel(); + } + break; + + case EXT_BUTTON_INSERT: + { + CDialogWindow *dialog = DAGORED2->createDialog(_pxScaled(250), _pxScaled(120), "Insert generation layer"); + PropPanel2 *panel = dialog->getPanel(); + panel->createEditBox(0, "Enter generation layer name:"); + panel->setFocusById(0); + + int ret = dialog->showDialog(); + if (ret == DIALOG_ID_OK) + { + HmapLandPlugin::self->addGenLayer(panel->getText(0), slotIdx); + if (wingw::message_box(wingw::MBS_YESNO | wingw::MBS_QUEST, "Confirmation", + "Generation layers changed.\nRegenerate all?\n(generation may be started manually with Ctrl-G later)") == + wingw::MB_ID_YES) + HmapLandPlugin::self->refillPanel(true); + else + HmapLandPlugin::self->refillPanel(); + } + DAGORED2->deleteDialog(dialog); + } + break; + + case EXT_BUTTON_UP: + if (HmapLandPlugin::self->moveGenLayer(this, true)) + { + if (wingw::message_box(wingw::MBS_YESNO | wingw::MBS_QUEST, "Confirmation", + "Generation layers changed.\nRegenerate all?\n(generation may be started manually with Ctrl-G later)") == + wingw::MB_ID_YES) + HmapLandPlugin::self->refillPanel(true); + else + HmapLandPlugin::self->refillPanel(); + } + break; + + case EXT_BUTTON_DOWN: + if (HmapLandPlugin::self->moveGenLayer(this, false)) + { + if (wingw::message_box(wingw::MBS_YESNO | wingw::MBS_QUEST, "Confirmation", + "Generation layers changed.\nRegenerate all?\n(generation may be started manually with Ctrl-G later)") == + wingw::MB_ID_YES) + HmapLandPlugin::self->refillPanel(true); + else + HmapLandPlugin::self->refillPanel(); + } + break; + + case EXT_BUTTON_RENAME: + { + CDialogWindow *dialog = DAGORED2->createDialog(_pxScaled(250), _pxScaled(120), "Rename generation layer"); + PropPanel2 *panel = dialog->getPanel(); + panel->createEditBox(0, "Change generation layer name:", paramName); + panel->setFocusById(0); + + int ret = dialog->showDialog(); + if (ret == DIALOG_ID_OK) + { + paramName = panel->getText(0); + HmapLandPlugin::self->refillPanel(); + } + DAGORED2->deleteDialog(dialog); + } + break; + } + } + else if (pid >= pidBase + PID_ELC_EDIT_MASK_BASE && pid <= pidBase + PID_ELC_EDIT_MASK_LAST) + { + int idx = pid - (pidBase + PID_ELC_EDIT_MASK_BASE); + ScriptParam *curEd = HmapLandPlugin::self->getEditedScriptImage(); + if (PostScriptParamLandLayer *gl = PostScriptParamLandLayer::cast(curEd)) + gl->finishEdit(panel); + else if (ScriptParamMask *sm = ScriptParamMask::cast(curEd)) + sm->finishEdit(panel); + + HmapLandPlugin::self->editScriptImage(this, idx); + bool isEditImage = HmapLandPlugin::self->getEditedScriptImage() == this; + panel.setCaption(pid, String(0, isEditImage ? "%s - Done!" : "elcMask: %s", elcMaskList.getName(idx))); + HmapLandPlugin::self->setShowBlueWhiteMask(); + + if (!isEditImage) + HmapLandPlugin::self->setSelectMode(); + } + } + virtual bool onPPChangeEx(int pid, PropPanel2 &p) + { + if (pid < pidBase || pid >= pidBase + PID__COUNT) + return false; + onPPChange(pid, p); + ; + return true; + } + virtual bool onPPBtnPressedEx(int pid, PropPanel2 &p) + { + if (pid < pidBase || pid >= pidBase + PID__COUNT) + return false; + onPPBtnPressed(pid, p); + return true; + } + + virtual void finishEdit(PropPanel2 &panel) + { + if (elcMaskCurIdx < 0) + panel.setCaption(pidBase + PID_EDIT_MASK, "Edit"); + else + { + panel.setCaption(pidBase + PID_ELC_EDIT_MASK_BASE + elcMaskCurIdx, + String(0, "elcMask: %s", elcMaskList.getName(elcMaskCurIdx))); + elcMaskCurIdx = elcMaskImageIndex = elcMaskImageBpp = -1; + } + } + + virtual void save(DataBlock &blk) + { + blk.setStr("name", paramName); + if (!enabled) + blk.setBool("enabled", enabled); + if (sumWeights) + blk.setBool("sumWt", sumWeights); + if (!lc1.asset.empty()) + blk.setStr("lc1", lc1.asset); + if (!lc2.asset.empty()) + blk.setStr("lc2", lc2.asset); + blk.setInt("lcIdx", landIdx); + + if (areaSelect) + blk.setInt("area_select", areaSelect); + + if (maskConv) + blk.setInt("mask_conv", maskConv); + if (!maskName.empty()) + blk.setStr("mask", maskName); + if (detRectMappedMask) + blk.setBool("maskDRM", detRectMappedMask); + + if (ht.conv) + blk.setInt("ht_conv", ht.conv); + if (ht.v0) + blk.setReal("ht_v0", ht.v0); + if (ht.dv) + blk.setReal("ht_dv", ht.dv); + + if (ang.conv) + blk.setInt("ang_conv", ang.conv); + if (ang.v0) + blk.setReal("ang_v0", ang.v0); + if (ang.dv) + blk.setReal("ang_dv", ang.dv); + + if (curv.conv) + blk.setInt("curv_conv", curv.conv); + if (curv.v0) + blk.setReal("curv_v0", curv.v0); + if (curv.dv) + blk.setReal("curv_dv", curv.dv); + + if (!writeDetTex) + blk.setBool("writeDetTex", writeDetTex); + if (!writeLand1) + blk.setBool("writeLand1", writeLand1); + if (writeLand2) + blk.setBool("writeLand2", writeLand2); + if (writeImportance) + blk.setBool("writeImportance", writeImportance); + if (writeDetTexThres) + blk.setReal("writeDetTexThres", writeDetTexThres); + if (writeLand1Thres) + blk.setReal("writeLand1Thres", writeLand1Thres); + if (writeLand2Thres) + blk.setReal("writeLand2Thres", writeLand2Thres); + + int nid = elcLayers.getNameId("elc_layer"); + for (int i = 0; i < elcLayers.blockCount(); i++) + if (elcLayers.getBlock(i)->getBlockNameId() == nid) + blk.addNewBlock(elcLayers.getBlock(i)); + } + + virtual void load(const DataBlock &blk) + { + paramName = blk.getStr("name", ""); + enabled = blk.getBool("enabled", true); + sumWeights = blk.getBool("sumWt", false); + lc1.asset = blk.getStr("lc1", NULL); + lc2.asset = blk.getStr("lc2", NULL); + landIdx = blk.getInt("lcIdx", -1); + + areaSelect = blk.getInt("area_select", 0); + + maskConv = blk.getInt("mask_conv", 0); + maskName = blk.getStr("mask", NULL); + detRectMappedMask = blk.getBool("maskDRM", false); + + ht.conv = blk.getInt("ht_conv", 0); + ht.v0 = blk.getReal("ht_v0", 0); + ht.dv = blk.getReal("ht_dv", 0); + ang.conv = blk.getInt("ang_conv", 0); + ang.v0 = blk.getReal("ang_v0", 0); + ang.dv = blk.getReal("ang_dv", 0); + curv.conv = blk.getInt("curv_conv", 0); + curv.v0 = blk.getReal("curv_v0", 0); + curv.dv = blk.getReal("curv_dv", 0); + writeDetTex = blk.getBool("writeDetTex", true); + writeLand1 = blk.getBool("writeLand1", true); + writeLand2 = blk.getBool("writeLand2", false); + writeImportance = blk.getBool("writeImportance", false); + writeDetTexThres = blk.getReal("writeDetTexThres", 0); + writeLand1Thres = blk.getReal("writeLand1Thres", 0); + writeLand2Thres = blk.getReal("writeLand2Thres", 0); + + imageIndex = HmapLandPlugin::self->getScriptImage(maskName, 1, -1); + imageBpp = HmapLandPlugin::self->getScriptImageBpp(imageIndex); + + elcLayers.reset(); + int nid = blk.getNameId("elc_layer"); + for (int i = 0; i < blk.blockCount(); i++) + if (blk.getBlock(i)->getBlockNameId() == nid) + elcLayers.addNewBlock(blk.getBlock(i)); + + dlg->updateTitle(); + } + + virtual void setToScript(HSQUIRRELVM vm) {} + + void registerAssets() + { + registerAsset(lc1); + registerAsset(lc2); + updateEditableLandClassFlag(); + } + + void changeSlotIdx(int idx) + { + unregisterAsset(lc1); + unregisterAsset(lc2); + detIdx = slotIdx = idx; + registerAsset(lc1); + registerAsset(lc2); + dlg->updateTitle(); + updateEditableLandClassFlag(); + } + + + void registerAsset(LandClassRec &lc) + { + if (lc.asset.empty()) + return unregisterAsset(lc); + + void *handle = HmapLandPlugin::self->getLayersHandle(); + int lc_li = HmapLandPlugin::hmlService->getBitLayerIndexByName(handle, &lc == &lc1 ? "land" : "adds"); + int lc_base = lc_li < 0 ? 0 : (1 << HmapLandPlugin::hmlService->getBitLayersList(handle)[lc_li].bitCount) - 1; + if (lc_li >= 0 && landIdx >= 0) + HmapLandPlugin::self->getLandClassMgr().setLandClass(lc_li, lc_base - landIdx, lc.asset); + + int phys_li = HmapLandPlugin::hmlService->getBitLayerIndexByName(handle, "phys"); + if (phys_li >= 0 && landIdx >= 0) + HmapLandPlugin::self->getLandClassMgr().setLandClass(phys_li, landIdx, lc.asset); + + regetAsset(lc); + if (&lc == &lc2) + return; + + int det_layer_id = HmapLandPlugin::self->getDetLayerIdx(); + int det_base = + (det_layer_id < 0 || !HmapLandPlugin::self->usesGenScript()) + ? 0 + : (1 << HmapLandPlugin::hmlService->getBitLayersList(HmapLandPlugin::self->getLayersHandle())[det_layer_id].bitCount) - 1; + if (det_layer_id >= 0 && slotIdx >= 0 && lc.assetData) + HmapLandPlugin::self->setDetailTexSlot(detIdx = (det_base ? det_base - slotIdx : slotIdx), lc.asset); + else + detIdx = -1; + badDetTex = det_layer_id < 0; // badDetTex = det_layer_id < 0 || !lc.assetData->detTex; + if (badDetTex && writeDetTex) + DAEDITOR3.conError("bad asset <%s> to write detTex weight in layer %d", lc.asset, slotIdx); + } + + void unregisterAsset(LandClassRec &lc) + { + if (!HmapLandPlugin::self) + return; + + LandClassSlotsManager::releaseAsset(lc.assetData); + lc.assetData = NULL; + + void *handle = HmapLandPlugin::self->getLayersHandle(); + int lc_li = HmapLandPlugin::hmlService->getBitLayerIndexByName(handle, &lc == &lc1 ? "land" : "adds"); + int lc_base = lc_li < 0 ? 0 : (1 << HmapLandPlugin::hmlService->getBitLayersList(handle)[lc_li].bitCount) - 1; + if (lc_li >= 0 && landIdx >= 0) + HmapLandPlugin::self->getLandClassMgr().setLandClass(lc_li, lc_base - landIdx, NULL); + + if (&lc == &lc2) + return; + + int det_layer_id = HmapLandPlugin::self->getDetLayerIdx(); + int det_base = + (det_layer_id < 0 || !HmapLandPlugin::self->usesGenScript()) + ? 0 + : (1 << HmapLandPlugin::hmlService->getBitLayersList(HmapLandPlugin::self->getLayersHandle())[det_layer_id].bitCount) - 1; + if (det_layer_id >= 0 && slotIdx >= 0) + HmapLandPlugin::self->setDetailTexSlot(detIdx = (det_base ? det_base - slotIdx : slotIdx), NULL); + else + detIdx = -1; + badDetTex = true; + } + + void regetAsset(LandClassRec &lc) + { + landclass::AssetData *a = lc.assetData; + lc.assetData = LandClassSlotsManager::getAsset(lc.asset); + LandClassSlotsManager::releaseAsset(a); + } + + // IAssetUpdateNotify interface + virtual void onLandClassAssetChanged(landclass::AssetData *data) + { + bool changed = lc1.assetData == data || lc2.assetData == data; + if (lc1.assetData == data) + { + unregisterAsset(lc1); + registerAsset(lc1); + updateEditableLandClassFlag(); + } + if (lc2.assetData == data) + { + unregisterAsset(lc2); + registerAsset(lc2); + } + if (changed) + HmapLandPlugin::self->getLandClassMgr().regenerateObjects(HmapLandPlugin::self->getlandClassMap()); + } + virtual void onLandClassAssetTexturesChanged(landclass::AssetData *data) override {} + virtual void onSplineClassAssetChanged(splineclass::AssetData *data) {} + + + inline float getMask(float fx, float fy) const; + inline void setMask(float fx, float fy, int c); + inline float getMaskDirect(float fx, float fy) const; + inline void setMaskDirect(float fx, float fy, int c); + inline float getMaskDirectEx(float fx, float fy) const; + inline void setMaskDirectEx(float fx, float fy, int c); + inline float calcWeight(float height, float angDiff, float curvature) const; + + static inline PostScriptParamLandLayer *cast(ScriptParam *es) + { + if (es && es->get_interface('Layr')) + return static_cast(es); + return NULL; + } + void updateEditableLandClassFlag() + { + bool new_elc = lc1.assetData && lc1.assetData->editableMasks; + if (new_elc != editableLandClass) + { + editableLandClass = new_elc; + HmapLandPlugin::hmlService->destroyDetailRenderData(drdHandle); + drdHandle = NULL; + dlg->refillPanel(); + } + else + updateElcMasks(); + } +}; + +bool HmapLandPlugin::loadGenLayers(const DataBlock &blk) +{ + int nid = blk.getNameId("layer"); + genLayers.clear(); + Tab usedIdx(tmpmem); + int lc1_li = hmlService->getBitLayerIndexByName(getLayersHandle(), "land"); + int bits = lc1_li < 0 ? 0 : hmlService->getBitLayersList(getLayersHandle())[lc1_li].bitCount; + usedIdx.resize((1 << bits) - 1); + mem_set_0(usedIdx); + + for (int i = 0, idx = 0; i < blk.blockCount(); i++) + if (blk.getBlock(i)->getBlockNameId() == nid) + { + PostScriptParamLandLayer *l = new PostScriptParamLandLayer(idx, 0, ""); + l->load(*blk.getBlock(i)); + if (l->landIdx < 0 || l->landIdx >= usedIdx.size() || usedIdx[l->landIdx]) + { + l->landIdx = find_value_idx(usedIdx, false); + DAEDITOR3.conWarning("replaced layer[%d].landIdx with %d", idx, l->landIdx); + } + if (l->landIdx >= 0) + usedIdx[l->landIdx] = true; + genLayers.push_back(l); + l->registerAssets(); + idx++; + } + return true; +} +bool HmapLandPlugin::saveGenLayers(DataBlock &blk) +{ + for (int i = 0; i < genLayers.size(); i++) + genLayers[i]->save(*blk.addNewBlock("layer")); + return true; +} +void HmapLandPlugin::prepareEditableLandClasses() +{ + for (int i = 0; i < genLayers.size(); i++) + if (PostScriptParamLandLayer *gl = PostScriptParamLandLayer::cast(genLayers[i])) + gl->prepareDrdHandle(); +} +void HmapLandPlugin::addGenLayer(const char *name, int insert_before) +{ + Tab usedIdx(tmpmem); + int lc1_li = hmlService->getBitLayerIndexByName(getLayersHandle(), "land"); + int bits = lc1_li < 0 ? 0 : hmlService->getBitLayersList(getLayersHandle())[lc1_li].bitCount; + usedIdx.resize((1 << bits) - 1); + mem_set_0(usedIdx); + for (int i = 0; i < genLayers.size(); i++) + { + PostScriptParamLandLayer &gl = *static_cast(genLayers[i].get()); + if (gl.landIdx >= 0) + usedIdx[gl.landIdx] = true; + } + + PostScriptParamLandLayer *l = new PostScriptParamLandLayer(genLayers.size(), find_value_idx(usedIdx, false), name); + genLayers.push_back(l); + if (genLayers.size() == 1) + l->writeDetTex = l->writeLand1 = true; + + l->registerAssets(); + if (insert_before != -1) + for (int i = genLayers.size() - 1; i > insert_before; i--) + moveGenLayer(genLayers[i], true); +} +bool HmapLandPlugin::moveGenLayer(ScriptParam *gl, bool up) +{ + for (int i = 0; i < genLayers.size(); i++) + if (genLayers[i] == gl) + { + if (up && i > 0) + { + Ptr tmp = genLayers[i]; + genLayers[i] = genLayers[i - 1]; + genLayers[i - 1] = tmp; + static_cast(genLayers[i - 1].get())->changeSlotIdx(i - 1); + static_cast(genLayers[i].get())->changeSlotIdx(i); + return true; + } + else if (!up && i + 1 < genLayers.size()) + { + Ptr tmp = genLayers[i]; + genLayers[i] = genLayers[i + 1]; + genLayers[i + 1] = tmp; + static_cast(genLayers[i].get())->changeSlotIdx(i); + static_cast(genLayers[i + 1].get())->changeSlotIdx(i + 1); + return true; + } + break; + } + return false; +} +bool HmapLandPlugin::delGenLayer(ScriptParam *gl) +{ + for (int i = 0; i < genLayers.size(); i++) + if (genLayers[i] == gl) + { + erase_items(genLayers, i, 1); + for (; i < genLayers.size(); i++) + static_cast(genLayers[i].get())->changeSlotIdx(i); + return true; + } + return false; +} +void HmapLandPlugin::regenLayerTex() +{ + for (int i = 0; i < genLayers.size(); i++) + if (PostScriptParamLandLayer *gl = PostScriptParamLandLayer::cast(genLayers[i])) + HmapLandPlugin::hmlService->updateDetailRenderData(gl->drdHandle, gl->elcLayers); +} + +void HmapLandPlugin::storeLayerTex() +{ + if (d3d::is_stub_driver() || !hmlService) + return; + String prefix(DAGORED2->getPluginFilePath(this, "elc")); + + for (int i = 0; i < genLayers.size(); i++) + if (PostScriptParamLandLayer *gl = PostScriptParamLandLayer::cast(genLayers[i])) + { + HmapLandPlugin::hmlService->updateDetailRenderData(gl->drdHandle, gl->elcLayers); + HmapLandPlugin::hmlService->storeDetailRenderData(gl->drdHandle, prefix, true, true); + } +} + +// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ// + +namespace LandColorGenData +{ +enum +{ + FSZ = 7, + FC = 3 +}; +static real curvWt[FSZ][FSZ]; +static bool curvatureReady = false; +static HeightMapStorage *hmap = NULL; +static HeightMapStorage *hmapDet = NULL; +static int detDiv = 0; +static IBBox2 detRectC; +static int curv_dx = 0, curv_dy = 0; + +static Point3 normal; +static real height, curvature; + +static real heightMapX, heightMapZ; + +static real gridCellSize; +static Point2 heightMapOffset; +static int heightMapSizeX, heightMapSizeZ; + +struct WeighedTexIdx +{ + float w; + int idx; + static int cmp(const WeighedTexIdx *a, const WeighedTexIdx *b) + { + float d = b->w - a->w; + return d > 0 ? 1 : (d < 0 ? -1 : 0); + } +}; +static Tab blendTex(inimem); + +static float getNormalX() { return normal.x; } +static float getNormalY() { return normal.y; } +static float getNormalZ() { return normal.z; } +static float getHeight() { return height; } + +static bool insideDetRectC(int x, int y) { return x >= detRectC[0].x && x < detRectC[1].x && y >= detRectC[0].y && y < detRectC[1].y; } +static float sampleHeight(int x, int y) +{ + if (detDiv && insideDetRectC(x * detDiv, y * detDiv)) + { + x *= detDiv; + y *= detDiv; + int x0 = max(x - detDiv / 2, detRectC[0].x), y0 = max(y - detDiv / 2, detRectC[0].y); + int x1 = min(x + detDiv / 2, detRectC[1].x), y1 = min(y + detDiv / 2, detRectC[1].y); + float h = 0; + for (y = y0; y <= y1; y++) + for (x = x0; x <= x1; x++) + h += hmapDet->getFinalData(x, y); + return h / (x1 - x0 + 1) / (y1 - y0 + 1); + } + return hmap->getFinalData(x, y); +} +static float getCurvature() +{ + if (curvatureReady) + return curvature; + + double curv = 0; + for (int fy = 0; fy < FSZ; ++fy) + for (int fx = 0; fx < FSZ; ++fx) + curv += sampleHeight(fx + curv_dx, fy + curv_dy) * curvWt[fy][fx]; + + curvatureReady = true; + return curvature = curv; +} + +static float getHeightMapX() { return heightMapX; } +static float getHeightMapZ() { return heightMapZ; } +static int getHeightMapSizeX() { return heightMapSizeX; } +static int getHeightMapSizeZ() { return heightMapSizeZ; } + +static unsigned makeColor(int r, int g, int b, int t) +{ + if (r < 0) + r = 0; + else if (r > 255) + r = 255; + if (g < 0) + g = 0; + else if (g > 255) + g = 255; + if (b < 0) + b = 0; + else if (b > 255) + b = 255; + + return E3DCOLOR(r, g, b, t); +} + +static unsigned setType(unsigned u, int t) +{ + E3DCOLOR c = u; + c.a = t; + return c; +} + +static int getType(unsigned u) { return E3DCOLOR(u).a; } + +static unsigned blendColors(unsigned u1, unsigned u2, float t) +{ + if (t <= 0) + return u1; + if (t >= 1) + return u2; + + E3DCOLOR c1 = u1, c2 = u2; + + return E3DCOLOR(real2int(c1.r * (1 - t) + c2.r * t), real2int(c1.g * (1 - t) + c2.g * t), real2int(c1.b * (1 - t) + c2.b * t), + (t <= 0.5f ? c1.a : c2.a)); +} +static bool blendedInvalidLandClasses = false; +static void resetBlendDetTex() { blendTex.clear(); } + +static void blendDetTex(unsigned idx, float t) +{ + if (t <= 0) + return; + + if (!blendTex.size() || t > 1.0f) + t = 1.0f; + if (idx >= HmapLandPlugin::self->lcRemap.size() || HmapLandPlugin::self->lcRemap[idx] == 0xFF) + blendedInvalidLandClasses = true; + + int id = -1; + for (int i = 0; i < blendTex.size(); i++) + if (blendTex[i].idx != idx) + { + blendTex[i].w *= (1.0f - t); + } + else + { + blendTex[i].w = blendTex[i].w * (1.0f - t) + t; + id = i; + } + + if (id < 0) + { + WeighedTexIdx &w = blendTex.push_back(); + w.idx = idx; + w.w = t; + } +} + +static void applyBlendDetTex(int x, int y, int def_det_tex) +{ + float sum = 0; + if (!blendTex.size()) + { + if (!HmapLandPlugin::self->getDetTexIdxMap()) + return; + WeighedTexIdx &w = blendTex.push_back(); + w.idx = def_det_tex; + sum = w.w = 1.0f; + } + else + { + sort(blendTex, &WeighedTexIdx::cmp); + // if (blendTex.size() > HmapLandPlugin::HMAX_DET_TEX_NUM) + // blendTex.resize(HmapLandPlugin::HMAX_DET_TEX_NUM); + for (int i = 0; i < blendTex.size(); i++) + if (blendTex[i].w > 0) + sum += blendTex[i].w; + else + { + blendTex.resize(i); + break; + } + /*if (blendTex.size() > 1) + debug("blend %d tex, sum=%.4f, %.3f,%.3f,%.3f", blendTex.size(), sum, + blendTex[0].w, blendTex[1].w, blendTex[2].w);*/ + } + + MapStorage *map_idx = HmapLandPlugin::self->getDetTexIdxMap(); + MapStorage *map_wt = HmapLandPlugin::self->getDetTexWtMap(); + if (!map_idx) + { + HmapLandPlugin::self->prepareDetTexMaps(); + map_idx = HmapLandPlugin::self->getDetTexIdxMap(); + map_wt = HmapLandPlugin::self->getDetTexWtMap(); + } + + uint64_t p_idx = 0; + uint64_t p_wt = 0; + for (int i = 0; i < blendTex.size(); i++) + { + p_wt |= (uint64_t(floorf(blendTex[i].w / sum * 255.0f)) & 0xFF) << (i * 8); + p_idx |= (uint64_t(blendTex[i].idx) & 0xFF) << (i * 8); + } + /*if (blendTex.size() > 1) + debug("wt=%08X%08X idx=%08X%08X", + unsigned(p_wt>>32), unsigned(p_wt), unsigned(p_idx>>32), unsigned(p_idx));*/ + + map_idx->setData(x, y, p_idx); + map_wt->setData(x, y, p_wt); +} + +static unsigned mulColors(unsigned u1, unsigned u2) +{ + E3DCOLOR c1 = u1, c2 = u2; + + return E3DCOLOR((c1.r * c2.r + 127) / 255, (c1.g * c2.g + 127) / 255, (c1.b * c2.b + 127) / 255, c1.a); +} + +static unsigned mulColors2x(unsigned u1, unsigned u2) +{ + E3DCOLOR c1 = u1, c2 = u2; + + int r = (c1.r * c2.r * 2 + 127) / 255; + int g = (c1.g * c2.g * 2 + 127) / 255; + int b = (c1.b * c2.b * 2 + 127) / 255; + + if (r > 255) + r = 255; + if (g > 255) + g = 255; + if (b > 255) + b = 255; + + return E3DCOLOR(r, g, b, c1.a); +} + +static unsigned dissolveOver(unsigned u1, unsigned u2, float t, float mask) +{ + if (t <= 0) + return u1; + if (t >= 1) + return u2; + + if (t >= mask) + return u2; + return u1; +} + +static float calcBlendK(float val0, float val1, float v) +{ + float d = val1 - val0; + if (!float_nonzero(d)) + { + if (v < val0) + return 0; + return 1; + } + + float t = (v - val0) / d; + + if (t <= 0) + return 0; + if (t >= 1) + return 1; + return t; +} + +static float smoothStep(float t) +{ + if (t <= 0) + return 0; + if (t >= 1) + return 1; + return (3 - 2 * t) * t * t; +} + +static unsigned sampleImage(SqPlus::SQAnythingPtr ptr) +{ + if (!ptr) + return E3DCOLOR(255, 255, 255, 0); + + E3DCOLOR c = ((ScriptParamImage *)ptr)->sampleImage(); + return c; +} + +static float sampleImage1(SqPlus::SQAnythingPtr ptr) { return ptr ? ((ScriptParamImage *)ptr)->sampleImage1() : 1.0; } + +static float sampleImage8(SqPlus::SQAnythingPtr ptr) { return ptr ? ((ScriptParamImage *)ptr)->sampleImage8() : 1.0; } + +static unsigned sampleImageAt(SqPlus::SQAnythingPtr ptr, float u, float v) +{ + if (!ptr) + return E3DCOLOR(255, 255, 255, 0); + + E3DCOLOR c = ((ScriptParamImage *)ptr)->sampleImageAt(u, v); + return c; +} + +static bool saveImage(SqPlus::SQAnythingPtr ptr) { return ((ScriptParamImage *)ptr)->saveImage(); } + +static void setMask(SqPlus::SQAnythingPtr ptr, float val) +{ + ScriptParamMask &m = *(ScriptParamMask *)ptr; + if (m.bitsPerPixel == 1) + m.setMask1(val > 0); + else if (m.bitsPerPixel == 8) + m.setMask8((unsigned char)(val * 255.0)); +} + +static void setMask1(SqPlus::SQAnythingPtr ptr, float val) +{ + if (!ptr) + return; + ((ScriptParamMask *)ptr)->setMask1(val > 0); +} + +static void setMask8(SqPlus::SQAnythingPtr ptr, float val) +{ + if (!ptr) + return; + ((ScriptParamMask *)ptr)->setMask8((unsigned char)(val * 255.0)); +} + +static float sampleMask(SqPlus::SQAnythingPtr ptr) +{ + ScriptParamMask &m = *(ScriptParamMask *)ptr; + if (m.bitsPerPixel == 1) + return m.sampleMask1(); + if (m.bitsPerPixel == 8) + return m.sampleMask8(); + if (m.bitsPerPixel == 32) + { + E3DCOLOR c = ((ScriptParamImage *)ptr)->sampleImage(); + return ((int)c.r + (int)c.g + (int)c.b) / 3.0 / 255.0; + } + return 1.0; +} + +static float sampleMask1(SqPlus::SQAnythingPtr ptr) { return ptr ? ((ScriptParamMask *)ptr)->sampleMask1() : 1.0; } + +static float sampleMask8(SqPlus::SQAnythingPtr ptr) { return ptr ? ((ScriptParamMask *)ptr)->sampleMask8() : 1.0; } + +static void registerInScript(HSQUIRRELVM vm) +{ +#define REG(func) SqPlus::RegisterGlobal(vm, func, _T(#func)) + + REG(getNormalX); + REG(getNormalY); + REG(getNormalZ); + REG(getHeight); + REG(getCurvature); + REG(getHeightMapX); + REG(getHeightMapZ); + REG(getHeightMapSizeX); + REG(getHeightMapSizeZ); + REG(makeColor); + REG(setType); + REG(getType); + REG(blendColors); + REG(blendDetTex); + REG(mulColors); + REG(mulColors2x); + REG(dissolveOver); + REG(calcBlendK); + REG(smoothStep); + REG(sampleImage); + REG(sampleImage1); + REG(sampleImage8); + REG(sampleImageAt); + REG(setMask); + REG(setMask1); + REG(setMask8); + REG(sampleMask); + REG(sampleMask1); + REG(sampleMask8); + REG(saveImage); + +#undef REG +} +}; // namespace LandColorGenData + + +void ScriptParamImage::calcMapping(real x, real z, Point2 &p) +{ + if (mappingType == MAPPING_HMAP_PERCENT) + { + p.x = x / LandColorGenData::heightMapSizeX; + p.y = z / LandColorGenData::heightMapSizeZ; + + p -= offset / 100; + + if (float_nonzero(tile.x)) + p.x = p.x * 100 / tile.x; + if (float_nonzero(tile.y)) + p.y = p.y * 100 / tile.y; + } + else if (mappingType == MAPPING_WORLD) + { + p.x = x; + p.y = z; + + p *= LandColorGenData::gridCellSize; + + p -= offset; + + if (float_nonzero(tile.x)) + p.x = p.x / tile.x; + if (float_nonzero(tile.y)) + p.y = p.y / tile.y; + } + else if (mappingType == MAPPING_VERT_U || mappingType == MAPPING_VERT_V) + { + p.x = p.y = 0; + + if (mappingType == MAPPING_VERT_U) + p.x = LandColorGenData::height; + else + p.y = LandColorGenData::height; + + p -= offset; + + if (float_nonzero(tile.x)) + p.x = p.x / tile.x; + if (float_nonzero(tile.y)) + p.y = p.y / tile.y; + } + else + { + p.x = x; + p.y = z; + + p -= offset; + + if (float_nonzero(tile.x)) + p.x = p.x * 100 / tile.x; + if (float_nonzero(tile.y)) + p.y = p.y * 100 / tile.y; + + p.x /= HmapLandPlugin::self->getScriptImageWidth(imageIndex); + p.y /= HmapLandPlugin::self->getScriptImageHeight(imageIndex); + } + + flipAndSwapUV(p.x, p.y); +} + + +E3DCOLOR ScriptParamImage::sampleImage() +{ + Point2 p; + calcMapping(LandColorGenData::heightMapX, LandColorGenData::heightMapZ, p); + + E3DCOLOR c = HmapLandPlugin::self->sampleScriptImageUV(imageIndex, p.x, p.y, clampU, clampV); + c.a = detailType; + return c; +} + +float ScriptParamImage::sampleImage1() +{ + Point2 p; + calcMapping(LandColorGenData::heightMapX, LandColorGenData::heightMapZ, p); + + return HmapLandPlugin::self->sampleMask1UV(imageIndex, p.x, p.y, clampU, clampV); +} + +float ScriptParamImage::sampleImage8() +{ + Point2 p; + calcMapping(LandColorGenData::heightMapX, LandColorGenData::heightMapZ, p); + + return HmapLandPlugin::self->sampleMask8UV(imageIndex, p.x, p.y, clampU, clampV); +} + +void ScriptParamImage::setImage(E3DCOLOR c) +{ + Point2 p; + calcMapping(LandColorGenData::heightMapX, LandColorGenData::heightMapZ, p); + + HmapLandPlugin::self->paintScriptImageUV(imageIndex, p.x, p.y, p.x, p.y, clampU, clampV, c); +} + +bool ScriptParamImage::saveImage() { return HmapLandPlugin::self->saveImage(imageIndex); } + + +E3DCOLOR ScriptParamImage::sampleImagePixel() +{ + E3DCOLOR c = sampleImagePixelTrueAlpha(); + c.a = detailType; + return c; +} + + +E3DCOLOR ScriptParamImage::sampleImagePixelTrueAlpha() +{ + Point2 p; + calcMapping(LandColorGenData::heightMapX, LandColorGenData::heightMapZ, p); + + E3DCOLOR c = HmapLandPlugin::self->sampleScriptImagePixelUV(imageIndex, p.x, p.y, clampU, clampV); + return c; +} + + +void ScriptParamImage::paintImage(E3DCOLOR color) +{ + Point2 p0, p1; + calcMapping(LandColorGenData::heightMapX, LandColorGenData::heightMapZ, p0); + calcMapping(LandColorGenData::heightMapX + 1.0f, LandColorGenData::heightMapZ + 1.0f, p1); + + HmapLandPlugin::self->paintScriptImageUV(imageIndex, p0.x, p0.y, p1.x, p1.y, clampU, clampV, color); +} + +float ScriptParamMask::sampleMask1() +{ + float fx = LandColorGenData::heightMapX / LandColorGenData::heightMapSizeX, + fy = LandColorGenData::heightMapZ / LandColorGenData::heightMapSizeZ; + return HmapLandPlugin::self->sampleMask1UV(imageIndex, fx, fy); +} +float ScriptParamMask::sampleMask8() +{ + float fx = LandColorGenData::heightMapX / LandColorGenData::heightMapSizeX, + fy = LandColorGenData::heightMapZ / LandColorGenData::heightMapSizeZ; + return HmapLandPlugin::self->sampleMask8UV(imageIndex, fx, fy); +} +float ScriptParamMask::sampleMask1Pixel() +{ + float fx = LandColorGenData::heightMapX / LandColorGenData::heightMapSizeX, + fy = LandColorGenData::heightMapZ / LandColorGenData::heightMapSizeZ; + return HmapLandPlugin::self->sampleMask1PixelUV(imageIndex, fx, fy); +} +float ScriptParamMask::sampleMask8Pixel() +{ + float fx = LandColorGenData::heightMapX / LandColorGenData::heightMapSizeX, + fy = LandColorGenData::heightMapZ / LandColorGenData::heightMapSizeZ; + return HmapLandPlugin::self->sampleMask8PixelUV(imageIndex, fx, fy); +} +void ScriptParamMask::setMask1(bool c) +{ + float fx = LandColorGenData::heightMapX / LandColorGenData::heightMapSizeX, + fy = LandColorGenData::heightMapZ / LandColorGenData::heightMapSizeZ; + return HmapLandPlugin::self->paintMask1UV(imageIndex, fx, fy, c); +} +void ScriptParamMask::setMask8(char c) +{ + float fx = LandColorGenData::heightMapX / LandColorGenData::heightMapSizeX, + fy = LandColorGenData::heightMapZ / LandColorGenData::heightMapSizeZ; + return HmapLandPlugin::self->paintMask8UV(imageIndex, fx, fy, c); +} + + +inline float PostScriptParamLandLayer::getMaskDirect(float fx, float fy) const +{ + if (imageBpp == 1) + return HmapLandPlugin::self->sampleMask1UV(imageIndex, fx, fy); + else if (imageBpp == 8) + return HmapLandPlugin::self->sampleMask8UV(imageIndex, fx, fy); + return 1; +} +inline void PostScriptParamLandLayer::setMaskDirect(float fx, float fy, int c) +{ + if (imageBpp == 1) + HmapLandPlugin::self->paintMask1UV(imageIndex, fx, fy, c); + else if (imageBpp == 8) + HmapLandPlugin::self->paintMask8UV(imageIndex, fx, fy, c); +} +inline float PostScriptParamLandLayer::getMaskDirectEx(float fx, float fy) const +{ + int idx = elcMaskCurIdx < 0 ? imageIndex : elcMaskImageIndex; + switch (elcMaskCurIdx < 0 ? imageBpp : elcMaskImageBpp) + { + case 1: return HmapLandPlugin::self->sampleMask1UV(idx, fx, fy); + case 8: return HmapLandPlugin::self->sampleMask8UV(idx, fx, fy); + } + return 1; +} +inline void PostScriptParamLandLayer::setMaskDirectEx(float fx, float fy, int c) +{ + int idx = elcMaskCurIdx < 0 ? imageIndex : elcMaskImageIndex; + switch (elcMaskCurIdx < 0 ? imageBpp : elcMaskImageBpp) + { + case 1: HmapLandPlugin::self->paintMask1UV(idx, fx, fy, c); break; + case 8: HmapLandPlugin::self->paintMask8UV(idx, fx, fy, c); break; + } +} +inline float PostScriptParamLandLayer::getMask(float fx, float fy) const +{ + if (detRectMappedMask) + if (!HmapLandPlugin::self->mapGlobalTCtoDetRectTC(fx, fy)) + return 0; + return getMaskDirect(fx, fy); +} +inline void PostScriptParamLandLayer::setMask(float fx, float fy, int c) +{ + if (detRectMappedMask) + if (!HmapLandPlugin::self->mapGlobalTCtoDetRectTC(fx, fy)) + return; + return setMaskDirect(fx, fy, c); +} + +inline float PostScriptParamLandLayer::calcWeight(float height, float angDiff, float curvature) const +{ + float wt[] = {1, 1, 1, 1}; + + float *w = &wt[0]; + if (maskConv == WtRange::WMT_zero) + *w = 0; + else if (maskConv != WtRange::WMT_one) + { + float fx = LandColorGenData::heightMapX / LandColorGenData::heightMapSizeX, + fy = LandColorGenData::heightMapZ / LandColorGenData::heightMapSizeZ; + *w = getMask(fx, fy); + if (maskConv == WtRange::WMT_smoothStep) + *w = LandColorGenData::smoothStep(*w); + } + + w++; + if (ht.conv == WtRange::WMT_zero) + *w = 0; + else if (ht.conv != WtRange::WMT_one) + { + if (fabsf(ht.dv) < 1e-4) + *w = (fabsf(height - ht.v0) < 1e-4); + else + *w = clamp((height - ht.v0) / ht.dv, 0.0f, 1.0f); + if (ht.conv == WtRange::WMT_smoothStep) + *w = LandColorGenData::smoothStep(*w); + } + + w++; + if (ang.conv == WtRange::WMT_zero) + *w = 0; + else if (ang.conv != WtRange::WMT_one) + { + if (fabsf(ang.dv) < 1e-4) + *w = (fabsf(angDiff - ang.v0) < 1e-4); + else + *w = clamp((angDiff - ang.v0) / ang.dv, 0.0f, 1.0f); + if (ang.conv == WtRange::WMT_smoothStep) + *w = LandColorGenData::smoothStep(*w); + } + + w++; + if (curv.conv == WtRange::WMT_zero) + *w = 0; + else if (curv.conv != WtRange::WMT_one) + { + if (fabsf(curv.dv) < 1e-4) + *w = (fabsf(curvature - curv.v0) < 1e-4); + else + *w = clamp((curvature - curv.v0) / curv.dv, 0.0f, 1.0f); + if (curv.conv == WtRange::WMT_smoothStep) + *w = LandColorGenData::smoothStep(*w); + } + + return sumWeights ? (wt[0] + wt[1] + wt[2] + wt[3]) : (wt[0] * wt[1] * wt[2] * wt[3]); +} + +// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ// + +static void scriptPrintFunc(HSQUIRRELVM v, const SQChar *s, ...) +{ + static char temp[2048]; + va_list vl; + va_start(vl, s); + vsprintf(temp, s, vl); + va_end(vl); + + int len = (int)strlen(temp); + if (temp[len] == '\n') + temp[len] = 0; + + CoolConsole &con = DAGORED2->getConsole(); + con.addMessage(ILogWriter::WARNING, "Script: %s", temp); +} + +static const char *skipBom(const char *in) +{ + if (in && (strncmp(in, "\xef\xbb\xbf", 3) == 0)) + return in + 3; + return in; +} + +bool HmapLandPlugin::compileAndRunColorGenScript(bool &was_inited, SQPRINTFUNCTION &old_print_func, SQPRINTFUNCTION &old_err_func) +{ + if (!heightMap.isFileOpened()) + return false; + + was_inited = SquirrelVM::IsInitialized(); + + if (!was_inited) + SquirrelVM::Init(); + + old_print_func = sq_getprintfunc(SquirrelVM::GetVMPtr()); + old_err_func = sq_geterrorfunc(SquirrelVM::GetVMPtr()); + sq_setprintfunc(SquirrelVM::GetVMPtr(), ::scriptPrintFunc, ::scriptPrintFunc); + + try + { + LandColorGenData::registerInScript(SquirrelVM::GetVMPtr()); + + String scriptFilename(colorGenScriptFilename); + file_ptr_t f = df_open(scriptFilename, DF_READ | DF_IGNORE_MISSING); + if (!f) + { + scriptFilename.append(".nut"); + f = df_open(scriptFilename, DF_READ | DF_IGNORE_MISSING); + } + + if (!f) + { + logerr_ctx("failed to open script file %s", scriptFilename.str()); + return false; + } + + Tab sqBuf; + sqBuf.resize(df_length(f) + 1); + df_read(f, sqBuf.data(), data_size(sqBuf) - 1); + sqBuf.back() = '\0'; + + SquirrelObject sqInst, ret; + if (!SquirrelVM::CompileBuffer(skipBom(sqBuf.data()), sqInst, nullptr, scriptFilename)) + throw SquirrelError(); + + if (!SquirrelVM::RunScript(sqInst, ret)) + throw SquirrelError(); + } + catch (SquirrelError e) + { + CoolConsole &con = DAGORED2->getConsole(); + con.addMessage(ILogWriter::ERROR, "Script error: %s", e.desc); + return false; + } + + return true; +} + + +bool HmapLandPlugin::createDefaultScript(const char *path) const +{ + file_ptr_t f = ::df_open(path, DF_WRITE | DF_CREATE); + if (f) + { + ::df_write(f, ::defScript, (int)strlen(::defScript)); + ::df_close(f); + return true; + } + + return false; +} + + +void HmapLandPlugin::closeColorGenScript(bool &was_inited, SQPRINTFUNCTION &old_print_func, SQPRINTFUNCTION &old_err_func) +{ + sq_setprintfunc(SquirrelVM::GetVMPtr(), old_print_func, old_err_func); + + if (was_inited) + SquirrelVM::Shutdown(); +} + + +bool HmapLandPlugin::getColorGenVarsFromScript() +{ + if (!heightMap.isFileOpened()) + return false; + + if (colorGenScriptFilename.empty() && genLayers.size()) + return true; // allow gen-layers only setup + if (!usesGenScript()) + { + DAEDITOR3.conWarning("Script not used"); + return true; + } + + CoolConsole &con = DAGORED2->getConsole(); + con.startLog(); + + con.addMessage(ILogWriter::NOTE, "getting parameters from generator script..."); + + // save old tuned values first + for (int i = 0; i < colorGenParams.size(); ++i) + colorGenParams[i]->save(*colorGenParamsData); + + SimpleString editedImageName; + if (editedScriptImage) + { + editedImageName = editedScriptImage->paramName; + editedScriptImage = NULL; + } + + detailedLandMask = NULL; + colorGenParams.clear(); + + bool wasSqInited; + SQPRINTFUNCTION oldPrintFunc, oldErrFunc; + + if (!compileAndRunColorGenScript(wasSqInited, oldPrintFunc, oldErrFunc)) + { + con.addMessage(ILogWriter::ERROR, "Error running generator script"); + return false; + } + + try + { + SqPlus::SquirrelFunction func(_T("getParamsList")); + + if (!func.func.IsNull()) + { + SquirrelObject list = func(); + int len = list.Len(); + + con.addMessage(ILogWriter::NOTE, "%d script params in the list", len); + + const SQChar *defName = _T("value"); + const SQChar *layersName = _T("layers"); + + for (int pi = 0; pi < len; ++pi) + { + SquirrelObject param = list.GetValue(pi); + + const char *name = param.GetString(_T("name")); + if (!name) + { + con.addMessage(ILogWriter::WARNING, "param #%d has no name - skipped", pi); + continue; + } + + const char *typeName = param.GetString(_T("type")); + if (!typeName) + { + con.addMessage(ILogWriter::WARNING, "param #%d has no type - skipped", pi); + continue; + } + + if (stricmp(typeName, "int") == 0 || stricmp(typeName, "integer") == 0) + { + int val = 0; + if (param.Exists(defName)) + val = param.GetInt(defName); + colorGenParams.push_back(new ScriptParamInt(name, val)); + } + else if (stricmp(typeName, "real") == 0 || stricmp(typeName, "float") == 0) + { + real val = 0; + if (param.Exists(defName)) + val = param.GetFloat(defName); + colorGenParams.push_back(new ScriptParamReal(name, val)); + } + else if (stricmp(typeName, "color") == 0) + { + E3DCOLOR val = E3DCOLOR(255, 255, 255, 0); + if (param.Exists(defName)) + val = param.GetInt(defName); + colorGenParams.push_back(new ScriptParamColor(name, val)); + } + else if (stricmp(typeName, "image") == 0) + { + ScriptParamImage::DefParams def; + if (param.Exists(defName)) + { + SquirrelObject defValues = param.GetValue(defName); + + if (defValues.GetType() == OT_TABLE) + { + if (defValues.Exists("imageName")) + def.imageName = defValues.GetString("imageName"); + if (defValues.Exists("mappingType")) + def.mappingType = defValues.GetInt("mappingType"); + if (defValues.Exists("detailType")) + def.detailType = defValues.GetInt("detailType"); + if (defValues.Exists("tileX")) + def.tile.x = defValues.GetFloat("tileX"); + if (defValues.Exists("tileY")) + def.tile.y = defValues.GetFloat("tileY"); + if (defValues.Exists("offsetX")) + def.offset.x = defValues.GetFloat("offsetX"); + if (defValues.Exists("offsetY")) + def.offset.y = defValues.GetFloat("offsetY"); + if (defValues.Exists("clampU")) + def.clampU = defValues.GetBool("clampU"); + if (defValues.Exists("clampV")) + def.clampV = defValues.GetBool("clampV"); + if (defValues.Exists("flipU")) + def.flipU = defValues.GetBool("flipU"); + if (defValues.Exists("flipV")) + def.flipV = defValues.GetBool("flipV"); + if (defValues.Exists("swapUV")) + def.swapUV = defValues.GetBool("swapUV"); + } + else if (defValues.GetType() == OT_STRING) + def.imageName = defValues.ToString(); + } + colorGenParams.push_back(new ScriptParamImage(name, def)); + } + else if (stricmp(typeName, "mask1") == 0 || stricmp(typeName, "mask8") == 0) + { + int bpp = stricmp(typeName, "mask1") == 0 ? 1 : 8; + int div = 0; + bool det = false; + if (strcmp(name, "$detailedLandMask") == 0) + { + if (param.Exists(_T("step"))) + div = getGridCellSize() / param.GetFloat(_T("step")); + else if (param.Exists(_T("divisor"))) + div = param.GetFloat(_T("divisor")); + } + else if (detailedLandMask && param.Exists(_T("detailed"))) + det = param.GetBool(_T("detailed")); + + if (div > 1) + colorGenParams.push_back(detailedLandMask = new ScriptParamMask(name, bpp, true, div)); + else + { + div = detailedLandMask ? static_cast(detailedLandMask.get())->divisor : 1; + colorGenParams.push_back(new ScriptParamMask(name, bpp, det, div)); + } + } + else if (stricmp(typeName, "grid") == 0) + { + con.addMessage(ILogWriter::ERROR, "obsolete grid-type parameter '%s'", name); + } + else if (stricmp(typeName, "landClass") == 0) + { + ScriptParamLandClass::DefParams def; + clear_and_resize(def.layerIdx, landClsLayer.size()); + mem_set_ff(def.layerIdx); + int lcs_attr_id = hmlService->getBitLayerAttrId(getLayersHandle(), "landClassSlot"); + + if (param.Exists(layersName)) + { + SquirrelObject defValues = param.GetValue(layersName); + + if (defValues.GetType() == OT_TABLE && defValues.BeginIteration()) + { + SquirrelObject key, value; + while (defValues.Next(key, value)) + { + int id = hmlService->getBitLayerIndexByName(getLayersHandle(), key.ToString()); + if (id < 0) + { + con.addMessage(ILogWriter::ERROR, "Unknown layer '%s' in parameter '%s'", key.ToString(), name); + continue; + } + + if (id == getDetLayerIdx()) + def.detailIdx = value.ToInteger(); + + if (hmlService->testBitLayerAttr(getLayersHandle(), id, lcs_attr_id)) + def.layerIdx[id] = value.ToInteger(); + } + defValues.EndIteration(); + } + } + + if (param.Exists(defName)) + { + SquirrelObject defValues = param.GetValue(defName); + + if (defValues.GetType() == OT_TABLE) + { + if (defValues.Exists("asset")) + def.asset = defValues.GetString("asset"); + } + else if (defValues.GetType() == OT_STRING) + def.asset = defValues.ToString(); + } + + colorGenParams.push_back(new ScriptParamLandClass(name, def)); + } + else if (stricmp(typeName, "detailTex") == 0) + { + if (!param.Exists("slot")) + { + con.addMessage(ILogWriter::ERROR, "parameter '%s' type '%s' must have 'slot' property", name, typeName); + continue; + } + + ScriptParamDetailTex::DefParams def; + def.detailSlot = param.GetInt("slot"); + if (param.Exists(defName)) + { + SquirrelObject defValues = param.GetValue(defName); + + if (defValues.GetType() == OT_TABLE) + { + if (defValues.Exists("asset")) + def.blkName = defValues.GetString("asset"); + } + else if (defValues.GetType() == OT_STRING) + def.blkName = defValues.ToString(); + } + colorGenParams.push_back(new ScriptParamDetailTex(name, def)); + } + else + { + con.addMessage(ILogWriter::ERROR, "Unknown parameter '%s' type '%s'", name, typeName); + } + } + } + } + catch (SquirrelError e) + { + con.addMessage(ILogWriter::ERROR, "Script error: %s", e.desc); + } + + closeColorGenScript(wasSqInited, oldPrintFunc, oldErrFunc); + + ScriptParam *imageParam = NULL; + + for (int i = 0; i < colorGenParams.size(); ++i) + { + colorGenParams[i]->load(*colorGenParamsData); + + if (strcmp(colorGenParams[i]->paramName, editedImageName) == 0) + imageParam = colorGenParams[i]; + } + + editScriptImage(imageParam); + con.endLog(); + + return true; +} + + +void HmapLandPlugin::generateLandColors(const IBBox2 *in_rect, bool finished) +{ + if (!heightMap.isFileOpened()) + return; + + CoolConsole &con = DAGORED2->getConsole(); + con.startLog(); + + updateScriptImageList(); + + bool wasSqInited; + SQPRINTFUNCTION oldPrintFunc, oldErrFunc; + bool use_script = usesGenScript(); + + if (!use_script && genLayers.size()) + ; // allow gen-layers only setup + else if (!compileAndRunColorGenScript(wasSqInited, oldPrintFunc, oldErrFunc)) + { + con.addMessage(ILogWriter::ERROR, "Error running generator script"); + return; + } + + if (!in_rect) + { + if (hasColorTex) + colorMap.reset(heightMap.getMapSizeX(), heightMap.getMapSizeY(), E3DCOLOR(255, 10, 255, 0)); + createColormapFile(con); + resizeLandClassMapFile(DAGORED2->getConsole()); + } + + int time0 = ::get_time_msec(); + + if (!in_rect) + { + con.startProgress(); + con.setActionDesc("generating land colors..."); + con.setTotal(landClsMap.getMapSizeY() / lcmScale); + } + + Color3 grassColor(0.5f, 0.5f, 0.1f); + Color3 dirtColor(0.6f, 0.4f, 0.3f); + + LandColorGenData::gridCellSize = gridCellSize; + LandColorGenData::heightMapSizeX = heightMap.getMapSizeX(); + LandColorGenData::heightMapSizeZ = heightMap.getMapSizeY(); + LandColorGenData::heightMapOffset = heightMapOffset; + + using LandColorGenData::FC; + using LandColorGenData::FSZ; + + double wtSum = 0, kSum = 0; + int samples_processed = 0; + LandColorGenData::blendedInvalidLandClasses = false; + LandColorGenData::hmap = &heightMap; + LandColorGenData::hmapDet = &heightMapDet; + LandColorGenData::detDiv = detDivisor; + LandColorGenData::detRectC = detRectC; + + Tab layerVal; + int lc1_li = hmlService->getBitLayerIndexByName(getLayersHandle(), "land"); + int lc2_li = hmlService->getBitLayerIndexByName(getLayersHandle(), "adds"); + int lc1_base = lc1_li < 0 ? 0 : (1 << hmlService->getBitLayersList(getLayersHandle())[lc1_li].bitCount) - 1; + int lc2_base = lc2_li < 0 ? 0 : (1 << hmlService->getBitLayersList(getLayersHandle())[lc2_li].bitCount) - 1; + int phys_li = hmlService->getBitLayerIndexByName(getLayersHandle(), "phys"); + int phys_li_max = phys_li < 0 ? 0 : (1 << hmlService->getBitLayersList(getLayersHandle())[phys_li].bitCount) - 1; + int imp_scale = impLayerIdx < 0 ? 0 : (1 << hmlService->getBitLayersList(getLayersHandle())[impLayerIdx].bitCount) - 1; + int det_val_max = detLayerIdx < 0 ? 0 : (1 << hmlService->getBitLayersList(getLayersHandle())[detLayerIdx].bitCount) - 1; + layerVal.resize(landClsLayer.size()); + + for (int fy = 0; fy < FSZ; ++fy) + for (int fx = 0; fx < FSZ; ++fx) + { + if (fx == FC && fy == FC) + continue; + + int dx = fx - FC; + int dy = fy - FC; + real d = sqrtf(dx * dx + dy * dy); + + real k = (FC + 1 - d) / (FC + 1); + if (k < 0) + k = 0; + + k = (3 - 2 * k) * k * k; + + LandColorGenData::curvWt[fy][fx] = k / (d * gridCellSize); + wtSum += LandColorGenData::curvWt[fy][fx]; + kSum += k; + } + + LandColorGenData::curvWt[FC][FC] = -wtSum; + + for (int fy = 0; fy < FSZ; ++fy) + for (int fx = 0; fx < FSZ; ++fx) + LandColorGenData::curvWt[fy][fx] /= kSum; + + for (int l = 0; l < genLayers.size(); l++) + if (PostScriptParamLandLayer *gl = static_cast(genLayers[l].get())) + { + if (gl->writeDetTex && !gl->badDetTex) + if (gl->detIdx < 0 || gl->detIdx >= det_val_max) + { + DAEDITOR3.conError("Bad detIdx=%d in layer %d \"%s\", maxDet=%d", gl->detIdx, l, gl->paramName, det_val_max); + return; + } + if (gl->writeLand1 && lc1_base) + if (gl->landIdx < 0 || gl->landIdx >= lc1_base) + { + DAEDITOR3.conError("Bad landIdx=%d in layer %d \"%s\", maxLand[1]=%d", gl->landIdx, l, gl->paramName, lc1_base); + return; + } + if (gl->writeLand2 && lc2_base) + if (gl->landIdx < 0 || gl->landIdx >= lc2_base) + { + DAEDITOR3.conError("Bad landIdx=%d in layer %d \"%s\", maxLand[2]=%d", gl->landIdx, l, gl->paramName, lc2_base); + return; + } + } + + bool layers_use_curv = false; + for (int l = 0; l < genLayers.size(); l++) + if (static_cast(genLayers[l].get())->enabled && + static_cast(genLayers[l].get())->curv.conv != PostScriptParamLandLayer::WtRange::WMT_one) + { + layers_use_curv = true; + break; + } + + try + { + SqPlus::SquirrelFunction genFunc; + SquirrelObject layers; + + if (use_script) + { + for (int i = 0; i < colorGenParams.size(); ++i) + colorGenParams[i]->save(*colorGenParamsData); + + HSQUIRRELVM vm = SquirrelVM::GetVMPtr(); + for (int i = 0; i < colorGenParams.size(); ++i) + colorGenParams[i]->setToScript(vm); + for (int i = 0; i < landClsLayer.size(); i++) + { + sq_pushroottable(vm); + sq_pushstring(vm, String(32, "_%s", hmlService->getBitLayerName(landClsLayersHandle, i)), -1); + sq_pushinteger(vm, i); + sq_newslot(vm, -3, false); + sq_pop(vm, 1); + } + + SqPlus::SquirrelFunction getGenFunc(_T("getGenerator")); + genFunc.v = SquirrelVM::GetVMPtr(); + genFunc.object = SquirrelVM::GetRootTable(); + genFunc.func = getGenFunc(); + layers = SquirrelVM::CreateArray(landClsLayer.size()); + } + + int x0 = 0, x1 = heightMap.getMapSizeX(); + int y0 = 0, y1 = heightMap.getMapSizeY(); + + if (in_rect) + { + x0 = in_rect->lim[0].x; + x1 = in_rect->lim[1].x; + y0 = in_rect->lim[0].y + 1; + y1 = in_rect->lim[1].y + 1; + } + + for (int y = y0, cnt = 0; y < y1; ++y) + { + if (--cnt <= 0) + cnt = heightMap.getElemSize(); + + LandColorGenData::curv_dy = y - FC; + + for (int x = x0; x < x1; ++x) + { + real h = LandColorGenData::sampleHeight(x, y); + + real hu = (LandColorGenData::sampleHeight(x + 1, y) - LandColorGenData::sampleHeight(x - 1, y)) * 0.5f; + real hv = (LandColorGenData::sampleHeight(x, y + 1) - LandColorGenData::sampleHeight(x, y - 1)) * 0.5f; + + real d = gridCellSize; + + Point3 normal(-hu, d, -hv); + + real len = sqrtf(d * d + hu * hu + hv * hv); + normal /= len; + + LandColorGenData::normal = normal; + float angDiff = acos(normal.y) * 180 / PI; + LandColorGenData::height = h; + + LandColorGenData::curv_dx = x - FC; + LandColorGenData::curvatureReady = false; + + for (int ly = 0; ly < lcmScale; ly++) + for (int lx = 0; lx < lcmScale; lx++) + { + LandColorGenData::heightMapX = x + float(lx) / lcmScale; + LandColorGenData::heightMapZ = y + float(ly) / lcmScale; + + LandColorGenData::resetBlendDetTex(); + mem_set_0(layerVal); + int detIdx = 0; + + if (use_script) + { + unsigned res = genFunc(layers) & 0x00FFFFFF; + if (hasColorTex && !lx && !ly) + colorMap.setData(x, y, res); + + if (!LandColorGenData::blendTex.size()) + detIdx = layers.GetInt(detLayerIdx); + + for (int l = 0; l < landClsLayer.size(); l++) + { + if (l == detLayerIdx) + continue; + layerVal[l] = layers.GetInt(l); + layers.SetValue(l, 0); + } + } + + float curv = layers_use_curv ? LandColorGenData::getCurvature() : 0; + bool in_det = detDivisor ? insideDetRectC(x * detDivisor, y * detDivisor) : false; + int physSplattingLc = 0; + double maxPhysWeight = -1.0; + for (int l = 0; l < genLayers.size(); l++) + { + PostScriptParamLandLayer &gl = *static_cast(genLayers[l].get()); + if (!gl.enabled) + continue; + if (gl.areaSelect == gl.AREA_main && in_det) + continue; + if (gl.areaSelect == gl.AREA_det && !in_det) + continue; + + double wt = gl.calcWeight(h, angDiff, curv); + if (!lx && !ly && gl.writeDetTex && !gl.badDetTex) + LandColorGenData::blendDetTex(gl.detIdx, wt); + if (gl.writeLand1 && wt > gl.writeLand1Thres && lc1_li >= 0) + layerVal[lc1_li] = lc1_base - gl.landIdx; + if (gl.writeLand2 && wt > gl.writeLand2Thres && lc2_li >= 0) + layerVal[lc2_li] = lc2_base - gl.landIdx; + if (gl.writeImportance && impLayerIdx >= 0) + layerVal[impLayerIdx] = wt * imp_scale; + if (gl.writeDetTex && (wt >= maxPhysWeight) && (gl.landIdx < phys_li_max)) // physmat "splatting" (choose lc with biggest + // weight) + { + maxPhysWeight = wt; + physSplattingLc = gl.landIdx; + } + } + if (phys_li >= 0) + layerVal[phys_li] = physSplattingLc; + + if (!lx && !ly) + LandColorGenData::applyBlendDetTex(x, y, detIdx); + + unsigned w = 0; + if (detLayerIdx >= 0) + w = landClsLayer[detLayerIdx].setLayerData(w, + (getDetTexIdxMap() && LandColorGenData::blendTex.size()) ? LandColorGenData::blendTex[0].idx : detIdx); + + for (int l = 0; l < landClsLayer.size(); l++) + if (l != detLayerIdx) + w = landClsLayer[l].setLayerData(w, layerVal[l]); + + samples_processed++; + landClsMap.setData(x * lcmScale + lx, y * lcmScale + ly, w); + } + } + + if (!in_rect && cnt == heightMap.getElemSize()) + { + if (hasColorTex && !colorMap.flushData()) + con.addMessage(ILogWriter::ERROR, "Error writing data to color map file"); + if (!landClsMap.flushData()) + con.addMessage(ILogWriter::ERROR, "Error writing data to land-class map file"); + + heightMap.unloadUnchangedData(y + 1); + landClsMap.unloadUnchangedData(y * lcmScale + 1); + if (hasColorTex) + colorMap.unloadUnchangedData(y + 1); + } + + if (!in_rect) + con.incDone(); + } + } + catch (SquirrelError e) + { + con.addMessage(ILogWriter::ERROR, "Script error: %s", e.desc); + } + if (LandColorGenData::blendedInvalidLandClasses) + con.addMessage(ILogWriter::ERROR, "Some of empty land classes were blend as textures!"); + + if (!in_rect) + { + heightMap.unloadAllUnchangedData(); + + if (!landClsMap.flushData()) + con.addMessage(ILogWriter::ERROR, "Error writing data to land-class map file"); + if (hasColorTex && !colorMap.flushData()) + con.addMessage(ILogWriter::ERROR, "Error writing data to color map file"); + landClsMap.unloadAllUnchangedData(); + if (hasColorTex) + colorMap.unloadAllUnchangedData(); + } + + if (use_script) + { + SqPlus::SquirrelFunction endGenerator(_T("endGenerator")); + if (!endGenerator.func.IsNull()) + { + SqPlus::SquirrelFunction endGeneratorFunc(SquirrelVM::GetRootTable(), endGenerator()); + if (!endGeneratorFunc.func.IsNull()) + endGeneratorFunc(); + } + + closeColorGenScript(wasSqInited, oldPrintFunc, oldErrFunc); + } + + if (!in_rect) + con.endProgress(); + + int genTime = ::get_time_msec() - time0; + con.addMessage(ILogWriter::NOTE, "generated in %d msec (%d samples)", genTime, samples_processed); + + con.endLog(); + if (in_rect) + onLandRegionChanged((*in_rect)[0].x * lcmScale, (*in_rect)[0].y * lcmScale, (*in_rect)[1].x * lcmScale + 1, + (*in_rect)[1].y * lcmScale + 1, finished); + else + onLandRegionChanged(0, 0, landClsMap.getMapSizeX(), landClsMap.getMapSizeY(), finished); +} + + +// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ// + + +HmapLandPlugin::ScriptParam *HmapLandPlugin::getEditedScriptImage() { return editedScriptImage; } + +IHmapBrushImage::Channel HmapLandPlugin::getEditedChannel() const +{ + if (PostScriptParamLandLayer *gl = PostScriptParamLandLayer::cast(editedScriptImage)) + return IHmapBrushImage::CHANNEL_RGB; + ScriptParamImage *edImage = (ScriptParamImage *)editedScriptImage.get(); + return edImage && edImage->bitsPerPixel == 32 ? edImage->channel : IHmapBrushImage::CHANNEL_RGB; +} + + +bool HmapLandPlugin::showEditedMask() const +{ + if (PostScriptParamLandLayer *gl = PostScriptParamLandLayer::cast(editedScriptImage)) + return showBlueWhiteMask; + ScriptParamImage *edImage = (ScriptParamImage *)editedScriptImage.get(); + return edImage ? (edImage->bitsPerPixel == 32 ? edImage->showMask : showBlueWhiteMask) : true; +} + + +void HmapLandPlugin::setShowBlueWhiteMask() +{ + static int blueWhiteMaskVarId = dagGeom->getShaderVariableId("blue_white_mask_tex"); + bool show = (editedScriptImage && showEditedMask()) && showBlueWhiteMask; + if (show) + { + Color4 world_to_bw_mask; + world_to_bw_mask.r = 1.f / (esiGridW * esiGridStep); + world_to_bw_mask.g = 1.f / (esiGridH * esiGridStep); + world_to_bw_mask.b = (-esiOrigin.x + 0.5) * world_to_bw_mask.r; + world_to_bw_mask.a = (-esiOrigin.y + 0.5) * world_to_bw_mask.g; + + dagGeom->shaderGlobalSetColor4(dagGeom->getShaderVariableId("world_to_bw_mask"), world_to_bw_mask); + } + dagGeom->shaderGlobalSetTexture(blueWhiteMaskVarId, show ? bluewhiteTexId : BAD_TEXTUREID); +} + +void HmapLandPlugin::updateGenerationMask(const IBBox2 *rect) +{ + PostScriptParamLandLayer *gl = PostScriptParamLandLayer::cast(editedScriptImage); + if (!gl || editedScriptImageIdx < 0) + return; + + const char *mask_nm = gl->elcMaskList.getName(editedScriptImageIdx); + int img_idx = gl->elcMaskImageIndex; + int img_bpp = gl->elcMaskImageBpp; + if (img_bpp != 1 && img_bpp != 8) + { + DAEDITOR3.conWarning("strange mask texture <%s> bpp=%d", mask_nm, img_bpp); + return; + } + + for (int i = 0; i < genLayers.size(); i++) + { + gl = PostScriptParamLandLayer::cast(genLayers[i]); + Texture *tex = mask_nm ? HmapLandPlugin::hmlService->getDetailRenderDataMaskTex(gl->drdHandle, mask_nm) : NULL; + if (!tex) + continue; + + TextureInfo ti; + uint8_t *imgPtr; + int stride; + int x0, y0, x1, y1; + + if (!tex->getinfo(ti)) + { + DAEDITOR3.conWarning("failed to get mask texture sizes <%s>", mask_nm); + continue; + } + + if (rect) + { + x0 = clamp(int((rect->lim[0].x * gridCellSize + heightMapOffset.x - esiOrigin.x) / esiGridStep * ti.w / esiGridW), 0, ti.w - 1); + y1 = ti.h - 1 - + clamp(int((rect->lim[0].y * gridCellSize + heightMapOffset.y - esiOrigin.y) / esiGridStep * ti.h / esiGridH), 0, ti.h - 1); + x1 = clamp(int((rect->lim[1].x * gridCellSize + heightMapOffset.x - esiOrigin.x - 1) / esiGridStep * ti.w / esiGridW + 1), 0, + ti.w - 1); + y0 = ti.h - 1 - + clamp(int((rect->lim[1].y * gridCellSize + heightMapOffset.y - esiOrigin.y - 1) / esiGridStep * ti.h / esiGridH + 1), 0, + ti.h - 1); + } + else + x0 = y0 = 0, x1 = ti.w - 1, y1 = ti.h - 1; + + // fill mask texture + unsigned texLockFlags = TEXLOCK_UPDATEFROMSYSTEX | TEXLOCK_RWMASK | TEXLOCK_SYSTEXLOCK; + if (tex->lockimg((void **)&imgPtr, stride, 0, texLockFlags)) + { + imgPtr += stride * y0 + x0; + int use_stride = stride - (x1 - x0 + 1); + + switch (img_bpp) + { + case 1: + for (int y = y0; y <= y1; ++y, imgPtr += use_stride) + for (int x = x0; x <= x1; ++x, ++imgPtr) + *imgPtr = real2uchar(HmapLandPlugin::self->sampleMask1UV(img_idx, x / float(ti.w), 1.0f - y / float(ti.h))); + break; + case 8: + for (int y = y0; y <= y1; ++y, imgPtr += use_stride) + for (int x = x0; x <= x1; ++x, ++imgPtr) + *imgPtr = real2uchar(HmapLandPlugin::self->sampleMask8UV(img_idx, x / float(ti.w), 1.0f - y / float(ti.h))); + break; + } + tex->unlockimg(); + HmapLandPlugin::hmlService->updateDetailRenderData(gl->drdHandle, gl->elcLayers); + } + } +} + +void HmapLandPlugin::updateBlueWhiteMask(const IBBox2 *rect) +{ + static int blueWhiteMaskVarId = dagGeom->getShaderVariableId("blue_white_mask_tex"); + if (!(editedScriptImage && showEditedMask())) + { + setShowBlueWhiteMask(); + updateGenerationMask(rect); + hmlService->invalidateClipmap(false); + return; + } + if (bluewhiteTex) + { + TextureInfo ti; + bluewhiteTex->getinfo(ti, 0); + if (ti.w != esiGridW || ti.h != esiGridH) + { + dagGeom->shaderGlobalSetTexture(blueWhiteMaskVarId, BAD_TEXTUREID); + dagRender->releaseManagedTexVerified(bluewhiteTexId, bluewhiteTex); + } + } + if (!bluewhiteTex) + { + bluewhiteTex = d3d::create_tex(NULL, esiGridW, esiGridH, TEXFMT_L8 | TEXCF_READABLE | TEXCF_DYNAMIC, 1, "blueWhite"); + G_ASSERT(bluewhiteTex); + + bluewhiteTexId = dagRender->registerManagedTex("bluewhiteTex", bluewhiteTex); + setShowBlueWhiteMask(); + } + int x0, y0, x1, y1; + if (!rect) + { + x0 = y0 = 0; + x1 = esiGridW - 1; + y1 = esiGridH - 1; + } + else + { + x0 = clamp(int((rect->lim[0].x * gridCellSize + heightMapOffset.x - esiOrigin.x) / esiGridStep), 0, esiGridW - 1); + y0 = clamp(int((rect->lim[0].y * gridCellSize + heightMapOffset.y - esiOrigin.y) / esiGridStep), 0, esiGridH - 1); + x1 = clamp(int((rect->lim[1].x * gridCellSize + heightMapOffset.x - esiOrigin.x - 1) / esiGridStep + 1), 0, esiGridW - 1); + y1 = clamp(int((rect->lim[1].y * gridCellSize + heightMapOffset.y - esiOrigin.y - 1) / esiGridStep + 1), 0, esiGridH - 1); + } + uint8_t *imgPtr; + int stride; + + // fill color texture + unsigned texLockFlags = TEXLOCK_UPDATEFROMSYSTEX | TEXLOCK_RWMASK | TEXLOCK_SYSTEXLOCK; + if (bluewhiteTex->lockimg((void **)&imgPtr, stride, 0, texLockFlags)) + { + if (stride < x1 - x0 + 1) + { + logerr("invalid update bluewhite"); + bluewhiteTex->unlockimg(); + return; + } + + imgPtr += stride * y0 + x0; + int use_stride = stride - (x1 - x0 + 1); + for (int y = y0; y <= y1; ++y, imgPtr += use_stride) + { + for (int x = x0; x <= x1; ++x, ++imgPtr) + *imgPtr = real2uchar(getBrushImageData(x, y, getEditedChannel())); + } + + bluewhiteTex->unlockimg(); + } + + updateGenerationMask(rect); + hmlService->invalidateClipmap(false); +} + +void HmapLandPlugin::editScriptImage(ScriptParam *image, int idx) +{ + if (editedScriptImage == image && editedScriptImageIdx == idx) + image = NULL, idx = -1; + + editedScriptImage = image; + editedScriptImageIdx = idx; + + esiGridW = esiGridH = 1; + esiGridStep = 1; + esiOrigin.set(0, 0); + if (image) + { + if (PostScriptParamLandLayer *gl = PostScriptParamLandLayer::cast(editedScriptImage)) + { + IBitMaskImageMgr::BitmapMask *bm = scriptImages[gl->imageIndex]; + /*if (idx >= 0) + { + gl->elcMaskCurIdx = idx; + gl->elcMaskImageIndex = HmapLandPlugin::self->getScriptImage(gl->elcMaskList.getName(idx), 1, -1); + gl->elcMaskImageBpp = HmapLandPlugin::self->getScriptImageBpp(gl->elcMaskImageIndex); + + bm = scriptImages[gl->elcMaskImageIndex]; + + float sz = safediv(1.0f, gl->lc1.assetData->detTex->tile); + esiGridStep = min(sz/bm->getWidth(), sz/bm->getHeight()); + esiGridW = sz/esiGridStep; + esiGridH = sz/esiGridStep; + esiOrigin = -gl->lc1.assetData->detTex->offset; + } + else */ + if (gl->detRectMappedMask && hasDetaledRect()) + { + esiGridStep = min((detRect[1].x - detRect[0].x) / bm->getWidth(), (detRect[1].y - detRect[0].y) / bm->getHeight()); + esiGridW = (detRect[1].x - detRect[0].x) / esiGridStep; + esiGridH = (detRect[1].y - detRect[0].y) / esiGridStep; + esiOrigin = detRect[0]; + } + else + { + if (gl->detRectMappedMask) + DAEDITOR3.conError("mask <%s> is marked as detRectMappedMask, but detail rect is not present", gl->maskName); + esiGridStep = min(getHeightmapSizeX() * gridCellSize / bm->getWidth(), getHeightmapSizeY() * gridCellSize / bm->getHeight()); + esiGridW = getHeightmapSizeX() * gridCellSize / esiGridStep; + esiGridH = getHeightmapSizeY() * gridCellSize / esiGridStep; + esiOrigin = heightMapOffset; + } + } + else + { + esiGridW = getHeightmapSizeX() * lcmScale; + esiGridH = getHeightmapSizeY() * lcmScale; + esiGridStep = gridCellSize / lcmScale; + esiOrigin = heightMapOffset; + } + updateScriptImageList(); + + setShowBlueWhiteMask(); + if (showBlueWhiteMask) + updateBlueWhiteMask(NULL); + } + + DAGORED2->repaint(); +} + +real HmapLandPlugin::getBrushImageData(int x, int y, IHmapBrushImage::Channel channel) +{ + if (editedScriptImage) + { + if (PostScriptParamLandLayer *gl = PostScriptParamLandLayer::cast(editedScriptImage)) + return gl->getMaskDirectEx(float(x) / esiGridW, float(y) / esiGridH); + + LandColorGenData::heightMapX = x / float(lcmScale); + LandColorGenData::heightMapZ = y / float(lcmScale); + + LandColorGenData::gridCellSize = gridCellSize; + LandColorGenData::heightMapSizeX = heightMap.getMapSizeX(); + LandColorGenData::heightMapSizeZ = heightMap.getMapSizeY(); + + ScriptParamImage *edImage = (ScriptParamImage *)editedScriptImage.get(); + if (edImage->bitsPerPixel == 1) + return edImage->sampleMask1Pixel(); + else if (edImage->bitsPerPixel == 8) + return edImage->sampleMask8Pixel(); + + E3DCOLOR c = channel == IHmapBrushImage::CHANNEL_RGB ? edImage->sampleImagePixel() : edImage->sampleImagePixelTrueAlpha(); + + switch (channel) + { + case IHmapBrushImage::CHANNEL_R: return c.r / 255.0f; + case IHmapBrushImage::CHANNEL_G: return c.g / 255.0f; + case IHmapBrushImage::CHANNEL_B: return c.b / 255.0f; + case IHmapBrushImage::CHANNEL_A: return c.a / 255.0f; + } + + return (c.r + c.g + c.b) / (255.0f * 3); + } + if (!detDivisor) + return heightMap.getInitialData(x, y); + if (insideDetRectC(x, y)) + return heightMapDet.getInitialData(x, y); + return heightMap.getInitialData(x / detDivisor, y / detDivisor); +} + + +void HmapLandPlugin::setBrushImageData(int x, int y, real v, IHmapBrushImage::Channel channel) +{ + if (editedScriptImage) + { + int c = real2int(v * 255); + + if (c < 0) + c = 0; + else if (c > 255) + c = 255; + + if (PostScriptParamLandLayer *gl = PostScriptParamLandLayer::cast(editedScriptImage)) + return gl->setMaskDirectEx(float(x) / esiGridW, float(y) / esiGridH, c); + + LandColorGenData::heightMapX = x / float(lcmScale); + LandColorGenData::heightMapZ = y / float(lcmScale); + + LandColorGenData::gridCellSize = gridCellSize; + LandColorGenData::heightMapSizeX = heightMap.getMapSizeX(); + LandColorGenData::heightMapSizeZ = heightMap.getMapSizeY(); + + ScriptParamImage *edImage = (ScriptParamImage *)(ScriptParam *)editedScriptImage; + if (edImage->bitsPerPixel == 1) + return edImage->setMask1(c); + else if (edImage->bitsPerPixel == 8) + return edImage->setMask8(c); + + E3DCOLOR col = edImage->sampleImagePixelTrueAlpha(); + + switch (channel) + { + case IHmapBrushImage::CHANNEL_RGB: col = E3DCOLOR(c, c, c, col.a); break; + + case IHmapBrushImage::CHANNEL_R: col.r = c; break; + + case IHmapBrushImage::CHANNEL_G: col.g = c; break; + + case IHmapBrushImage::CHANNEL_B: col.b = c; break; + + case IHmapBrushImage::CHANNEL_A: col.a = c; break; + } + + edImage->paintImage(col); + return; + } + + if (!detDivisor) + heightMap.setInitialData(x, y, v); + else if (insideDetRectC(x, y)) + { + heightMapDet.setInitialData(x, y, v); + if (x == detRectC[0].x || y == detRectC[0].y || x == detRectC[1].x - 1 || y == detRectC[1].y - 1) + if ((x % detDivisor) + (y % detDivisor) == 0) + heightMap.setInitialData(x / detDivisor, y / detDivisor, v); + } + else if ((x % detDivisor) + (y % detDivisor) == 0) + heightMap.setInitialData(x / detDivisor, y / detDivisor, v); +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlHoleObject.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlHoleObject.cpp new file mode 100644 index 000000000..c8bedd646 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlHoleObject.cpp @@ -0,0 +1,259 @@ +#include "hmlHoleObject.h" +#include "hmlCm.h" +#include "common.h" + +#include +#include + +#include + + +HmapLandHoleObject::HmapLandHoleObject() : boxSize(1, 1, 1) +{ + normal_color = E3DCOLOR(200, 10, 10); + selected_color = E3DCOLOR(255, 255, 255); +} + + +void HmapLandHoleObject::update(real dt) {} + + +void HmapLandHoleObject::beforeRender() {} + + +void HmapLandHoleObject::render() +{ + BBox3 box; + getWorldBox(box); + + dagRender->setLinesTm(TMatrix::IDENT); + dagRender->renderBox(box, isSelected() ? selected_color : normal_color); +} + + +void HmapLandHoleObject::renderTrans() {} + + +void HmapLandHoleObject::buildBoxEdges(IGenViewportWnd *vp, Point2 edges[12][2]) const +{ + BBox3 box; + getWorldBox(box); + + Point2 verts[2][2][2]; + + for (int i = 0; i < 2; ++i) + for (int j = 0; j < 2; ++j) + for (int k = 0; k < 2; ++k) + vp->worldToClient(Point3(box[i].x, box[j].y, box[k].z), verts[i][j][k]); + + for (int i = 0; i < 2; ++i) + for (int j = 0; j < 2; ++j) + { + edges[i * 2 + j + 0][0] = verts[0][i][j]; + edges[i * 2 + j + 0][1] = verts[1][i][j]; + } + + for (int i = 0; i < 2; ++i) + for (int j = 0; j < 2; ++j) + { + edges[i * 2 + j + 4][0] = verts[i][0][j]; + edges[i * 2 + j + 4][1] = verts[i][1][j]; + } + + for (int i = 0; i < 2; ++i) + for (int j = 0; j < 2; ++j) + { + edges[i * 2 + j + 8][0] = verts[i][j][0]; + edges[i * 2 + j + 8][1] = verts[i][j][1]; + } +} + + +bool HmapLandHoleObject::isSelectedByRectangle(IGenViewportWnd *vp, const EcRect &rect) const +{ + Point2 edges[12][2]; + buildBoxEdges(vp, edges); + + BBox2 rectBox; + int r = 2; + rectBox[0].x = rect.l - r; + rectBox[1].x = rect.r + r; + rectBox[0].y = rect.t - r; + rectBox[1].y = rect.b + r; + + for (int i = 0; i < 12; ++i) + if (::isect_line_segment_box(edges[i][0], edges[i][1], rectBox)) + return true; + + return false; +} + + +bool HmapLandHoleObject::isSelectedByPointClick(IGenViewportWnd *vp, int x, int y) const +{ + Point2 edges[12][2]; + buildBoxEdges(vp, edges); + + Point2 p(x, y); + + for (int i = 0; i < 12; ++i) + if (::distance_point_to_line_segment(p, edges[i][0], edges[i][1]) < 3) + return true; + + return false; +} + + +bool HmapLandHoleObject::getWorldBox(BBox3 &box) const +{ + Point3 center = getPos(); + + Point3 size; + size.x = fabsf(boxSize.x); + size.y = fabsf(boxSize.y); + size.z = fabsf(boxSize.z); + + box[0] = center - size * 0.5f; + box[1] = center + size * 0.5f; + return true; +} + + +void HmapLandHoleObject::save(DataBlock &blk) +{ + blk.setStr("name", getName()); + blk.setPoint3("pos", getPos()); + blk.setPoint3("boxSize", boxSize); +} + + +void HmapLandHoleObject::load(const DataBlock &blk) +{ + getObjEditor()->setUniqName(this, blk.getStr("name", "HoleBox")); + setPos(blk.getPoint3("pos", getPos())); + boxSize = blk.getPoint3("boxSize", boxSize); +} + + +class UndoHmapLandObjectParams : public UndoRedoObject +{ +public: + struct Params + { + Point3 boxSize; + + void getFrom(HmapLandHoleObject *o) + { + boxSize = o->getBoxSize(); + o->getObjEditor()->invalidateObjectProps(); + } + + void setTo(HmapLandHoleObject *o) + { + o->setBoxSize(boxSize); + o->getObjEditor()->invalidateObjectProps(); + if (HmapLandPlugin::self) + HmapLandPlugin::self->invalidateRenderer(); + } + }; + + Ptr object; + Params undoParams, redoParams; + + + UndoHmapLandObjectParams(HmapLandHoleObject *o) : object(o) + { + undoParams.getFrom(object); + redoParams.getFrom(object); + } + + virtual void restore(bool save_redo) + { + if (save_redo) + redoParams.getFrom(object); + undoParams.setTo(object); + } + + virtual void redo() { redoParams.setTo(object); } + + virtual size_t size() { return sizeof(*this); } + virtual void accepted() {} + virtual void get_description(String &s) { s = "UndoHmapLandObjectParams"; } +}; + + +void HmapLandHoleObject::fillProps(PropPanel2 &panel, DClassID for_class_id, dag::ConstSpan objects) +{ + panel.createEditFloat(PID_BOX_SIZE_X, "Box size X:", boxSize.x); + panel.createEditFloat(PID_BOX_SIZE_Y, "Box size Y (visual):", boxSize.y); + panel.createEditFloat(PID_BOX_SIZE_Z, "Box size Z:", boxSize.z); + + for (int i = 0; i < objects.size(); ++i) + { + HmapLandHoleObject *o = RTTI_cast(objects[i]); + if (!o) + continue; + + if (o->boxSize.x != boxSize.x) + panel.resetById(PID_BOX_SIZE_X); + if (o->boxSize.y != boxSize.y) + panel.resetById(PID_BOX_SIZE_Y); + if (o->boxSize.z != boxSize.z) + panel.resetById(PID_BOX_SIZE_Z); + } +} + + +void HmapLandHoleObject::onPPChange(int pid, bool edit_finished, PropPanel2 &panel, dag::ConstSpan objects) +{ +#define CHANGE_VAL(type, pname, getfunc) \ + { \ + if (!edit_finished) \ + return; \ + type val = panel.getfunc(pid); \ + if (fabsf(val) < 1e-6) \ + val = 1; \ + for (int i = 0; i < objects.size(); ++i) \ + { \ + HmapLandHoleObject *o = (HmapLandHoleObject *)objects[i]; \ + getObjEditor()->getUndoSystem()->put(new UndoHmapLandObjectParams(o)); \ + o->pname = val; \ + } \ + HmapLandPlugin::self->resetRenderer(); \ + } + + if (pid == PID_BOX_SIZE_X) + CHANGE_VAL(float, boxSize.x, getFloat) + else if (pid == PID_BOX_SIZE_Y) + CHANGE_VAL(float, boxSize.y, getFloat) + else if (pid == PID_BOX_SIZE_Z) + CHANGE_VAL(float, boxSize.z, getFloat) + + setBoxSize(boxSize); + + // else __super::onPPChange(pid, edit_finished, panel, objects); + +#undef CHANGE_VAL +} + +void HmapLandHoleObject::scaleObject(const Point3 &delta, const Point3 &origin, IEditorCoreEngine::BasisType basis) +{ + __super::scaleObject(delta, origin, basis); + + boxSize.x = matrix.getcol(0).x; + boxSize.y = matrix.getcol(1).y; + boxSize.z = matrix.getcol(2).z; + + objectWasScaled = true; +} + +void HmapLandHoleObject::setBoxSize(Point3 &s) +{ + boxSize = s; + Point3 pos = getPos(); + + matrix.setcol(0, Point3(s.x, 0, 0)); + matrix.setcol(1, Point3(0, s.y, 0)); + matrix.setcol(2, Point3(0, 0, s.z)); + matrix.setcol(3, pos); +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlHoleObject.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlHoleObject.h new file mode 100644 index 000000000..330b16a37 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlHoleObject.h @@ -0,0 +1,55 @@ +#pragma once + + +#include "hmlPlugin.h" + +#include + + +static constexpr unsigned CID_HmapLandHoleObject = 0xB00BA8AFu; // HmapLandHoleObject +static const int HMAP_TYPE_HOLE = 0; + + +class DataBlock; + + +class HmapLandHoleObject : public RenderableEditableObject +{ +public: + Point3 boxSize; + + HmapLandHoleObject(); + + virtual void update(real dt); + virtual void beforeRender(); + virtual void render(); + virtual void renderTrans(); + + virtual bool isSelectedByRectangle(IGenViewportWnd *vp, const EcRect &rect) const; + virtual bool isSelectedByPointClick(IGenViewportWnd *vp, int x, int y) const; + virtual bool getWorldBox(BBox3 &box) const; + + virtual void fillProps(PropPanel2 &panel, DClassID for_class_id, dag::ConstSpan objects); + + virtual void onPPChange(int pid, bool edit_finished, PropPanel2 &panel, dag::ConstSpan objects); + + virtual void rotateObject(const Point3 &delta, const Point3 &origin, IEditorCoreEngine::BasisType basis) {} + + virtual void scaleObject(const Point3 &delta, const Point3 &origin, IEditorCoreEngine::BasisType basis); + + virtual void putRotateUndo() {} + + virtual void save(DataBlock &blk); + virtual void load(const DataBlock &blk); + + + EO_IMPLEMENT_RTTI(CID_HmapLandHoleObject) + + + void buildBoxEdges(IGenViewportWnd *vp, Point2 edges[12][2]) const; + void setBoxSize(Point3 &s); + Point3 getBoxSize() { return boxSize; } + + + E3DCOLOR normal_color, selected_color; +}; diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlIGenEditorPlugin.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlIGenEditorPlugin.cpp new file mode 100644 index 000000000..bc6302d3d --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlIGenEditorPlugin.cpp @@ -0,0 +1,6772 @@ +#include "hmlPlugin.h" +#include "hmlCm.h" +#include "hmlPanel.h" + +#include "hmlExportSizeDlg.h" +#include "hmlSplineObject.h" +#include "hmlSplinePoint.h" +#include "hmlEntity.h" + +#include "Brushes/hmlBrush.h" +#include "landClassSlotsMgr.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include "editorLandRayTracer.h" + +#include <3d/dag_render.h> +#include <3d/dag_drv3d.h> +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include + +#include + +#include +#include "common.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include "renderLandNormals.h" + +#include + +using hdpi::_pxScaled; + +extern bool allow_debug_bitmap_dump; + + +#define HEIGHTMAP_FILENAME "heightmap.dat" +#define LANDCLSMAP_FILENAME "landclsmap.dat" +#define COLORMAP_FILENAME "colormap.dat" +#define LIGHTMAP_FILENAME "lightmap.dat" +#define DETTEXMAP_FILENAME "detTexIdx.dat" +#define DETTEXWMAP_FILENAME "detTexWt.dat" +#define WATER_HEIGHTMAP_DET_FILENAME "waterHeightmapDet.dat" +#define WATER_HEIGHTMAP_MAIN_FILENAME "waterHeightmapMain.dat" + +#define BLUR_LM_KEREL_SIZE 1 +#define BLUR_LM_SIGMA 0.7 + + +static class DefNewHMParams +{ +public: + Point2 sizePixels; + Point2 sizeMeters; + real cellSize; + real heightScale; + real heightOffset; + Point2 originOffset; + Point2 collisionOffset; + Point2 collisionSize; + bool collisionShow; + bool doAutocenter; + IPoint2 tileTexSz; + String scriptPath; + String tileTex; + + DefNewHMParams() : + sizePixels(1024, 1024), + sizeMeters(1024, 1024), + cellSize(1.0), + heightScale(200.0), + heightOffset(0.0), + originOffset(0, 0), + collisionOffset(0, 0), + collisionSize(100, 100), + tileTexSz(32, 32), + collisionShow(false), + doAutocenter(true) + { + originOffset = -sizeMeters * cellSize / 2; + } +} defaultHM; + + +static bool ignoreEvents = true; +static int transformZVarId = -1; +static int znZfarVarId = -1; +static int landTileVerticalTexVarId = -1; +static int landTileVerticalNmTexVarId = -1; +static int landTileVerticalDetTexVarId = -1; + +static bool skipExportLtmap = false; +static bool missing_tile_reported = false; + +static void setZTransformPersp(float zn, float zf) +{ + if (transformZVarId < 0) + return; + float q = zf / (zf - zn); + dagGeom->shaderGlobalSetColor4(transformZVarId, Color4(q, 1, -zn * q, 0)); + dagGeom->shaderGlobalSetColor4(znZfarVarId, Color4(zn, zf, 0, 0)); +} + +static bool is_tga_or_tiff(const char *fn) +{ + return trail_stricmp(fn, ".tga") || trail_stricmp(fn, ".tif") || trail_stricmp(fn, ".tiff"); +} + +static TexImage32 *load_tga_or_tiff(const char *fn, IMemAlloc *mem) +{ + if (trail_stricmp(fn, ".tga")) + return load_tga32(fn, mem); + else + return load_tiff32(fn, mem); +} + +static TexImage32 *try_find_and_load_tga_or_tiff(const char *fn, IMemAlloc *mem) +{ + String fnWithExt(256, "%s.tif", fn); + TexImage32 *image = load_tiff32(fnWithExt, mem); + if (image) + return image; + + fnWithExt.printf(256, "%s.tiff", fn); + image = load_tiff32(fnWithExt, mem); + if (image) + return image; + + fnWithExt.printf(256, "%s.tga", fn); + return load_tga32(fnWithExt, mem); +} + +// IGenEditorPlugin +//============================================================================== +void HmapLandPlugin::registered() +{ +#define REGISTER_COMMAND(cmd_name) \ + if (!dagConsole->registerCommand(DAGORED2->getConsole(), cmd_name, this)) \ + DAEDITOR3.conError("[%s] Couldn't register command '" cmd_name "'", getMenuCommandName()) + REGISTER_COMMAND("land.ltmap"); + REGISTER_COMMAND("land.rebuild_colors"); + REGISTER_COMMAND("land.commit_changes"); +#undef REGISTER_COMMAND + + znZfarVarId = dagGeom->getShaderVariableId("zn_zfar"); + transformZVarId = dagGeom->getShaderVariableId("transform_z"); + + + clear_and_resize(brushes, BRUSHES_COUNT); + brushes[HILLUP_BRUSH] = heightmap_land::getUpHillBrush(this, *this); + brushes[HILLDOWN_BRUSH] = heightmap_land::getDownHillBrush(this, *this); + brushes[SMOOTH_BRUSH] = heightmap_land::getSmoothBrush(this, *this); + brushes[ALIGN_BRUSH] = heightmap_land::getAlignBrush(this, *this); + brushes[SHADOWS_BRUSH] = heightmap_land::getShadowsBrush(this, *this); + brushes[SCRIPT_BRUSH] = heightmap_land::getScriptBrush(this, *this); + + DAGORED2->registerCustomCollider(this); + DAGORED2->registerCustomCollider(&objEd); + DAGORED2->registerCustomCollider(&objEd.loftGeomCollider); + DAGORED2->registerCustomCollider(&objEd.polyGeomCollider); + + if (hmapSubtypeMask == -1) + hmapSubtypeMask = 1 << IDaEditor3Engine::get().registerEntitySubTypeId("hmap_obj"); + + if (lmeshSubtypeMask == -1) + lmeshSubtypeMask = 1 << IDaEditor3Engine::get().registerEntitySubTypeId("lmesh_obj"); + + if (lmeshDetSubtypeMask == -1) + lmeshDetSubtypeMask = 1 << IDaEditor3Engine::get().registerEntitySubTypeId("lmesh_obj_det"); + + if (grasspSubtypeMask == -1) + grasspSubtypeMask = 1 << IDaEditor3Engine::get().registerEntitySubTypeId("grass_obj"); + + if (navmeshSubtypeMask == -1) + navmeshSubtypeMask = 1 << IDaEditor3Engine::get().registerEntitySubTypeId("navmesh"); + + + snowPrevievSVId = dagGeom->getShaderVariableId("snow_preview_mode"); + snowValSVId = dagGeom->getShaderVariableId("snow_preview_avg_level"); + landTileVerticalTexVarId = dagGeom->getShaderVariableId("vertical_tex"); + landTileVerticalNmTexVarId = dagGeom->getShaderVariableId("vertical_nm_tex"); + landTileVerticalDetTexVarId = dagGeom->getShaderVariableId("vertical_det_tex"); +} + + +//============================================================================== +void HmapLandPlugin::unregistered() +{ + if (IRendInstGenService *rigenSrv = DAGORED2->queryEditorInterface()) + { + rigenSrv->clearRtRIGenData(); + rigenSrv->setCustomGetHeight(NULL); + } + dagConsole->unregisterCommand(DAGORED2->getConsole(), "land.ltmap", this); + dagConsole->unregisterCommand(DAGORED2->getConsole(), "land.rebuild_colors", this); + dagConsole->unregisterCommand(DAGORED2->getConsole(), "land.commit_changes", this); + DAGORED2->unregisterCustomCollider(&objEd.polyGeomCollider); + DAGORED2->unregisterCustomCollider(&objEd.loftGeomCollider); + DAGORED2->unregisterCustomCollider(&objEd); + DAGORED2->unregisterCustomCollider(this); + + hmlService->destroyLandMeshRenderer(landMeshRenderer); + hmlService->destroyLandMeshManager(landMeshManager); + + heightMap.closeFile(); + landClsMap.closeFile(); + colorMap.closeFile(); + lightMapScaled.closeFile(); + waterHeightmapDet.closeFile(); + waterHeightmapMain.closeFile(); + + if (detTexIdxMap) + detTexIdxMap->closeFile(); + if (detTexWtMap) + detTexWtMap->closeFile(); + + for (int i = 0; i < brushes.size(); ++i) + del_it(brushes[i]); + + clear_and_shrink(brushes); + objEd.unloadRoadBuilderDll(); + + self = NULL; +} + +bool HmapLandPlugin::onConsoleCommand(const char *cmd, dag::ConstSpan params) +{ + CoolConsole &con = DAGORED2->getConsole(); + + if (!stricmp(cmd, "land.ltmap")) + { + int errCnt = con.getErrorsCount() + con.getFatalsCount(); + if (params.size() == 1) + skipExportLtmap = true; + calcGoodLandLighting(); + if (params.size() == 1) + resetRenderer(); + skipExportLtmap = false; + + if (params.size() == 1) + { + unsigned target = _MAKE4C('DDS'); + if (stricmp(dd_get_fname_ext(params[0]), ".tga") == 0) + target = _MAKE4C('TGA'); + + String prj(DAGORED2->getSdkDir()); + exportLightmapToFile(::make_full_path(prj, params[0]), target, true); + } + return con.getErrorsCount() + con.getFatalsCount() == errCnt; + } + if (!stricmp(cmd, "land.rebuild_colors")) + { + DAEDITOR3.conNote("batch cmd: rebuild HMAP colors"); + onPluginMenuClick(CM_REBUILD); + return true; + } + if (!stricmp(cmd, "land.commit_changes")) + { + DAEDITOR3.conNote("batch cmd: commit HMAP changes"); + onPluginMenuClick(CM_COMMIT_HM_CHANGES); + return true; + } + + return false; +} + + +const char *HmapLandPlugin::onConsoleCommandHelp(const char *cmd) +{ + if (!stricmp(cmd, "land.ltmap")) + return "Type:\n" + "'land.ltmap [file_path]' to calculate and save lightmaps;\n" + "optional file_path is relative to develop;\n" + "with no file_path builtScene/lightmap.dds is saved.\n"; + + if (!stricmp(cmd, "land.rebuild_colors")) + return "Type:\n" + "'land.rebuild_colors'\n" + "to rebuild colors/lighting/detailmaps for landmesh/heightmap in Landscape plugin"; + + if (!stricmp(cmd, "land.commit_changes")) + return "Type:\n" + "'land.commit_changes'\n" + "to save DAT files in Landscape plugin"; + + return NULL; +} + +//============================================================================== +bool HmapLandPlugin::begin(int toolbar_id, unsigned menu_id) +{ + createMenu(menu_id); + toolbarId = toolbar_id; + createPropPanel(); + + PropertyContainerControlBase *toolbar = DAGORED2->getCustomPanel(toolbar_id); + G_ASSERT(toolbar); + objEd.initUi(toolbar_id); + // objEd.objectPropBar->hidePanel(); + + IWndManager *manager = IEditorCoreEngine::get()->getWndManager(); + manager->registerWindowHandler(this); + + + if (propPanel) // && (objEd.toolBar->isButtonChecked(CM_SHOW_PANEL))) + propPanel->showPropPanel(true); + + brushDlg = DAGORED2->createDialog(_pxScaled(220), _pxScaled(440), "Heightmap brush"); + brushDlg->showButtonPanel(false); + PropertyContainerControlBase *_panel = brushDlg->getPanel(); + _panel->setEventHandler(this); + + updateSnowSources(); + + return true; +} + + +//============================================================================== +bool HmapLandPlugin::end() +{ + if (propPanel->isVisible()) + propPanel->showPropPanel(false); + + IWndManager *manager = IEditorCoreEngine::get()->getWndManager(); + manager->unregisterWindowHandler(this); + + objEd.closeUi(); + DAGORED2->endBrushPaint(); + objEd.setEditMode(CM_OBJED_MODE_SELECT); + return true; +} + + +//============================================================================== + + +IWndEmbeddedWindow *HmapLandPlugin::onWmCreateWindow(void *handle, int type) +{ + switch (type) + { + case PROPBAR_EDITOR_WTYPE: + { + if (propPanel->getPanelWindow()) + return NULL; + + IWndManager *manager = IEditorCoreEngine::get()->getWndManager(); + manager->setCaption(handle, "Properties"); + + CPanelWindow *_panel_window = IEditorCoreEngine::get()->createPropPanel(this, handle); + + if (_panel_window) + { + propPanel->setPanelWindow(_panel_window); + _panel_window->setEventHandler(propPanel); + propPanel->fillPanel(false); + } + + PropertyContainerControlBase *tool_bar = DAGORED2->getCustomPanel(toolbarId); + if (tool_bar) + tool_bar->setBool(CM_SHOW_PANEL, true); + + return propPanel->getPanelWindow(); + } + break; + } + + return NULL; +} + + +bool HmapLandPlugin::onWmDestroyWindow(void *handle) +{ + if (propPanel->getPanelWindow() && propPanel->getPanelWindow()->getParentWindowHandle() == handle) + { + mainPanelState.reset(); + propPanel->getPanelWindow()->saveState(mainPanelState); + + CPanelWindow *_panel_window = propPanel->getPanelWindow(); + propPanel->setPanelWindow(NULL); + + IEditorCoreEngine::get()->deleteCustomPanel(_panel_window); + + PropertyContainerControlBase *tool_bar = DAGORED2->getCustomPanel(toolbarId); + if (tool_bar) + tool_bar->setBool(CM_SHOW_PANEL, false); + + return true; + } + + return false; +} + +//============================================================================== + + +// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ// + +void HmapLandPlugin::updateHtLevelCurves() +{ + static int heightmap_show_level_curves_gvid = dagGeom->getShaderVariableId("heightmap_show_level_curves"); + static int heightmap_level_curves_params_gvid = dagGeom->getShaderVariableId("heightmap_level_curves_params"); + dagGeom->shaderGlobalSetInt(heightmap_show_level_curves_gvid, showHtLevelCurves ? 1 : 0); + dagGeom->shaderGlobalSetColor4(heightmap_level_curves_params_gvid, + Color4(htLevelCurveStep, htLevelCurveThickness * 0.5f, htLevelCurveOfs, 1.0f - htLevelCurveDarkness)); +} + +void HmapLandPlugin::updateRendererLighting() +{ + genHmap->sunColor = ldrLight.getSunLightColor(); + genHmap->skyColor = ldrLight.getSkyLightColor(); + DAGORED2->repaint(); +} + + +void HmapLandPlugin::resetRenderer(bool imm) +{ + if (imm) + delayedResetRenderer(); + else + pendingResetRenderer = true; +} + + +bool HmapLandPlugin::loadLevelSettingsBlk(DataBlock &level_blk) +{ + String fn(0, "levels/%s", DAGORED2->getProjectFileName()); + String app_root(DAGORED2->getWorkspace().getAppDir()); + DataBlock appblk(String(260, "%s/application.blk", app_root)); + + class LevelsFolderIncludeFileResolver : public DataBlock::IIncludeFileResolver + { + public: + LevelsFolderIncludeFileResolver() : prefix(tmpmem), appDir(NULL) {} + virtual bool resolveIncludeFile(String &inout_fname) + { + String fn; + for (int i = 0; i < prefix.size(); i++) + { + fn.printf(0, "%s/%s/levels/%s", appDir, prefix[i], inout_fname); + if (dd_file_exists(fn)) + { + inout_fname = fn; + return true; + } + } + return false; + } + void preparePrefixes(const DataBlock *b, const char *app_dir) + { + prefix.clear(); + appDir = app_dir; + if (!b) + return; + for (int i = 0; i < b->paramCount(); i++) + if (b->getParamType(i) == DataBlock::TYPE_STRING) + prefix.push_back(b->getStr(i)); + } + Tab prefix; + const char *appDir; + }; + static LevelsFolderIncludeFileResolver inc_resv; + + inc_resv.preparePrefixes(appblk.getBlockByName("levelsBlkPrefix"), app_root); + DataBlock::setIncludeResolver(&inc_resv); + + while (char *p = (char *)dd_get_fname_ext(fn)) + *p = '\0'; + fn.updateSz(); + fn += ".blk"; + + debug("Loading level settings from \"%s\"", fn); + bool loaded = false; + int prefix_tried = 0; + for (int i = 0; i < inc_resv.prefix.size(); i++) + { + String fpath(0, "%s/%s/%s", app_root, inc_resv.prefix[i], fn); + if (dd_file_exists(fpath) && level_blk.load(fpath)) + { + loaded = true; + levelBlkFName = fpath; + break; + } + else + { + debug("%s is %s", fpath, dd_file_exists(fpath) ? "CORRUPT" : "MISSING"); + prefix_tried++; + } + } + + if (!loaded) + { + loaded = level_blk.load(fn); + if (loaded) + levelBlkFName = fn; + } + if (!loaded && DAGORED2->getExportPath(_MAKE4C('PC')) && + appblk.getBlockByNameEx("levelsBlkPrefix")->getBool("useExportBinPath", false)) + { + String fn; + fn = DAGORED2->getExportPath(_MAKE4C('PC')); + if (!fn.empty()) + { + while (char *p = (char *)dd_get_fname_ext(fn)) + *p = '\0'; + fn.updateSz(); + fn += ".blk"; + debug("try export path level blk %s", fn); + loaded = level_blk.load(fn); + if (loaded) + levelBlkFName = fn; + } + } + + if (!loaded) + DAEDITOR3.conWarning("cannot load %s (tried also with %d prefixes)", fn, prefix_tried); + hmlService->onLevelBlkLoaded(loaded ? level_blk : DataBlock()); + if (IRendInstGenService *rendInstGenService = DAGORED2->queryEditorInterface()) + rendInstGenService->onLevelBlkLoaded(loaded ? level_blk : DataBlock()); + + DataBlock::setRootIncludeResolver(app_root); + return loaded; +} + +void HmapLandPlugin::updateWaterSettings(const DataBlock &level_blk) +{ + if (!waterService) + return; + + waterService->set_level(level_blk.getReal("water_level", 0.f)); + + Point2 windDir(0.6, 0.8); + windDir = level_blk.getPoint2("windDir", windDir); + const DataBlock *weatherTypeBlk = NULL; + if (ISkiesService *skiesSrv = DAGORED2->queryEditorInterface()) + weatherTypeBlk = skiesSrv->getWeatherTypeBlk(); + + float stormStrength = (weatherTypeBlk ? weatherTypeBlk->getReal("wind_strength", 4) : 4) * level_blk.getReal("wind_scale", 1); + stormStrength = min(stormStrength, level_blk.getReal("max_wind_strength", 6)); + stormStrength = max(stormStrength, 1.0f); + waterService->set_wind(stormStrength, windDir); + + BBox2 water3DQuad; + water3DQuad[0] = level_blk.getPoint2("waterCoord0", Point2(-256000, -256000)); + water3DQuad[1] = level_blk.getPoint2("waterCoord1", Point2(+256000, +256000)); + waterService->set_render_quad(water3DQuad.width().x < 128000 ? water3DQuad : BBox2()); +} + +void HmapLandPlugin::rebuildLandmeshDump() +{ + if (lmDump) + lmDump->deleteChain(lmDump); + lmDump = NULL; + + mkbindump::BinDumpSaveCB cwr(32 << 20, _MAKE4C('PC'), false); + if (!exportLandMesh(cwr, NULL, NULL, true)) + DAEDITOR3.conError("exportLandMesh failed"); + else + lmDump = cwr.getRawWriter().takeMem(); +} +void HmapLandPlugin::rebuildLandmeshManager() +{ + hmlService->destroyLandMeshRenderer(landMeshRenderer); + hmlService->destroyLandMeshManager(landMeshManager); + if (lmDump) + { + MemoryLoadCB crd(lmDump, false); + landMeshManager = hmlService->createLandMeshManager(crd); + if (const IBBox2 *b = getExclCellBBox()) + { + landMeshManager->cullingState.useExclBox = true; + landMeshManager->cullingState.exclBox[0] = b->lim[0] + landMeshManager->getCellOrigin(); + landMeshManager->cullingState.exclBox[1] = b->lim[1] + landMeshManager->getCellOrigin(); + } + else + landMeshManager->cullingState.useExclBox = false; + } + clearTexCache(); +} +void HmapLandPlugin::delayedResetRenderer() +{ + if (!hmlService) + return; + hmlService->destroyLandMeshRenderer(landMeshRenderer); + if (!cableService) + cableService = DAGORED2->queryEditorInterface(); + if (exportType == EXPORT_PSEUDO_PLANE) + { + pendingResetRenderer = false; + return; + } + + if (render.gridStep < 1) + render.gridStep = 1; + if (render.elemSize < 2) + render.elemSize = 2; + if (render.radiusElems < 1) + render.radiusElems = 1; + if (render.ringElems < 1) + render.ringElems = 1; + if (render.numLods < 0) + render.numLods = 0; + if (render.maxDetailLod < 0) + render.maxDetailLod = 0; + if (render.maxDetailLod > render.numLods) + render.maxDetailLod = render.numLods; + if (!float_nonzero(render.detailTile)) + render.detailTile = 1; + if (!float_nonzero(render.canyonHorTile)) + render.canyonHorTile = 1; + if (!float_nonzero(render.canyonVertTile)) + render.canyonVertTile = 1; + if (render.holesLod < 0) + render.holesLod = 0; + if (render.holesLod > render.numLods) + render.holesLod = render.numLods; + + String fn; + if (heightMap.isFileOpened()) + { + getTexEntry(tileTexName, &fn, NULL); + + if (strchr(fn, '*') || ::dd_file_exist(fn)) + tileTexId = dagRender->addManagedTexture(fn); + else if (DAGORED2->isInBatchOp() && requireTileTex) + { + tileTexId = BAD_TEXTUREID; + DAEDITOR3.conError("HeightMap tile texture is missing!"); + } + else if (requireTileTex) + { + tileTexId = BAD_TEXTUREID; + if (!missing_tile_reported) + DAEDITOR3.conError("HeightMap tile texture is missing!"); + else + { + wingw::message_box(wingw::MBS_HAND, "Error", "HeightMap tile texture is missing <%s>!", fn); + missing_tile_reported = true; + } + } + } + + if (loadLevelSettingsBlk(levelBlk)) + { + dagGeom->shaderGlobalSetVarsFromBlk(*levelBlk.getBlockByNameEx("shader_vars")); + loadGPUGrassFromBlk(levelBlk); + loadGrassFromBlk(levelBlk); + } + + if (ISkiesService *skiesSrv = DAGORED2->queryEditorInterface()) + skiesSrv->overrideWeather(0, NULL, NULL, -1, NULL, levelBlk.getBlockByNameEx("stars")); + + if (useMeshSurface && !landMeshMap.isEmpty() && lmDump) + { + // prepareEditableLandClasses(); + + int texElemSize, texSize; + + texElemSize = real2int(landMeshMap.getCellSize() / gridCellSize); + for (texSize = 1; texSize < texElemSize; texSize <<= 1) + ; + + render.detMapSize = texSize; + render.detMapElemSize = texElemSize; + int landTypeId = DAEDITOR3.getAssetTypeId("land"); + /*landClassInfo.clear(); + landClassInfo.resize(detailTexBlkName.size()); + const DataBlock &grass_blk = *level_blk.getBlockByNameEx("randomGrass"); + for (int i = 0; i < landClassInfo.size(); ++i) + { + landClassInfo[i].editorId = i; + DagorAsset *asset = DAEDITOR3.getAssetByName(detailTexBlkName[i], landTypeId); + if (!asset) + continue; + const DataBlock *blk = asset->props.getBlockByName("detail"); + if (!blk) + continue; + load_land_class_info(landClassInfo[i], *blk, LC_ALL_DATA); + landClassInfo[i].editorId = i; + landClassInfo[i].name = detailTexBlkName[i].str(); + if (blk->getStr("detailmap", NULL) && blk->getStr("splattingmap", NULL)) + { + DAEDITOR3.conError("Ambiguos landclass = <%s>, it has both splattingmap and detailmap!", detailTexBlkName[i].str()); + } + }*/ + + if (!landMeshManager) + rebuildLandmeshManager(); + + G_ASSERT(landMeshManager); + landMeshRenderer = hmlService->createLandMeshRenderer(*landMeshManager); + + lcRemap.resize(detailTexBlkName.size()); + mem_set_ff(lcRemap); + for (int i = 0; i < landMeshManager->getLCCount(); i++) + lcRemap[landMeshManager->getLCEditorId(i)] = i; + + // fixme: check if landclasses has same colormap (in landmesh via debug callback) + /*for (int i = 0; i < landClasses.size(); ++i) + { + if (landClasses[i].colormapId == BAD_TEXTUREID) + continue; + int j; + for (j = i+1; j < landClasses.size(); ++j) + if (landClasses[i].colormapId == landClasses[j].colormapId) + break; + if (j < landClasses.size()) + DAEDITOR3.conWarning( + "two different landclasses %d<%s> and %d<%s> has same colormap = <%s>", i, detailTexBlkName[i].str(), + j, detailTexBlkName[j].str(), landInfo[i].colormapName); + }*/ + + if (!landMeshRenderer) + { + DAEDITOR3.conError("cannot create landMesh renderer (shader is missing?), switched to pseudo-plane"); + exportType = EXPORT_PSEUDO_PLANE; + genHmap->altCollider = NULL; + pendingResetRenderer = false; + if (propPanel) + propPanel->getPanelWindow()->setInt(PID_HM_EXPORT_TYPE, exportType); + return; + } + + G_ASSERT(landMeshRenderer->checkVerLabel()); + + + if (!grassService) + { + grassService = DAGORED2->queryEditorInterface(); + if (grassService) + { + if (grassBlk != NULL) + { + grassService->create_grass(*grassBlk); + grassService->enableGrass(enableGrass); + } + else + grassBlk = grassService->create_default_grass(); + loadGrassFromBlk(*grassBlk); + loadGrassLayers(*grassBlk, false); + } + } + + if (!gpuGrassService) + { + gpuGrassService = DAGORED2->queryEditorInterface(); + if (gpuGrassService) + { + if (gpuGrassBlk != nullptr) + { + gpuGrassService->createGrass(*gpuGrassBlk); + gpuGrassService->enableGrass(enableGrass); + } + else + gpuGrassBlk = gpuGrassService->createDefaultGrass(); + + loadGPUGrassFromBlk(*gpuGrassBlk); + } + } + + if (!waterProjectedFxSrv) + waterProjectedFxSrv = DAGORED2->queryEditorInterface(); + + + if (!waterService) + { + waterService = DAGORED2->queryEditorInterface(); + if (waterService) + waterService->loadSettings(DataBlock()); + } + + if (waterService) + { + bool has_water = hasWaterSurf(); + + for (int i = 0; i < objEd.objectCount(); i++) + if (SplineObject *o = RTTI_cast(objEd.getObject(i))) + if (o->isPoly() && o->polyGeom.altGeom) + has_water = true; + + if (!has_water) + if (IGenEditorPlugin *p = DAGORED2->getPluginByName("_waterSurf")) + p->setVisible(false); + + updateWaterSettings(levelBlk); + } + + hmlService->updatePropertiesFromLevelBlk(levelBlk); + + SunSkyLight < = ldrLight; + + refillTexCache(); + updateVertTex(); + } + + if (heightMap.isFileOpened()) + { + int texElemSize, texSize; + + texElemSize = (render.elemSize * render.gridStep) << render.maxDetailLod; + for (texSize = 1; texSize < texElemSize; texSize <<= 1) + ; + + render.detMapSize = texSize; + render.detMapElemSize = texElemSize; + + texElemSize = (render.elemSize * render.gridStep) << render.numLods; + for (texSize = 1; texSize < texElemSize; texSize <<= 1) + ; + + render.landTexSize = texSize; + render.landTexElemSize = texElemSize; + } + + // Set lightmap texture. + if (lightmapTexId != BAD_TEXTUREID) + dagRender->releaseManagedTex(lightmapTexId); + lightmapTexId = BAD_TEXTUREID; + + String prj; + DAGORED2->getProjectFolderPath(prj); + String fileName = ::make_full_path(prj, "builtScene/lightmap.tga"); + + if (!::dd_file_exist(fileName)) + { + DAEDITOR3.conWarning("missing ltmap: %s, trying to use commonData/tex/lmesh_ltmap.tga instead", fileName.str()); + fileName = ::make_full_start_path("../commonData/tex/lmesh_ltmap.tga"); + } + + if (::dd_file_exist(fileName)) + { + lightmapTexId = dagRender->addManagedTexture(fileName); + dagRender->acquireManagedTex(lightmapTexId); + + dagGeom->shaderGlobalSetTexture(dagGeom->getShaderVariableId("lightmap_tex"), lightmapTexId); + + if (getNumCellsX() > 0) + { + Color4 world_to_lightmap(1.f / (getNumCellsX() * getLandCellSize()), 1.f / (getNumCellsY() * getLandCellSize()), + -(float)getCellOrigin().x / getNumCellsX() - getOffset().x / getLandCellSize() / getNumCellsX(), + -(float)getCellOrigin().y / getNumCellsY() - getOffset().z / getLandCellSize() / getNumCellsY()); + + world_to_lightmap.b += 0.5 * world_to_lightmap.r * gridCellSize; + world_to_lightmap.a += 0.5 * world_to_lightmap.g * gridCellSize; + + dagGeom->shaderGlobalSetColor4(dagGeom->getShaderVariableId("world_to_lightmap"), world_to_lightmap); + } + } + else + DAEDITOR3.conError("missing ltmap: %s", fileName.str()); + + if (syncLight) + getAllSunSettings(); + else if (syncDirLight) + getDirectionSunSettings(); + + pendingResetRenderer = false; + if (landMeshRenderer) + landMeshRenderer->setCellsDebug(debugLmeshCells); + DAGORED2->invalidateViewportCache(); +} + + +void HmapLandPlugin::updateHorizontalTex() +{ + if (!useHorizontalTex) + { + dagGeom->shaderGlobalSetTexture(dagGeom->getShaderVariableId("land_geometry_horizontal_tex"), BAD_TEXTUREID); + dagGeom->shaderGlobalSetTexture(dagGeom->getShaderVariableId("land_geometry_horizontal_det_tex"), BAD_TEXTUREID); + return; + } + + TEXTUREID tid = horizontalTexName.empty() ? BAD_TEXTUREID : dagRender->addManagedTexture(String(32, "%s*", horizontalTexName.str())); + TEXTUREID detail_tid = + horizontalDetailTexName.empty() ? BAD_TEXTUREID : dagRender->addManagedTexture(String(32, "%s*", horizontalDetailTexName.str())); + + dagGeom->shaderGlobalSetTexture(dagGeom->getShaderVariableId("land_geometry_horizontal_tex"), tid); + dagGeom->shaderGlobalSetTexture(dagGeom->getShaderVariableId("land_geometry_horizontal_det_tex"), detail_tid); + + // Color4(1.f / max(vertDetTexXZtile, 1e-3f), -1.f / max(vertDetTexYtile, 1e-3f), vertDetTexYOffset / max(vertDetTexYtile, 1e-3f), + // 0.f)); + + dagGeom->shaderGlobalSetColor4(dagGeom->getShaderVariableId("land_geometry_horizontal_tex_map_tc"), + Color4(1.f / max(horizontalTex_TileSizeX, 1e-3f), -1.f / max(horizontalTex_TileSizeY, 1e-3f), + horizontalTex_OffsetX / max(horizontalTex_TileSizeX, 1e-3f), horizontalTex_OffsetY / max(horizontalTex_TileSizeY, 1e-3f))); + dagGeom->shaderGlobalSetColor4(dagGeom->getShaderVariableId("land_geometry_horizontal_detailtex_map_tc"), + Color4(1.f / max(horizontalTex_DetailTexSizeX, 1e-3f), -1.f / max(horizontalTex_DetailTexSizeY, 1e-3f), 0.f, 0.f)); +} + +void HmapLandPlugin::acquireHorizontalTexRef() +{ + dagRender->acquireManagedTex( + horizontalTexName.empty() ? BAD_TEXTUREID : dagRender->addManagedTexture(String(32, "%s*", horizontalTexName.str()))); + dagRender->acquireManagedTex( + horizontalDetailTexName.empty() ? BAD_TEXTUREID : dagRender->addManagedTexture(String(32, "%s*", horizontalDetailTexName.str()))); +} + +void HmapLandPlugin::releaseHorizontalTexRef() +{ + dagRender->releaseManagedTex( + horizontalTexName.empty() ? BAD_TEXTUREID : dagRender->addManagedTexture(String(32, "%s*", horizontalTexName.str()))); + dagRender->releaseManagedTex( + horizontalDetailTexName.empty() ? BAD_TEXTUREID : dagRender->addManagedTexture(String(32, "%s*", horizontalDetailTexName.str()))); +} + + +void HmapLandPlugin::saveHorizontalTex(DataBlock &blk) +{ + blk.setBool("use", useHorizontalTex); + blk.setStr("texName", horizontalTexName.str()); + blk.setStr("detailTexName", horizontalDetailTexName.str()); + + blk.setReal("tileSizeX", horizontalTex_TileSizeX); + blk.setReal("tileSizeY", horizontalTex_TileSizeY); + + blk.setReal("offsetX", horizontalTex_OffsetX); + blk.setReal("offsetY", horizontalTex_OffsetY); + + blk.setReal("detailTexSizeX", horizontalTex_DetailTexSizeX); + blk.setReal("detailTexSizeY", horizontalTex_DetailTexSizeY); +} +void HmapLandPlugin::loadHorizontalTex(const DataBlock &blk) +{ + useHorizontalTex = blk.getBool("use", false); + horizontalTexName = blk.getStr("texName", ""); + horizontalDetailTexName = blk.getStr("detailTexName", ""); + + horizontalTex_TileSizeX = blk.getReal("tileSizeX", 128.f); + horizontalTex_TileSizeY = blk.getReal("tileSizeY", 128.f); + + horizontalTex_OffsetX = blk.getReal("offsetX", 0.f); + horizontalTex_OffsetY = blk.getReal("offsetY", 0.f); + + horizontalTex_DetailTexSizeX = blk.getReal("detailTexSizeX", 128.f); + horizontalTex_DetailTexSizeY = blk.getReal("detailTexSizeY", 128.f); + updateHorizontalTex(); +} + + +void HmapLandPlugin::updateLandModulateColorTex() +{ + if (!useLandModulateColorTex) + { + dagGeom->shaderGlobalSetTexture(dagGeom->getShaderVariableId("land_modulate_color_tex"), BAD_TEXTUREID); + return; + } + + TEXTUREID tid = + landModulateColorTexName.empty() ? BAD_TEXTUREID : dagRender->addManagedTexture(String(32, "%s*", landModulateColorTexName.str())); + + float edge1 = landModulateColorEdge0; + float edge2 = landModulateColorEdge1; + dagGeom->shaderGlobalSetColor4(dagGeom->getShaderVariableId("land_modulate_color_edges"), + Color4(-1.0f / (edge2 - edge1), 1.0f + edge1 / (edge2 - edge1), 0.f, 0.f)); + + dagGeom->shaderGlobalSetTexture(dagGeom->getShaderVariableId("land_modulate_color_tex"), tid); + + if (hmlService) + hmlService->invalidateClipmap(true); +} + +void HmapLandPlugin::acquireLandModulateColorTexRef() +{ + dagRender->acquireManagedTex(landModulateColorTexName.empty() + ? BAD_TEXTUREID + : dagRender->addManagedTexture(String(32, "%s*", landModulateColorTexName.str()))); +} +void HmapLandPlugin::releaseLandModulateColorTexRef() +{ + dagRender->releaseManagedTex(landModulateColorTexName.empty() + ? BAD_TEXTUREID + : dagRender->addManagedTexture(String(32, "%s*", landModulateColorTexName.str()))); +} + +void HmapLandPlugin::saveLandModulateColorTex(DataBlock &blk) +{ + blk.setBool("use", useLandModulateColorTex); + blk.setStr("texName", landModulateColorTexName.str()); + blk.setReal("edge0", landModulateColorEdge0); + blk.setReal("edge1", landModulateColorEdge1); +} +void HmapLandPlugin::loadLandModulateColorTex(const DataBlock &blk) +{ + useLandModulateColorTex = blk.getBool("use", false); + landModulateColorTexName = blk.getStr("texName", ""); + landModulateColorEdge0 = blk.getReal("edge0", 0); + landModulateColorEdge1 = blk.getReal("edge1", 1); + updateLandModulateColorTex(); +} + + +void HmapLandPlugin::setRendinstlayeredDetailColor() +{ + Color4 colorFrom, colorTo; + if (useRendinstDetail2Modulation) + { + colorFrom = color4(rendinstDetail2ColorFrom); + colorTo = color4(rendinstDetail2ColorTo); + } + else + { + colorFrom = Color4(0.5f, 0.5f, 0.5f, 0.5f); + colorTo = Color4(0.5f, 0.5f, 0.5f, 0.5f); + } + dagGeom->shaderGlobalSetColor4(dagGeom->getShaderVariableId("detail2_color_from"), colorFrom); + dagGeom->shaderGlobalSetColor4(dagGeom->getShaderVariableId("detail2_color_to"), colorTo); +} + +void HmapLandPlugin::saveRendinstDetail2Color(DataBlock &blk) +{ + blk.setBool("useRendinstDetail2Modulation", useRendinstDetail2Modulation); + blk.setE3dcolor("detail2_color_from", rendinstDetail2ColorFrom); + blk.setE3dcolor("detail2_color_to", rendinstDetail2ColorTo); +} +void HmapLandPlugin::loadRendinstDetail2Color(const DataBlock &blk) +{ + useRendinstDetail2Modulation = blk.getBool("useRendinstDetail2Modulation", false); + rendinstDetail2ColorFrom = blk.getE3dcolor("detail2_color_from", E3DCOLOR(128, 128, 128, 128)); + rendinstDetail2ColorTo = blk.getE3dcolor("detail2_color_to", E3DCOLOR(128, 128, 128, 128)); + setRendinstlayeredDetailColor(); +} + +//--- + +void HmapLandPlugin::updateVertTex() +{ + if (!useVertTex || vertTexAng0 >= vertTexAng1) + { + dagGeom->shaderGlobalSetColor4(dagGeom->getShaderVariableId("vertical_param"), Color4(1.f, 1.f, 1000.f, 0.0f)); + dagGeom->shaderGlobalSetColor4(dagGeom->getShaderVariableId("vertical_param_2"), Color4(1.f, 0.f, 0.f, 0.f)); + dagGeom->shaderGlobalSetTexture(landTileVerticalTexVarId, BAD_TEXTUREID); + dagGeom->shaderGlobalSetTexture(landTileVerticalNmTexVarId, BAD_TEXTUREID); + dagGeom->shaderGlobalSetTexture(landTileVerticalDetTexVarId, BAD_TEXTUREID); + return; + } + + float blendFromY = cosf(DEG_TO_RAD * vertTexAng0); + float blendToY = cosf(DEG_TO_RAD * vertTexAng1); + float sxz = 1.f / max(vertTexXZtile, 1e-3f), sy = -1.f / max(vertTexYtile, 1e-3f); + TEXTUREID tid = vertTexName.empty() ? BAD_TEXTUREID : dagRender->addManagedTexture(String(32, "%s*", vertTexName.str())); + TEXTUREID tid_nm = vertNmTexName.empty() ? BAD_TEXTUREID : dagRender->addManagedTexture(String(32, "%s*", vertNmTexName.str())); + TEXTUREID tid_det = vertDetTexName.empty() ? BAD_TEXTUREID : dagRender->addManagedTexture(String(32, "%s*", vertDetTexName.str())); + + dagGeom->shaderGlobalSetColor4(dagGeom->getShaderVariableId("vertical_param"), + Color4(sxz, sy, 1.f / (blendFromY - blendToY), -blendToY / (blendFromY - blendToY))); + + dagGeom->shaderGlobalSetColor4(dagGeom->getShaderVariableId("vertical_param_2"), + Color4(vertTexHorBlend, -vertTexYOffset * sy, 0.f, 0.f)); + + dagGeom->shaderGlobalSetColor4(dagGeom->getShaderVariableId("vertical_param_3"), + Color4(1.f / max(vertDetTexXZtile, 1e-3f), -1.f / max(vertDetTexYtile, 1e-3f), vertDetTexYOffset / max(vertDetTexYtile, 1e-3f), + 0.f)); + + dagGeom->shaderGlobalSetTexture(landTileVerticalTexVarId, tid); + dagGeom->shaderGlobalSetTexture(landTileVerticalNmTexVarId, tid_nm); + dagGeom->shaderGlobalSetTexture(landTileVerticalDetTexVarId, tid_det); +} +void HmapLandPlugin::acquireVertTexRef() +{ + dagRender->acquireManagedTex( + vertTexName.empty() ? BAD_TEXTUREID : dagRender->addManagedTexture(String(32, "%s*", vertTexName.str()))); + dagRender->acquireManagedTex( + vertNmTexName.empty() ? BAD_TEXTUREID : dagRender->addManagedTexture(String(32, "%s*", vertNmTexName.str()))); + dagRender->acquireManagedTex( + vertDetTexName.empty() ? BAD_TEXTUREID : dagRender->addManagedTexture(String(32, "%s*", vertDetTexName.str()))); +} +void HmapLandPlugin::releaseVertTexRef() +{ + dagRender->releaseManagedTex( + vertTexName.empty() ? BAD_TEXTUREID : dagRender->addManagedTexture(String(32, "%s*", vertTexName.str()))); + dagRender->releaseManagedTex( + vertNmTexName.empty() ? BAD_TEXTUREID : dagRender->addManagedTexture(String(32, "%s*", vertNmTexName.str()))); + dagRender->releaseManagedTex( + vertDetTexName.empty() ? BAD_TEXTUREID : dagRender->addManagedTexture(String(32, "%s*", vertDetTexName.str()))); +} + +void HmapLandPlugin::invalidateRenderer() { hmlService->destroyLandMeshRenderer(landMeshRenderer); } + + +void HmapLandPlugin::gatherStaticCollisionGeomGame(StaticGeometryContainer &cont) +{ + gatherStaticGeometry(cont, 0, true); +#if !defined(USE_LMESH_ACES) + if (useMeshSurface && exportType == EXPORT_LANDMESH && + (DAEDITOR3.getEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_COLLISION) & lmeshSubtypeMask)) + { + if (landMeshMap.isEmpty()) + generateLandMeshMap(landMeshMap, DAGORED2->getConsole(), false, NULL); + landMeshMap.addStaticCollision(cont); + } +#endif +} + +// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ// + +bool HmapLandPlugin::getHeight(const Point2 &p, real &ht, Point3 *normal) const +{ + if (detDivisor && (detRect & p)) + { + HMDetGH det_hm; + return get_height_midpoint_heightmap(det_hm, p, ht, normal); + } + + if (!landMeshMap.getGameLandRayTracer()) + return false; + return landMeshMap.getGameLandRayTracer()->getHeight(p, ht, normal); +} + +bool HmapLandPlugin::exportLightmapToFile(const char *file_name, int target_code, bool high_qual) +{ + if (!hasLightmapTex) + return false; + + CoolConsole &con = DAGORED2->getConsole(); + + if (!lightMapScaled.isFileOpened()) + { + con.addMessage(ILogWriter::ERROR, "No lightmap data"); + con.endLog(); + return false; + } + + int time0 = dagTools->getTimeMsec(); + + // Convert to image. + + int width = lightMapScaled.getMapSizeX(); + int height = lightMapScaled.getMapSizeY(); + + SmallTab image; + clear_and_resize(image, width * height); + + if (useNormalMap) + { + for (unsigned int y = 0, id = 0; y < height; y++) + for (unsigned int x = 0; x < width; x++, id++) + { + unsigned lt = lightMapScaled.getData(x, y); + unsigned nx = (lt >> 16) & 0xFF; + unsigned nz = (lt >> 24) & 0xFF; + image[id].c = E3DCOLOR(0, nx, 0, nz); + } + } + else if (storeNxzInLtmapTex) + { + for (unsigned int y = 0, id = 0; y < height; y++) + for (unsigned int x = 0; x < width; x++, id++) + { + unsigned lt = lightMapScaled.getData(x, y); + unsigned sunLight = (lt >> 0) & 0xFF; + unsigned skyLight = (lt >> 8) & 0xFF; + unsigned nx = (lt >> 16) & 0xFF; + unsigned nz = (lt >> 24) & 0xFF; + image[id].c = E3DCOLOR(nx, nz, skyLight, sunLight); + } + } + else + { + for (unsigned int y = 0, id = 0; y < height; y++) + for (unsigned int x = 0; x < width; x++, id++) + { + unsigned lt = lightMapScaled.getData(x, y); + unsigned sunLight = (lt >> 0) & 0xFF; + unsigned skyLight = (lt >> 8) & 0xFF; + image[id].c = E3DCOLOR(skyLight, skyLight, skyLight, sunLight); + } + } + con.addMessage(ILogWriter::REMARK, "lightmap converted to rgba for %.1f sec", (dagTools->getTimeMsec() - time0) / 1000.0f); + time0 = dagTools->getTimeMsec(); + // Save textrue. + if (target_code == _MAKE4C('TGA')) + { + ::save_tga32(file_name, image.data(), width, height, width * 4); + return true; + } + + ddstexture::Converter cnv; + cnv.format = ddstexture::Converter::fmtDXT5; + if (target_code == _MAKE4C('iOS')) + cnv.format = ddstexture::Converter::fmtASTC4; + cnv.mipmapType = ddstexture::Converter::mipmapGenerate; + cnv.mipmapCount = ddstexture::Converter::AllMipMaps; + cnv.mipmapFilter = ddstexture::Converter::filterBox; + cnv.quality = high_qual ? ddstexture::Converter::QualityProduction : ddstexture::Converter::QualityFastest; + int memneeded = width * height * 2; + DynamicMemGeneralSaveCB memcwr(tmpmem, 0, memneeded); + bool res = dagTools->ddsConvertImage(cnv, memcwr, &image[0], width, height, width * sizeof(TexPixel32)); + if (!res) + { + con.addMessage(ILogWriter::ERROR, "Failed to convert lightmap to DDS"); + // con.showConsole(true); + return false; + } + + if (target_code == _MAKE4C('DDS')) + { + FullFileSaveCB ddsFile(file_name); + ddsFile.write(memcwr.data(), memcwr.size()); + } + else + { + ddsx::Buffer b; + ddsx::ConvertParams cp; + cp.packSzThres = 8 << 10; + cp.allowNonPow2 = false; + cp.addrU = ddsx::ConvertParams::ADDR_CLAMP; + cp.addrV = ddsx::ConvertParams::ADDR_CLAMP; + cp.mipOrdRev = HmapLandPlugin::defMipOrdRev; + res = dagTools->ddsxConvertDds(target_code, b, memcwr.data(), memcwr.size(), cp); + if (!res) + { + con.addMessage(ILogWriter::ERROR, "Failed to convert lightmap to DDSX"); + // con.showConsole(true); + return false; + } + + FullFileSaveCB cwr(file_name); + if (!cwr.fileHandle) + { + con.addMessage(ILogWriter::ERROR, "Failed to save lightmap to '%s'", file_name); + // con.showConsole(true); + return false; + } + + cwr.write(b.ptr, b.len); + + dagTools->ddsxFreeBuffer(b); + } + + con.addMessage(ILogWriter::REMARK, "lightmap converted to dds for %.1f sec", (dagTools->getTimeMsec() - time0) / 1000.0f); + + return true; +} + +extern bool game_res_sys_v2; + +bool HmapLandPlugin::buildAndWrite(BinDumpSaveCB &cwr, const ITextureNumerator &tn, PropPanel2 *params) +{ + if (pendingResetRenderer) + delayedResetRenderer(); + storeLayerTex(); + + int st_mask = DAEDITOR3.getEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_EXPORT); + String tmp_stor; + + const int edMode = objEd.getEditMode(); + if (edMode == CM_CREATE_ENTITY) + objEd.setEditMode(CM_OBJED_MODE_MOVE); + + CoolConsole &con = DAGORED2->getConsole(); + con.startLog(); + + int time0 = dagTools->getTimeMsec(); + + if ((st_mask & lmeshSubtypeMask) && exportType == EXPORT_LANDMESH) + { + // export land + int localStart = dagTools->getTimeMsec(); + con.addMessage(ILogWriter::REMARK, "Exporting land mesh..."); + LandRayTracer *gameTracer = NULL; +#if defined(USE_LMESH_ACES) + bool import_sgeom = true; +#else + bool import_sgeom = false; +#endif + bool strip_det_hmap_from_tracer = (st_mask & hmapSubtypeMask) && detDivisor; + if (!generateLandMeshMap(landMeshMap, DAGORED2->getConsole(), import_sgeom, &gameTracer, strip_det_hmap_from_tracer)) + { + DAEDITOR3.conError("failed to generateLandMeshMap"); + return false; + } + con.addMessage(ILogWriter::REMARK, "generated land mesh in %g seconds.", (dagTools->getTimeMsec() - localStart) / 1000.0); + + localStart = dagTools->getTimeMsec(); + onWholeLandChanged(); // Place objects on current hmap. + objEd.updateSplinesGeom(); + con.addMessage(ILogWriter::REMARK, "objects placed in %g seconds.", (dagTools->getTimeMsec() - localStart) / 1000.0); + + localStart = dagTools->getTimeMsec(); + + cwr.beginTaggedBlock(_MAKE4C('lmap')); + try + { + if (!exportLandMesh(cwr, NULL, gameTracer)) + return false; + con.addMessage(ILogWriter::REMARK, "export landmesh in %g seconds.", (dagTools->getTimeMsec() - localStart) / 1000.0); + } + catch (IGenSave::SaveException e) + { + CoolConsole &con = DAGORED2->getConsole(); + con.startLog(); + con.addMessage(ILogWriter::ERROR, "Error exporting heightmap '%s'", e.excDesc); + + con.endLog(); + return false; + } + if (gameTracer) + del_it(gameTracer); + + cwr.align8(); + cwr.endBlock(); + + + //---export land modulate color tex + if (useLandModulateColorTex && !landModulateColorTexName.empty()) + { + cwr.beginTaggedBlock(_MAKE4C('lmct')); // lmct = land modulate color texture + + cwr.writeDwString(landModulateColorTexName.str()); + cwr.writeReal(landModulateColorEdge0); + cwr.writeReal(landModulateColorEdge1); + + cwr.align8(); + cwr.endBlock(); + } + + //---export rendinst detail2 color + if (useRendinstDetail2Modulation) + { + cwr.beginTaggedBlock(_MAKE4C('d2co')); // d2co = detail 2 color + + Color4 colorFrom = color4(rendinstDetail2ColorFrom); + Color4 colorTo = color4(rendinstDetail2ColorTo); + +#define WRITE_COLOR(v) \ + cwr.writeReal(v.r); \ + cwr.writeReal(v.g); \ + cwr.writeReal(v.b); \ + cwr.writeReal(v.a); + + WRITE_COLOR(colorFrom) + WRITE_COLOR(colorTo) + + cwr.align8(); + cwr.endBlock(); + } + + //---export rendinst vertical tex + if (useHorizontalTex && !horizontalTexName.empty()) // && !rendinstVerticalDiffuseDetailTexName.isEmpty()) + { + cwr.beginTaggedBlock(_MAKE4C('lght')); // lght = landscape geometry horizontal texture + + cwr.writeDwString(horizontalTexName.str()); + cwr.writeDwString(horizontalDetailTexName.str()); + + cwr.writeReal(horizontalTex_TileSizeX); + cwr.writeReal(horizontalTex_TileSizeY); + + cwr.writeReal(horizontalTex_OffsetX); + cwr.writeReal(horizontalTex_OffsetY); + + cwr.writeReal(horizontalTex_DetailTexSizeX); + cwr.writeReal(horizontalTex_DetailTexSizeY); + + cwr.align8(); + cwr.endBlock(); + } + + + if (detDivisor && (st_mask & hmapSubtypeMask)) + { + DataBlock app_blk; + HmapVersion exp_ver = HmapVersion::HMAP_DELTA_COMPRESSION_VER; + unsigned export_chunk_sz = 0, exp_chunk_cnt = 0; + unsigned hrb_subsz = 0; + if (!app_blk.load(DAGORED2->getWorkspace().getAppPath())) + DAEDITOR3.conError("cannot read <%s>", DAGORED2->getWorkspace().getAppPath()); + else if (app_blk.getBlockByNameEx("projectDefaults")->getBlockByNameEx("hmap")->getBool("exportCBlockDC", false)) + { + exp_ver = HmapVersion::HMAP_CBLOCK_DELTAC_VER; + export_chunk_sz = app_blk.getBlockByNameEx("projectDefaults")->getBlockByNameEx("hmap")->getInt("exportChunkBytes", 4 << 20); + hrb_subsz = app_blk.getBlockByNameEx("projectDefaults")->getBlockByNameEx("hmap")->getInt("htRangeBlocksSubSz", 64); + } + + cwr.beginTaggedBlock(_MAKE4C('HM2')); + + IBBox2 eb = *getExclCellBBox(); + float hmin = heightMapDet.getFinalData(detRectC[0].x, detRectC[0].y), hmax = hmin; + int st_pos = cwr.tell(); + + for (int y = detRectC[0].y; y < detRectC[1].y; y++) + for (int x = detRectC[0].x; x < detRectC[1].x; x++) + { + float h = heightMapDet.getFinalData(x, y); + inplace_min(hmin, h); + inplace_max(hmax, h); + } + debug("detailed HMAP minimax: %.4f - %.4f", hmin, hmax); + float hdelta = ceil(hmax + 1) - floor(hmin); + if (hdelta >= 256) + hdelta = ceilf(hdelta / 256.0f) * 256.0; + else + for (int i = 1; i <= 256; i *= 2) + if (hdelta < i) + { + hdelta = ceilf(hdelta / i) * i; + break; + } + hmax = ceil(hmax + 1); + hmin = hmax - hdelta; + debug("detailed HMAP minimax, rounded: %.4f - %.4f, eps=%.4f", hmin, hmax, hdelta / 65536); + + cwr.writeFloat32e(gridCellSize / detDivisor); + cwr.writeFloat32e(hmin); + cwr.writeFloat32e(hdelta); + cwr.writeFloat32e(detRect[0].x); + cwr.writeFloat32e(detRect[0].y); + int width = detRectC[1].x - detRectC[0].x; + int height = detRectC[1].y - detRectC[0].y; + const int hmap_version = (int)exp_ver; + cwr.writeInt32e(width | (hmap_version << HMAP_WIDTH_BITS)); + cwr.writeInt32e(height); + cwr.writeInt32e(eb[0].x); + cwr.writeInt32e(eb[0].y); + cwr.writeInt32e(eb[1].x); + cwr.writeInt32e(eb[1].y); + + CompressedHeightmap c_hmap; + Tab c_hmap_stor; + if (exp_ver == HmapVersion::HMAP_CBLOCK_DELTAC_VER) + { + uint8_t block_shift = 3; + if (width != height) + hrb_subsz = 0; + else if (hrb_subsz * 2 > width) + hrb_subsz = width / 2; + uint8_t hrb_subsz_bits = hrb_subsz > 1 ? __bsf(hrb_subsz) : 0; + if (!hrb_subsz_bits) + hrb_subsz = 0; + else if ((1 << hrb_subsz_bits) != hrb_subsz) + { + DAEDITOR3.conError("bad htRangeBlocksSubSz=%d, must be > 1 and pow-of-2 (hrb_subsz_bits=%d)", hrb_subsz, hrb_subsz_bits); + hrb_subsz = hrb_subsz_bits = 0; + } + c_hmap_stor.resize(CompressedHeightmap::calc_data_size_needed(width, height, block_shift, hrb_subsz)); + + Tab hmap16; + hmap16.reserve(width * height); + for (int y = detRectC[0].y; y < detRectC[1].y; y++) + for (int x = detRectC[0].x; x < detRectC[1].x; x++) + hmap16.push_back(floorf((heightMapDet.getFinalData(x, y) - hmin) * 65535.0 / (hdelta))); + c_hmap = + CompressedHeightmap::compress(c_hmap_stor.data(), c_hmap_stor.size(), hmap16.data(), width, height, block_shift, hrb_subsz); + + if (export_chunk_sz & 0xFFFu) + { + DAEDITOR3.conError("bad exportChunkBytes=%d, must be >= %d", hrb_subsz, hrb_subsz_bits, 1 << 12); + export_chunk_sz = 0; + } + export_chunk_sz = ((export_chunk_sz >> c_hmap.block_size_shift) << c_hmap.block_size_shift) & ~0xFFFu; + if (hmap16.size() <= export_chunk_sz) + export_chunk_sz = 0; + if (export_chunk_sz) + exp_chunk_cnt = (hmap16.size() + export_chunk_sz - 1) / export_chunk_sz; + + cwr.writeInt32e(export_chunk_sz | (unsigned(hrb_subsz_bits) << 8) | c_hmap.block_width_shift); + } + + Tab cwr_chunk; + cwr_chunk.resize(exp_chunk_cnt); + for (unsigned i = 0; i < exp_chunk_cnt; i++) + cwr_chunk[i] = new mkbindump::BinDumpSaveCB(64 << 10, cwr.getTarget(), cwr.WRITE_BE); + + unsigned written_raw_data_sz = 0; + if (exp_chunk_cnt) + threadpool::init(min(cpujobs::get_physical_core_count(), 4), exp_chunk_cnt, 256 << 10); + threadpool::parallel_for_inline(0, exp_chunk_cnt + 1, 1, [&](uint32_t begin, uint32_t, uint32_t) { + mkbindump::BinDumpSaveCB cwr_hm(16 << 10, cwr.getTarget(), cwr.WRITE_BE); + if (exp_ver == HmapVersion::HMAP_CBLOCK_DELTAC_VER) + { + unsigned b0 = 0, b1 = c_hmap.bw * c_hmap.bh; + if (begin == 0) + { + cwr_hm.writeRaw(c_hmap.fullData, c_hmap.blockVariance - c_hmap.fullData); + if (exp_chunk_cnt) // when writing more than 1 chunk we write block data separately + b1 = b0; + } + else + { + b0 = (begin - 1) * (export_chunk_sz >> c_hmap.block_size_shift); + b1 = min(b1, begin * (export_chunk_sz >> c_hmap.block_size_shift)); + } + + for (auto *b = c_hmap.getBlockVariance(b0), *be = c_hmap.getBlockVariance(b1); b < be; b++) + { + cwr_hm.writeInt8e(*b); + for (unsigned bsz = (1 << c_hmap.block_size_shift) - 1; bsz > 0; bsz--, b++) + cwr_hm.writeInt8e(b[1] - b[0]); + } + + if (begin == 0 && hrb_subsz) + cwr_hm.writeRaw(c_hmap.htRangeBlocks, c_hmap.fullData + c_hmap_stor.size() - (uint8_t *)c_hmap.htRangeBlocks); + } + else + for (int y = detRectC[0].y; y < detRectC[1].y; y++) + { + uint16_t prev_data = 0; + for (int x = detRectC[0].x; x < detRectC[1].x; x++) + { + uint16_t c_data = floorf((heightMapDet.getFinalData(x, y) - hmin) * 65535.0 / (hdelta)); + cwr_hm.writeInt16e(x == detRectC[0].x ? c_data : (int16_t)(int(c_data) - int(prev_data))); + prev_data = c_data; + } + } + + mkbindump::BinDumpSaveCB &dest = (begin == 0) ? cwr : *cwr_chunk[begin - 1]; + dest.beginBlock(); + MemoryLoadCB mcrd(cwr_hm.getMem(), false); + if (preferZstdPacking && allowOodlePacking) + oodle_compress_data(dest.getRawWriter(), mcrd, cwr_hm.getSize()); + else if (preferZstdPacking || exp_ver == HmapVersion::HMAP_CBLOCK_DELTAC_VER) + zstd_compress_data(dest.getRawWriter(), mcrd, cwr_hm.getSize(), 1 << 20, 19); + else + lzma_compress_data(dest.getRawWriter(), 9, mcrd, cwr_hm.getSize()); + dest.endBlock(preferZstdPacking ? (allowOodlePacking ? btag_compr::OODLE : btag_compr::ZSTD) : btag_compr::UNSPECIFIED); + interlocked_add(written_raw_data_sz, cwr_hm.getSize()); + }); + if (exp_chunk_cnt) + threadpool::shutdown(); + + for (auto *c : cwr_chunk) + { + c->copyDataTo(cwr.getRawWriter()); + delete c; + } + cwr_chunk.clear(); + + cwr.align8(); + cwr.endBlock(); + debug("HM2 written, %d packed, %d unpacked (ver=%d: %d chunks, chunk_sz=%d, CBsz=%dx%d HRBsubsz=%dx%d)", cwr.tell() - st_pos, + written_raw_data_sz, (int)exp_ver, exp_chunk_cnt + 1, export_chunk_sz, // + c_hmap.block_width, c_hmap.block_width, hrb_subsz, hrb_subsz); + } +#if defined(USE_LMESH_ACES) + generateLandMeshMap(landMeshMap, DAGORED2->getConsole(), false, NULL); +#endif + + if (true) + { + int phys_li = hmlService->getBitLayerIndexByName(getLayersHandle(), "phys"); + if (phys_li < 0) + { + phys_li = hmlService->getBitLayerIndexByName(getLayersHandle(), "land"); + } + HmapBitLayerDesc layer = landClsLayer[phys_li]; + SmallTab pmMap; + SmallTab pmIndexedMap; + FastNameMap pmNames; + + SmallTab physMap; + int physMap_w = detDivisor ? detRectC.width().x : 0, physMap_h = detDivisor ? detRectC.width().y : 0; + + clear_and_resize(pmMap, 5 << (layer.bitCount + 1)); + mem_set_0(pmMap); + pmNames.addNameId(hmlService->getLandPhysMatName(0)); + for (int i = 0; i < pmMap.size(); i += 5) + if (landclass::AssetData *d = getLandClassMgr().getLandClass(phys_li, i / 5)) + { + pmMap[i + 0] = pmNames.addNameId(hmlService->getLandPhysMatName(d->physMatId[0])); + pmMap[i + 1] = pmNames.addNameId(hmlService->getLandPhysMatName(d->physMatId[1])); + pmMap[i + 2] = pmNames.addNameId(hmlService->getLandPhysMatName(d->physMatId[2])); + pmMap[i + 3] = pmNames.addNameId(hmlService->getLandPhysMatName(d->physMatId[3])); + pmMap[i + 4] = pmNames.addNameId(hmlService->getLandPhysMatName(d->physMatId[4])); + } + clear_and_resize(pmIndexedMap, 64 << (layer.bitCount + 1)); + mem_set_0(pmIndexedMap); + for (int i = 0; i < pmIndexedMap.size(); i += 64) + if (landclass::AssetData *d = getLandClassMgr().getLandClass(phys_li, i / 64)) + for (int j = 0; j < 64; j++) + pmIndexedMap[i + j] = pmNames.addNameId(hmlService->getLandPhysMatName(d->indexedPhysMatId[j])); + + if (detDivisor) + { + clear_and_resize(physMap, physMap_w * physMap_h); + mem_set_0(physMap); + + SmallTab stexMap; + SmallTab splattingTypesMap; + int texTypeId = DAEDITOR3.getAssetTypeId("tex"); + + clear_and_resize(stexMap, 1 << layer.bitCount); + mem_set_ff(stexMap); + + enum + { + UNDEFINED = 0, + RGB_SPLATTING = 1, + INDEXED_SPLATTING = 2 + }; + + clear_and_resize(splattingTypesMap, 1 << layer.bitCount); + for (int i = 0; i < splattingTypesMap.size(); i++) + splattingTypesMap[i] = UNDEFINED; + + for (int y = detRectC[0].y; y < detRectC[1].y; y++) + for (int x = detRectC[0].x; x < detRectC[1].x; x++) + { + int land = layer.getLayerData(landClsMap.getData(x * lcmScale / detDivisor, y * lcmScale / detDivisor)); + physMap[(y - detRectC[0].y) * physMap_w + x - detRectC[0].x] = pmMap[5 * land]; + if (intptr_t(stexMap[land]) == intptr_t(-1)) + { + stexMap[land] = NULL; + if (landclass::AssetData *d = getLandClassMgr().getLandClass(phys_li, land)) + { + if (d->detTex && d->detTex->getStr("splattingmap")) + { + const char *splattingMap = d->detTex->getStr("splattingmap"); + if (splattingMap[0] == '*') + { + SimpleString nm(splattingMap + 1); + if (char *p = strchr(nm.str(), ':')) + *p = '\0'; + String fn(0, "%s/%s", DAGORED2->getPluginFilePath(this, "elc"), nm); + // debug("load %s", fn); + stexMap[land] = try_find_and_load_tga_or_tiff(fn, tmpmem); + splattingTypesMap[land] = RGB_SPLATTING; + } + else if (DagorAsset *a = DAEDITOR3.getAssetByName(splattingMap, texTypeId)) + { + String fn(a->getTargetFilePath()); + if (is_tga_or_tiff(fn)) + { + // debug("load %s", fn); + stexMap[land] = load_tga_or_tiff(fn, tmpmem); + splattingTypesMap[land] = RGB_SPLATTING; + } + else + DAEDITOR3.conError("texture asset <%s> refernces to non-compatible %s", a->getName(), fn); + } + else + DAEDITOR3.conError("failed to resolve texture asset <%s> referenced by detailMap in landclass", splattingMap); + } + else if (d->indicesTex && d->indicesTex->getStr("indices")) + { + const char *indicesMap = d->indicesTex->getStr("indices"); + if (indicesMap[0] == '*') + { + SimpleString nm(indicesMap + 1); + if (char *p = strchr(nm.str(), ':')) + *p = '\0'; + String fn(0, "%s/%s", DAGORED2->getPluginFilePath(this, "elc"), nm); + // debug("load %s", fn); + stexMap[land] = try_find_and_load_tga_or_tiff(fn, tmpmem); + splattingTypesMap[land] = INDEXED_SPLATTING; + } + else if (DagorAsset *a = DAEDITOR3.getAssetByName(indicesMap, texTypeId)) + { + String fn(a->getTargetFilePath()); + if (is_tga_or_tiff(fn)) + { + // debug("load %s", fn); + stexMap[land] = load_tga_or_tiff(fn, tmpmem); + splattingTypesMap[land] = INDEXED_SPLATTING; + } + else + DAEDITOR3.conError("texture asset <%s> refernces to non-compatible %s", a->getName(), fn); + } + else + DAEDITOR3.conError("failed to resolve texture asset <%s> referenced by detailMap in landclass", indicesMap); + } + } + if (stexMap[land] && intptr_t(stexMap[land]) != intptr_t(-1)) + { + // We need to reverse image in vertical way + TexPixel32 *pix = stexMap[land]->getPixels(); + Tab tempBuffer; + tempBuffer.resize(stexMap[land]->w); + for (int y = 0; y < stexMap[land]->h / 2; ++y) + { + memcpy(tempBuffer.data(), &pix[(stexMap[land]->h - y - 1) * stexMap[land]->w], data_size(tempBuffer)); + memcpy(&pix[(stexMap[land]->h - y - 1) * stexMap[land]->w], &pix[y * stexMap[land]->w], data_size(tempBuffer)); + memcpy(&pix[y * stexMap[land]->w], tempBuffer.data(), data_size(tempBuffer)); + } + } + // debug("stexMap[%d]=%p", land, stexMap[land]); + } + if (stexMap[land] && intptr_t(stexMap[land]) != intptr_t(-1)) + { + landclass::AssetData *d = getLandClassMgr().getLandClass(phys_li, land); + // fixme: this is awful copy paste of 'opaque' landclass logic in order to create physmap + float tile = safediv(1.f, d->detTex->getPoint2("size", Point2(1, 1)).x); + Point2 offset = d->detTex->getPoint2("offset", Point2(0, 0)); // mask origin relative to main HMAP origin + // + const TexPixel32 *pix = stexMap[land]->getPixels(); + + int w = stexMap[land]->w, h = stexMap[land]->h; + float fx = -0.001f + fmodf(((x + 0.5f) * gridCellSize / detDivisor - offset.x) * tile, 1.0f) * w; + float fy = -0.001f + fmodf(((y + 0.5f) * gridCellSize / detDivisor - offset.y) * tile, 1.0f) * h; + + if (fx < 0) + fx += w; + if (fy < 0) + fy += h; + int ix = floorf(fx), iy = floorf(fy); + float tx = fx - ix, ty = fy - iy; + + E3DCOLOR p00(pix[iy * w + ix].u); + E3DCOLOR p10(pix[iy * w + ((ix + 1) % w)].u); + E3DCOLOR p01(pix[((iy + 1) % h) * w + ix].u); + E3DCOLOR p11(pix[((iy + 1) % h) * w + ((ix + 1) % w)].u); + + if (splattingTypesMap[land] == RGB_SPLATTING) // mega landclass + { + float ch[4]; + ch[0] = ((p00.r * (1 - tx) + p01.r * tx) * (1 - ty) + (p10.r * (1 - tx) + p11.r * tx) * ty) / 255.0f; + ch[1] = ((p00.g * (1 - tx) + p01.g * tx) * (1 - ty) + (p10.g * (1 - tx) + p11.g * tx) * ty) / 255.0f; + ch[2] = ((p00.b * (1 - tx) + p01.b * tx) * (1 - ty) + (p10.b * (1 - tx) + p11.b * tx) * ty) / 255.0f; + ch[3] = clamp(1 - ch[0] - ch[1] - ch[2], 0.f, 1.f); + for (int i = 0; i < 4; i++) + if (ch[i] > 0.5) + physMap[(y - detRectC[0].y) * physMap_w + x - detRectC[0].x] = pmMap[5 * land + 1 + i]; + } + if (splattingTypesMap[land] == INDEXED_SPLATTING) // indexed landclass + { + int index00 = floorf(p00.r + 0.1f); + int index01 = floorf(p01.r + 0.1f); + int index10 = floorf(p10.r + 0.1f); + int index11 = floorf(p11.r + 0.1f); + float weight00 = (1.0f - tx) * (1.0f - ty); + float weight01 = tx * (1.0f - ty); + float weight10 = (1.0f - tx) * ty; + float weight11 = tx * ty; + + unsigned char phys00, phys01, phys10, phys11; + phys00 = pmIndexedMap[64 * land + index00]; + phys01 = pmIndexedMap[64 * land + index01]; + phys10 = pmIndexedMap[64 * land + index10]; + phys11 = pmIndexedMap[64 * land + index11]; + + // physmats can be the same, so choose not from individual weights of indicies, but from physmat weights + float Sweight00 = + weight00 + (phys00 == phys01) * weight01 + (phys00 == phys10) * weight10 + (phys00 == phys11) * weight11; + float Sweight01 = weight01 + (phys01 == phys10) * weight10 + (phys01 == phys11) * weight11; + float Sweight10 = weight10 + (phys10 == phys11) * weight11; + float Sweight11 = weight11; + + float maxWeight = max(max(Sweight00, Sweight01), max(Sweight10, Sweight11)); + unsigned char mat = phys00; + mat = maxWeight == Sweight01 ? phys01 : mat; + mat = maxWeight == Sweight10 ? phys10 : mat; + mat = maxWeight == Sweight11 ? phys11 : mat; + + physMap[(y - detRectC[0].y) * physMap_w + x - detRectC[0].x] = mat; + } + } + } + for (int i = 0; i < stexMap.size(); i++) + if (stexMap[i] && intptr_t(stexMap[i]) != intptr_t(-1)) + memfree(stexMap[i], tmpmem); + } + + bool full_zero = true; + for (int i = 0; i < physMap.size() && full_zero; i += 8) + if ((*(int64_t *)&physMap[i])) + full_zero = false; + + if (allow_debug_bitmap_dump) + { + if (physMap_w && physMap_h) + { + IBitMaskImageMgr::BitmapMask img; + bitMaskImgMgr->createBitMask(img, physMap_w, physMap_h, 8); + for (int y = 0; y < physMap_h; y++) + for (int x = 0; x < physMap_w; x++) + img.setMaskPixel8(x, y, physMap[y * physMap_w + x] * 8); + bitMaskImgMgr->saveImage(img, ".", "pmMap2"); + bitMaskImgMgr->destroyImage(img); + } + } + StaticGeometryContainer *geoCont = dagGeom->newStaticGeometryContainer(); + for (int i = 0; i < DAGORED2->getPluginCount(); ++i) + { + IGenEditorPlugin *plugin = DAGORED2->getPlugin(i); + IGatherStaticGeometry *geom = plugin->queryInterface(); + if (!geom) + continue; + geom->gatherStaticVisualGeometry(*geoCont); + } + + struct TexturePhysInfo + { + int alphaThreshold; + bool heightAbove; // invert alpha + }; + + Tab decalNodes(tmpmem); + Tab> physMatIds(tmpmem); + Tab> bitmapIds(tmpmem); + FastNameMap textureNames; + Tab texturePhysInfos(tmpmem); + Tab hasAtLeastOneSolidMat(tmpmem); + decalNodes.reserve(geoCont->nodes.size()); + int hasAtLeastOneSolidMatCounter = 0; + for (int i = 0; i < geoCont->nodes.size(); ++i) + { + StaticGeometryNode *node = geoCont->nodes[i]; + + if (!node) + continue; + if (!node->mesh->mesh.check_mesh()) + continue; + + SmallTab phMatIds; + SmallTab bmpIds; + dag::Vector isSolidMat; + clear_and_resize(phMatIds, node->mesh->mats.size()); + mem_set_ff(phMatIds); + clear_and_resize(bmpIds, node->mesh->mats.size()); + mem_set_ff(bmpIds); + clear_and_resize(isSolidMat, node->mesh->mats.size()); + mem_set_0(isSolidMat); + bool nodeAdded = false; + int solidMatCounter = 0; + for (int mi = 0; mi < node->mesh->mats.size(); ++mi) + { + if (!node->mesh->mats[mi]) + continue; + bool isDecal = false; + CfgReader c; + c.getdiv_text(String(128, "[q]\r\n%s\r\n", node->mesh->mats[mi]->scriptText.str()), "q"); + if (strstr(node->mesh->mats[mi]->className.str(), "decal")) + isDecal = true; + else if ( + strstr(node->mesh->mats[mi]->scriptText.str(), "render_landmesh_combined") && !c.getbool("render_landmesh_combined", 1)) + isDecal = true; + if (isDecal) + { + const char *physMatName = c.getstr("phmat", NULL); + if (!physMatName) + continue; + phMatIds[mi] = pmNames.addNameId(physMatName); + if (hmlService->getIsSolidByPhysMatName(physMatName)) + { + isSolidMat[mi] = true; + solidMatCounter++; + } + if (!nodeAdded) + decalNodes.push_back(node); + const char *textureName = node->mesh->mats[mi]->textures[0]->fileName.str(); + if (textureNames.getNameId(textureName) < 0) + { + TexturePhysInfo &physInfo = texturePhysInfos.push_back(); + physInfo.alphaThreshold = c.getint("alpha_threshold", 127); + physInfo.heightAbove = c.getint("height_above", 1); + } + bmpIds[mi] = textureNames.addNameId(textureName); + nodeAdded = true; + full_zero = false; + } + } + if (nodeAdded) + { + if (solidMatCounter > 0) + { + int listSize = phMatIds.size(); + // We will copy solid ids to end of vector, so reserve space for them now + phMatIds.reserve(solidMatCounter + listSize); + bmpIds.reserve(solidMatCounter + listSize); + // copy soft ids to begin of vector and solid ids to end of vector + int copyTo = 0; + for (int i = 0; i < listSize; i++) + { + if (isSolidMat[i]) + { + // Make a copy of solid mat at the end of vector + phMatIds.push_back(phMatIds[i]); + bmpIds.push_back(bmpIds[i]); + } + else + { + if (i != copyTo) + { + phMatIds[copyTo] = phMatIds[i]; + bmpIds[copyTo] = bmpIds[i]; + } + copyTo++; + } + } + // Values in interval [copyTo..listSize) contain just part of initial vector; + // all these values were copied to [0..copyTo) or [listSize..newSize) intervals. So this interval can be removed now. + phMatIds.erase(phMatIds.begin() + copyTo, phMatIds.begin() + listSize); + bmpIds.erase(bmpIds.begin() + copyTo, bmpIds.begin() + listSize); + hasAtLeastOneSolidMatCounter++; + hasAtLeastOneSolidMat.push_back(1); + } + else + { + hasAtLeastOneSolidMat.push_back(0); + } + physMatIds.push_back(phMatIds); + bitmapIds.push_back(bmpIds); + } + } + // making sort in order that solid physmats are drawn last + int listSize = physMatIds.size(); + // We will copy solid ids to end of vector, so reserve space for them now + physMatIds.reserve(hasAtLeastOneSolidMatCounter + listSize); + bitmapIds.reserve(hasAtLeastOneSolidMatCounter + listSize); + decalNodes.reserve(hasAtLeastOneSolidMatCounter + listSize); + // copy soft ids to begin of vector and solid ids to end of vector + int copyTo = 0; + for (int i = 0; i < listSize; i++) + { + if (hasAtLeastOneSolidMat[i]) + { + // Make a copy of solid mat at the end of vector + physMatIds.push_back(physMatIds[i]); + bitmapIds.push_back(bitmapIds[i]); + decalNodes.push_back(decalNodes[i]); + } + else + { + if (i != copyTo) + { + physMatIds[copyTo] = physMatIds[i]; + bitmapIds[copyTo] = bitmapIds[i]; + decalNodes[copyTo] = decalNodes[i]; + } + copyTo++; + } + } + // Values in interval [copyTo..listSize) contain just part of initial vector; + // all these values were copied to [0..copyTo) or [listSize..newSize) intervals. So this interval can be removed now. + physMatIds.erase(physMatIds.begin() + copyTo, physMatIds.begin() + listSize); + bitmapIds.erase(bitmapIds.begin() + copyTo, bitmapIds.begin() + listSize); + decalNodes.erase(decalNodes.begin() + copyTo, decalNodes.begin() + listSize); + + if (!full_zero) + { + // write physmat map + cwr.beginTaggedBlock(_MAKE4C('LMp2')); + int st_pos = cwr.tell(); + + int version = 1; + cwr.writeInt32e(version); + cwr.writeInt32e(pmNames.nameCount()); + for (int i = 0; i < pmNames.nameCount(); i++) + cwr.writeDwString(pmNames.getName(i)); + + cwr.writeInt32e(physMap_w); + cwr.writeInt32e(physMap_h); + cwr.writeFloat32e(detDivisor ? detRect[0].x : 0); + cwr.writeFloat32e(detDivisor ? detRect[0].y : 0); + cwr.writeFloat32e(detDivisor ? gridCellSize / detDivisor : 0); + + mkbindump::BinDumpSaveCB cwr_pm(2 << 10, cwr.getTarget(), cwr.WRITE_BE); + + TreeBitmapNode physMapParent; + physMapParent.create(physMap, IPoint2(physMap_w, physMap_h)); + mkbindump::save_tree_bitmap(cwr_pm, &physMapParent); + + // write meshes + debug("decal nodes %d", decalNodes.size()); + cwr_pm.writeInt16e(decalNodes.size()); + for (int i = 0; i < decalNodes.size(); ++i) + { + StaticGeometryNode *node = decalNodes[i]; + + // Prepare + Mesh tempMesh = node->mesh->mesh; + tempMesh.transform(node->wtm); + + // Optimize + Bitarray usedFaces; + usedFaces.resize(tempMesh.face.size()); + usedFaces.reset(); + for (int fidx = 0; fidx < tempMesh.face.size(); ++fidx) + if (physMatIds[i][tempMesh.face[fidx].mat] >= 0) + usedFaces.set(fidx); + tempMesh.removeFacesFast(usedFaces); + tempMesh.kill_unused_verts(); + tempMesh.kill_bad_faces(); + tempMesh.sort_faces_by_mat(); + + // Simplify + SmallTab vertices; + SmallTab texCoords; + clear_and_resize(vertices, tempMesh.vert.size()); + for (int vert = 0; vert < tempMesh.vert.size(); ++vert) + vertices[vert] = Point2::xz(tempMesh.vert[vert]); + cwr_pm.writeInt16e(vertices.size()); + cwr_pm.writeRaw(vertices.data(), data_size(vertices)); + cwr_pm.writeInt16e(tempMesh.tvert[0].size()); + cwr_pm.writeRaw(tempMesh.tvert[0].data(), data_size(tempMesh.tvert[0])); + + if (tempMesh.face.empty()) + { + cwr_pm.writeInt8e(0); // 0 mat + cwr_pm.writeInt16e(0); // 0 faces + // useless node actually for some reason + continue; + } + int curPhysMat = -1; + int curFaceIdx = 0; + int faceNumOffset = -1; + for (int fi = 0; fi < tempMesh.face.size(); ++fi) + { + int physMat = physMatIds[i][tempMesh.face[fi].mat]; + if (physMat != curPhysMat) + { + cwr_pm.writeInt8e(physMat); + curPhysMat = physMat; + if (faceNumOffset >= 0) + { + cwr_pm.seekto(faceNumOffset); + cwr_pm.writeInt16e(fi - curFaceIdx); + cwr_pm.seekToEnd(); + cwr_pm.writeInt16e(bitmapIds[i][tempMesh.face[fi].mat]); + for (int tfi = curFaceIdx; tfi < fi; ++tfi) + { + cwr_pm.writeInt16e(tempMesh.tface[0][tfi].t[0]); + cwr_pm.writeInt16e(tempMesh.tface[0][tfi].t[1]); + cwr_pm.writeInt16e(tempMesh.tface[0][tfi].t[2]); + } + } + faceNumOffset = cwr_pm.tell(); + curFaceIdx = fi; + cwr_pm.writeInt16e(0); // 0 faces, we don't know number yet + } + cwr_pm.writeInt16e(tempMesh.face[fi].v[0]); + cwr_pm.writeInt16e(tempMesh.face[fi].v[1]); + cwr_pm.writeInt16e(tempMesh.face[fi].v[2]); + } + if (!tempMesh.tface[0].empty()) + cwr_pm.writeInt16e(bitmapIds[i][tempMesh.face.back().mat]); + for (int tfi = curFaceIdx; tfi < tempMesh.tface[0].size(); ++tfi) + { + cwr_pm.writeInt16e(tempMesh.tface[0][tfi].t[0]); + cwr_pm.writeInt16e(tempMesh.tface[0][tfi].t[1]); + cwr_pm.writeInt16e(tempMesh.tface[0][tfi].t[2]); + } + cwr_pm.seekto(faceNumOffset); + cwr_pm.writeInt16e(tempMesh.face.size() - curFaceIdx); + cwr_pm.seekToEnd(); + + // stop + cwr_pm.writeInt8e(0); + cwr_pm.writeInt16e(0); + } + + const int delta = (EXTENDED_DECAL_BITMAP_SZ - DECAL_BITMAP_SZ) / 2; + cwr_pm.writeInt16e(textureNames.nameCount()); + int texTypeId = DAEDITOR3.getAssetTypeId("tex"); + for (int i = 0; i < textureNames.nameCount(); ++i) + { + int numOfDrawedPixels = 0; + HmapLandPlugin::PackedDecalBitmap bitmap; + HmapLandPlugin::ExtendedDecalBitmap accumulated_bitmap; + mem_set_0(bitmap); + mem_set_0(accumulated_bitmap); + String aname(DagorAsset::fpath2asset(TextureMetaData::decodeFileName(textureNames.getName(i), &tmp_stor))); + if (aname.length() > 0 && aname[aname.length() - 1] == '*') + erase_items(aname, aname.length() - 1, 1); + DagorAsset *a = DAEDITOR3.getAssetByName(aname.str(), texTypeId); + String fname; + if (a) + fname = eastl::move(a->getTargetFilePath()); + if (!fname.empty() && (is_tga_or_tiff(fname))) + { + TexImage32 *image = load_tga_or_tiff(fname, tmpmem); + TexPixel32 *pixels = image->getPixels(); + for (int y = 0; y < DECAL_BITMAP_SZ; ++y) + { + for (int x = 0; x < DECAL_BITMAP_SZ; ++x) + { + float accumulatedAlpha = 0.f; + for (int yy = (y * image->h) / DECAL_BITMAP_SZ; yy < ((y + 1) * image->h) / DECAL_BITMAP_SZ; ++yy) + for (int xx = (x * image->w) / DECAL_BITMAP_SZ; xx < ((x + 1) * image->w) / DECAL_BITMAP_SZ; ++xx) + accumulatedAlpha += pixels[yy * image->w + xx].a; + + const TexturePhysInfo &physInfo = texturePhysInfos[i]; + float threshold = physInfo.alphaThreshold; + accumulatedAlpha *= float(sqr(DECAL_BITMAP_SZ)) / float(image->h * image->w); + if ((accumulatedAlpha > threshold) == physInfo.heightAbove) + { + accumulated_bitmap[((y + delta) * EXTENDED_DECAL_BITMAP_SZ) + (x + delta)] = 1; + numOfDrawedPixels++; + } + } + } + // assume that if less then 10% of bitmap are filled with physmat value then something is strange happened + // we do it before closing process to understand how many pixels we have from alpha texture + if (numOfDrawedPixels <= (DECAL_BITMAP_SZ * DECAL_BITMAP_SZ) * 0.1f) + { + DAEDITOR3.conWarning("There is something strange with texture \"%s\"\nBitmap filled only %d pixel of 1024\n" + "Please check alpha texture or params in mat.blk \n", + textureNames.getName(i), numOfDrawedPixels); + } + + applyClosingPostProcess(accumulated_bitmap); + bitmap = to_1bit_bitmap(accumulated_bitmap); + } + else + { + DAEDITOR3.conError("Unsuported texture '%s' used in decal for PhysMap, only tga's or tiff's supported", + textureNames.getName(i)); + if (fname) + DAEDITOR3.conError("Texture was tried to be loaded from '%s'", fname); + } + cwr_pm.write32ex(bitmap.data(), data_size(bitmap)); + } + + cwr.beginBlock(); + MemoryLoadCB mcrd(cwr_pm.getMem(), false); + if (preferZstdPacking && allowOodlePacking) + { + cwr.writeInt32e(cwr_pm.getSize()); + oodle_compress_data(cwr.getRawWriter(), mcrd, cwr_pm.getSize()); + } + else if (preferZstdPacking) + zstd_compress_data(cwr.getRawWriter(), mcrd, cwr_pm.getSize(), 1 << 20, 19); + else + lzma_compress_data(cwr.getRawWriter(), 9, mcrd, cwr_pm.getSize()); + cwr.endBlock(preferZstdPacking ? (allowOodlePacking ? btag_compr::OODLE : btag_compr::ZSTD) : btag_compr::UNSPECIFIED); + + cwr.align8(); + cwr.endBlock(); + debug("LMpm written, %d packed, %d unpacked", cwr.tell() - st_pos, cwr_pm.getSize()); + } + dagGeom->deleteStaticGeometryContainer(geoCont); + } + + IWaterService *waterSrv = EDITORCORE->queryEditorInterface(); + if (waterSrv) + waterSrv->exportHeightmap(cwr, preferZstdPacking, allowOodlePacking); + + int genTime = dagTools->getTimeMsec() - time0; + con.addMessage(ILogWriter::REMARK, "exported in %g seconds", genTime / 1000.0f); + con.endLog(); + } +#if defined(USE_LMESH_ACES) + else if ((st_mask & hmapSubtypeMask) && exportType == EXPORT_HMAP) + { + con.addMessage(ILogWriter::NOTE, "Exporting land..."); + + if (!heightMap.isFileOpened()) + { + con.addMessage(ILogWriter::ERROR, "No heightmap data"); + con.endLog(); + return false; + } + + if (!landClsMap.isFileOpened()) + { + con.addMessage(ILogWriter::ERROR, "No landClsMap data"); + con.endLog(); + return false; + } + + if (hasColorTex && !colorMap.isFileOpened()) + { + con.addMessage(ILogWriter::ERROR, "No colormap data"); + con.endLog(); + return false; + } + + if (hasLightmapTex && !lightMapScaled.isFileOpened()) + { + con.addMessage(ILogWriter::ERROR, "No lightmap data"); + con.endLog(); + return false; + } + + if (exportType == EXPORT_HMAP) + { + cwr.beginTaggedBlock(_MAKE4C('hmap')); + try + { + cwr.setOrigin(); + exportLand(cwr); + cwr.popOrigin(); + } + catch (IGenSave::SaveException e) + { + CoolConsole &con = DAGORED2->getConsole(); + con.startLog(); + con.addMessage(ILogWriter::ERROR, "Error exporting heightmap '%s'", e.excDesc); + + con.endLog(); + return false; + } + + cwr.align8(); + cwr.endBlock(); + + cwr.beginTaggedBlock(_MAKE4C('hset')); + cwr.writeInt32e(render.gridStep); + cwr.writeInt32e(render.radiusElems); + cwr.writeInt32e(render.ringElems); + cwr.align8(); + cwr.endBlock(); + } + } +#endif + + exportSplines(cwr); + if (cableService) + cableService->exportCables(cwr); + + bool exp_err = false; + BBox2 water_bb; + bool has_water = false; + water_bb.setempty(); + for (int i = 0; i < objEd.objectCount(); i++) + { + SplineObject *o = RTTI_cast(objEd.getObject(i)); + BBox3 wbb; + if (o && o->isPoly() && o->polyGeom.altGeom && o->polyGeom.bboxAlignStep > 0 && o->getWorldBox(wbb)) + { + float grid = max(o->polyGeom.bboxAlignStep, 1.0f); + wbb[0].x = floorf(wbb[0].x / grid) * grid; + wbb[0].z = floorf(wbb[0].z / grid) * grid; + wbb[1].x = ceilf(wbb[1].x / grid) * grid; + wbb[1].z = ceilf(wbb[1].z / grid) * grid; + water_bb += Point2::xz(wbb[0]); + water_bb += Point2::xz(wbb[1]); + has_water = true; + } + } + if (has_water) + { + DAEDITOR3.conNote("export: has water"); + cwr.beginTaggedBlock(_MAKE4C('wt3d')); + cwr.writeInt32e(0x20150909); + if (water_bb.isempty()) + cwr.writeInt32e(0); + else + { + cwr.writeInt32e(1); + cwr.write32ex(&water_bb, sizeof(water_bb)); + DAEDITOR3.conNote("export: water bbox=%@", water_bb); + } + cwr.align8(); + cwr.endBlock(); + } + BBox3 worldBBox; + if (IRendInstGenService *rigenSrv = EDITORCORE->queryEditorInterface()) + worldBBox = rigenSrv->calcWorldBBox(); + + if (landMeshManager) + worldBBox += hmlService->getLMeshBBoxWithHMapWBBox(*landMeshManager); + if (!worldBBox.isempty()) + { + cwr.beginTaggedBlock(_MAKE4C('WBBX')); + cwr.write32ex(&worldBBox, sizeof(worldBBox)); + cwr.endBlock(); + } + buildAndWriteNavMesh(cwr); + + GeomObject *obj = dagGeom->newGeomObject(midmem); + gatherStaticGeometry(*obj->getGeometryContainer(), StaticGeometryNode::FLG_RENDERABLE, false, 1); + if (obj->getGeometryContainer()->nodes.size()) + { + cwr.beginTaggedBlock(_MAKE4C('rivM')); + if (!hmlService->exportGeomToShaderMesh(cwr, *obj->getGeometryContainer(), DAGORED2->getPluginFilePath(this, ".work/rivers.dat"), + tn)) + { + DAEDITOR3.conError("failed to export river geom"); + exp_err = true; + } + cwr.align8(); + cwr.endBlock(); + } + dagGeom->deleteGeomObject(obj); + + int genTime = dagTools->getTimeMsec() - time0; + con.addMessage(ILogWriter::REMARK, "exported in %g seconds", genTime / 1000.0f); + con.endLog(); + + return !exp_err; +} + +void HmapLandPlugin::applyClosingPostProcess(HmapLandPlugin::ExtendedDecalBitmap &accum_bitmap) +{ + // dilation pass + carray temp; + mem_copy_to(accum_bitmap, temp.data()); + for (int y = KERNEL_RAD; y < EXTENDED_DECAL_BITMAP_SZ - KERNEL_RAD; y++) + { + for (int x = KERNEL_RAD; x < EXTENDED_DECAL_BITMAP_SZ - KERNEL_RAD; x++) + { + for (int yy = -KERNEL_RAD; yy <= KERNEL_RAD; yy++) + { + for (int xx = -KERNEL_RAD; xx <= KERNEL_RAD; xx++) + { + char centralVal = accum_bitmap[y * EXTENDED_DECAL_BITMAP_SZ + x]; + char kernalVal = temp[(y + yy) * EXTENDED_DECAL_BITMAP_SZ + (x + xx)]; + accum_bitmap[y * EXTENDED_DECAL_BITMAP_SZ + x] = eastl::max(centralVal, kernalVal); + } + } + } + } + // erosion pass + mem_copy_to(accum_bitmap, temp.data()); + for (int y = KERNEL_RAD; y < EXTENDED_DECAL_BITMAP_SZ - KERNEL_RAD; y++) + { + for (int x = KERNEL_RAD; x < EXTENDED_DECAL_BITMAP_SZ - KERNEL_RAD; x++) + { + for (int yy = -KERNEL_RAD; yy <= KERNEL_RAD; yy++) + { + for (int xx = -KERNEL_RAD; xx <= KERNEL_RAD; xx++) + { + char centralVal = accum_bitmap[y * EXTENDED_DECAL_BITMAP_SZ + x]; + char kernalVal = temp[(y + yy) * EXTENDED_DECAL_BITMAP_SZ + (x + xx)]; + accum_bitmap[y * EXTENDED_DECAL_BITMAP_SZ + x] = eastl::min(centralVal, kernalVal); + } + } + } + } +} + +HmapLandPlugin::PackedDecalBitmap HmapLandPlugin::to_1bit_bitmap(const HmapLandPlugin::ExtendedDecalBitmap &accum_bitmap) +{ + HmapLandPlugin::PackedDecalBitmap outputBitmap; + mem_set_0(outputBitmap); + int delta = (EXTENDED_DECAL_BITMAP_SZ - DECAL_BITMAP_SZ) / 2; + for (int y = delta; y < DECAL_BITMAP_SZ + delta; y++) + { + for (int x = delta; x < DECAL_BITMAP_SZ + delta; x++) + { + outputBitmap[y - delta] |= accum_bitmap[y * EXTENDED_DECAL_BITMAP_SZ + x] << (x - delta); + } + } + return outputBitmap; +} + +void HmapLandPlugin::writeAddLtinputData(IGenSave &cwr) +{ + class BlankTextureRemap : public ITextureNumerator + { + public: + virtual int addTextureName(const char *fname) { return -1; } + virtual int addDDSxTexture(const char *fname, ddsx::Buffer &b) { return -1; } + virtual int getTextureOrdinal(const char *fname) const { return -1; } + virtual int getTargetCode() const { return _MAKE4C('PC'); } + }; + + BlankTextureRemap temp; + mkbindump::BinDumpSaveCB bdcwr(128 << 20, _MAKE4C('PC'), false); + buildAndWrite(bdcwr, temp, NULL); + bdcwr.copyDataTo(cwr); +} +// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ// + + +void HmapLandPlugin::requestHeightmapData(int x0, int y0, int step, int x_size, int y_size) {} + +bool HmapLandPlugin::isLandPreloadRequestComplete() { return true; } + + +void HmapLandPlugin::getHeightmapData(int x0, int y0, int step, int x_size, int y_size, real *data, int stride_bytes) +{ + char *ptr = (char *)data; + /* + if (exportType == EXPORT_PSEUDO_PLANE) + { + float y0 = 0; //heightMap.heightOffset; + for (int y=0, yc=y0; y maxColor) + maxColor = cell[i]; + } + + static uint8_t ramp[4]; + ramp[0] = minColor; + ramp[1] = maxColor; + ramp[2] = (minColor * 2 + maxColor + 1) / 3; + ramp[3] = (maxColor * 2 + minColor + 1) / 3; + + for (int i = 0; i < 16; ++i) + { + uint32_t bestInd = 0; + int bestDiff = abs(cell[i] - ramp[bestInd]); + + for (int j = 1; j < 4; ++j) + { + int d = abs(cell[i] - ramp[j]); + if (d < bestDiff) + { + bestDiff = d; + bestInd = j; + } + } + + bestCode |= bestInd << (i * 2); + } + + // output packed color + uint16_t pc1 = ::make565GrayColor(minColor); + uint16_t pc2 = ::make565GrayColor(maxColor); + + if (pc1 == pc2) + { + bestCode = 0; + } + else if (pc1 < pc2) + { + // swap + uint16_t c = pc1; + pc1 = pc2; + pc2 = c; + bestCode ^= 0x55555555; + } + + *(uint16_t *)output = pc1; + output += 2; + *(uint16_t *)output = pc2; + output += 2; + + *(uint32_t *)output = bestCode; + output += 4; +} + + +static __forceinline void packDxtCellInterpAlpha(uint8_t cell[16], uint8_t *&output) +{ + uint8_t minAlpha = 255, maxAlpha = 0; + bool useBlack = false; + + int i; + for (i = 0; i < 16; ++i) + { + if (cell[i] == 0) + useBlack = true; + else + { + if (cell[i] < minAlpha) + minAlpha = cell[i]; + if (cell[i] > maxAlpha) + maxAlpha = cell[i]; + } + } + + static uint8_t alpha[8]; + + if (useBlack) + { + // 6-alpha block. + // Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated. + alpha[0] = minAlpha; + alpha[1] = maxAlpha; + alpha[2] = (4 * alpha[0] + 1 * alpha[1] + 2) / 5; // Bit code 010 + alpha[3] = (3 * alpha[0] + 2 * alpha[1] + 2) / 5; // Bit code 011 + alpha[4] = (2 * alpha[0] + 3 * alpha[1] + 2) / 5; // Bit code 100 + alpha[5] = (1 * alpha[0] + 4 * alpha[1] + 2) / 5; // Bit code 101 + alpha[6] = 0; // Bit code 110 + alpha[7] = 255; // Bit code 111 + } + else + { + // 8-alpha block. + // Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated. + alpha[0] = maxAlpha; + alpha[1] = minAlpha; + alpha[2] = (6 * alpha[0] + 1 * alpha[1] + 3) / 7; // bit code 010 + alpha[3] = (5 * alpha[0] + 2 * alpha[1] + 3) / 7; // bit code 011 + alpha[4] = (4 * alpha[0] + 3 * alpha[1] + 3) / 7; // bit code 100 + alpha[5] = (3 * alpha[0] + 4 * alpha[1] + 3) / 7; // bit code 101 + alpha[6] = (2 * alpha[0] + 5 * alpha[1] + 3) / 7; // bit code 110 + alpha[7] = (1 * alpha[0] + 6 * alpha[1] + 3) / 7; // bit code 111 + } + + __int64 code = 0; + for (i = 0; i < 16; ++i) + { + int a = cell[i]; + + int bestCode = 0; + int bestDiff = abs(a - alpha[0]); + + for (int j = 1; j < 8; ++j) + { + int d = abs(a - alpha[j]); + if (d < bestDiff) + { + bestDiff = d; + bestCode = j; + } + } + + code |= __int64(bestCode) << (i * 3); + } + + // output packed alpha + output[0] = alpha[0]; + output[1] = alpha[1]; + output += 2; + + *(uint32_t *)output = code; + output += 4; + *(uint16_t *)output = code >> 32; + output += 2; +} + + +/*void HmapLandPlugin::loadLandDetailTexture(int x0, int y0, Texture *tex, Texture *tex2, + uint8_t detail_tex_ids[HMAX_DET_TEX_NUM+1], bool *done_mark) +{ + loadLandDetailTexture(x0, y0, tex, tex2, detail_tex_ids, done_mark, + render.detMapSize, render.detMapElemSize); +}*/ + +void HmapLandPlugin::loadLandDetailTexture(int x0, int y0, Texture *tex1, Texture *tex2, + carray &detail_tex_ids, bool *done_mark, int texSize, int elemSize) +{ + char *imgPtr = NULL; + char *imgPtr2 = NULL; + int stride = 0, stride2 = 0; + d3d_err(tex1->lockimg((void **)&imgPtr, stride, 0, TEXLOCK_WRITE)); + d3d_err(tex2->lockimg((void **)&imgPtr2, stride2, 0, TEXLOCK_WRITE)); + loadLandDetailTexture(_MAKE4C('PC'), x0, y0, imgPtr, stride, imgPtr2, stride2, detail_tex_ids, done_mark, texSize, elemSize, true, + true); + + d3d_err(tex1->unlockimg()); + d3d_err(tex2->unlockimg()); +} + +#define PROFILE_BLOCK_START(varn) int varn##Start = dagTools->getTimeMsec(); +#define PROFILE_BLOCK_END(varn) int varn = dagTools->getTimeMsec() - varn##Start; +static __forceinline unsigned convert_4bit_to8bit(unsigned a) +{ + a &= 0xF; + return (a << 4) | a; +} +static __forceinline unsigned convert_argb4_to_argb8(unsigned a) +{ + return (convert_4bit_to8bit(a)) | (convert_4bit_to8bit(a >> 4) << 8) | (convert_4bit_to8bit(a >> 8) << 16) | + (convert_4bit_to8bit(a >> 12) << 24); +} + +int HmapLandPlugin::loadLandDetailTexture(unsigned targetCode, int x0, int y0, char *tex1, int stride, char *tex2, int stride2, + carray &detail_tex_ids, bool *done_mark, int det_size, int det_elem_size, bool tex1_rgba, bool tex2_rgba) +{ + uint16_t *imgPtr = (uint16_t *)tex1; + uint8_t *imgPtr2 = (uint8_t *)tex2; + x0 *= det_elem_size; + y0 *= det_elem_size; + + int texSize = det_size; + int texDataSize = min(det_elem_size + 4, texSize); + + SmallTab typeRemap; + clear_and_resize(typeRemap, 256); + mem_set_ff(typeRemap); + memset(detail_tex_ids.data(), 0xFF, LMAX_DET_TEX_NUM); + + PROFILE_BLOCK_START(calcUsedTypes) + int typesUsed = getMostUsedDetTex(x0, y0, texDataSize, detail_tex_ids.data(), typeRemap.data(), tex2 ? LMAX_DET_TEX_NUM : 5); + PROFILE_BLOCK_END(calcUsedTypes) + if (tex1_rgba && tex2_rgba) + for (int i = 0; i < detail_tex_ids.size(); i++) + if (detail_tex_ids[i] != 0xFF) + detail_tex_ids[i] = lcRemap.size() ? lcRemap[detail_tex_ids[i]] : 0xFF; + + // encode texels + PROFILE_BLOCK_START(encodeTexels); + SmallTab pix2Data; + unsigned pix2DataPtrStride = 0; + if (tex2 && !tex2_rgba) + { + clear_and_resize(pix2Data, texSize * texSize); + pix2DataPtrStride = texSize * 4; + mem_set_0(pix2Data); + } + if (tex2_rgba) + { + G_ASSERT(stride2 >= texSize * 4); + pix2DataPtrStride = stride2; + } + TexPixel32 *pix2DataPtr = tex2_rgba ? (TexPixel32 *)tex2 : pix2Data.data(); + + int add_step1 = (stride / (tex1_rgba ? 4 : 2) - texDataSize) * (tex1_rgba ? 2 : 1); + int add_step2 = pix2DataPtrStride / 4 - texDataSize; + if (detTexWtMap) + { + uint16_t *p = (uint16_t *)tex1; + TexPixel32 *p2 = pix2DataPtr; + + for (int yc = y0, yce = yc + texDataSize; yc < yce; yc++, p += add_step1, p2 += add_step2) + for (int xc = x0, xce = xc + texDataSize; xc < xce; xc++, p++, p2++) + { + uint64_t p_wt = detTexWtMap->getData(xc, yc); + uint64_t p_idx = detTexIdxMap->getData(xc, yc); + unsigned u = 0, u2 = 0xFF000000; + + for (int i = 0; i < 8; i++, p_wt >>= 8, p_idx >>= 8) + if (p_wt) + { + int idx = typeRemap[int(p_idx & 0xFF)]; + if (idx == 0xFF) + continue; + if (idx < 3) + u |= ((p_wt >> 4) & 0xF) << (8 - idx * 4); + else if (idx == 3) + u |= (p_wt & 0xF0) << 8; + else if (idx < 6) + u2 |= (p_wt & 0xFF) << (16 - (idx - 4) * 8); + } + else + break; + if (tex1_rgba) + { + *(unsigned *)p = convert_argb4_to_argb8(u); //-V1032 + p++; + } + else + *p = u; + if (tex2) + p2->u = u2; + } + G_ASSERT((char *)p <= tex1 + stride * texSize); + G_ASSERT(!tex2 || (char *)p2 <= ((char *)pix2DataPtr) + pix2DataPtrStride * texSize); + } + else + { + G_ASSERTF(lcmScale <= 1, "lcmScale > 1 without detTex WeightMap not supported!"); + uint16_t *p = (uint16_t *)tex1; + TexPixel32 *p2 = pix2DataPtr; + + for (int yc = y0, yce = yc + texDataSize; yc < yce; yc++, p += add_step1, p2 += add_step2) + for (int xc = x0, xce = xc + texDataSize; xc < xce; xc++, p++, p2++) + { + uint8_t idx = typeRemap[getDetLayerDesc().getLayerData(landClsMap.getData(xc, yc))]; + if (idx == 0xFF) + idx = 0; + if (idx < 3) + *p = 0xF << (8 - idx * 4); + else if (idx == 3) + *p = 0xF << 12; + else if (idx < 6 && tex2) + p2->u = (0xFF << (16 - (idx - 4) * 8)) | 0xFF000000; + if (tex1_rgba) + { + *(unsigned *)p = convert_argb4_to_argb8(*p); //-V1032 + p++; + } + } + G_ASSERT((char *)p <= tex1 + stride * texSize); + G_ASSERT(!tex2 || (char *)p2 <= ((char *)pix2DataPtr) + pix2DataPtrStride * texSize); + } + PROFILE_BLOCK_END(encodeTexels); + + PROFILE_BLOCK_START(dxtCvt); + if (tex2 && !tex2_rgba) + { + ddstexture::Converter cnv; + cnv.format = ddstexture::Converter::fmtDXT1a; + if (targetCode == _MAKE4C('iOS')) + cnv.format = ddstexture::Converter::fmtASTC8, stride2 = stride2 / 2; + cnv.mipmapType = ddstexture::Converter::mipmapNone; + cnv.mipmapCount = 0; + + DynamicMemGeneralSaveCB cwr(tmpmem, texSize * texSize + 256, 64 << 10); + if (!dagTools->ddsConvertImage(cnv, cwr, pix2DataPtr, texSize, texSize, texSize * 4)) + DAEDITOR3.conError("cannot convert %dx%d image at (%d,%d)", texSize, texSize, x0, y0); + else + { + if (0 && typesUsed > 1 && cnv.format != ddstexture::Converter::fmtASTC8) + { + save_tga32(String(260, "det_wt_%d,%d_%d.tga", x0, y0, typesUsed), pix2DataPtr, texSize, texSize, texSize * 4); + + Tab pix(tmpmem); + pix.resize(texSize * texSize); + uint16_t *p = (uint16_t *)tex1; + for (int i = 0; i < pix.size(); i++, p++) + pix[i].u = ((*p & 0xF) << 4) | ((*p & 0xF0) << 8) | ((*p & 0xF00) << 12) | ((*p & 0xF000) << 16); + save_tga32(String(260, "det_wt1_%d,%d_%d.tga", x0, y0, typesUsed), pix.data(), texSize, texSize, texSize * 4); + + FullFileSaveCB fcwr(String(260, "det_wt_%d,%d_%d.dds", x0, y0, typesUsed)); + fcwr.write(cwr.data(), cwr.size()); + } + G_ASSERT((texSize / 4) * stride2 == cwr.size() - 128); + memcpy(tex2, cwr.data() + 128, (texSize / 4) * stride2); + } + } + PROFILE_BLOCK_END(dxtCvt); + + int totalMs = calcUsedTypes + encodeTexels + dxtCvt; + if (totalMs > 30) + debug("%s done for %d msec (calcUsed %d, %d encode, %d dxtCvt), texSize %d", __FUNCTION__, totalMs, calcUsedTypes, encodeTexels, + dxtCvt, texSize); + + *done_mark = true; + return typesUsed; +} + +static const int MAX_DETAILS_PER_QUAD = 64; +struct QuadData +{ + uint8_t *data; + int w, h; + + QuadData() : data(NULL), w(0), h(0) {} + ~QuadData() + { + if (data) + memfree_anywhere(data); + } +}; +class UpdateRawTextures +{ +public: + Texture *texture[256]; + bool textureLocked[256]; + uint8_t *textureData[256]; + int textureStride[256]; + uint8_t lockedTextures[256]; + int lockedTexturesCnt; + int wd, ht; + UpdateRawTextures(int w, int h) : wd(w), ht(h) + { + memset(texture, 0, sizeof(texture)); + memset(textureLocked, 0, sizeof(textureLocked)); + memset(textureData, 0, sizeof(textureData)); + memset(textureStride, 0, sizeof(textureStride)); + memset(lockedTextures, 0, sizeof(lockedTextures)); + lockedTexturesCnt = 0; + } + void startUpdateData(int x0, int y0, int x1, int y1) { G_ASSERT(lockedTexturesCnt == 0); } + + void updateData(uint8_t texId, int x, int y, uint8_t val) + { + if (!textureLocked[texId]) + { + if (!texture[texId]) + texture[texId] = d3d::create_tex(NULL, wd, ht, TEXFMT_L8 | TEXCF_READABLE | TEXCF_DYNAMIC, 1, "blueWhite"); + G_ASSERT(texture[texId]); + unsigned texLockFlags = TEXLOCK_UPDATEFROMSYSTEX | TEXLOCK_NOSYSLOCK | TEXLOCK_RWMASK | TEXLOCK_SYSTEXLOCK; + if (texture[texId]->lockimg((void **)&textureData[texId], textureStride[texId], 0, texLockFlags)) + { + textureLocked[texId] = true; + lockedTextures[lockedTexturesCnt] = texId; + lockedTexturesCnt++; + } + } + if (!textureLocked[texId]) + return; + textureData[texId][clamp(x, 0, wd - 1) + clamp(y, 0, ht - 1) * textureStride[texId]] = val; + } + void endUpdateData(uint8_t texId, int x, int y, uint8_t val) + { + for (int i = 0; i < lockedTexturesCnt; ++i) + { + int texId = lockedTextures[i]; + G_ASSERT(textureLocked[texId]); + if (textureLocked[texId]) + { + texture[texId]->unlockimg(); + textureLocked[texId] = false; + } + } + lockedTexturesCnt = 0; + } +}; + +template +int HmapLandPlugin::updateLandclassWeight(int x0, int y0, int x1, int y1, UpdateLC &update_cb) +{ + G_ASSERT(detTexWtMap) + update_cb.startUpdateData(x0, y0, x1, y1); + int w = y1 - y0 + 1, h = x1 - x0 + 1; + for (int yc = y0; yc <= y1; yc++) + for (int xc = x0; xc <= x1; xc++) + { + uint64_t p_wt = detTexWtMap->getData(xc, yc); + uint64_t p_idx = detTexIdxMap->getData(xc, yc); + unsigned u = 0, u2 = 0xFF000000; + + for (int i = 0; i < 8; i++, p_wt >>= 8, p_idx >>= 8) + if (p_wt) + { + int idx = int(p_idx & 0xFF); + update_cb.updateData(idx, xc, yc, uint8_t(p_wt & 0xFF)); + } + else + break; + } + update_cb.endUpdateData(); + + return typesUsed; +} + +// Return total types should be used. If more, than max_detail_tex - the cell is invalid +int HmapLandPlugin::getMostUsedDetTex(int x0, int y0, int texDataSize, uint8_t *det_tex_ids, uint8_t *idx_remap, int max_dtn) +{ + int texUsed = 0; + + // get most used types + SmallTab typeCnt; + clear_and_resize(typeCnt, numDetailTextures >= 1 ? numDetailTextures : 1); + mem_set_0(typeCnt); + + if (detTexWtMap) + { + for (int yc = y0, yce = yc + texDataSize; yc < yce; yc++) + for (int xc = x0, xce = xc + texDataSize; xc < xce; xc++) + { + uint64_t p_wt = detTexWtMap->getData(xc, yc); + uint64_t p_idx = detTexIdxMap->getData(xc, yc); + for (int i = 0; i < 8; i++, p_wt >>= 8, p_idx >>= 8) + if (p_wt) + { + if (unsigned(p_idx & 0xFF) < typeCnt.size()) + typeCnt[int(p_idx & 0xFF)] += p_wt & 0xFF; + } + else + break; + } + } + else + for (int y = 0, yc = y0; y < texDataSize; ++y, yc++) + for (int x = 0, xc = x0; x < texDataSize; ++x, xc++) + { + uint8_t t = getDetLayerDesc().getLayerData(landClsMap.getData(xc, yc)); + if (t >= typeCnt.size()) + t = 0; + typeCnt[t] += 255; + } + uint8_t taken[256]; + memset(taken, 0xFF, 256); + for (int i = 0; i < max_dtn; ++i) + { + int bi = 0; + unsigned bc = 0; + + for (int j = 0; j < typeCnt.size(); ++j) + if (taken[j] == 0xFF && typeCnt[j] > bc) + { + bc = typeCnt[j]; + bi = j; + } + + if (!bc) + break; + det_tex_ids[i] = bi; + taken[bi] = i; + // idx_remap[bi] = i; + texUsed++; + } + + struct AscendCompare + { + bool operator()(uint8_t a, uint8_t b) const { return a < b; } + }; + stlsort::sort(det_tex_ids, det_tex_ids + texUsed, AscendCompare()); + for (int i = 0; i < texUsed; ++i) + idx_remap[det_tex_ids[i]] = i; + + return texUsed; +} + +// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ// +void autocenterHM(PropPanel2 &panel) +{ + bool autocenter = panel.getBool(PID_HEIGHTMAP_AUTOCENTER); + if (autocenter) + { + Point2 size = panel.getPoint2(PID_HM_SIZE_METERS); + Point2 offset = Point2(-size.x / 2, -size.y / 2); + + panel.setPoint2(PID_HEIGHTMAP_OFFSET, offset); + } + + panel.setEnabledById(PID_HEIGHTMAP_OFFSET, !autocenter); +}; + + +void HmapLandPlugin::createHeightmap() +{ + class CreateHeightmapEventHandler : public ControlEventHandler + { + public: + CreateHeightmapEventHandler(HmapLandPlugin *plugin) : mPlugin(plugin) {} + + void onChange(int pcb_id, PropPanel2 *panel) + { + Point2 p2; + + switch (pcb_id) + { + case PID_HM_SIZE_PIXELS: + { + p2 = panel->getPoint2(PID_HM_SIZE_PIXELS); + if (p2.x != real2int(p2.x) || p2.y != real2int(p2.y)) + { + p2.x = real2int(p2.x); + p2.y = real2int(p2.y); + panel->setPoint2(PID_HM_SIZE_PIXELS, p2); + } + } + break; + + case PID_GRID_CELL_SIZE: + { + p2 = panel->getPoint2(PID_HM_SIZE_PIXELS) * panel->getFloat(PID_GRID_CELL_SIZE); + + panel->setPoint2(PID_HM_SIZE_METERS, p2); + autocenterHM(*panel); + } + break; + + case PID_HEIGHTMAP_AUTOCENTER: autocenterHM(*panel); break; + + case PID_SCRIPT_FILE: + { + String newfn(panel->getText(pcb_id)); + + if (newfn.length()) + ::defaultHM.scriptPath = newfn; + } + break; + } + } + + private: + HmapLandPlugin *mPlugin; + }; + + CreateHeightmapEventHandler eventHandler(this); + + + CDialogWindow *myDlg = DAGORED2->createDialog(_pxScaled(280), _pxScaled(600), "Create heightmap..."); + PropertyContainerControlBase *myPanel = myDlg->getPanel(); + myPanel->setEventHandler(&eventHandler); + + + PropertyContainerControlBase *grp = myPanel->createGroupBox(-1, "Heightmap size"); + + grp->createPoint2(PID_HM_SIZE_PIXELS, "Size in pixels:", ::defaultHM.sizePixels); + grp->createPoint2(PID_HM_SIZE_METERS, "Size in meters:", ::defaultHM.sizeMeters, 0); + + grp = myPanel->createGroupBox(-1, "Heightmap parameters"); + + grp->createEditFloat(PID_GRID_CELL_SIZE, "Cell size:", ::defaultHM.cellSize); + grp->createEditFloat(PID_HEIGHT_SCALE, "Height scale:", ::defaultHM.heightScale); + grp->createEditFloat(PID_HEIGHT_OFFSET, "Height offset:", ::defaultHM.heightOffset); + grp->createPoint2(PID_HEIGHTMAP_OFFSET, "Origin offset:", ::defaultHM.originOffset, !::defaultHM.doAutocenter); + grp->createCheckBox(PID_HEIGHTMAP_AUTOCENTER, "Autocenter", ::defaultHM.doAutocenter); + + PropertyContainerControlBase *subGrp = grp->createGroupBox(-1, "Preload collision area"); + + subGrp->createPoint2(PID_HM_COLLISION_OFFSET, "Offset (in %):", ::defaultHM.collisionOffset); + subGrp->createPoint2(PID_HM_COLLISION_SIZE, "Size (in %):", ::defaultHM.collisionSize); + subGrp->createCheckBox(PID_HM_COLLISION_SHOW, "Show area", ::defaultHM.collisionShow); + + grp->createFileEditBox(PID_SCRIPT_FILE, "Script file:", "" /*::defaultHM.scriptPath*/); + + Tab filters(tmpmem); + filters.push_back() = "Script files (*.nut)|*.nut"; + filters.push_back() = "All files (*.*)|*.*"; + myPanel->setStrings(PID_SCRIPT_FILE, filters); + // myPanel->setText(PID_SCRIPT_FILE, DAGORED2->getSdkDir()); + + + if (myDlg->showDialog() == DIALOG_ID_OK) + { + const char *scriptPath = ::defaultHM.scriptPath; + + if (scriptPath && *scriptPath && !::dd_file_exist(scriptPath)) + { + wingw::message_box(wingw::MBS_EXCL, "Creation error", "Color generation script file not exists of not specified."); + return; + } + + ::defaultHM.sizePixels = myPanel->getPoint2(PID_HM_SIZE_PIXELS); + ::defaultHM.sizeMeters = myPanel->getPoint2(PID_HM_SIZE_METERS); + ::defaultHM.cellSize = myPanel->getFloat(PID_GRID_CELL_SIZE); + ::defaultHM.heightScale = myPanel->getFloat(PID_HEIGHT_SCALE); + ::defaultHM.heightOffset = myPanel->getFloat(PID_HEIGHT_OFFSET); + ::defaultHM.doAutocenter = myPanel->getBool(PID_HEIGHTMAP_AUTOCENTER); + ::defaultHM.originOffset = myPanel->getPoint2(PID_HEIGHTMAP_OFFSET); + ::defaultHM.collisionOffset = myPanel->getPoint2(PID_HM_COLLISION_OFFSET); + ::defaultHM.collisionSize = myPanel->getPoint2(PID_HM_COLLISION_SIZE); + ::defaultHM.collisionShow = myPanel->getBool(PID_HM_COLLISION_SHOW); + + colorGenScriptFilename = ::defaultHM.scriptPath; + + gridCellSize = ::defaultHM.cellSize; + if (gridCellSize <= 0) + gridCellSize = 1.0; + + heightMap.heightScale = ::defaultHM.heightScale; + heightMap.heightOffset = ::defaultHM.heightOffset; + heightMapOffset = ::defaultHM.originOffset; + doAutocenter = ::defaultHM.doAutocenter; + collisionArea.ofs = ::defaultHM.collisionOffset; + collisionArea.sz = ::defaultHM.collisionSize; + collisionArea.show = ::defaultHM.collisionShow; + tileTexName = defaultHM.tileTex; + tileXSize = defaultHM.tileTexSz.x; + tileYSize = defaultHM.tileTexSz.y; + if (colorGenScriptFilename.empty() && !genLayers.size()) + addGenLayer("default"); + + if (propPanel) + propPanel->fillPanel(); + + IPoint2 size(::defaultHM.sizePixels.x, ::defaultHM.sizePixels.y); + CoolConsole &con = DAGORED2->getConsole(); + + MapStorage &hm = heightMap.getInitialMap(); + hm.reset(size.x, size.y, 0); + createHeightmapFile(con); + + heightMap.resetFinal(); + + if (!heightMap.flushData()) + { + con.addMessage(ILogWriter::ERROR, "Error saving heightmap data"); + con.endLog(); + return; + } + + getColorGenVarsFromScript(); + applyHmModifiers(false); + generateLandColors(); + calcFastLandLighting(); + // autocenterHeightmap(propPanel->getPanel(), false); + autocenterHeightmap(propPanel->getPanelWindow(), false); + + resetRenderer(); + onLandSizeChanged(); + } + + DAGORED2->deleteDialog(myDlg); +} + + +void HmapLandPlugin::importHeightmap() +{ + int import_det_hmap = 0; + if (detDivisor) + switch (wingw::message_box(wingw::MBS_QUEST | wingw::MBS_YESNOCANCEL, "Select heightmap to import", + "Level contains both main and detailed heightmap\n" + "Select YES to import MAIN heightmap, or NO to import DETAILED heightmap")) + { + case wingw::MB_ID_YES: import_det_hmap = 0; break; + case wingw::MB_ID_NO: import_det_hmap = 1; break; + default: return; + } + + String path; + path = wingw::file_open_dlg(NULL, "Import heightmap", hmapImportCaption, "r32", lastHmapImportPath); + + if (path.length()) + { + lastHmapImportPath = path; + if (import_det_hmap) + lastHmapImportPathDet = path; + else + lastHmapImportPathMain = path; + + const char *ext = dd_get_fname_ext(path); + + if (stricmp(ext, ".r32") != 0 && stricmp(ext, ".height") != 0 && !import_det_hmap && lastMinHeight[import_det_hmap] != MAX_REAL && + lastHeightRange[import_det_hmap] != MAX_REAL) + { + if (wingw::message_box(wingw::MBS_QUEST | wingw::MBS_YESNO, "Set parameters from last export", + "Set offset and scale from last heightmap export?\n" + "Last offset = %g, scale = %g", + lastMinHeight[import_det_hmap], lastHeightRange[import_det_hmap]) == wingw::MB_ID_YES) + { + heightMap.heightOffset = lastMinHeight[import_det_hmap]; + heightMap.heightScale = lastHeightRange[import_det_hmap]; + } + } + if (stricmp(ext, ".r32") != 0 && stricmp(ext, ".height") != 0) + { + class HmapImportSizeDlg : public ControlEventHandler + { + enum + { + ID_MIN_HEIGHT = 1, + ID_HEIGHT_RANGE, + }; + + public: + HmapImportSizeDlg(float &min_height, float &height_range) : minHeight(min_height), heightRange(height_range), mDialog(NULL) + { + mDialog = DAGORED2->createDialog(_pxScaled(240), _pxScaled(170), "Import HMAP data range"); + + PropPanel2 &panel = *mDialog->getPanel(); + panel.setEventHandler(this); + + if (minHeight > MAX_REAL / 2 && heightRange > MAX_REAL / 2) + minHeight = 0, heightRange = 8192; + else + panel.createStatic(-1, "From last HMAP export:"); + panel.createEditFloat(ID_MIN_HEIGHT, "Minimal height:", minHeight); + panel.createEditFloat(ID_HEIGHT_RANGE, "Height range:", heightRange); + } + + ~HmapImportSizeDlg() { del_it(mDialog); } + + virtual bool execute() + { + int ret = mDialog->showDialog(); + + if (ret == DIALOG_ID_OK) + { + PropPanel2 &panel = *mDialog->getPanel(); + minHeight = panel.getFloat(ID_MIN_HEIGHT); + heightRange = panel.getFloat(ID_HEIGHT_RANGE); + return true; + } + return false; + } + + private: + float &minHeight; + float &heightRange; + + CDialogWindow *mDialog; + }; + + HmapImportSizeDlg dlg(lastMinHeight[import_det_hmap], lastHeightRange[import_det_hmap]); + if (!dlg.execute()) + return; + } + + if (importHeightmap(path, import_det_hmap ? HeightmapTypes::HEIGHTMAP_DET : HeightmapTypes::HEIGHTMAP_MAIN)) + { + updateHeightMapTex(false); + updateHeightMapTex(true); + if (wingw::message_box(wingw::MBS_YESNO | wingw::MBS_QUEST, "Rebuild everything", + "Rebuild everything for updated HMAP data?\n(recommended)") == wingw::MB_ID_YES) + { + generateLandColors(); + calcFastLandLighting(); + } + autocenterHeightmap(propPanel ? propPanel->getPanelWindow() : NULL, false); + resetRenderer(); + } + } +} + +bool HmapLandPlugin::checkAndReimport(String &path, FileChangeStat &lastChangeOld, HeightmapTypes type) +{ + const char *type_str = "?"; + switch (type) + { + case HeightmapTypes::HEIGHTMAP_DET: type_str = "detailed"; break; + case HeightmapTypes::HEIGHTMAP_MAIN: type_str = "main"; break; + case HeightmapTypes::HEIGHTMAP_WATER_DET: type_str = "water det"; break; + case HeightmapTypes::HEIGHTMAP_WATER_MAIN: type_str = "water main"; break; + } + + if (path.length()) + { + DagorStat s; + if (df_stat(path, &s) < 0) + { + DAEDITOR3.conError("Failed get filestat for: %s", path); + return false; + } + if (s.mtime == lastChangeOld.mtime && s.size == lastChangeOld.size) + { + DAEDITOR3.conWarning("Skip reloading %s heightmap: %s (not changed)", type_str, path); + return false; + } + if (importHeightmap(path, type)) + { + lastChangeOld.mtime = s.mtime; + lastChangeOld.size = s.size; + DAEDITOR3.conNote("=== Reloaded %s heightmap: %s", type_str, path); + + if (type == HeightmapTypes::HEIGHTMAP_MAIN) + updateHeightMapTex(false); + else if (type == HeightmapTypes::HEIGHTMAP_DET) + updateHeightMapTex(true); + else if (type == HeightmapTypes::HEIGHTMAP_WATER_DET || type == HeightmapTypes::HEIGHTMAP_WATER_MAIN) + { + if (IWaterService *waterSrv = EDITORCORE->queryEditorInterface()) + { + Point2 hmapSize(heightMap.getMapSizeX() * gridCellSize, heightMap.getMapSizeY() * gridCellSize); + Point2 hmapEnd = heightMapOffset + hmapSize; + waterSrv->setHeightmap(waterHeightmapDet, waterHeightmapMain, waterHeightMinRangeDet, waterHeightMinRangeMain, detRect, + BBox2(heightMapOffset.x, heightMapOffset.y, hmapEnd.x, hmapEnd.y)); + } + } + return true; + } + else + { + DAEDITOR3.conError("Failed to re-import %s heightmap: %s", type_str, path); + return false; + } + } + else + { + DAEDITOR3.conWarning("No %s heightmap to be reloaded, import it first", type_str); + return false; + } +} + +void HmapLandPlugin::reimportHeightmap() +{ + bool rebuildDet = checkAndReimport(lastHmapImportPathDet, lastChangeDet, HeightmapTypes::HEIGHTMAP_DET); + bool rebuildMain = checkAndReimport(lastHmapImportPathMain, lastChangeMain, HeightmapTypes::HEIGHTMAP_MAIN); + bool rebuildWaterDet = checkAndReimport(lastWaterHeightmapImportPathDet, lastChangeWaterDet, HeightmapTypes::HEIGHTMAP_WATER_DET); + bool rebuildWaterMain = + checkAndReimport(lastWaterHeightmapImportPathMain, lastChangeWaterMain, HeightmapTypes::HEIGHTMAP_WATER_MAIN); + + if (rebuildDet || rebuildMain || rebuildWaterDet || rebuildWaterMain) + { + DAEDITOR3.conNote("Rebuild reloaded heightmaps"); + generateLandColors(); + calcFastLandLighting(); + autocenterHeightmap(propPanel ? propPanel->getPanelWindow() : NULL, false); + resetRenderer(); + } +} + + +void HmapLandPlugin::eraseHeightmap() +{ + if (wingw::message_box(wingw::MBS_QUEST | wingw::MBS_YESNO, "Confirm erase", "Erase heightmap?") == wingw::MB_ID_YES) + { + heightMap.clear(); + landMeshMap.clear(true); + colorMap.eraseFile(); + lightMapScaled.eraseFile(); + landClsMap.eraseFile(); + if (detTexIdxMap) + detTexIdxMap->eraseFile(); + if (detTexWtMap) + detTexWtMap->eraseFile(); + resetRenderer(); + onLandSizeChanged(); + } +} + +void HmapLandPlugin::importWaterHeightmap(bool det) +{ + IWaterService *waterSrv = EDITORCORE->queryEditorInterface(); + if (!waterSrv) + return; + enum + { + ID_MIN_HEIGHT = 1, + ID_HEIGHT_RANGE, + }; + eastl::string dialogText{eastl::string::CtorSprintf{}, "Importing water %s heightmap.", det ? "DET" : "MAIN"}; + CDialogWindow *dialog = DAGORED2->createDialog(_pxScaled(240), _pxScaled(170), dialogText.c_str()); + PropPanel2 &panel = *dialog->getPanel(); + panel.setEventHandler(this); + Point2 *waterHeightMinRange = &waterHeightMinRangeDet; + HeightMapStorage *waterHeightmap = &waterHeightmapDet; + if (!det) + { + waterHeightMinRange = &waterHeightMinRangeMain; + waterHeightmap = &waterHeightmapMain; + } + if (waterHeightMinRange->y <= 0) + { + waterHeightMinRange->x = heightMap.heightOffset; + waterHeightMinRange->y = heightMap.heightScale; + } + panel.createEditFloat(ID_MIN_HEIGHT, "Minimal height:", waterHeightMinRange->x); + panel.createEditFloat(ID_HEIGHT_RANGE, "Height range:", waterHeightMinRange->y); + int ret = dialog->showDialog(); + if (ret == DIALOG_ID_OK) + { + PropPanel2 &panel = *dialog->getPanel(); + waterHeightMinRange->x = panel.getFloat(ID_MIN_HEIGHT); + waterHeightMinRange->y = panel.getFloat(ID_HEIGHT_RANGE); + String path; + String initialPath = det ? lastWaterHeightmapImportPathDet : lastWaterHeightmapImportPathMain; + if (initialPath.empty()) + initialPath = lastWaterHeightmapImportPath; + path = wingw::file_open_dlg(NULL, "Import heightmap", hmapImportCaption, "r32", initialPath); + del_it(dialog); + + if (path.length()) + { + lastWaterHeightmapImportPath = path; + if (det) + lastWaterHeightmapImportPathDet = path; + else + lastWaterHeightmapImportPathMain = path; + waterHeightmap->heightOffset = 0.0; + waterHeightmap->heightScale = 1.0; + hmlService->destroyStorage(*waterHeightmap); + hmlService->createStorage(*waterHeightmap, detRectC[1].x - detRectC[0].x, detRectC[1].y - detRectC[0].y, false); + createWaterHmapFile(DAGORED2->getConsole(), det); + if (!importHeightmap(path, det ? HeightmapTypes::HEIGHTMAP_WATER_DET : HeightmapTypes::HEIGHTMAP_WATER_MAIN)) + { + hmlService->destroyStorage(*waterHeightmap); + hmlService->createStorage(*waterHeightmap, 0, 0, false); + waterHeightmap->getInitialMap().eraseFile(); + } + else + { + Point2 hmapSize(heightMap.getMapSizeX() * gridCellSize, heightMap.getMapSizeY() * gridCellSize); + Point2 hmapEnd = heightMapOffset + hmapSize; + waterSrv->setHeightmap(waterHeightmapDet, waterHeightmapMain, waterHeightMinRangeDet, waterHeightMinRangeMain, detRect, + BBox2(heightMapOffset.x, heightMapOffset.y, hmapEnd.x, hmapEnd.y)); + } + } + } +} + +void HmapLandPlugin::eraseWaterHeightmap() +{ + enum + { + ID_REMOVE_MAIN = 1, + ID_REMOVE_DET, + }; + eastl::string dialogText{eastl::string::CtorSprintf{}, "Choose heightmaps for erase."}; + CDialogWindow *dialog = DAGORED2->createDialog(_pxScaled(240), _pxScaled(170), dialogText.c_str()); + PropPanel2 &panel = *dialog->getPanel(); + panel.setEventHandler(this); + panel.createCheckBox(ID_REMOVE_MAIN, "Erase MAIN hmap"); + panel.createCheckBox(ID_REMOVE_DET, "Erase DET hmap"); + int ret = dialog->showDialog(); + if (ret == DIALOG_ID_OK) + { + PropPanel2 &panel = *dialog->getPanel(); + bool removeCheckboxes[2] = {panel.getBool(ID_REMOVE_MAIN), panel.getBool(ID_REMOVE_DET)}; + HeightMapStorage *waterHeightmap[2] = {&waterHeightmapMain, &waterHeightmapDet}; + for (int i = 0; i < 2; i++) + { + if (!removeCheckboxes[i]) + continue; + hmlService->destroyStorage(*waterHeightmap[i]); + hmlService->createStorage(*waterHeightmap[i], 0, 0, false); + waterHeightmap[i]->getInitialMap().eraseFile(); + } + Point2 hmapSize(heightMap.getMapSizeX() * gridCellSize, heightMap.getMapSizeY() * gridCellSize); + Point2 hmapEnd = heightMapOffset + hmapSize; + IWaterService *waterSrv = EDITORCORE->queryEditorInterface(); + if (waterSrv) + waterSrv->setHeightmap(waterHeightmapDet, waterHeightmapMain, waterHeightMinRangeDet, waterHeightMinRangeMain, detRect, + BBox2(heightMapOffset.x, heightMapOffset.y, hmapEnd.x, hmapEnd.y)); + } +} + +void HmapLandPlugin::exportLand() +{ + String path = wingw::file_save_dlg(NULL, "Export land to game", "Land files (*.lnd.dat)|*.lnd.dat|All files (*.*)|*.*", "lnd.dat", + lastLandExportPath); + + if (path.length()) + { + lastLandExportPath = path; + + if (exportLand(path)) + wingw::message_box(wingw::MBS_INFO, "Export land to game", "Export was successful."); + } +} + +void HmapLandPlugin::exportLoftMasks(const char *_out_folder, int main_hmap_sz, int det_hmap_sz, float hmin, float hmax, + int prefab_dest_idx) +{ + ISplineGenService *splSrv = EDITORCORE->queryEditorInterface(); + FastIntList loft_layers; + OAHashNameMap loft_tags; + uint64_t layers_hide_mask = DAEDITOR3.getEntityLayerHiddenMask(); + + String out_folder[2]; + for (int i = 0; i < 2; i++) + { + out_folder[i] = _out_folder; + if (lastExpLoftUseRect[i] && lastExpLoftCreateAreaSubfolders) + { + out_folder[i].aprintf(0, "/.loft-area(%g,%g)-%gx%g", lastExpLoftRect[i][0].x, lastExpLoftRect[i][0].y, + lastExpLoftRect[i].width().x, lastExpLoftRect[i].width().y); + dd_mkdir(out_folder[i]); + } + } + + loft_layers.addInt(0); + if (prefab_dest_idx >= 0) + prefab_dest_idx = loft_tags.addNameId(String(0, "prefabs_%d", prefab_dest_idx)); + + if (splSrv) + { + splSrv->gatherLoftLayers(loft_layers, false); + splSrv->gatherLoftTags(loft_tags); + } + for (int i = 0; i < objEd.splinesCount(); ++i) + objEd.getSpline(i)->gatherPolyGeomLoftTags(loft_tags); + + for (int i = 0; i < 2; i++) + { + Tab old_files; + find_files_in_folder(old_files, out_folder[i], ".ddsx", false, true, false); + for (SimpleString &s : old_files) + { + const char *fn = dd_get_fname(s); + if (strncmp(fn, "loftMask_", 9) != 0) + continue; + if ((i == 0 && strncmp(fn + 9, "m_", 2) == 0) || (i == 1 && strncmp(fn + 9, "d_", 2) == 0)) + if (strchr("mhif", *(dd_get_fname_ext(fn) - 1))) + dd_erase(s); + } + } + + GeomObject *all_loft_obj = dagGeom->newGeomObject(midmem); + for (int lli = 0; lli < loft_layers.size(); lli++) + { + int ll = loft_layers.getList()[lli]; + if (splSrv) + splSrv->gatherStaticGeometry(*all_loft_obj->getGeometryContainer(), StaticGeometryNode::FLG_RENDERABLE, false, ll, 2, -1, + layers_hide_mask); + for (int i = 0; i < objEd.splinesCount(); ++i) + if (((layers_hide_mask >> objEd.getSpline(i)->getEditLayerIdx()) & 1) == 0) + objEd.getSpline(i)->gatherStaticGeometry(*all_loft_obj->getGeometryContainer(), StaticGeometryNode::FLG_RENDERABLE, false, ll, + 2); + } + + int layers_exported = 0; + auto gather_layer_func = [&](int ltNid, const char *ln) { + GeomObject *obj = dagGeom->newGeomObject(midmem); + + if (ltNid == prefab_dest_idx) + { + if (IGenEditorPlugin *p = DAGORED2->getPluginByName("_prefabEntMgr")) + if (IGatherStaticGeometry *geom = p->queryInterface()) + geom->gatherStaticVisualGeometryForStage(*obj->getGeometryContainer(), prefabs::LOFT_MASK_EXPORT); + } + else + for (int i = 0; i < all_loft_obj->getGeometryContainer()->nodes.size(); ++i) + { + StaticGeometryNode *node = all_loft_obj->getGeometryContainer()->nodes[i]; + if (node && ltNid == loft_tags.getNameId(node->script.getStr("layerTag", ""))) + { + obj->getGeometryContainer()->nodes.push_back(node); + all_loft_obj->getGeometryContainer()->nodes[i] = NULL; + } + } + + if (obj->getGeometryContainer()->nodes.size()) + { + obj->setTm(TMatrix::IDENT); + obj->notChangeVertexColors(true); + dagGeom->geomObjectRecompile(*obj); + obj->notChangeVertexColors(false); + + String fn0, fn1, fnI, fnF; + if (main_hmap_sz > 0) + { + fn0.printf(0, "%s/loftMask_m_%s_m.ddsx", out_folder[0], ln); + fn1.printf(0, "%s/loftMask_m_%s_h.ddsx", out_folder[0], ln); + fnI.printf(0, "%s/loftMask_m_%s_i.ddsx", out_folder[0], ln); + fnF.printf(0, "%s/loftMask_m_%s_f.ddsx", out_folder[1], ln); + hmlService->exportLoftMasks(fn0, fnI, fn1, ltNid == prefab_dest_idx ? nullptr : fnF.str(), main_hmap_sz, + lastExpLoftUseRect[0] ? Point3::xVy(lastExpLoftRect[0][0], hmin) : Point3::xVz(landBox[0], hmin), + lastExpLoftUseRect[0] ? Point3::xVy(lastExpLoftRect[0][1], hmax) : Point3::xVz(landBox[1], hmax), obj); + } + if (det_hmap_sz > 0) + { + fn0.printf(0, "%s/loftMask_d_%s_m.ddsx", out_folder[1], ln); + fn1.printf(0, "%s/loftMask_d_%s_h.ddsx", out_folder[1], ln); + fnI.printf(0, "%s/loftMask_d_%s_i.ddsx", out_folder[1], ln); + fnF.printf(0, "%s/loftMask_d_%s_f.ddsx", out_folder[1], ln); + hmlService->exportLoftMasks(fn0, fnI, fn1, ltNid == prefab_dest_idx ? nullptr : fnF.str(), det_hmap_sz, + Point3::xVy(lastExpLoftUseRect[1] ? lastExpLoftRect[1][0] : detRect[0], hmin), + Point3::xVy(lastExpLoftUseRect[1] ? lastExpLoftRect[1][1] : detRect[1], hmax), obj); + } + layers_exported++; + } + dagGeom->deleteGeomObject(obj); + }; + gather_layer_func(-1, "def"); + iterate_names(loft_tags, gather_layer_func); + dagGeom->deleteGeomObject(all_loft_obj); + wingw::message_box(layers_exported ? wingw::MBS_INFO : wingw::MBS_EXCL, "Loft masks exported", + (lastExpLoftUseRect[0] || lastExpLoftUseRect[1]) && lastExpLoftCreateAreaSubfolders + ? String(0, "Exported %d loft masks (stage:i=2) to\n\n%s\n%s", layers_exported, main_hmap_sz > 0 ? out_folder[0].str() : "", + det_hmap_sz > 0 ? out_folder[1].str() : "") + : String(0, "Exported %d loft masks (stage:i=2) to\n %s", layers_exported, _out_folder)); +} + +void HmapLandPlugin::exportHeightmap() +{ + int export_det_hmap = 0; + if (detDivisor) + switch (wingw::message_box(wingw::MBS_QUEST | wingw::MBS_YESNOCANCEL, "Select heightmap to export", + "Level contains both main and detailed heightmap\n" + "Select YES to export MAIN heightmap, or NO to export DETAILED heightmap")) + { + case wingw::MB_ID_YES: export_det_hmap = 0; break; + case wingw::MB_ID_NO: export_det_hmap = 1; break; + default: return; + } + + String path = wingw::file_save_dlg(NULL, "Export heightmap", + "TIFF 16-bit files (*.tif)|*.tif;*.tiff|" + "Raw 32f (*.r32)|*.r32|Raw 16 (*.r16)|*.r16|Photoshop Raw 16 (*.raw)|*.raw|" + "Raw 32f with header (*.height)|*.height|TGA files (*.tga)|*.tga|All files (*.*)|*.*", + "r32", lastHmapExportPath); + + if (path.length()) + { + lastHmapExportPath = path; + + bool doExport = true; + real minHeight = lastMinHeight[export_det_hmap]; + real heightRange = lastHeightRange[export_det_hmap]; + + const char *ext = dd_get_fname_ext(path); + if (!ext) + { + path += ".r16"; + ext = dd_get_fname_ext(path); + } + + if (stricmp(ext, ".r32") != 0 && stricmp(ext, ".height") != 0) + { + HeightMapStorage &hm = export_det_hmap ? heightMapDet : heightMap; + int x0 = export_det_hmap ? detRectC[0].x : 0; + int y0 = export_det_hmap ? detRectC[0].y : 0; + int x1 = export_det_hmap ? detRectC[1].x : heightMap.getMapSizeX(); + int y1 = export_det_hmap ? detRectC[1].y : heightMap.getMapSizeY(); + + real minHeightHm; + real heightRangeHm; + real minH = hm.getFinalData(x0, x0); + real maxH = minH; + + for (int y = y0; y < y1; ++y) + { + for (int x = x0; x < x1; ++x) + { + real h = hm.getFinalData(x, y); + + if (h < minH) + minH = h; + else if (h > maxH) + maxH = h; + } + } + + minHeightHm = minH; + heightRangeHm = maxH - minH; + + if (minHeight == MAX_REAL || heightRange == MAX_REAL) + { + minHeight = minHeightHm; + heightRange = heightRangeHm; + } + + HmapExportSizeDlg dlg(minHeight, heightRange, minHeightHm, heightRangeHm); + doExport = dlg.execute(); + } + + if (doExport) + { + lastMinHeight[export_det_hmap] = minHeight; + lastHeightRange[export_det_hmap] = heightRange; + + exportHeightmap(path, minHeight, heightRange, export_det_hmap); + } + } +} + + +void HmapLandPlugin::autocenterHeightmap(PropPanel2 *panel, bool reset_render) +{ + Point2 oldOffset = heightMapOffset; + + if (doAutocenter) + { + heightMapOffset.x = -heightMap.getMapSizeX() * gridCellSize / 2; + heightMapOffset.y = -heightMap.getMapSizeY() * gridCellSize / 2; + + if (heightMapOffset != oldOffset && reset_render) + resetRenderer(); + } + + if (panel) + { + panel->setPoint2(PID_HEIGHTMAP_OFFSET, heightMapOffset); + panel->setEnabledById(PID_HEIGHTMAP_OFFSET, !doAutocenter); + } +} + + +// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ// + + +void HmapLandPlugin::exportColormap() +{ + String path = + wingw::file_save_dlg(NULL, "Export color map", "TGA files (*.tga)|*.tga|All files (*.*)|*.*", "tga", lastColormapExportPath); + + if (path.length()) + { + lastColormapExportPath = path; + exportColormap(path); + } +} + + +static bool exportColormapAsTga(const char *filename, MapStorage &colormap) +{ + CoolConsole &con = DAGORED2->getConsole(); + + file_ptr_t handle = ::df_open(filename, DF_WRITE | DF_CREATE); + + if (!handle) + { + con.addMessage(ILogWriter::ERROR, "Can't create file '%s'", filename); + return false; + } + + int mapSizeX = colormap.getMapSizeX(); + int mapSizeY = colormap.getMapSizeY(); + + SmallTab buf; + clear_and_resize(buf, mapSizeX); + + con.startProgress(); + con.setActionDesc("exporting color map..."); + con.setTotal(mapSizeY); + + ::df_write(handle, "\0\0\2\0\0\0\0\0\0\0\0\0", 12); + ::df_write(handle, &mapSizeX, 2); + ::df_write(handle, &mapSizeY, 2); + ::df_write(handle, "\x20\x08", 2); + + for (int y = 0; y < mapSizeY; ++y) + { + for (int x = 0; x < mapSizeX; ++x) + buf[x] = colormap.getData(x, y); + + if (::df_write(handle, buf.data(), data_size(buf)) != data_size(buf)) + { + con.addMessage(ILogWriter::ERROR, "Error writing file '%s'", filename); + ::df_close(handle); + con.endProgress(); + return false; + } + + colormap.unloadUnchangedData(y + 1); + + con.incDone(); + } + + colormap.unloadAllUnchangedData(); + + con.endProgress(); + + ::df_close(handle); + + return true; +} + + +bool HmapLandPlugin::exportColormap(String &filename) +{ + CoolConsole &con = DAGORED2->getConsole(); + con.startLog(); + + if (exportColormapAsTga(filename, colorMap)) + con.addMessage(ILogWriter::NOTE, "Exported color map to '%s'", (const char *)filename); + + con.endLog(); + return true; +} + + +// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ// + + +static real skyFunc(real t) +{ + if (t <= 0) + return 0.25f; + return 0.25f / ((1 + t)); +} + + +Point3 HmapLandPlugin::calcSunLightDir() const +{ + return -Point3(cosf(sunAzimuth) * cosf(sunZenith), sinf(sunZenith), sinf(sunAzimuth) * cosf(sunZenith)); +} + +static float calc_sky(float h, float hl, float hr, float hu, float hd, float gridCellSize) +{ + float sky; + sky = skyFunc((hu - h) / gridCellSize); + sky += skyFunc((hd - h) / gridCellSize); + sky += skyFunc((hl - h) / gridCellSize); + sky += skyFunc((hr - h) / gridCellSize); + return sky; +} + +static Point3 get_normal(float hl, float hr, float hu, float hd, float gridCellSize) +{ + return normalize(Point3(hl - hr, 2 * gridCellSize, hd - hu)); +} + + +inline void HmapLandPlugin::getNormal(int x, int y, Point3 &normal) +{ + real hl, hr, hu, hd; + hl = heightMap.getFinalData(x - 1, y); + hr = heightMap.getFinalData(x + 1, y); + hu = heightMap.getFinalData(x, y + 1); + hd = heightMap.getFinalData(x, y - 1); + normal = get_normal(hl, hr, hu, hd, gridCellSize); +} + +inline void HmapLandPlugin::getNormalAndSky(int x, int y, Point3 &normal, real &sky, float *height) +{ + real h, hl, hr, hu, hd; + h = heightMap.getFinalData(x, y); + hl = heightMap.getFinalData(x - 1, y); + hr = heightMap.getFinalData(x + 1, y); + hu = heightMap.getFinalData(x, y + 1); + hd = heightMap.getFinalData(x, y - 1); + + normal = get_normal(hl, hr, hu, hd, gridCellSize); + if (!height) + sky = calc_sky(h, hl, hr, hu, hd, gridCellSize); + else + { + int ht = heightMap.getMapSizeY(), wd = heightMap.getMapSizeX(); + h = height[clamp(y, 0, ht - 1) * wd + clamp(x, 0, wd - 1)]; + hl = height[clamp(y, 0, ht - 1) * wd + clamp(x - 1, 0, wd - 1)]; + hr = height[clamp(y, 0, ht - 1) * wd + clamp(x + 1, 0, wd - 1)]; + hu = height[clamp(y + 1, 0, ht - 1) * wd + clamp(x - 1, 0, wd - 1)]; + hd = height[clamp(y - 1, 0, ht - 1) * wd + clamp(x + 1, 0, wd - 1)]; + sky = calc_sky(h, hl, hr, hu, hd, gridCellSize); + } +} + +unsigned HmapLandPlugin::calcFastLandLightingAt(float ox, float oy, const Point3 &sun_light_dir) +{ + Point2 frac, cell; + int x, y; + frac.x = modff(ox, &cell.x); + frac.y = modff(oy, &cell.y); + x = cell.x; + y = cell.y; + Point3 normal; + real sky; + if (fabsf(ox - x) < 0.001 && fabsf(oy - y) < 0.001) + { + getNormalAndSky(x, y, normal, sky); + } + else + { + Point3 normalLU, normalRU, normalLD, normalRD; + real skyLU, skyRU, skyLD, skyRD; + getNormalAndSky(x, y, normalLU, skyLU); + getNormalAndSky(x + 1, y, normalRU, skyRU); + getNormalAndSky(x, y + 1, normalLD, skyLD); + getNormalAndSky(x + 1, y + 1, normalRD, skyRD); + normal = + normalize((normalLU * (1 - frac.x) + normalRU * frac.x) * (1 - frac.y) + (normalLD * (1 - frac.x) + normalRD * frac.x) * frac.y); + sky = (skyLU * (1 - frac.x) + skyRU * frac.x) * (1 - frac.y) + (skyLD * (1 - frac.x) + skyRD * frac.x) * frac.y; + } + + // if ( true /*render.showFinalHM*/ ) + // { + + int sunLight = real2int(normal * sun_light_dir * -255); + if (sunLight < 0) + sunLight = 0; + else if (sunLight > 255) + sunLight = 255; + + int skyLight = sky * 255; + if (skyLight < 0) + skyLight = 0; + else if (skyLight > 255) + skyLight = 255; + + unsigned lt = sunLight | (skyLight << 8); + return lt; +} + +unsigned HmapLandPlugin::calcNormalAt(float ox, float oy) +{ + Point2 frac, cell; + int x, y; + frac.x = modff(ox, &cell.x); + frac.y = modff(oy, &cell.y); + x = cell.x; + y = cell.y; + Point3 normal; + + if (fabsf(ox - x) < 0.001 && fabsf(oy - y) < 0.001) + { + getNormal(x, y, normal); + } + else + { + Point3 normalLU, normalRU, normalLD, normalRD; + getNormal(x, y, normalLU); + getNormal(x + 1, y, normalRU); + getNormal(x, y + 1, normalLD); + getNormal(x + 1, y + 1, normalRD); + + normal = + normalize((normalLU * (1 - frac.x) + normalRU * frac.x) * (1 - frac.y) + (normalLD * (1 - frac.x) + normalRD * frac.x) * frac.y); + } + + unsigned nx = real2uchar(normal.x * 0.5 + 0.5); + + unsigned nz = real2uchar(normal.z * 0.5 + 0.5); + + unsigned nm = nx | (nz << 8); + return nm; +} + +void HmapLandPlugin::blurLightmap(int kernel_size, float sigma, const IBBox2 *calc_box) +{ + + int time0 = dagTools->getTimeMsec(); + CoolConsole &con = DAGORED2->getConsole(); + con.startLog(); + + con.startProgress(); + con.setActionDesc("gaussian blur on lightmap"); + con.setTotal(lightMapScaled.getMapSizeY()); + + static float weights[5 * 5], totalWeight; + static int previos_kernel_size = 0; + static float previos_sigma = 0.0; + if (previos_sigma != sigma || previos_kernel_size != kernel_size) + { + int weightsStride = (kernel_size * 2 + 1); + G_ASSERT(weightsStride <= 5); + totalWeight = 0; + for (int j = -kernel_size, id = 0; j <= kernel_size; ++j) + for (int i = -kernel_size; i <= kernel_size; ++i, ++id) + { + float expPow = -(i * i + j * j) / (2.0f * sigma * sigma * kernel_size * kernel_size); //-V636 + float w = expf(expPow) / (sqrtf(TWOPI) * sigma); + weights[id] = w; + totalWeight += w; + } + for (int i = 0; i < weightsStride * weightsStride; ++i) + weights[i] /= totalWeight * 255.0f; + } + + IBBox2 calcBox; + if (calc_box) + calcBox = *calc_box; + else + { + calcBox[0].x = 0; + calcBox[1].x = lightMapScaled.getMapSizeX(); + calcBox[0].y = 0; + calcBox[1].y = lightMapScaled.getMapSizeY(); + } + IBBox2 filterBox; + filterBox = calcBox; + filterBox[0] -= IPoint2(1, 1); + filterBox[1] += IPoint2(1, 1); + filterBox[0].x = max(filterBox[0].x, 0); + filterBox[0].y = max(filterBox[0].y, 0); + + filterBox[1].x = min(filterBox[0].x, lightMapScaled.getMapSizeX()); + filterBox[1].y = min(filterBox[0].y, lightMapScaled.getMapSizeY()); + + SmallTab lightMapBlurred; + // todo: can be optimized by coping only required info + // lightMapBlurred.resize(filterBox.width().x*filterBox.width().y); + + int width = lightMapScaled.getMapSizeX(); + int height = lightMapScaled.getMapSizeY(); + clear_and_resize(lightMapBlurred, width * height); + for (int i = 0, y = 0; y < lightMapScaled.getMapSizeY(); ++y) + for (int x = 0; x < lightMapScaled.getMapSizeX(); ++x, ++i) + { + lightMapBlurred[i] = lightMapScaled.getData(x, y); + } + + for (int y = calcBox[0].y; y < calcBox[1].y; ++y) + { + for (int x = calcBox[0].x; x < calcBox[1].x; ++x) + { + float ltSky = 0, ltSun = 0; + for (int j = -kernel_size, id = 0; j <= kernel_size; ++j) + { + for (int i = -kernel_size; i <= kernel_size; ++i, ++id) + { + unsigned lt = lightMapBlurred[width * clamp(y + j, 0, height - 1) + clamp(x + i, 0, width - 1)]; + lightMapScaled.getData(x + i, y + j); + float w = weights[id]; + ltSky += (lt & 0xFF) * w; + ltSun += ((lt >> 8) & 0xFF) * w; + } + } + lightMapScaled.setData(x, y, real2uchar(ltSky) | (real2uchar(ltSun) << 8) | (lightMapBlurred[width * y + x] & 0xFFFF0000)); + } + con.incDone(); + } + con.endProgress(); + int genTime = dagTools->getTimeMsec() - time0; + con.addMessage(ILogWriter::REMARK, "reloaded in %g seconds", genTime / 1000.0f); + con.endLog(); +} + +void HmapLandPlugin::calcGoodLandLighting() +{ +#if defined(USE_LMESH_ACES) + calcLandLighting(); +#else + calcLandLighting(); //< something wrong here +#endif +} + + +void HmapLandPlugin::calcGoodLandLightingInBox(const IBBox2 &calc_box) +{ + IBBox2 box; + box[0].x = calc_box[0].x * lightmapScaleFactor; + box[0].y = calc_box[0].y * lightmapScaleFactor; + box[1].x = calc_box[1].x * lightmapScaleFactor; + box[1].y = calc_box[1].y * lightmapScaleFactor; + +#if defined(USE_LMESH_ACES) + calcLandLighting(&box); +#else + calcLandLighting(&box); +#endif + + resetRenderer(); +} + + +void HmapLandPlugin::calcFastLandLighting() { calcLandLighting(); } +// #include + +template +bool HmapLandPlugin::calcLandLighting(const IBBox2 *calc_box) +{ + if (!hasLightmapTex) + return false; + + CoolConsole &con = DAGORED2->getConsole(); + applyHmModifiers(false); + + if (!calc_box) + { + lightMapScaled.reset(heightMap.getMapSizeX() * lightmapScaleFactor, heightMap.getMapSizeY() * lightmapScaleFactor, 0xFFFF); + + createLightmapFile(con); + } + else + { + String fname(DAGORED2->getPluginFilePath(this, LIGHTMAP_FILENAME)); + if (!::dd_file_exist(fname)) + createLightmapFile(con); + } + + int time0 = dagTools->getTimeMsec(); + + Point3 sunLightDir = calcSunLightDir(); + if (shadowDensity < 0) + shadowDensity = 0; + else if (shadowDensity > 1) + shadowDensity = 1; + + int startX = calc_box ? calc_box->lim[0].x : 0; + int endX = calc_box ? calc_box->lim[1].x + 1 : lightMapScaled.getMapSizeX(); + + int startY = calc_box ? calc_box->lim[0].y : 0; + int endY = calc_box ? calc_box->lim[1].y + 1 : lightMapScaled.getMapSizeY(); + + if (startX < 0) + startX = 0; + + if (endX > lightMapScaled.getMapSizeX()) + endX = lightMapScaled.getMapSizeX(); + + if (startY < 0) + startY = 0; + + if (endY > lightMapScaled.getMapSizeY()) + endY = lightMapScaled.getMapSizeY(); + if (endX <= startX || endY <= startY) + return true; + + con.startLog(); + +#if USE_LMESH_ACES + const int normalsSS = 3; + SmallTab normalsMap; + SmallTab landHeightMap; + if (storeNxzInLtmapTex || useNormalMap) + { + SmallTab landHeightMapSS; + int ltime0 = dagTools->getTimeMsec(); + int w = (endX - startX) * normalsSS; + int h = (endY - startY) * normalsSS; + clear_and_resize(normalsMap, w * h); + mem_set_ff(normalsMap); + clear_and_resize(landHeightMapSS, normalsMap.size()); + for (int i = 0; i < normalsMap.size(); ++i) + landHeightMapSS[i] = MIN_REAL; + NormalFrameBuffer frameBuffer; + frameBuffer.ht = frameBuffer.start_ht = landHeightMapSS.data(); + frameBuffer.normal = normalsMap.data(); + float scale = float(normalsSS) / gridCellSize; + if (!::create_lmesh_normal_map(landMeshMap, frameBuffer, + startX * gridCellSize + heightMapOffset[0] - (0.5 * normalsSS) / scale, // -.5f + startY * gridCellSize + heightMapOffset[1] - (0.5 * normalsSS) / scale, // -.5f + scale, (endX - startX) * normalsSS, (endY - startY) * normalsSS)) + clear_and_shrink(normalsMap); + con.addMessage(ILogWriter::REMARK, "calculated lmesh normals in %g seconds", (dagTools->getTimeMsec() - ltime0) / 1000.0f); + if (cast_shadows && normalsMap.size() && startX == 0 && endX == lightMapScaled.getMapSizeX()) + { + clear_and_resize(landHeightMap, (endX - startX) * (endY - startY)); + + for (int hi = 0, y = 0; y < (endY - startY); ++y) + for (int x = 0; x < (endX - startX); ++x, ++hi) + { + int mapssi = y * w * normalsSS + x * normalsSS; + double newHt = 0; + double origHt = heightMap.getFinalData(x + startX, y + startY); + for (int j = 0; j < normalsSS; ++j, mapssi += w - normalsSS) + for (int i = 0; i < normalsSS; ++i, ++mapssi) + { + if (normalsMap[mapssi] == 0xFFFF) + newHt += origHt; + else + { + newHt += landHeightMapSS[mapssi]; + } + } + landHeightMap[hi] = newHt / (normalsSS * normalsSS); + } + } + /* + SmallTab pix; + pix.resize(normalsMap.size()); + mem_set_ff(pix); + for (int i = 0; iMIN_REAL) + { + pix[i].a = normalsMap[i] == 0xFFFF?128:0; + pix[i].r = normalsMap[i]&0xFF; + pix[i].g = normalsMap[i]>>8; + pix[i].b = real2uchar((landHeightMap[i]-700.0)/1000.0); + } + } + save_tga32("normals1.tga", pix.data(), w,h, w*4); + pix.resize((endY-startY)*(endX-startX)); + + for (int i=0,y=startY; y>8; + float h + = heightMap.getFinalData(float(x)/lightmapScaleFactor, float(y)/lightmapScaleFactor); + pix[i].b = real2uchar((h-700.0)/1000.0); + } + + save_tga32("normals2.tga", pix.data(), endX-startX, endY-startY, (endX-startX)*4); + //map.clear(); + pix.clear(); + //*/ + // landHeightMap.clear(); + } +#endif + + + if (useNormalMap) + con.setActionDesc("land normal mapping..."); + else + con.setActionDesc(cast_shadows ? "land lighting..." : "fast land lighting..."); + SimpleProgressCB progressCB; + + con.startProgress(&progressCB); + + con.setTotal(endY - startY); + + for (int y = startY, yi = 0, cnt = 0; y < endY; ++y, ++yi) + { + if (progressCB.mustStop) + { + con.endLogAndProgress(); + return false; + } + + if (--cnt <= 0) + cnt = lightMapScaled.getElemSize(); + + for (int xi = 0, x = startX; x < endX; ++x, ++xi) + { + unsigned lt = 0; + +#if USE_LMESH_ACES + // fixme: + // todo:not supported detailed lightmaps now + G_ASSERT(lightmapScaleFactor == 1); + Point3 origNormal; + float sky; + getNormalAndSky(float(x) / lightmapScaleFactor, float(y) / lightmapScaleFactor, origNormal, sky, landHeightMap.data()); + Point3 newNormal(0, 0, 0); + if (normalsMap.size()) + { + // Point3 origNormal + // = calcP3NormalAt(float(x)/lightmapScaleFactor, float(y)/lightmapScaleFactor); + int wd = (endX - startX) * normalsSS; + int mapssi = (yi * normalsSS) * wd + xi * normalsSS; + for (int j = 0; j < normalsSS; ++j, mapssi += wd - normalsSS) + for (int i = 0; i < normalsSS; ++i, ++mapssi) + { + if (normalsMap[mapssi] == 0xFFFF) + newNormal += origNormal; + else + { + Point3 n; + n.x = (normalsMap[mapssi] & 0xFF) * 2.0f / 255.0f - 1.f; + n.z = (normalsMap[mapssi] >> 8) * 2.0f / 255.0f - 1.f; + n.y = sqrtf(1.0f - n.x * n.x - n.z * n.z); + newNormal += n; + } + } + newNormal.normalize(); + } + else + newNormal = origNormal; + unsigned nx = real2uchar(newNormal.x * 0.5 + 0.5); + + unsigned nz = real2uchar(newNormal.z * 0.5 + 0.5); + + int sunLight = clamp(real2int((newNormal * sunLightDir) * -255), 0, 255); + if (cast_shadows && sunLight > 0) + { + real shadow = + calcSunShadow(float(x) / lightmapScaleFactor, float(y) / lightmapScaleFactor, sunLightDir, landHeightMap.data()) * + shadowDensity; + sunLight *= (1 - shadow); + } + int skyLight = clamp(real2int(sky * 255), 0, 255); + + lt = unsigned(sunLight | (skyLight << 8)) | ((nx | (nz << 8)) << 16); +#else + + if (useNormalMap) + lt = (calcNormalAt(float(x) / lightmapScaleFactor, float(y) / lightmapScaleFactor) << 16) | 0xFFFF; + else + { + lt = calcFastLandLightingAt(float(x) / lightmapScaleFactor, float(y) / lightmapScaleFactor, sunLightDir); + + if (cast_shadows && (lt & 0xFF) != 0) + { + real shadow = calcSunShadow(float(x) / lightmapScaleFactor, float(y) / lightmapScaleFactor, sunLightDir) * shadowDensity; + lt = (lt & ~0xFF) | (real2int((lt & 0xFF) * (1 - shadow))); + // lt=(lt&~0xFF)|(real2int((1-shadow)*255)); + } + if (storeNxzInLtmapTex) + lt |= calcNormalAt(float(x) / lightmapScaleFactor, float(y) / lightmapScaleFactor) << 16; + } +#endif + + lightMapScaled.setData(x, y, lt); + } + if (cnt == lightMapScaled.getElemSize()) + { + if (!lightMapScaled.flushData()) + con.addMessage(ILogWriter::ERROR, "Error writing data to light map file"); + + heightMap.unloadUnchangedData(y + 1); + lightMapScaled.unloadUnchangedData(y + 1); + } + + con.setDone(y - startY + 1); + } + con.endProgress(); + + heightMap.unloadAllUnchangedData(); + lightMapScaled.unloadAllUnchangedData(); + + if (!lightMapScaled.flushData()) + con.addMessage(ILogWriter::ERROR, "Error writing data to light map file"); + + int genTime = dagTools->getTimeMsec() - time0; + con.addMessage(ILogWriter::REMARK, "calculated in %g seconds", genTime / 1000.0f); + if (high_quality) + blurLightmap(BLUR_LM_KEREL_SIZE, BLUR_LM_SIGMA, calc_box); + + // Set lightmap texture to shader. + if (hasLightmapTex && !useNormalMap && !skipExportLtmap) + { + time0 = dagTools->getTimeMsec(); + + String prj; + DAGORED2->getProjectFolderPath(prj); + ::dd_mkdir(::make_full_path(prj, "builtScene")); + + dagGeom->shaderGlobalSetTexture(dagGeom->getShaderVariableId("lightmap_tex"), BAD_TEXTUREID); + exportLightmapToFile(::make_full_path(prj, "builtScene/lightmap.tga"), _MAKE4C('TGA'), high_quality); + + con.addMessage(ILogWriter::NOTE, "exported in %.1f sec", (dagTools->getTimeMsec() - time0) / 1000.0f); + } + + con.endLog(); + return true; +} + +void HmapLandPlugin::recalcLightingInRect(const IBBox2 &rect) +{ + if (!hasLightmapTex) + return; + + applyHmModifiers(false); + Point3 sunLightDir = calcSunLightDir(); + + for (int y = rect[0].y * lightmapScaleFactor; y <= rect[1].y * lightmapScaleFactor; ++y) + for (int x = rect[0].x * lightmapScaleFactor; x <= rect[1].x * lightmapScaleFactor; ++x) + { + unsigned lt = 0; + if (useNormalMap) + lt = (calcNormalAt(float(x) / lightmapScaleFactor, float(y) / lightmapScaleFactor) << 16) | 0xFFFF; + else + { + lt = calcFastLandLightingAt(float(x) / lightmapScaleFactor, float(y) / lightmapScaleFactor, sunLightDir); + if (storeNxzInLtmapTex) + lt |= calcNormalAt(float(x) / lightmapScaleFactor, float(y) / lightmapScaleFactor) << 16; + } + + lightMapScaled.setData(x, y, lt); + } +} + +// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ// +struct HeightmapProvider +{ + float *height; + int wd, ht; + Point3 offset; + float cellSz; + HeightmapProvider(float *ht, int w, int h, const Point3 &ofs, float cellsz) : height(ht), wd(w), ht(h), cellSz(cellsz), offset(ofs) + {} + float get_ht(int x, int y) const { return height[x + y * wd]; }; + int getHeightmapSizeX() const { return wd; } + int getHeightmapSizeY() const { return ht; } + float getHeightmapCellSize() const { return cellSz; } + Point3 getHeightmapOffset() const { return offset; } + bool getHeightmapHeight(const IPoint2 &cell, real &h) const + { + if (cell.x < 0 || cell.y < 0 || cell.x >= wd || cell.y >= ht) + return false; + + h = height[cell.x + cell.y * wd]; + return true; + } + bool getHeightmapCell5Pt(const IPoint2 &cell, real &h0, real &hx, real &hy, real &hxy, real &hmid) const + { + if (cell.x < 0 || cell.y < 0 || cell.x + 1 >= wd || cell.y + 1 >= ht) + return false; + + h0 = get_ht(cell.x, cell.y); + hx = get_ht(cell.x + 1, cell.y); + hy = get_ht(cell.x, cell.y + 1); + hxy = get_ht(cell.x + 1, cell.y + 1); + + hmid = (h0 + hx + hy + hxy) * 0.25f; + + return true; + } +}; + +real HmapLandPlugin::calcSunShadow(float ox, float oy, const Point3 &sun_light_dir, float *height) +{ + float ht[3][3], baseht[4][4]; + + int numHit = 0; + Point2 frac, cell; + int x, y; + frac.x = modff(ox, &cell.x); + frac.y = modff(oy, &cell.y); + x = cell.x; + y = cell.y; + if (height) + { + int mapSizeX = heightMap.getMapSizeX(); + int mapSizeY = heightMap.getMapSizeY(); + int stride = mapSizeX; + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 4; ++j) + baseht[i][j] = height[clamp(y + i - 1, 0, mapSizeY - 1) * stride + clamp(x + j - 1, 0, mapSizeX - 1)]; + } + else + { + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 4; ++j) + baseht[i][j] = heightMap.getFinalData(x + j - 1, y + i - 1); + } + + for (int i = 0; i < 3; ++i) + for (int j = 0; j < 3; ++j) + { + ht[i][j] = lerp(lerp(baseht[i][j], baseht[i][j + 1], frac.x), lerp(baseht[i + 1][j], baseht[i + 1][j + 1], frac.x), frac.y); + } + Point3 stpt((ox + 0.5f / lightmapScaleFactor) * gridCellSize + heightMapOffset.x, ht[1][1] + shadowBias, + (oy + 0.5f / lightmapScaleFactor) * gridCellSize + heightMapOffset.y); + + float httest; + if (height && getHeightmapHeight(IPoint2(0, 0), httest)) + { + HeightmapProvider hmp(height, heightMap.getMapSizeX(), heightMap.getMapSizeY(), getHeightmapOffset(), getHeightmapCellSize()); + if (ray_hit_midpoint_heightmap_approximate(hmp, stpt, -sun_light_dir, shadowTraceDist)) + return 1.0; + } + else if (ray_hit_midpoint_heightmap_approximate(*this, stpt, -sun_light_dir, shadowTraceDist)) + return 1.0; + + ht[1][1] *= 0.75f / 2; + ht[1][0] *= 0.5f / 2; + ht[0][1] *= 0.5f / 2; + ht[2][1] *= 0.5f / 2; + ht[1][2] *= 0.5f / 2; + ht[0][0] *= 0.25f / 2; + ht[2][2] *= 0.25f / 2; + ht[0][2] *= 0.25f / 2; + ht[2][0] *= 0.25f / 2; + calculating_shadows = true; + for (int dy = 0; dy < 2; ++dy) + for (int dx = 0; dx < 2; ++dx) + { + real h = (ht[dy][dx] + ht[dy][dx + 1] + ht[dy + 1][dx] + ht[dy + 1][dx + 1]); //*0.25f; + + Point3 pt((ox + (0.25f + dx * 0.5) / lightmapScaleFactor) * gridCellSize + heightMapOffset.x, h + shadowBias, + (oy + (0.25f + dy * 0.5) / lightmapScaleFactor) * gridCellSize + heightMapOffset.y); + + real t = shadowTraceDist; + if (DAGORED2->shadowRayHitTest(pt, -sun_light_dir, t)) + numHit++; + } + calculating_shadows = false; + + return numHit / 4.0f; +} + + +bool HmapLandPlugin::getDirectionSunSettings() +{ + ISceneLightService *ltService = DAGORED2->queryEditorInterface(); + debug("get dir"); + if (ltService) + { + sunAzimuth = HALFPI - ltService->getSunEx(0).azimuth; + sunZenith = ltService->getSunEx(0).zenith; + + if (DAGORED2->curPlugin() == this) + propPanel->updateLightGroup(); + + updateRendererLighting(); + } + else + return false; + + return true; +} + +bool HmapLandPlugin::getAllSunSettings() +{ + ISceneLightService *ltService = DAGORED2->queryEditorInterface(); + + if (ltService) + { + Point3 sun1_dir, sun2_dir; + Color3 sun1_col, sun2_col, sky_col; + ltService->getDirectLight(sun1_dir, sun1_col, sun2_dir, sun2_col, sky_col); + + ldrLight.skyPower = ldrLight.sunPower = 1.0; + ldrLight.skyColor = dagRender->normalizeColor4(::color4(sky_col, 1), ldrLight.skyPower); + ldrLight.sunColor = dagRender->normalizeColor4(::color4(sun1_col, 1), ldrLight.sunPower); + ldrLight.specularColor = ldrLight.sunColor; + sunAzimuth = HALFPI - ltService->getSunEx(0).azimuth; + sunZenith = ltService->getSunEx(0).zenith; + + if (DAGORED2->curPlugin() == this) + propPanel->updateLightGroup(); + + updateRendererLighting(); + } + else + return false; + + return true; +} + + +// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ// + +template +bool flushDataTo(const char *base_path, const char *orig_base_path, T &map) +{ + int base_path_slen = i_strlen(base_path); + if (strcmp(base_path, orig_base_path) == 0) + { + if (strncmp(map.getFileName(), base_path, base_path_slen) != 0) + DAEDITOR3.conError("Internal error: map=%s, base_path=%s", map.getFileName(), base_path); + return map.flushData(); + } + + debug("SaveAs: flushDataTo(%s, %s, %p(%s))", base_path, orig_base_path, &map, map.getFileName()); + + int orig_base_path_slen = i_strlen(orig_base_path); + if (strncmp(map.getFileName(), orig_base_path, orig_base_path_slen) != 0) + { + DAEDITOR3.conError("Internal error: map=%s, orig_base_path=%s", map.getFileName(), orig_base_path); + return false; + } + + String orig_fn(map.getFileName()); + if (orig_fn.suffix("/") || orig_fn.suffix("\\")) + erase_items(orig_fn, orig_fn.size() - 2, 1); + String orig_backup_fn(0, "%s.orig#", orig_fn); + String new_fn(0, "%s%s", base_path, orig_fn + orig_base_path_slen); + Tab flist; + + // clear dest + find_files_in_folder(flist, new_fn, "", false, true, false); + for (int i = 0; i < flist.size(); i++) + remove(flist[i]); + + // copy last to backup + dd_mkdir(orig_backup_fn); + flist.clear(); + find_files_in_folder(flist, orig_fn, "", false, true, false); + for (int i = 0; i < flist.size(); i++) + { + String dest(0, "%s%s", orig_backup_fn, flist[i].str() + orig_fn.length()); + dagTools->copyFile(flist[i], dest); + } + + // flush changes + dd_mkdir(orig_fn); + bool res = map.flushData(); + map.closeFile(true); + + // move final changes to dest + dd_mkdir(new_fn); + flist.clear(); + find_files_in_folder(flist, orig_fn, "", false, true, false); + for (int i = 0; i < flist.size(); i++) + { + String dest(0, "%s%s", new_fn, flist[i].str() + orig_fn.length()); + rename(flist[i], dest); + } + + // move backup copy back + flist.clear(); + find_files_in_folder(flist, orig_backup_fn, "", false, true, false); + for (int i = 0; i < flist.size(); i++) + { + String dest(0, "%s%s", orig_fn, flist[i].str() + orig_backup_fn.length()); + rename(flist[i], dest); + } + dd_rmdir(orig_backup_fn); + + // reopen data in new place + map.openFile(new_fn + ".dat"); + return res; +} + +template +void HmapLandPlugin::loadMapFile(MapStorage &map, const char *filename, CoolConsole &con) +{ + String fileName(DAGORED2->getPluginFilePath(this, filename)); + + if (HmapLandPlugin::hmlService->mapStorageFileExists(fileName)) + { + if (!map.openFile(fileName)) + con.addMessage(ILogWriter::ERROR, "Error loading %s file", filename); + else + con.addMessage(ILogWriter::NOTE, "Loaded %dx%d %s", map.getMapSizeX(), map.getMapSizeY(), filename); + } +} + +static MapStorage *loadMap64File(const char *filename, CoolConsole &con) +{ + String fileName(DAGORED2->getPluginFilePath(HmapLandPlugin::self, filename)); + + if (HmapLandPlugin::hmlService->mapStorageFileExists(fileName)) + { + MapStorage *map = HmapLandPlugin::hmlService->createUint64MapStorage(512, 512, 0); + + if (!map->openFile(fileName)) + { + con.addMessage(ILogWriter::ERROR, "Error loading %s file", filename); + delete map; + return NULL; + } + else + con.addMessage(ILogWriter::NOTE, "Loaded %dx%d %s", map->getMapSizeX(), map->getMapSizeY(), filename); + return map; + } + return NULL; +} +void HmapLandPlugin::prepareDetTexMaps() +{ + String fileName; + int w = heightMap.getMapSizeX(), h = heightMap.getMapSizeY(); + + if (!detTexIdxMap) + { + fileName = DAGORED2->getPluginFilePath(this, DETTEXMAP_FILENAME); + detTexIdxMap = hmlService->createUint64MapStorage(w, h, 0); + detTexIdxMap->createFile(fileName); + } + if (!detTexWtMap) + { + fileName = DAGORED2->getPluginFilePath(this, DETTEXWMAP_FILENAME); + detTexWtMap = hmlService->createUint64MapStorage(w, h, 0xFF); + detTexWtMap->createFile(fileName); + } +} + +void HmapLandPlugin::loadObjects(const DataBlock &blk, const DataBlock &local_data, const char *base_path) +{ +#define LD_LOCAL_VAR(X, TYPE) X = local_data.get##TYPE(#X, X) + EditLayerProps::resetLayersToDefauls(); + if (blk.getBlockByName("layers")) + EditLayerProps::loadLayersConfig(blk, local_data); + + origBasePath = base_path; + if (d3d::is_stub_driver()) + { + // avoid unpredictable caches in DE3xq + DAEDITOR3.conNote("removing delaunayGen.cache.bin"); + dd_erase(DAGORED2->getPluginFilePath(HmapLandPlugin::self, "delaunayGen.cache.bin")); + } + + ignoreEvents = true; + + lastHmapImportPath = local_data.getStr("lastHmapImportPath", lastHmapImportPath); + LD_LOCAL_VAR(lastHmapImportPathMain, Str); + LD_LOCAL_VAR(lastChangeMain.size, Int64); + LD_LOCAL_VAR(lastChangeMain.mtime, Int64); + LD_LOCAL_VAR(lastHmapImportPathDet, Str); + LD_LOCAL_VAR(lastChangeDet.size, Int64); + LD_LOCAL_VAR(lastChangeDet.mtime, Int64); + lastWaterHeightmapImportPath = local_data.getStr("lastHmapImportPathWater", lastWaterHeightmapImportPath); + LD_LOCAL_VAR(lastWaterHeightmapImportPathDet, Str); + LD_LOCAL_VAR(lastChangeWaterDet.size, Int64); + LD_LOCAL_VAR(lastChangeWaterDet.mtime, Int64); + LD_LOCAL_VAR(lastWaterHeightmapImportPathMain, Str); + LD_LOCAL_VAR(lastChangeWaterMain.size, Int64); + LD_LOCAL_VAR(lastChangeWaterMain.mtime, Int64); + + lastLandExportPath = local_data.getStr("lastLandExportPath", lastLandExportPath); + lastHmapExportPath = local_data.getStr("lastHmapExportPath", lastHmapExportPath); + lastColormapExportPath = local_data.getStr("lastColormapExportPath", lastColormapExportPath); + lastTexImportPath = local_data.getStr("lastTexImportPath", lastTexImportPath); + objEd.autoUpdateSpline = local_data.getBool("autoUpdateSpline", true); + objEd.maxPointVisDist = local_data.getReal("maxPointVisDist", 5000.0); + + lastExpLoftFolder = local_data.getStr("lastExpLoftFolder", ""); + lastExpLoftMain = blk.getBool("lastExpLoftMain", local_data.getBool("lastExpLoftMain", true)); + lastExpLoftDet = blk.getBool("lastExpLoftDet", local_data.getBool("lastExpLoftDet", true)); + lastExpLoftMainSz = blk.getInt("lastExpLoftMainSz", local_data.getInt("lastExpLoftMainSz", 4096)); + lastExpLoftDetSz = blk.getInt("lastExpLoftDetSz", local_data.getInt("lastExpLoftDetSz", 4096)); + lastExpLoftUseRect[0] = blk.getBool("lastExpLoftUseRectM", local_data.getBool("lastExpLoftUseRectM", false)); + lastExpLoftRect[0][0] = blk.getPoint2("lastExpLoftRectM0", local_data.getPoint2("lastExpLoftRectM0", Point2(0, 0))); + lastExpLoftRect[0][1] = blk.getPoint2("lastExpLoftRectM1", local_data.getPoint2("lastExpLoftRectM1", Point2(1024, 1024))); + lastExpLoftUseRect[1] = blk.getBool("lastExpLoftUseRectD", local_data.getBool("lastExpLoftUseRectD", false)); + lastExpLoftRect[1][0] = blk.getPoint2("lastExpLoftRectD0", local_data.getPoint2("lastExpLoftRectD0", Point2(0, 0))); + lastExpLoftRect[1][1] = blk.getPoint2("lastExpLoftRectD1", local_data.getPoint2("lastExpLoftRectD1", Point2(1024, 1024))); + lastExpLoftCreateAreaSubfolders = + blk.getBool("lastExpLoftCreateAreaSubfolders", local_data.getBool("lastExpLoftCreateAreaSubfolders", true)); + + SimpleString exportTypeStr(blk.getStr("hmapExportType", useMeshSurface ? "lmesh" : "hmap")); + if (stricmp(exportTypeStr, "hmap") == 0) + exportType = EXPORT_HMAP; + else if (stricmp(exportTypeStr, "lmesh") == 0) + exportType = EXPORT_LANDMESH; + else if (stricmp(exportTypeStr, "plane") == 0) + exportType = EXPORT_PSEUDO_PLANE; + genHmap->altCollider = (exportType == EXPORT_LANDMESH) ? this : NULL; + + meshPreviewDistance = blk.getReal("meshPreviewDistance", meshPreviewDistance); + meshCells = blk.getInt("meshCells", meshCells); + meshErrorThreshold = blk.getReal("meshErrorThreshold", meshErrorThreshold); + numMeshVertices = blk.getInt("numMeshVertices", numMeshVertices); + + lod1TrisDensity = blk.getInt("lod1TrisDensity", -1); + if (lod1TrisDensity < 0) + { + DataBlock appblk(String(260, "%s/application.blk", DAGORED2->getWorkspace().getAppDir())); + lod1TrisDensity = appblk.getBlockByNameEx("projectDefaults")->getBlockByNameEx("hmap")->getInt("lod1TrisDensity", 30); + } + + if (lod1TrisDensity <= 0) + lod1TrisDensity = 1; + if (lod1TrisDensity > 100) + lod1TrisDensity = 100; + + importanceMaskScale = blk.getReal("importanceMaskScale", importanceMaskScale); + geomLoftBelowAll = blk.getBool("geomLoftBelowAll", false); + + hasWaterSurface = blk.getBool("hasWaterSurface", false); + waterMatAsset = blk.getStr("waterMatAsset", NULL); + waterSurfaceLevel = blk.getReal("waterSurfaceLevel", 0); + minUnderwaterBottomDepth = blk.getReal("minUnderwaterBottomDepth", 2); + hasWorldOcean = blk.getBool("hasWorldOcean", true); + worldOceanExpand = blk.getReal("worldOceanExpand", 100); + worldOceanShorelineTolerance = blk.getReal("worldOceanShorelineTolerance", 0.3); + waterMask.resize(0, 0); + waterMaskScale = 1; + + lastMinHeight[0] = blk.getReal("lastMinHeight", MAX_REAL); + lastHeightRange[0] = blk.getReal("lastHeightRange", MAX_REAL); + lastMinHeight[1] = blk.getReal("lastMinHeightDet", MAX_REAL); + lastHeightRange[1] = blk.getReal("lastHeightRangeDet", MAX_REAL); + + waterHeightMinRangeDet = blk.getPoint2("waterHeightMinRangeDet"); + waterHeightMinRangeMain = blk.getPoint2("waterHeightMinRangeMain"); + + colorGenScriptFilename = blk.getStr("colorGenScriptFilename", ""); + + if (!colorGenScriptFilename.empty()) + colorGenScriptFilename = ::find_in_base_smart(colorGenScriptFilename, DAGORED2->getSdkDir(), colorGenScriptFilename); + + doAutocenter = blk.getBool("doAutocenter", doAutocenter); + + gridCellSize = blk.getReal("gridCellSize", gridCellSize); + + heightMap.heightScale = blk.getReal("heightScale", heightMap.heightScale); + heightMap.heightOffset = blk.getReal("heightOffset", heightMap.heightOffset); + + heightMapOffset = blk.getPoint2("heightMapOffset", heightMapOffset); + + + detDivisor = blk.getInt("detDivisor", 0); + detRect[0] = blk.getPoint2("detRect0", Point2(0, 0)); + detRect[1] = blk.getPoint2("detRect1", Point2(0, 0)); + detRectC[0].set_xy((detRect[0] - heightMapOffset) / gridCellSize); + detRectC[0] *= detDivisor; + detRectC[1].set_xy((detRect[1] - heightMapOffset) / gridCellSize); + detRectC[1] *= detDivisor; + + collisionArea.ofs = blk.getPoint2("collisionArea_ofs", collisionArea.ofs); + collisionArea.sz = blk.getPoint2("collisionArea_sz", collisionArea.sz); + collisionArea.show = blk.getBool("collisionArea_show", collisionArea.show); + + shadowBias = blk.getReal("shadowBias", shadowBias); + shadowTraceDist = blk.getReal("shadowTraceDist", shadowTraceDist); + shadowDensity = blk.getReal("shadowDensity", shadowDensity); + + tileXSize = blk.getReal("tileXSize", tileXSize); + tileYSize = blk.getReal("tileYSize", tileYSize); + tileTexName = blk.getStr("tileTexName", NULL); + + useVertTex = blk.getBool("useVertTex", useVertTex); + useVertTexForHMAP = blk.getBool("useVertTexForHMAP", useVertTexForHMAP); + vertTexName = blk.getStr("vertTexName", NULL); + vertNmTexName = blk.getStr("vertNmTexName", NULL); + if (!vertTexName.empty() && vertNmTexName.empty()) + { + vertNmTexName = String(128, "%s_nm", vertTexName.str()); + if (!DAEDITOR3.getAssetByName(vertNmTexName, DAEDITOR3.getAssetTypeId("tex"))) + vertNmTexName = NULL; + } + + vertDetTexName = blk.getStr("vertDetTexName", NULL); + + vertTexXZtile = blk.getReal("vertTexXZtile", vertTexXZtile); + vertTexYtile = blk.getReal("vertTexYtile", vertTexYtile); + vertTexYOffset = blk.getReal("vertTexYOffset", vertTexYOffset); + vertTexAng0 = blk.getReal("vertTexAng0", vertTexAng0); + vertTexAng1 = blk.getReal("vertTexAng1", vertTexAng1); + vertTexHorBlend = blk.getReal("vertTexHorBlend", vertTexHorBlend); + vertDetTexXZtile = blk.getReal("vertDetTexXZtile", vertDetTexXZtile); + vertDetTexYtile = blk.getReal("vertDetTexYtile", vertDetTexYtile); + vertDetTexYOffset = blk.getReal("vertDetTexYOffset", vertDetTexYOffset); + + const DataBlock *brushBlk; + + brushBlk = local_data.getBlockByName("smoothBrush"); + + if (brushBlk) + brushes[SMOOTH_BRUSH]->loadFromBlk(*brushBlk); + + brushBlk = local_data.getBlockByName("alignBrush"); + + if (brushBlk) + brushes[ALIGN_BRUSH]->loadFromBlk(*brushBlk); + + brushBlk = local_data.getBlockByName("shadowsBrush"); + + if (brushBlk) + brushes[SHADOWS_BRUSH]->loadFromBlk(*brushBlk); + + brushBlk = local_data.getBlockByName("scriptBrush"); + + if (brushBlk) + brushes[SCRIPT_BRUSH]->loadFromBlk(*brushBlk); + + brushBlk = local_data.getBlockByName("hillUpBrush"); + + if (brushBlk) + brushes[HILLUP_BRUSH]->loadFromBlk(*brushBlk); + + brushBlk = local_data.getBlockByName("hillDownBrush"); + + if (brushBlk) + brushes[HILLDOWN_BRUSH]->loadFromBlk(*brushBlk); + + const DataBlock &renderBlk = *blk.getBlockByNameEx("render"); + + render.gridStep = renderBlk.getInt("gridStep", render.gridStep); + render.elemSize = renderBlk.getInt("elemSize", render.elemSize); + render.radiusElems = renderBlk.getInt("radiusElems", render.radiusElems); + render.ringElems = renderBlk.getInt("ringElems", render.ringElems); + render.numLods = renderBlk.getInt("numLods", render.numLods); + render.maxDetailLod = renderBlk.getInt("maxDetailLod", render.maxDetailLod); + render.detailTile = renderBlk.getReal("detailTile", render.detailTile); + render.canyonHorTile = renderBlk.getReal("canyonHorTile", render.canyonHorTile); + render.canyonVertTile = renderBlk.getReal("canyonVertTile", render.canyonVertTile); + render.canyonAngle = renderBlk.getReal("canyonAngle", render.canyonAngle); + render.canyonFadeAngle = renderBlk.getReal("canyonFadeAngle", render.canyonFadeAngle); + render.showFinalHM = renderBlk.getInt("showFinalHM", render.showFinalHM); + monochromeLandCol = renderBlk.getE3dcolor("monoLand", monochromeLandCol); + + LD_LOCAL_VAR(showMonochromeLand, Bool); + + LD_LOCAL_VAR(showHtLevelCurves, Bool); + LD_LOCAL_VAR(htLevelCurveStep, Real); + LD_LOCAL_VAR(htLevelCurveThickness, Real); + LD_LOCAL_VAR(htLevelCurveOfs, Real); + LD_LOCAL_VAR(htLevelCurveDarkness, Real); + LD_LOCAL_VAR(render.hm2YbaseForLod, Real); + render.hm2displacementQ = clamp(local_data.getInt("hm2displacementQ", 1), 0, 5); +#undef LD_LOCAL_VAR + + ldrLight.load("", blk); + + sunAzimuth = blk.getReal("sunAzimuth", sunAzimuth); + sunZenith = blk.getReal("sunZenith", sunZenith); + + lcmScale = blk.getInt("landClsMapScaleFactor", 1); + lightmapScaleFactor = blk.getInt("lightmapScaleFactor", 1); + syncLight = blk.getBool("syncLight", true); + syncDirLight = blk.getBool("syncDirLight", false); + + colorGenParamsData->setFrom(blk.getBlockByNameEx("colorGenParams")); + + const DataBlock *disShadows = blk.getBlockByName("disabled_shadows"); + + if (disShadows) + { + const int colCnt = DAGORED2->getCustomCollidersCount(); + + for (int ci = 0; ci < colCnt; ++ci) + { + const IDagorEdCustomCollider *collider = DAGORED2->getCustomCollider(ci); + if (collider) + { + bool doEnable = true; + const char *shadowName = collider->getColliderName(); + + for (int i = 0; i < disShadows->paramCount(); ++i) + { + const char *disName = disShadows->getStr(i); + + if (disName && !::stricmp(shadowName, disName)) + { + doEnable = false; + break; + } + } + + if (doEnable) + DAGORED2->enableCustomShadow(shadowName); + else + DAGORED2->disableCustomShadow(shadowName); + } + } + } + + CoolConsole &con = DAGORED2->getConsole(); + con.startLog(); + + showBlueWhiteMask = blk.getBool("showBlueWhiteMask", true); + + loadMapFile(heightMap.getInitialMap(), HEIGHTMAP_FILENAME, con); + heightMap.resetFinal(); + + if (detDivisor) + { + loadMapFile(heightMapDet.getInitialMap(), "det-" HEIGHTMAP_FILENAME, con); + heightMapDet.resetFinal(); + + int dw = heightMap.getMapSizeX() * detDivisor, dh = heightMap.getMapSizeY() * detDivisor; + + if (!heightMapDet.isFileOpened() || heightMapDet.getMapSizeX() != dw || heightMapDet.getMapSizeY() != dh) + resizeHeightMapDet(con); + } + + loadMapFile(landClsMap, LANDCLSMAP_FILENAME, con); + resizeLandClassMapFile(con); + + detTexIdxMap = ::loadMap64File(DETTEXMAP_FILENAME, con); + detTexWtMap = ::loadMap64File(DETTEXWMAP_FILENAME, con); + + if (hasColorTex) + loadMapFile(colorMap, COLORMAP_FILENAME, con); + if (hasLightmapTex && exportType != EXPORT_PSEUDO_PLANE) + { + loadMapFile(lightMapScaled, LIGHTMAP_FILENAME, con); + if (!lightMapScaled.isFileOpened() && heightMap.isFileOpened()) + { + String fname(DAGORED2->getPluginFilePath(this, LIGHTMAP_FILENAME)); + bool ltmapfile_exists = ::dd_file_exist(fname); + + lightMapScaled.reset(heightMap.getMapSizeX() * lightmapScaleFactor, heightMap.getMapSizeY() * lightmapScaleFactor, 0xFFFF); + createMapFile(lightMapScaled, LIGHTMAP_FILENAME, con); + if (ltmapfile_exists) + { + DAEDITOR3.conWarning("Obsolete/invalid lightmap.dat detected, starting Rebuild lighting"); + calcFastLandLighting(); + } + } + } + + IWaterService *waterSrv = EDITORCORE->queryEditorInterface(); + if (waterSrv) + { + loadMapFile(waterHeightmapDet.getInitialMap(), WATER_HEIGHTMAP_DET_FILENAME, con); + loadMapFile(waterHeightmapMain.getInitialMap(), WATER_HEIGHTMAP_MAIN_FILENAME, con); + if (waterHeightmapDet.isFileOpened() || waterHeightmapMain.isFileOpened()) + { + Point2 hmapSize(heightMap.getMapSizeX() * gridCellSize, heightMap.getMapSizeY() * gridCellSize); + Point2 hmapEnd = heightMapOffset + hmapSize; + waterSrv->setHeightmap(waterHeightmapDet, waterHeightmapMain, waterHeightMinRangeDet, waterHeightMinRangeMain, detRect, + BBox2(heightMapOffset.x, heightMapOffset.y, hmapEnd.x, hmapEnd.y)); + } + } + + autocenterHeightmap(NULL, false); + + genHmap->offset = heightMapOffset; + genHmap->cellSize = gridCellSize; + + loadGenLayers(*blk.getBlockByNameEx("genLayers")); + getColorGenVarsFromScript(); // Before landmesh to load importance mask. + + const DataBlock *grassBlock = blk.getBlockByNameEx("grassLayers", NULL); + if (grassBlock) + loadGrassLayers(*grassBlock); + + const DataBlock *rendinstDetail2ColorBlock = blk.getBlockByNameEx("rendinstDetail2Color", NULL); + if (rendinstDetail2ColorBlock) + loadRendinstDetail2Color(*rendinstDetail2ColorBlock); + + const DataBlock *landModulateColorTexBlock = blk.getBlockByNameEx("landModulateColorTex", NULL); + if (landModulateColorTexBlock) + loadLandModulateColorTex(*landModulateColorTexBlock); + + const DataBlock *horizontalTexBlock = blk.getBlockByNameEx("horizontalTex", NULL); + if (horizontalTexBlock) + loadHorizontalTex(*horizontalTexBlock); + + + objEd.lastExportPath = local_data.getStr("lastExportPath", objEd.lastExportPath); + objEd.lastImportPath = local_data.getStr("lastImportPath", objEd.lastImportPath); + objEd.lastExportPath = ::make_full_path(DAGORED2->getSdkDir(), objEd.lastExportPath); + objEd.lastImportPath = ::make_full_path(DAGORED2->getSdkDir(), objEd.lastImportPath); + + const DataBlock &loadBlk = *blk.getBlockByNameEx("objects"); + objEd.load(loadBlk); + + String blkPath(128, "%s/splines.blk", base_path); + DataBlock splinesBlk(blkPath); + blkPath = String(128, "%s/polys.blk", base_path); + DataBlock polysBlk(blkPath); + blkPath = String(128, "%s/entities.blk", base_path); + DataBlock entBlk(blkPath); + blkPath = String(128, "%s/lights.blk", base_path); + DataBlock ltBlk(blkPath); + + objEd.load(splinesBlk, polysBlk, entBlk, ltBlk, -1); + if (DAGORED2->curPlugin() == this) + objEd.updateToolbarButtons(); + + for (int i = 0; i < EditLayerProps::layerProps.size(); i++) + { + if (EditLayerProps::layerProps[i].nameId == 0) + continue; + + const char *lname = EditLayerProps::layerProps[i].name(); + switch (EditLayerProps::layerProps[i].type) + { + case EditLayerProps::SPL: + splinesBlk.load(String(128, "%s/splines.%s.blk", base_path, lname)); + objEd.load(splinesBlk, DataBlock::emptyBlock, DataBlock::emptyBlock, DataBlock::emptyBlock, i); + break; + case EditLayerProps::PLG: + polysBlk.load(String(128, "%s/polys.%s.blk", base_path, lname)); + objEd.load(DataBlock::emptyBlock, polysBlk, DataBlock::emptyBlock, DataBlock::emptyBlock, i); + break; + case EditLayerProps::ENT: + entBlk.load(String(128, "%s/entities.%s.blk", base_path, lname)); + objEd.load(DataBlock::emptyBlock, DataBlock::emptyBlock, entBlk, DataBlock::emptyBlock, i); + break; + } + } + + con.endLog(); + + updateHmap2Tesselation(); + resetRenderer(true); + onLandSizeChanged(); + + const DataBlock *panelStateBlk = local_data.getBlockByName("panel_state"); + if (panelStateBlk) + mainPanelState.setFrom(panelStateBlk); + + snowDynPreview = blk.getBool("snow_dyn_prewiew", false); + snowSpherePreview = blk.getBool("snow_sphere_prewiew", false); + ambSnowValue = blk.getReal("snow_amb_value", 0); + dynSnowValue = ambSnowValue; + + dagGeom->shaderGlobalSetInt(snowPrevievSVId, (snowDynPreview && snowSpherePreview) ? 2 : (snowDynPreview ? 1 : 0)); + dagGeom->shaderGlobalSetReal(snowValSVId, dynSnowValue); + + if (snowSpherePreview) + updateSnowSources(); + + acquireVertTexRef(); + + for (int i = 0; i < MAX_NAVMESHES; ++i) + navMeshProps[i] = *blk.getBlockByNameEx(i == 0 ? String("navMesh") : String(50, "navMesh%d", i + 1)); + + shownExportedNavMeshIdx = local_data.getInt("shownExportedNavMeshIdx", 0); + showExportedNavMesh = local_data.getBool("showExportedNavMesh", true); + showExportedCovers = local_data.getBool("showExportedCovers", true); + showExportedNavMeshContours = local_data.getBool("showExportedNavMeshContours", true); + showExpotedObstacles = local_data.getBool("showExpotedObstacles", true); + disableZtestForDebugNavMesh = local_data.getBool("disableZtestForDebugNavMesh", false); + + if (lcmScale > 1) + prepareDetTexMaps(); +} + + +void HmapLandPlugin::beforeMainLoop() +{ + ignoreEvents = false; + applyHmModifiers(false, true, false); + updateHeightMapTex(false); + updateHeightMapTex(true); + + if (useMeshSurface && exportType != EXPORT_PSEUDO_PLANE && landMeshMap.isEmpty()) // Before entities to place them correctly. + { + rebuildHtConstraintBitmask(); + generateLandMeshMap(landMeshMap, DAGORED2->getConsole(), false, NULL); + } + + if (syncLight) + getAllSunSettings(); + else if (syncDirLight) + getDirectionSunSettings(); + + resetRenderer(true); + + lastLandExportPath = DAGORED2->getWorkspace().getLevelsBinDir(); + rebuildSplinesBitmask(false); + onLandRegionChanged(0, 0, landClsMap.getMapSizeX(), landClsMap.getMapSizeY(), true); + updateHtLevelCurves(); + + // gizmoTranformMode was set during loading in LandscapeEntityObject::load() (and LandscapeEntityObject::propsChanged(true)) + for (int i = 0; i < objEd.objectCount(); i++) + if (LandscapeEntityObject *o = RTTI_cast(objEd.getObject(i))) + o->setGizmoTranformMode(false); +} + + +void HmapLandPlugin::restoreBackup() +{ + heightMap.closeFile(); + heightMapDet.closeFile(); + + CoolConsole &con = DAGORED2->getConsole(); + con.startLog(); + con.addMessage(ILogWriter::NOTE, "restoring heightmap from backup..."); + + DAGOR_TRY + { + heightMap.getInitialMap().revertChanges(); + if (detDivisor) + heightMapDet.getInitialMap().revertChanges(); + } + DAGOR_CATCH(DagorException e) + { + con.addMessage(ILogWriter::ERROR, "Error restoring heightmap backup: '%s'", e.excDesc); + con.endLog(); + + return; + } + + objEd.updateToolbarButtons(); + + loadMapFile(heightMap.getInitialMap(), HEIGHTMAP_FILENAME, con); + if (detDivisor) + loadMapFile(heightMapDet.getInitialMap(), "det-" HEIGHTMAP_FILENAME, con); + heightMap.resetFinal(); + if (detDivisor) + heightMapDet.resetFinal(); + applyHmModifiers(false); + resetRenderer(); + updateHeightMapTex(false); + updateHeightMapTex(true); + + con.addMessage(ILogWriter::NOTE, "Heightmap backup restored"); + con.endLog(); +} + + +// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ// + + +template +void HmapLandPlugin::createMapFile(MapStorage &map, const char *filename, CoolConsole &con) +{ + con.startProgress(); + con.setActionDesc("Creating %s file...", filename); + + String fileName(DAGORED2->getPluginFilePath(this, filename)); + if (!map.createFile(fileName)) + con.addMessage(ILogWriter::ERROR, "Error creating %s file", filename); + else + con.addMessage(ILogWriter::NOTE, "Created %dx%d %s file", map.getMapSizeX(), map.getMapSizeY(), filename); + + con.endProgress(); +} + +void HmapLandPlugin::createHeightmapFile(CoolConsole &con) +{ + createMapFile(heightMap.getInitialMap(), HEIGHTMAP_FILENAME, con); + heightMap.resetFinal(); + // reset water mask when heightmap size is changed + if (waterMask.getW() / waterMaskScale != getHeightmapSizeX() || waterMask.getH() / waterMaskScale != getHeightmapSizeY()) + { + waterMask.resize(0, 0); + waterMaskScale = 1; + } + applyHmModifiers(false); +} + +void HmapLandPlugin::createWaterHmapFile(CoolConsole &con, bool det) +{ + HeightMapStorage &hms = det ? waterHeightmapDet : waterHeightmapMain; + createMapFile(hms.getInitialMap(), det ? WATER_HEIGHTMAP_DET_FILENAME : WATER_HEIGHTMAP_MAIN_FILENAME, con); +} + +void HmapLandPlugin::resizeHeightMapDet(CoolConsole &con) +{ + int dw = heightMap.getMapSizeX() * detDivisor, dh = heightMap.getMapSizeY() * detDivisor; + heightMapDet.getInitialMap().reset(dw, dh, 0); + heightMapDet.resetFinal(); + createMapFile(heightMapDet.getInitialMap(), "det-" HEIGHTMAP_FILENAME, con); + heightMapDet.flushData(); +} + +void HmapLandPlugin::createColormapFile(CoolConsole &con) +{ + createMapFile(landClsMap, LANDCLSMAP_FILENAME, con); + if (hasColorTex) + createMapFile(colorMap, COLORMAP_FILENAME, con); +} + + +void HmapLandPlugin::createLightmapFile(CoolConsole &con) +{ + if (heightMap.isFileOpened()) + createMapFile(lightMapScaled, LIGHTMAP_FILENAME, con); +} +void HmapLandPlugin::resizeLandClassMapFile(CoolConsole &con) +{ + if (heightMap.getMapSizeX() * lcmScale == landClsMap.getMapSizeX() && heightMap.getMapSizeY() * lcmScale == landClsMap.getMapSizeY()) + return; + + if (landClsMap.isFileOpened()) + landClsMap.eraseFile(); + landClsMap.reset(heightMap.getMapSizeX() * lcmScale, heightMap.getMapSizeY() * lcmScale, 0); + createMapFile(landClsMap, LANDCLSMAP_FILENAME, con); + landClsMap.flushData(); +} + +void HmapLandPlugin::updateHeightMapConstants() +{ + bool show_hmap = (DAEDITOR3.getEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_RENDER) & hmapSubtypeMask); + bool show_lmap = (DAEDITOR3.getEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_RENDER) & lmeshSubtypeMask); + real gcsz = detDivisor ? gridCellSize / detDivisor : gridCellSize; + real calign = ((detDivisor && !show_hmap) ? gcsz : gridCellSize) * 32; + + hmlService->setupRenderHm2(gcsz, gcsz, calign, calign, show_hmap ? hmapTex[0] : NULL, hmapTexId[0], heightMapOffset.x, + heightMapOffset.y, heightMap.getMapSizeX() * gridCellSize, heightMap.getMapSizeY() * gridCellSize, + (detDivisor && (show_hmap || show_lmap)) ? hmapTex[1] : NULL, hmapTexId[1], detRect[0].x, detRect[0].y, detRect.width().x, + detRect.width().y); +} +void HmapLandPlugin::updateHeightMapTex(bool det_hmap, const IBBox2 *dirty_box) +{ + if (d3d::is_stub_driver() || !hmlService) + return; + + HeightMapStorage &hm = det_hmap ? heightMapDet : heightMap; + Texture *&tex = hmapTex[det_hmap ? 1 : 0]; + TEXTUREID &texId = hmapTexId[det_hmap ? 1 : 0]; + + if (!hm.isFileOpened()) + return; + if (det_hmap && !detDivisor) + return; + int dmsz_x = det_hmap ? detRectC[1].x - detRectC[0].x : hm.getMapSizeX(); + int dmsz_y = det_hmap ? detRectC[1].y - detRectC[0].y : hm.getMapSizeY(); + + int ox = det_hmap ? detRectC[0].x : 0; + int oy = det_hmap ? detRectC[0].y : 0; + int x0 = 0, y0 = 0, x1 = dmsz_x, y1 = dmsz_y; + if (dirty_box) + { + x0 = (*dirty_box)[0].x - ox; + y0 = (*dirty_box)[0].y - oy; + x1 = (*dirty_box)[1].x - ox + 1; + y1 = (*dirty_box)[1].y - oy + 1; + if (x0 < 0) + x0 = 0; + if (y0 < 0) + y0 = 0; + if (x1 > dmsz_x) + x1 = dmsz_x; + if (y1 > dmsz_y) + y1 = dmsz_y; + } + if (x1 <= x0 || y1 <= y0) + return; + + if (tex) + { + TextureInfo ti; + if (tex->getinfo(ti)) + if (ti.w != dmsz_x || ti.h != dmsz_y) + { + debug("updateHeightMapTex(%d): %dx%d -> %dx%d", det_hmap, ti.w, ti.h, dmsz_x, dmsz_y); + hmlService->setupRenderHm2(1, 1, 1, 1, NULL, BAD_TEXTUREID, 0, 0, 1, 1, NULL, BAD_TEXTUREID, 0, 0, 1, 1); + dagRender->releaseManagedTexVerified(texId, tex); + } + } + if (!tex) + { + tex = d3d::create_tex(NULL, dmsz_x, dmsz_y, TEXFMT_R32F | TEXCF_READABLE | TEXCF_DYNAMIC, 1, det_hmap ? "hmapDet" : "hmapMain"); + debug("updateHeightMapTex(%d): tex=%p %dx%d", det_hmap, tex, dmsz_x, dmsz_y); + if (tex) + { + tex->texaddr(TEXADDR_CLAMP); //== we render finite HMAP! (det_hmap ? TEXADDR_CLAMP : TEXADDR_MIRROR); + texId = dagRender->registerManagedTex(det_hmap ? "!hmapDet" : "!hmapMain", tex); + } + } + + if (!tex) + { + logerr_ctx("failed to create HMAP tex"); + return; + } + + // fill HMAP texture + unsigned texLockFlags = TEXLOCK_UPDATEFROMSYSTEX | TEXLOCK_RWMASK | TEXLOCK_SYSTEXLOCK; + float *imgPtr; + int stride; + + if (tex->lockimgEx(&imgPtr, stride, 0, texLockFlags)) + { + imgPtr += stride / sizeof(*imgPtr) * y0; + if (render.showFinalHM) + { + for (; y0 < y1; y0++, imgPtr += stride / sizeof(*imgPtr)) + for (int x = x0; x < x1; x++) + imgPtr[x] = hm.getFinalData(x + ox, y0 + oy); + } + else + { + for (; y0 < y1; y0++, imgPtr += stride / sizeof(*imgPtr)) + for (int x = x0; x < x1; x++) + imgPtr[x] = hm.getInitialData(x + ox, y0 + oy); + } + tex->unlockimg(); + } +} +void HmapLandPlugin::updateHmap2Tesselation() +{ + if (!hmlService) + return; + + DataBlock blk; + if (detDivisor) + { + float hmapCellSize = gridCellSize / detDivisor; + blk.setInt("tesselation", max(1 + render.hm2displacementQ + (int)(log2f(hmapCellSize)), 0)); + } + hmlService->initLodGridHm2(blk); +} + +void HmapLandPlugin::SunSkyLight::save(const char *prefix, DataBlock &blk) const +{ + blk.setE3dcolor(String(128, "sun%sLightColor", prefix), sunColor); + blk.setE3dcolor(String(128, "sky%sLightColor", prefix), skyColor); + blk.setReal(String(128, "sun%sLightPower", prefix), sunPower); + blk.setReal(String(128, "sky%sLightPower", prefix), skyPower); + blk.setE3dcolor(String(128, "%sspecularColor", prefix), specularColor); + blk.setReal(String(128, "%sspecularMul", prefix), specularMul); + blk.setReal(String(128, "%sspecularPower", prefix), specularPower); +} + +void HmapLandPlugin::SunSkyLight::load(const char *prefix, const DataBlock &blk) +{ + sunColor = blk.getE3dcolor(String(128, "sun%sLightColor", prefix), sunColor); + skyColor = blk.getE3dcolor(String(128, "sky%sLightColor", prefix), skyColor); + sunPower = blk.getReal(String(128, "sun%sLightPower", prefix), sunPower); + skyPower = blk.getReal(String(128, "sky%sLightPower", prefix), skyPower); + specularColor = blk.getE3dcolor(String(128, "%sspecularColor", prefix), specularColor); + specularMul = blk.getReal(String(128, "%sspecularMul", prefix), specularMul); + specularPower = blk.getReal(String(128, "%sspecularPower", prefix), specularPower); +} + +void HmapLandPlugin::autoSaveObjects(DataBlock &local_data) +{ + DataBlock &autoBlk = *local_data.addBlock("panel_state"); + if (propPanel && propPanel->getPanelWindow()) + { + mainPanelState.reset(); + propPanel->getPanelWindow()->saveState(mainPanelState); + } + autoBlk.setFrom(&mainPanelState); + +#define ST_LOCAL_VAR(X, TYPE) local_data.set##TYPE(#X, X) + ST_LOCAL_VAR(showMonochromeLand, Bool); + + ST_LOCAL_VAR(showHtLevelCurves, Bool); + ST_LOCAL_VAR(htLevelCurveStep, Real); + ST_LOCAL_VAR(htLevelCurveThickness, Real); + ST_LOCAL_VAR(htLevelCurveOfs, Real); + ST_LOCAL_VAR(htLevelCurveDarkness, Real); + + ST_LOCAL_VAR(shownExportedNavMeshIdx, Int); + ST_LOCAL_VAR(showExportedNavMesh, Bool); + ST_LOCAL_VAR(showExportedCovers, Bool); + ST_LOCAL_VAR(showExportedNavMeshContours, Bool); + ST_LOCAL_VAR(showExpotedObstacles, Bool); + ST_LOCAL_VAR(disableZtestForDebugNavMesh, Bool); + + ST_LOCAL_VAR(lastHmapImportPath, Str); + ST_LOCAL_VAR(lastHmapImportPathDet, Str); + ST_LOCAL_VAR(lastHmapImportPathMain, Str); + local_data.setStr("lastHmapImportPathWater", lastWaterHeightmapImportPath); + ST_LOCAL_VAR(lastWaterHeightmapImportPathDet, Str); + ST_LOCAL_VAR(lastWaterHeightmapImportPathMain, Str); + + ST_LOCAL_VAR(lastLandExportPath, Str); + ST_LOCAL_VAR(lastHmapExportPath, Str); + ST_LOCAL_VAR(lastColormapExportPath, Str); + ST_LOCAL_VAR(lastTexImportPath, Str); + + local_data.setBool("autoUpdateSpline", objEd.autoUpdateSpline); + local_data.setReal("maxPointVisDist", objEd.maxPointVisDist); + local_data.setStr("lastExportPath", objEd.lastExportPath); + local_data.setStr("lastImportPath", objEd.lastImportPath); + + ST_LOCAL_VAR(lastExpLoftFolder, Str); + ST_LOCAL_VAR(lastExpLoftMain, Bool); + ST_LOCAL_VAR(lastExpLoftDet, Bool); + ST_LOCAL_VAR(lastExpLoftMainSz, Int); + ST_LOCAL_VAR(lastExpLoftDetSz, Int); + local_data.setBool("lastExpLoftUseRectM", lastExpLoftUseRect[0]); + local_data.setPoint2("lastExpLoftRectM0", lastExpLoftRect[0][0]); + local_data.setPoint2("lastExpLoftRectM1", lastExpLoftRect[0][1]); + local_data.setBool("lastExpLoftUseRectD", lastExpLoftUseRect[1]); + local_data.setPoint2("lastExpLoftRectD0", lastExpLoftRect[1][0]); + local_data.setPoint2("lastExpLoftRectD1", lastExpLoftRect[1][1]); + local_data.setBool("lastExpLoftCreateAreaSubfolders", lastExpLoftCreateAreaSubfolders); + + if (render.hm2displacementQ != 1) + local_data.setInt("hm2displacementQ", render.hm2displacementQ); +#undef ST_LOCAL_VAR +} + +void HmapLandPlugin::saveObjects(DataBlock &blk, DataBlock &local_data, const char *base_path) +{ +#define ST_LOCAL_VAR(X, TYPE) local_data.set##TYPE(#X, X) + EditLayerProps::saveLayersConfig(blk, local_data); + + storeLayerTex(); + + local_data.setStr("lastHmapImportPath", lastHmapImportPath); + ST_LOCAL_VAR(lastHmapImportPathMain, Str); + if (!lastHmapImportPathMain.empty()) + { + ST_LOCAL_VAR(lastChangeMain.size, Int64); + ST_LOCAL_VAR(lastChangeMain.mtime, Int64); + } + ST_LOCAL_VAR(lastHmapImportPathDet, Str); + if (!lastHmapImportPathDet.empty()) + { + ST_LOCAL_VAR(lastChangeDet.size, Int64); + ST_LOCAL_VAR(lastChangeDet.mtime, Int64); + } + local_data.setStr("lastHmapImportPathWater", lastWaterHeightmapImportPath); + ST_LOCAL_VAR(lastWaterHeightmapImportPathDet, Str); + if (!lastWaterHeightmapImportPathDet.empty()) + { + ST_LOCAL_VAR(lastChangeWaterDet.size, Int64); + ST_LOCAL_VAR(lastChangeWaterDet.mtime, Int64); + } + ST_LOCAL_VAR(lastWaterHeightmapImportPathMain, Str); + if (!lastWaterHeightmapImportPathMain.empty()) + { + ST_LOCAL_VAR(lastChangeWaterMain.size, Int64); + ST_LOCAL_VAR(lastChangeWaterMain.mtime, Int64); + } + local_data.setStr("lastLandExportPath", lastLandExportPath); + local_data.setStr("lastHmapExportPath", lastHmapExportPath); + local_data.setStr("lastColormapExportPath", lastColormapExportPath); + local_data.setStr("lastTexImportPath", lastTexImportPath); + local_data.setBool("autoUpdateSpline", objEd.autoUpdateSpline); + local_data.setReal("maxPointVisDist", objEd.maxPointVisDist); + local_data.setStr("lastExpLoftFolder", lastExpLoftFolder); + blk.setBool("lastExpLoftMain", lastExpLoftMain); + blk.setBool("lastExpLoftDet", lastExpLoftDet); + blk.setInt("lastExpLoftMainSz", lastExpLoftMainSz); + blk.setInt("lastExpLoftDetSz", lastExpLoftDetSz); + blk.setBool("lastExpLoftUseRectM", lastExpLoftUseRect[0]); + blk.setPoint2("lastExpLoftRectM0", lastExpLoftRect[0][0]); + blk.setPoint2("lastExpLoftRectM1", lastExpLoftRect[0][1]); + blk.setBool("lastExpLoftUseRectD", lastExpLoftUseRect[1]); + blk.setPoint2("lastExpLoftRectD0", lastExpLoftRect[1][0]); + blk.setPoint2("lastExpLoftRectD1", lastExpLoftRect[1][1]); + blk.setBool("lastExpLoftCreateAreaSubfolders", lastExpLoftCreateAreaSubfolders); + + if (exportType == EXPORT_HMAP) + blk.setStr("hmapExportType", "hmap"); + else if (exportType == EXPORT_LANDMESH) + blk.setStr("hmapExportType", "lmesh"); + else if (exportType == EXPORT_PSEUDO_PLANE) + blk.setStr("hmapExportType", "plane"); + + blk.setReal("meshPreviewDistance", meshPreviewDistance); + blk.setInt("meshCells", meshCells); + blk.setReal("meshErrorThreshold", meshErrorThreshold); + blk.setInt("numMeshVertices", numMeshVertices); + blk.setInt("lod1TrisDensity", lod1TrisDensity); + blk.setReal("importanceMaskScale", importanceMaskScale); + blk.setBool("geomLoftBelowAll", geomLoftBelowAll); + + blk.setBool("hasWaterSurface", hasWaterSurface); + blk.setStr("waterMatAsset", waterMatAsset); + blk.setReal("waterSurfaceLevel", waterSurfaceLevel); + blk.setReal("minUnderwaterBottomDepth", minUnderwaterBottomDepth); + blk.setBool("hasWorldOcean", hasWorldOcean); + blk.setReal("worldOceanExpand", worldOceanExpand); + blk.setReal("worldOceanShorelineTolerance", worldOceanShorelineTolerance); + + if (lastMinHeight[0] != MAX_REAL) + blk.setReal("lastMinHeight", lastMinHeight[0]); + + if (lastHeightRange[0] != MAX_REAL) + blk.setReal("lastHeightRange", lastHeightRange[0]); + + if (lastMinHeight[1] != MAX_REAL) + blk.setReal("lastMinHeightDet", lastMinHeight[1]); + + if (lastHeightRange[1] != MAX_REAL) + blk.setReal("lastHeightRangeDet", lastHeightRange[1]); + + if (waterHeightMinRangeDet.y > 0.0) + blk.setPoint2("waterHeightMinRangeDet", waterHeightMinRangeDet); + if (waterHeightMinRangeMain.y > 0.0) + blk.setPoint2("waterHeightMinRangeMain", waterHeightMinRangeMain); + + if (!colorGenScriptFilename.empty()) + blk.setStr("colorGenScriptFilename", ::make_path_relative(colorGenScriptFilename, DAGORED2->getSdkDir())); + + blk.setBool("doAutocenter", doAutocenter); + + blk.setReal("gridCellSize", gridCellSize); + + blk.setReal("heightScale", heightMap.heightScale); + blk.setReal("heightOffset", heightMap.heightOffset); + + blk.setInt("detDivisor", detDivisor); + blk.setPoint2("detRect0", detRect[0]); + blk.setPoint2("detRect1", detRect[1]); + + blk.setPoint2("collisionArea_ofs", collisionArea.ofs); + blk.setPoint2("collisionArea_sz", collisionArea.sz); + blk.setBool("collisionArea_show", collisionArea.show); + + blk.setPoint2("heightMapOffset", heightMapOffset); + + blk.setReal("shadowBias", shadowBias); + blk.setReal("shadowTraceDist", shadowTraceDist); + blk.setReal("shadowDensity", shadowDensity); + + blk.setReal("tileXSize", tileXSize); + blk.setReal("tileYSize", tileYSize); + if (requireTileTex) + blk.setStr("tileTexName", tileTexName); + + blk.setBool("useVertTex", useVertTex); + blk.setBool("useVertTexForHMAP", useVertTexForHMAP); + blk.setStr("vertTexName", vertTexName); + blk.setStr("vertNmTexName", vertNmTexName); + blk.setStr("vertDetTexName", vertDetTexName); + blk.setReal("vertTexXZtile", vertTexXZtile); + blk.setReal("vertTexYtile", vertTexYtile); + blk.setReal("vertTexYOffset", vertTexYOffset); + blk.setReal("vertTexAng0", vertTexAng0); + blk.setReal("vertTexAng1", vertTexAng1); + blk.setReal("vertTexHorBlend", vertTexHorBlend); + blk.setReal("vertDetTexXZtile", vertDetTexXZtile); + blk.setReal("vertDetTexYtile", vertDetTexYtile); + blk.setReal("vertDetTexYOffset", vertDetTexYOffset); + + DataBlock &newBlk = *blk.addBlock("objects"); + + objEd.lastExportPath = ::make_path_relative(objEd.lastExportPath, DAGORED2->getSdkDir()); + objEd.lastImportPath = ::make_path_relative(objEd.lastImportPath, DAGORED2->getSdkDir()); + local_data.setStr("lastExportPath", objEd.lastExportPath); + local_data.setStr("lastImportPath", objEd.lastImportPath); + + objEd.save(newBlk); + + DataBlock splinesBlk, polysBlk, entBlk, ltBlk; + + objEd.save(splinesBlk, polysBlk, entBlk, ltBlk, -1); + + splinesBlk.saveToTextFile(String(128, "%s/splines.blk", base_path)); + polysBlk.saveToTextFile(String(128, "%s/polys.blk", base_path)); + entBlk.saveToTextFile(String(128, "%s/entities.blk", base_path)); + if (ltBlk.blockCount() || ltBlk.paramCount()) + ltBlk.saveToTextFile(String(128, "%s/lights.blk", base_path)); + else if (dd_file_exist(String(128, "%s/lights.blk", base_path))) + ltBlk.saveToTextFile(String(128, "%s/lights.blk", base_path)); + + for (int i = 0; i < EditLayerProps::layerProps.size(); i++) + { + if (EditLayerProps::layerProps[i].nameId == 0) + continue; + splinesBlk.clearData(), polysBlk.clearData(), entBlk.clearData(); + ltBlk.clearData(); + objEd.save(splinesBlk, polysBlk, entBlk, ltBlk, i); + + const char *lname = EditLayerProps::layerProps[i].name(); + switch (EditLayerProps::layerProps[i].type) + { + case EditLayerProps::SPL: splinesBlk.saveToTextFile(String(128, "%s/splines.%s.blk", base_path, lname)); break; + case EditLayerProps::PLG: polysBlk.saveToTextFile(String(128, "%s/polys.%s.blk", base_path, lname)); break; + case EditLayerProps::ENT: entBlk.saveToTextFile(String(128, "%s/entities.%s.blk", base_path, lname)); break; + } + } + + DataBlock *brushBlk; + + brushBlk = local_data.addNewBlock("smoothBrush"); + if (brushBlk) + brushes[SMOOTH_BRUSH]->saveToBlk(*brushBlk); + + brushBlk = local_data.addNewBlock("alignBrush"); + if (brushBlk) + brushes[ALIGN_BRUSH]->saveToBlk(*brushBlk); + + brushBlk = local_data.addNewBlock("shadowsBrush"); + if (brushBlk) + brushes[SHADOWS_BRUSH]->saveToBlk(*brushBlk); + + brushBlk = local_data.addNewBlock("scriptBrush"); + if (brushBlk) + brushes[SCRIPT_BRUSH]->saveToBlk(*brushBlk); + + brushBlk = local_data.addNewBlock("hillUpBrush"); + if (brushBlk) + brushes[HILLUP_BRUSH]->saveToBlk(*brushBlk); + + brushBlk = local_data.addNewBlock("hillDownBrush"); + if (brushBlk) + brushes[HILLDOWN_BRUSH]->saveToBlk(*brushBlk); + + DataBlock &renderBlk = *blk.addBlock("render"); + + renderBlk.setInt("gridStep", render.gridStep); + renderBlk.setInt("elemSize", render.elemSize); + renderBlk.setInt("radiusElems", render.radiusElems); + renderBlk.setInt("ringElems", render.ringElems); + renderBlk.setInt("numLods", render.numLods); + renderBlk.setInt("maxDetailLod", render.maxDetailLod); + renderBlk.setReal("detailTile", render.detailTile); + renderBlk.setReal("canyonHorTile", render.canyonHorTile); + renderBlk.setReal("canyonVertTile", render.canyonVertTile); + renderBlk.setReal("canyonAngle", render.canyonAngle); + renderBlk.setReal("canyonFadeAngle", render.canyonFadeAngle); + renderBlk.setInt("holesLod", render.holesLod); + renderBlk.setInt("showFinalHM", render.showFinalHM); + renderBlk.setE3dcolor("monoLand", monochromeLandCol); + + ST_LOCAL_VAR(showMonochromeLand, Bool); + + ST_LOCAL_VAR(showHtLevelCurves, Bool); + ST_LOCAL_VAR(htLevelCurveStep, Real); + ST_LOCAL_VAR(htLevelCurveThickness, Real); + ST_LOCAL_VAR(htLevelCurveOfs, Real); + ST_LOCAL_VAR(htLevelCurveDarkness, Real); + ST_LOCAL_VAR(render.hm2YbaseForLod, Real); +#undef ST_LOCAL_VAR + + ldrLight.save("", blk); + + blk.setReal("sunAzimuth", sunAzimuth); + blk.setReal("sunZenith", sunZenith); + + blk.setInt("landClsMapScaleFactor", lcmScale); + blk.setInt("lightmapScaleFactor", lightmapScaleFactor); + + blk.setBool("syncLight", syncLight); + blk.setBool("syncDirLight", syncDirLight); + + for (int i = 0; i < colorGenParams.size(); ++i) + colorGenParams[i]->save(*colorGenParamsData); + + blk.setBlock(colorGenParamsData, "colorGenParams"); + + DataBlock &disShadows = *blk.addNewBlock("disabled_shadows"); + + const int colCnt = DAGORED2->getCustomCollidersCount(); + + for (int i = 0; i < colCnt; ++i) + { + const IDagorEdCustomCollider *collider = DAGORED2->getCustomCollider(i); + + if (!DAGORED2->isCustomShadowEnabled(collider)) + disShadows.addStr("disable", collider->getColliderName()); + } + + CoolConsole &con = DAGORED2->getConsole(); + con.startLog(); + + for (int i = 0; i < scriptImages.size(); ++i) + if (scriptImages[i]->isImageModified()) + if (!scriptImages[i]->saveImage()) + con.addMessage(ILogWriter::ERROR, "Error saving script image '%s'", scriptImages[i]->getName()); + blk.setBool("showBlueWhiteMask", showBlueWhiteMask); + + if (heightMapDet.isFileOpened()) + if (!flushDataTo(base_path, origBasePath, heightMapDet.getInitialMap())) + con.addMessage(ILogWriter::ERROR, "Error saving DET heightmap data"); + if (heightMap.isFileOpened() || !landMeshMap.isEmpty()) + { + if (heightMap.isFileOpened()) + if (!flushDataTo(base_path, origBasePath, heightMap.getInitialMap())) + con.addMessage(ILogWriter::ERROR, "Error saving heightmap data"); + + if (!flushDataTo(base_path, origBasePath, landClsMap)) + con.addMessage(ILogWriter::ERROR, "Error saving landClsMap data"); + + if (detTexIdxMap) + if (!flushDataTo(base_path, origBasePath, *detTexIdxMap)) + DAEDITOR3.conError("Error saving detTexIdx data"); + if (detTexWtMap) + if (!flushDataTo(base_path, origBasePath, *detTexWtMap)) + DAEDITOR3.conError("Error saving detTexWt data"); + + if (hasColorTex) + { + if (!colorMap.isFileOpened()) + createColormapFile(con); + if (!flushDataTo(base_path, origBasePath, colorMap)) + con.addMessage(ILogWriter::ERROR, "Error saving color map data"); + } + + if (hasLightmapTex && exportType != EXPORT_PSEUDO_PLANE) + { + if (!lightMapScaled.isFileOpened()) + createLightmapFile(con); + if (!flushDataTo(base_path, origBasePath, lightMapScaled)) + con.addMessage(ILogWriter::ERROR, "Error saving light map data"); + } + } + + + if (HmapLandPlugin::self->isSnowAvailable() && (snowDynPreview || snowSpherePreview || dynSnowValue != 0 || ambSnowValue != 0)) + { + if (snowDynPreview) + blk.addBool("snow_dyn_prewiew", snowDynPreview); + if (snowSpherePreview) + blk.addBool("snow_sphere_prewiew", snowSpherePreview); + blk.addReal("snow_amb_value", ambSnowValue); + } + + DataBlock *b = blk.addBlock("genLayers"); + saveGenLayers(*b); + if (!b->blockCount()) + blk.removeBlock("genLayers"); + + + DataBlock *grassLayersBlk = blk.addBlock("grassLayers"); + if (!grassLayersBlk->blockCount()) + blk.removeBlock("grassLayers"); + + if (gpuGrassBlk && !levelBlkFName.empty()) + { + if (gpuGrassService && gpuGrassService->isGrassEnabled()) + { + if (!dd_file_exists(levelBlkFName)) + wingw::message_box(wingw::MBS_EXCL, "Error", "Level blk is not valid: %s", levelBlkFName.c_str()); + else if (!gpuGrassPanel.isGrassValid()) + wingw::message_box(wingw::MBS_EXCL, "Error", "Grass properties are not valid and will not be saved"); + else if (!equalDataBlocks(*levelBlk.getBlockByNameEx("grass"), *gpuGrassBlk)) + { + *levelBlk.addBlock("grass") = *gpuGrassBlk; + levelBlk.saveToTextFile(levelBlkFName.c_str()); + } + } + else + { + if (dd_file_exists(levelBlkFName) && levelBlk.getBlockByName("grass")) + { + levelBlk.removeBlock("grass"); + levelBlk.saveToTextFile(levelBlkFName.c_str()); + } + wingw::message_box(wingw::MBS_EXCL, "Warning", "Grass is disabled, properties will not be saved to level blk"); + } + } + DataBlock *detail2ColorBlk = blk.addBlock("rendinstDetail2Color"); + saveRendinstDetail2Color(*detail2ColorBlk); + + DataBlock *landModulateColorTexBlk = blk.addBlock("landModulateColorTex"); + saveLandModulateColorTex(*landModulateColorTexBlk); + + DataBlock *horizontalTexBlk = blk.addBlock("horizontalTex"); + saveHorizontalTex(*horizontalTexBlk); + + + for (int i = 0; i < MAX_NAVMESHES; ++i) + *blk.addBlock(i == 0 ? String("navMesh") : String(50, "navMesh%d", i + 1)) = navMeshProps[i]; + + local_data.setInt("shownExportedNavMeshIdx", shownExportedNavMeshIdx); + local_data.setBool("showExportedNavMesh", showExportedNavMesh); + local_data.setBool("showExportedCovers", showExportedCovers); + local_data.setBool("showExportedNavMeshContours", showExportedNavMeshContours); + local_data.setBool("showExpotedObstacles", showExpotedObstacles); + local_data.setBool("disableZtestForDebugNavMesh", disableZtestForDebugNavMesh); + + /*#if defined(USE_HMAP_ACES) + // Save tile offsets back to assets blk. + String text("You should manually change the following detail offset parameters:"); + bool wasChanged = false; + for (unsigned int tileTexNo = 0; + tileTexNo < detailTexBlkName.size() && tileTexNo < detailTexOffset.size(); + tileTexNo++) + { + DagorAsset *a = DAEDITOR3.getAssetByName(detailTexBlkName[tileTexNo], DAEDITOR3.getAssetTypeId("land")); + if (a) + { + const DataBlock *detailBlk = a->props.getBlockByNameEx("detail"); + Point2 prevOffset = detailBlk->getPoint2("offset", Point2(0.f, 0.f)); + if (!is_equal_float(prevOffset.x, detailTexOffset[tileTexNo].x) + || !is_equal_float(prevOffset.y, detailTexOffset[tileTexNo].y)) + { + text += String(200, + "\nin '%s': from 'detail { offset:p2 = %g, %g }' to 'detail { offset:p2 = %g, %g }'", + a->getSrcFilePath(), + prevOffset.x, + prevOffset.y, + detailTexOffset[tileTexNo].x, + detailTexOffset[tileTexNo].y); + + wasChanged = true; + } + } + else if (detailTexBlkName[tileTexNo].length() > 0) + DAEDITOR3.conError("detailTex[%d] asset <%s> not found", tileTexNo, detailTexBlkName[tileTexNo].str()); + } + + if (wasChanged) + DAEDITOR3.conWarning("%s", text.str()); + if (wasChanged && !DAGORED2->isInBatchOp()) + wingw::message_box(wingw::MBS_EXCL, "Tile offset changed", text); + #endif*/ + + con.endLog(); + if (strcmp(origBasePath, base_path) != 0) + origBasePath = base_path; +} + +bool HmapLandPlugin::hmCommitChanges() +{ + if (heightMap.isFileOpened()) + { + heightMap.getInitialMap().flushData(); + heightMap.getInitialMap().closeFile(true); + heightMap.getInitialMap().openFile(DAGORED2->getPluginFilePath(this, HEIGHTMAP_FILENAME)); + } + if (landClsMap.isFileOpened()) + { + landClsMap.flushData(); + landClsMap.closeFile(true); + landClsMap.openFile(DAGORED2->getPluginFilePath(this, LANDCLSMAP_FILENAME)); + } + if (colorMap.isFileOpened()) + { + colorMap.flushData(); + colorMap.closeFile(true); + colorMap.openFile(DAGORED2->getPluginFilePath(this, COLORMAP_FILENAME)); + } + if (lightMapScaled.isFileOpened()) + { + lightMapScaled.flushData(); + lightMapScaled.closeFile(true); + lightMapScaled.openFile(DAGORED2->getPluginFilePath(this, LIGHTMAP_FILENAME)); + } + + if (detTexIdxMap && detTexIdxMap->isFileOpened()) + { + detTexIdxMap->flushData(); + detTexIdxMap->closeFile(true); + detTexIdxMap->openFile(DAGORED2->getPluginFilePath(this, DETTEXMAP_FILENAME)); + } + if (detTexWtMap && detTexWtMap->isFileOpened()) + { + detTexWtMap->flushData(); + detTexWtMap->closeFile(true); + detTexWtMap->openFile(DAGORED2->getPluginFilePath(this, DETTEXWMAP_FILENAME)); + } + if (detDivisor && heightMapDet.isFileOpened()) + { + heightMapDet.getInitialMap().flushData(); + heightMapDet.getInitialMap().closeFile(true); + heightMapDet.getInitialMap().openFile(DAGORED2->getPluginFilePath(this, "det-" HEIGHTMAP_FILENAME)); + } + { + const char *names[2] = {WATER_HEIGHTMAP_DET_FILENAME, WATER_HEIGHTMAP_MAIN_FILENAME}; + HeightMapStorage *storages[2] = {&waterHeightmapDet, &waterHeightmapMain}; + for (int i = 0; i < 2; i++) + { + String filename = DAGORED2->getPluginFilePath(this, names[i]); + if (!storages[i]->isFileOpened()) + storages[i]->getInitialMap().createFile(filename.c_str()); + storages[i]->getInitialMap().flushData(); + storages[i]->getInitialMap().closeFile(true); + storages[i]->getInitialMap().openFile(filename); + } + } + return true; +} + +// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ// + + +void HmapLandPlugin::clearObjects() +{ + origBasePath = NULL; + hmlService->destroyLandMeshRenderer(landMeshRenderer); + hmlService->destroyLandMeshManager(landMeshManager); + debugLmeshCells = false; + renderAllSplinesAlways = false; + renderSelSplinesAlways = false; + + showBlueWhiteMask = true; + numDetailTextures = 0; + detailTexBlkName.clear(); + + doAutocenter = false; + objEd.removeAllObjects(false); + + editedScriptImage = NULL; + clear_and_shrink(colorGenParams); + colorGenParamsData->reset(); + clear_and_shrink(scriptImages); + + heightMap.closeFile(true); + heightMapDet.closeFile(true); + landClsMap.closeFile(true); + colorMap.closeFile(true); + lightMapScaled.closeFile(true); + waterHeightmapDet.closeFile(true); + waterHeightmapMain.closeFile(true); + + if (detTexIdxMap) + detTexIdxMap->closeFile(true); + if (detTexWtMap) + detTexWtMap->closeFile(true); + + currentBrushId = 0; + brushFullDirtyBox.setEmpty(); + noTraceNow = false; + + gridCellSize = 1.0; + heightMapOffset = Point2(0, 0); + + detDivisor = 0; + detRect[0].set(0, 0); + detRect[1].set(0, 0); + detRectC.setEmpty(); + if (hmlService) + hmlService->setupRenderHm2(1, 1, 1, 1, NULL, BAD_TEXTUREID, 0, 0, 1, 1, NULL, BAD_TEXTUREID, 0, 0, 1, 1); + for (int i = 0; i < 2; i++) + if (hmapTex[i]) + dagRender->releaseManagedTexVerified(hmapTexId[i], hmapTex[i]); + + collisionArea.ofs = Point2(0, 0); + collisionArea.sz = Point2(100, 100); + collisionArea.show = false; + tileXSize = 32; + tileYSize = 32; + tileTexName = "---"; + tileTexId = BAD_TEXTUREID; + + useVertTex = false; + useVertTexForHMAP = true; + releaseVertTexRef(); + vertTexName = NULL; + vertNmTexName = NULL; + vertDetTexName = NULL; + vertTexXZtile = vertTexYtile = 1; + vertTexYOffset = 0.f; + vertTexAng0 = 30; + vertTexAng1 = 90; + vertTexHorBlend = 1; + vertDetTexXZtile = vertDetTexYtile = 1; + vertDetTexYOffset = 0.f; + + hasWaterSurface = false; + waterMatAsset = NULL; + waterSurfaceLevel = 0; + minUnderwaterBottomDepth = 2; + hasWorldOcean = true; + geomLoftBelowAll = false; + worldOceanExpand = 100; + worldOceanShorelineTolerance = 0.3; + waterMask.resize(0, 0); + waterMaskScale = 1; + + renderDebugLines = false; + + render.init(); + showMonochromeLand = false; + monochromeLandCol = E3DCOLOR(20, 120, 20, 255); + + showHtLevelCurves = false; + htLevelCurveStep = 5.0f, htLevelCurveThickness = 0.3f, htLevelCurveOfs = 0.0f, htLevelCurveDarkness = 0.8f; + + sunAzimuth = DegToRad(135); + sunZenith = DegToRad(45); + + ldrLight.init(); + + shadowBias = 0.01f; + shadowTraceDist = 100; + shadowDensity = 0.90f; + + lightmapScaleFactor = 1; + lcmScale = 1; + + lastHmapImportPath = ""; + lastHmapImportPathDet = ""; + lastChangeDet = {}; + lastHmapImportPathMain = ""; + lastChangeMain = {}; + lastWaterHeightmapImportPath = ""; + lastWaterHeightmapImportPathDet = ""; + lastChangeWaterDet = {}; + lastWaterHeightmapImportPathMain = ""; + lastChangeWaterMain = {}; + lastLandExportPath = ""; + lastHmapExportPath = ""; + lastColormapExportPath = "", + // colorGenScriptFilename + lastTexImportPath = ""; + + lastExpLoftFolder = ""; + lastExpLoftMain = lastExpLoftDet = true; + lastExpLoftMainSz = lastExpLoftDetSz = 4096; + lastExpLoftCreateAreaSubfolders = true; + lastExpLoftUseRect[0] = lastExpLoftUseRect[1] = false; + lastExpLoftRect[0][0].set(0, 0); + lastExpLoftRect[0][1].set(1024, 1024); + lastExpLoftRect[1] = lastExpLoftRect[0]; + + isVisible = true; + + lastMinHeight[0] = lastMinHeight[1] = lastHeightRange[0] = lastHeightRange[1] = MAX_REAL; + waterHeightMinRangeDet = Point2(0, 0); + waterHeightMinRangeMain = Point2(0, 0); + + syncLight = false; + syncDirLight = false; + pendingResetRenderer = false; + objEd.clearToDefaultState(); + + DataBlock app_blk; + if (!app_blk.load(DAGORED2->getWorkspace().getAppPath())) + DAEDITOR3.conError("cannot read <%s>", DAGORED2->getWorkspace().getAppPath()); + const DataBlock &hmap_def = *app_blk.getBlockByNameEx("projectDefaults")->getBlockByNameEx("hmap"); + + defaultHM.sizePixels = hmap_def.getPoint2("sizePixels", Point2(1024, 1024)); + defaultHM.cellSize = hmap_def.getReal("cellSize", 1.0); + defaultHM.sizeMeters = hmap_def.getPoint2("sizeMeters", defaultHM.sizePixels * defaultHM.cellSize); + defaultHM.heightScale = hmap_def.getReal("heightScale", 200.0); + defaultHM.heightOffset = hmap_def.getReal("heightOffset", 0.0); + defaultHM.originOffset = hmap_def.getPoint2("originOffset", Point2(0, 0)); + defaultHM.collisionOffset = hmap_def.getPoint2("collisionOffset", Point2(0, 0)); + defaultHM.collisionSize = hmap_def.getPoint2("collisionSize", Point2(100, 100)); + defaultHM.collisionShow = hmap_def.getBool("collisionShow", false); + defaultHM.doAutocenter = hmap_def.getBool("doAutocenter", true); + defaultHM.tileTex = hmap_def.getStr("tileTex", ""); + defaultHM.tileTexSz = hmap_def.getIPoint2("tileTexSize", IPoint2(32, 32)); + if (defaultHM.doAutocenter) + defaultHM.originOffset = -defaultHM.sizePixels * defaultHM.cellSize * 0.5; + if (hmap_def.getStr("script", NULL)) + defaultHM.scriptPath.printf(260, "%s/%s", DAGORED2->getSdkDir(), hmap_def.getStr("script", "")); + else + defaultHM.scriptPath = ""; + + LandscapeEntityObject::loadColliders(*app_blk.getBlockByNameEx("projectDefaults")); + + heightMap.closeFile(); + colorMap.closeFile(); + lightMapScaled.closeFile(); + del_it(detTexIdxMap); + del_it(detTexWtMap); + + heightMap.reset(512, 512, 0); + landClsMap.reset(512, 512, 0); + if (hasColorTex) + colorMap.reset(512, 512, E3DCOLOR(255, 10, 255, 0)); + else + colorMap.defaultValue = E3DCOLOR(128, 128, 128, 0); + if (hasLightmapTex) + lightMapScaled.reset(512 * lightmapScaleFactor, 512 * lightmapScaleFactor, 0xFFFF); + else + lightMapScaled.defaultValue = E3DCOLOR(255, 10, 255, 0); + + if (propPanel) + propPanel->fillPanel(); + onLandSizeChanged(); + missing_tile_reported = false; +} + + +void HmapLandPlugin::onNewProject() { doAutocenter = true; } + + +// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ// + + +void HmapLandPlugin::setVisible(bool vis) { isVisible = vis; } + + +//============================================================================== + + +void HmapLandPlugin::actObjects(float dt) +{ + + if (isVisible) + { + if (waterService) + waterService->act(dt); + if (DAGORED2->curPlugin() == this) + objEd.update(dt); + if (pendingLandmeshRebuild) + { + DAEDITOR3.conNote("--- Rebuild landmesh"); + rebuildLandmeshDump(); + rebuildLandmeshManager(); + delayedResetRenderer(); + hmlService->invalidateClipmap(true); + pendingLandmeshRebuild = false; + } + if (pendingResetRenderer) + delayedResetRenderer(); + } +} + + +void HmapLandPlugin::renderHeight() +{ + int st_mask = DAEDITOR3.getEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_RENDER); + if (!(st_mask & (hmapSubtypeMask | lmeshSubtypeMask))) + return; + + bool need_hmap = (st_mask & hmapSubtypeMask) || (detDivisor && (st_mask & lmeshSubtypeMask)); + if (need_hmap && (exportType != EXPORT_PSEUDO_PLANE)) + { + if (!useVertTexForHMAP) + dagGeom->shaderGlobalSetTexture(landTileVerticalTexVarId, BAD_TEXTUREID); + + hmlService->renderHm2(dagRender->curView().pos - Point3(0, render.hm2YbaseForLod, 0), false, true); + + if (!useVertTexForHMAP) + updateVertTex(); + } + + if ((st_mask & lmeshSubtypeMask) && landMeshRenderer && !(editedScriptImage && showBlueWhiteMask)) + { + hmlService->prepareLandMesh(*landMeshRenderer, *landMeshManager, dagRender->curView().pos); + + dagGeom->shaderGlobalSetBlock(dagGeom->shaderGlobalGetBlockId("global_frame"), ShaderGlobal::LAYER_FRAME); + + hmlService->renderLandMeshHeight(*landMeshRenderer, *landMeshManager); + + dagGeom->shaderGlobalSetBlock(-1, ShaderGlobal::LAYER_FRAME); + } +} + +void HmapLandPlugin::renderGrassMask() +{ + int st_mask = DAEDITOR3.getEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_RENDER); + if (!(st_mask & (hmapSubtypeMask | lmeshSubtypeMask))) + return; + + + if ((st_mask & lmeshSubtypeMask) && landMeshRenderer && !(editedScriptImage && showBlueWhiteMask) && landMeshManager) + { + IGenViewportWnd *renderView = DAGORED2->getRenderViewport(); + IGenViewportWnd *curView = DAGORED2->getCurrentViewport(); + + DagorCurView saveCurView = dagRender->curView(); + if (renderView == curView) + hmlService->prepareLandMesh(*landMeshRenderer, *landMeshManager, dagRender->curView().pos); + dagRender->curView() = saveCurView; + } + + if (landMeshRenderer && landMeshManager) + { + DagorCurView saveCurView = dagRender->curView(); + dagGeom->shaderGlobalSetBlock(dagGeom->shaderGlobalGetBlockId("global_frame"), ShaderGlobal::LAYER_FRAME); + + hmlService->renderLandMeshGrassMask(*landMeshRenderer, *landMeshManager); + int oldMode = hmlService->setGrassMaskRenderingMode(); + objEd.renderGrassMask(); + hmlService->restoreRenderingMode(oldMode); + dagRender->curView() = saveCurView; + + dagGeom->shaderGlobalSetBlock(-1, ShaderGlobal::LAYER_FRAME); + } +} + +void HmapLandPlugin::renderGrass(Stage stage) +{ + if (grassService == NULL) + return; + + if (landMeshRenderer) + landMeshRenderer->setRenderInBBox(*grassService->getGrassBbox()); + + grassService->beforeRender(stage); + + if (landMeshRenderer) + landMeshRenderer->setRenderInBBox(BBox3()); + + + // randomGrass->renderOpaque(); + grassService->renderGeometry(stage); +} + +void HmapLandPlugin::renderGPUGrass(Stage stage) +{ + if (gpuGrassService == NULL) + return; + + if (landMeshRenderer) + landMeshRenderer->setRenderInBBox(*gpuGrassService->getGrassBbox()); + + gpuGrassService->beforeRender(stage); + + if (landMeshRenderer) + landMeshRenderer->setRenderInBBox(BBox3()); + + gpuGrassService->renderGeometry(stage); +} + +void HmapLandPlugin::resetGrassMask(const DataBlock &grassBlk) {} + +void HmapLandPlugin::replaceGrassMask(int colormapId, const char *newGrassMaskName) +{ + // recreate + if (grassService) + grassService->forceUpdate(); +} + +int HmapLandPlugin::getLandclassIndex(const char *landclass_name) +{ + // find index of landclass + if (landclass_name == NULL) + return -1; + + int i; + for (i = 0; i < detailTexBlkName.size(); i++) + if (strcmp(detailTexBlkName[i], landclass_name) == 0) + return i; + return -1; +} + + +void HmapLandPlugin::updateWaterProjectedFx() +{ + if (!waterProjectedFxSrv) + return; + + float waterLevel = getWaterSurfLevel(); + float significantWaveHeight = 2.f; // just a constant here + + dagGeom->shaderGlobalSetBlock(dagGeom->shaderGlobalGetBlockId("global_frame"), ShaderGlobal::LAYER_FRAME); + + waterProjectedFxSrv->render(waterLevel, significantWaveHeight); + + dagGeom->shaderGlobalSetBlock(-1, ShaderGlobal::LAYER_FRAME); +} + + +void HmapLandPlugin::renderWater(Stage stage) +{ + if (waterService == NULL) + return; + + updateWaterProjectedFx(); + + int st_mask = DAEDITOR3.getEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_RENDER); + if (!(st_mask & HmapLandObjectEditor::waterSurfSubtypeMask)) + { + if (waterService) + waterService->hide_water(); + return; + } + waterService->beforeRender(stage); + waterService->renderGeometry(stage); +} + +void HmapLandPlugin::renderCables() +{ + if (!cableService) + return; + + IGenViewportWnd *renderView = DAGORED2->getRenderViewport(); + int w, h; + renderView->getViewportSize(w, h); + float pixel_scale = tanf(renderView->getFov() * 0.5) / w; + cableService->beforeRender(pixel_scale); + cableService->renderGeometry(); +} + + +void HmapLandPlugin::beforeRenderObjects(IGenViewportWnd *vp) +{ + if (vp) //== no viewport-related update + return; + + if (landMeshManager) + { + if (const IBBox2 *b = getExclCellBBox()) + { + landMeshManager->cullingState.useExclBox = true; + landMeshManager->cullingState.exclBox[0] = b->lim[0] + landMeshManager->getCellOrigin(); + landMeshManager->cullingState.exclBox[1] = b->lim[1] + landMeshManager->getCellOrigin(); + } + else + landMeshManager->cullingState.useExclBox = false; + } + + objEd.beforeRender(); + + if (distFieldInvalid && waterService && get_time_msec() > distFieldBuiltAt + 1000 && useMeshSurface && !landMeshMap.isEmpty() && + landMeshRenderer && + (DAEDITOR3.getEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_RENDER) & HmapLandObjectEditor::waterSurfSubtypeMask)) + { + invalidateDistanceField(); + BBox2 hmap_area; + if (detDivisor) + hmap_area = detRect; + else + { + hmap_area[0].set_xz(landBox[0]); + hmap_area[1].set_xz(landBox[1]); + } + waterService->buildDistanceField(hmap_area.center(), max(hmap_area.width().x, hmap_area.width().y) / 2, -1); + distFieldInvalid = false; + distFieldBuiltAt = get_time_msec(); + DEBUG_DUMP_VAR(distFieldBuiltAt); + } +} + + +void HmapLandPlugin::renderGeometry(Stage stage) +{ + if (!isVisible && stage != STG_RENDER_TO_CLIPMAP) + return; + + int st_mask = DAEDITOR3.getEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_RENDER); + bool need_lmap = (st_mask & lmeshSubtypeMask); + bool need_lmap_det = need_lmap && (st_mask & lmeshDetSubtypeMask); + bool need_hmap = (st_mask & hmapSubtypeMask) || (detDivisor && need_lmap && !need_lmap_det); + + if (showMonochromeLand && stage == STG_RENDER_TO_CLIPMAP) + { + d3d::clearview(CLEAR_TARGET, monochromeLandCol, 0.f, 0); + return; + } + + switch (stage) + { + case STG_BEFORE_RENDER: + { + updateHeightMapConstants(); + +#if defined(USE_HMAP_ACES) + Driver3dPerspective p(0, 0, 1, 40000, 0, 0); + if (!d3d::getpersp(p)) + { + TMatrix4 tm; + d3d::gettm(TM_PROJ, &tm); + p.zf = 1.0f / tm.m[2][2]; + p.zn = -p.zf / (1.0f / tm.m[3][2] - 1.0f); + } + setZTransformPersp(p.zn, p.zf); + if (landMeshRenderer && landMeshManager) + { + Point3 p = dagRender->curView().pos; + float height = p.y; + if (getHeightmapPointHt(p, NULL)) + height = height - p.y; + if (!(editedScriptImage && showBlueWhiteMask)) + hmlService->prepareClipmap(*landMeshRenderer, *landMeshManager, height * 1.5); + } + + if (landMeshRenderer && !(editedScriptImage && showBlueWhiteMask) && landMeshManager) + hmlService->updateGrassTranslucency(*landMeshRenderer, *landMeshManager); + + if (landMeshManager) + { + if (need_lmap_det) + landMeshManager->cullingState.useExclBox = false; + else if (const IBBox2 *b = getExclCellBBox()) + { + landMeshManager->cullingState.useExclBox = true; + landMeshManager->cullingState.exclBox[0] = b->lim[0] + landMeshManager->getCellOrigin(); + landMeshManager->cullingState.exclBox[1] = b->lim[1] + landMeshManager->getCellOrigin(); + } + else + landMeshManager->cullingState.useExclBox = false; + } +#endif + + break; + } + + case STG_RENDER_STATIC_OPAQUE: + if (useMeshSurface && !landMeshMap.isEmpty() && !landMeshRenderer) + resetRenderer(); + + hmlService->startUAVFeedback(); + + if (need_hmap && exportType != EXPORT_PSEUDO_PLANE) + { + IGenViewportWnd *renderView = DAGORED2->getRenderViewport(); + IGenViewportWnd *curView = DAGORED2->getCurrentViewport(); + + if (!useVertTexForHMAP) + dagGeom->shaderGlobalSetTexture(landTileVerticalTexVarId, BAD_TEXTUREID); + hmlService->renderHm2(dagRender->curView().pos - Point3(0, render.hm2YbaseForLod, 0), false); + if (!useVertTexForHMAP) + updateVertTex(); + } + + if (need_lmap && landMeshRenderer && !(editedScriptImage && showBlueWhiteMask)) + { + IGenViewportWnd *renderView = DAGORED2->getRenderViewport(); + IGenViewportWnd *curView = DAGORED2->getCurrentViewport(); + + if (renderView == curView) + hmlService->prepareLandMesh(*landMeshRenderer, *landMeshManager, dagRender->curView().pos); + +#if defined(USE_HMAP_ACES) + dagGeom->shaderGlobalSetBlock(dagGeom->shaderGlobalGetBlockId("global_frame"), ShaderGlobal::LAYER_FRAME); +#endif + hmlService->renderLandMesh(*landMeshRenderer, *landMeshManager); +#if defined(USE_HMAP_ACES) + dagGeom->shaderGlobalSetBlock(-1, ShaderGlobal::LAYER_FRAME); +#endif + } + + hmlService->endUAVFeedback(); + + + // grass + if (st_mask & grasspSubtypeMask) + { +#if defined(USE_HMAP_ACES) + dagGeom->shaderGlobalSetBlock(dagGeom->shaderGlobalGetBlockId("global_frame"), ShaderGlobal::LAYER_FRAME); +#endif + + renderGrass(stage); + renderGPUGrass(stage); +#if defined(USE_HMAP_ACES) + dagGeom->shaderGlobalSetBlock(-1, ShaderGlobal::LAYER_FRAME); +#endif + } + + objEd.renderGeometry(true); + break; + + case STG_RENDER_TO_CLIPMAP: + if (useMeshSurface && !landMeshMap.isEmpty() && !landMeshRenderer) + resetRenderer(); + + if (landMeshRenderer && (need_lmap || need_hmap)) + { + hmlService->renderLandMeshClipmap(*landMeshRenderer, *landMeshManager); + break; + } + + if (geomLoftBelowAll) + objEd.renderGeometry(true); + break; + + case STG_RENDER_TO_CLIPMAP_LATE: + if (!geomLoftBelowAll) + objEd.renderGeometry(true); + break; + + case STG_RENDER_STATIC_TRANS: + objEd.renderGeometry(false); + renderWater(stage); + renderCables(); + break; + + case STG_RENDER_SHADOWS: objEd.renderGeometry(true); break; + + case STG_RENDER_SHADOWS_VSM: + if (useMeshSurface && !landMeshMap.isEmpty() && !landMeshRenderer) + resetRenderer(); + + if (need_hmap && (exportType != EXPORT_PSEUDO_PLANE)) + { + IGenViewportWnd *renderView = DAGORED2->getRenderViewport(); + IGenViewportWnd *curView = DAGORED2->getCurrentViewport(); + + if (!useVertTexForHMAP) + dagGeom->shaderGlobalSetTexture(landTileVerticalTexVarId, BAD_TEXTUREID); + hmlService->renderHm2VSM(dagRender->curView().pos - Point3(0, render.hm2YbaseForLod, 0)); + if (!useVertTexForHMAP) + updateVertTex(); + } + if (need_lmap && landMeshRenderer && !(editedScriptImage && showBlueWhiteMask)) + { + IGenViewportWnd *renderView = DAGORED2->getRenderViewport(); + IGenViewportWnd *curView = DAGORED2->getCurrentViewport(); + + if (renderView == curView) + hmlService->prepareLandMesh(*landMeshRenderer, *landMeshManager, dagRender->curView().pos); + + hmlService->renderLandMeshVSM(*landMeshRenderer, *landMeshManager); + } + break; + + + case STG_RENDER_HEIGHT_FIELD: + if (useMeshSurface && !landMeshMap.isEmpty() && !landMeshRenderer) + resetRenderer(); + + renderHeight(); + break; + + case STG_RENDER_GRASS_MASK: renderGrassMask(); break; + + case STG_RENDER_LAND_DECALS: + if (need_lmap) + hmlService->renderDecals(*landMeshRenderer, *landMeshManager); + break; + } +} + +void HmapLandPlugin::prepare(const Point3 ¢er_pos, const BBox3 &box) +{ + hmlService->prepare(*landMeshRenderer, *landMeshManager, center_pos, box); +} + +int HmapLandPlugin::setSubDiv(int lod) { return hmlService->setLod0SubDiv(lod); } + +void HmapLandPlugin::renderObjects() +{ + if (!isVisible) + return; + + objEd.render(); + + if (collisionArea.show) + { + // validate collision area settings + if (collisionArea.ofs.x < 0) + collisionArea.ofs.x = 0; + else if (collisionArea.ofs.x > 100) + collisionArea.ofs.x = 100; + + if (collisionArea.ofs.y < 0) + collisionArea.ofs.y = 0; + else if (collisionArea.ofs.y > 100) + collisionArea.ofs.y = 100; + + if (collisionArea.sz.x < 0) + collisionArea.sz.x = 0; + else if (collisionArea.ofs.x + collisionArea.sz.x > 100) + collisionArea.sz.x = 100 - collisionArea.ofs.x; + + if (collisionArea.sz.y < 0) + collisionArea.sz.y = 0; + else if (collisionArea.ofs.y + collisionArea.sz.y > 100) + collisionArea.sz.y = 100 - collisionArea.ofs.y; + + // draw collision area + real x0 = gridCellSize * heightMap.getMapSizeX() * collisionArea.ofs.x / 100 + heightMapOffset.x; + real y0 = gridCellSize * heightMap.getMapSizeY() * collisionArea.ofs.y / 100 + heightMapOffset.y; + real x1 = gridCellSize * heightMap.getMapSizeX() * (collisionArea.ofs.x + collisionArea.sz.x) / 100 + heightMapOffset.x; + real y1 = gridCellSize * heightMap.getMapSizeY() * (collisionArea.ofs.y + collisionArea.sz.y) / 100 + heightMapOffset.y; + E3DCOLOR c = E3DCOLOR(128, 0, 128, 255); + + dagRender->startLinesRender(); + dagRender->renderLine(Point3(x0, -10, y0), Point3(x1, -10, y0), c); + ::dagRender->renderLine(Point3(x1, -10, y0), Point3(x1, -10, y1), c); + dagRender->renderLine(Point3(x1, -10, y1), Point3(x0, -10, y1), c); + dagRender->renderLine(Point3(x0, -10, y1), Point3(x0, -10, y0), c); + dagRender->renderLine(Point3(x0, 250, y0), Point3(x1, 250, y0), c); + dagRender->renderLine(Point3(x1, 250, y0), Point3(x1, 250, y1), c); + dagRender->renderLine(Point3(x1, 250, y1), Point3(x0, 250, y1), c); + dagRender->renderLine(Point3(x0, 250, y1), Point3(x0, 250, y0), c); + + for (int i = 0; i < 10; i++) + { + dagRender->renderLine(Point3(x0 + (x1 - x0) * i / 10, -10, y0), Point3(x0 + (x1 - x0) * i / 10, 250, y0), c); + dagRender->renderLine(Point3(x0 + (x1 - x0) * i / 10, -10, y1), Point3(x0 + (x1 - x0) * i / 10, 250, y1), c); + dagRender->renderLine(Point3(x0, -10, y0 + (y1 - y0) * i / 10), Point3(x0, 250, y0 + (y1 - y0) * i / 10), c); + dagRender->renderLine(Point3(x1, -10, y0 + (y1 - y0) * i / 10), Point3(x1, 250, y0 + (y1 - y0) * i / 10), c); + } + + dagRender->endLinesRender(); + } +} + + +//============================================================================== +void HmapLandPlugin::renderTransObjects() +{ + if (!isVisible) + return; + + objEd.renderTrans(); + if (DAEDITOR3.getEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_RENDER) & navmeshSubtypeMask) + renderNavMeshDebug(); + + if (DAGORED2->curPlugin() == this) + DAGORED2->renderBrush(); +} + + +//============================================================================== +IGenEventHandler *HmapLandPlugin::getEventHandler() { return this; } + + +bool HmapLandPlugin::catchEvent(unsigned ev_huid, void *userData) +{ + if (ev_huid == HUID_AfterD3DReset) + { + updateHeightMapTex(false); + updateHeightMapTex(true); + regenLayerTex(); + if (editedScriptImage && showEditedMask()) + updateBlueWhiteMask(NULL); + delayedResetRenderer(); + hmlService->invalidateClipmap(true); + } + if (ev_huid == HUID_InvalidateClipmap) + { + hmlService->invalidateClipmap((bool)userData); + if (grassService) + grassService->forceUpdate(); + if (gpuGrassService) + gpuGrassService->invalidate(); + } + if (ev_huid == HUID_AutoSaveDueToCrash) + onPluginMenuClick(CM_COMMIT_HM_CHANGES); + return false; +} + +//============================================================================== +void *HmapLandPlugin::queryInterfacePtr(unsigned huid) +{ + RETURN_INTERFACE(huid, IBinaryDataBuilder); + RETURN_INTERFACE(huid, ILightingChangeClient); + RETURN_INTERFACE(huid, IHeightmap); + RETURN_INTERFACE(huid, IRoadsProvider); + RETURN_INTERFACE(huid, IWriteAddLtinputData); + RETURN_INTERFACE(huid, IRenderingService); + RETURN_INTERFACE(huid, IGatherStaticGeometry); + RETURN_INTERFACE(huid, IOnExportNotify); +#if defined(USE_HMAP_ACES) + RETURN_INTERFACE(huid, IEnvironmentSettings); +#endif + RETURN_INTERFACE(huid, IExportToDag); + RETURN_INTERFACE(huid, IPluginAutoSave); + RETURN_INTERFACE(huid, IPostProcessGeometry); + return NULL; +} + + +static float old_rad2 = 0, old_assym = 0, old_drad2 = 0; +static void setSuperEntityRef(ICompositObj *co, const char *nm) +{ + for (int j = 0, je = co->getCompositSubEntityCount(); j < je; j++) + if (IObjEntity *e = co->getCompositSubEntity(j)) + { + if (IObjEntityUserDataHolder *oeud = e->queryInterface()) + oeud->setSuperEntityRef(String(0, "%s/%d", nm, j)); + if (ICompositObj *co2 = e->queryInterface()) + setSuperEntityRef(co2, String(0, "%s/%d", nm, j)); + } +} + +void HmapLandPlugin::onBeforeExport(unsigned target_code) +{ + // update splines geometry if needed + objEd.updateSplinesGeom(); + rebuildSplinesBitmask(); + + // generate all data before export operation + lcMgr->exportEntityGenDataToFile(landClsMap, target_code); + + // update super entity name and subentity index for composit landscape entities + for (int i = 0; i < objEd.objectCount(); ++i) + { + LandscapeEntityObject *obj = RTTI_cast(objEd.getObject(i)); + if (!obj || !obj->getEntity()) + continue; + + const char *nm = obj->getName(); + if (ICompositObj *co = obj->getEntity()->queryInterface()) + setSuperEntityRef(co, nm); + else if (IObjEntityUserDataHolder *oeud = obj->getEntity()->queryInterface()) + oeud->setSuperEntityRef(nm); + } +} + +void HmapLandPlugin::onAfterExport(unsigned target_code) +{ + if (!DAGORED2->getCurrentViewport()) + return; + + TMatrix itm; + DAGORED2->getCurrentViewport()->getCameraTransform(itm); +} + +void HmapLandPlugin::selectLayerObjects(int lidx, bool sel) +{ + objEd.getUndoSystem()->begin(); + if (EditLayerProps::layerProps[lidx].type == EditLayerProps::ENT) + { + for (int i = 0; i < objEd.objectCount(); i++) + if (LandscapeEntityObject *o = RTTI_cast(objEd.getObject(i))) + if (o->getEditLayerIdx() == lidx) + o->selectObject(sel); + } + else if (EditLayerProps::layerProps[lidx].type == EditLayerProps::SPL) + { + for (int i = 0; i < objEd.objectCount(); i++) + if (SplineObject *o = RTTI_cast(objEd.getObject(i))) + if (!o->isPoly() && o->getEditLayerIdx() == lidx) + { + o->selectObject(sel); + if (!sel) + for (int j = 0; j < o->points.size(); j++) + o->points[j]->selectObject(false); + } + } + else if (EditLayerProps::layerProps[lidx].type == EditLayerProps::PLG) + { + for (int i = 0; i < objEd.objectCount(); i++) + if (SplineObject *o = RTTI_cast(objEd.getObject(i))) + if (o->isPoly() && o->getEditLayerIdx() == lidx) + { + o->selectObject(sel); + if (!sel) + for (int j = 0; j < o->points.size(); j++) + o->points[j]->selectObject(false); + } + } + objEd.getUndoSystem()->accept( + String(0, "%s layer \"%s\" objects", sel ? "Select" : "Deselect", EditLayerProps::layerProps[lidx].name())); +} +void HmapLandPlugin::moveObjectsToLayer(int lidx) +{ + class UndoLayerChange : public UndoRedoObject + { + Ptr obj; + int oldLayerIdx = -1, newLayerIdx = -1; + + public: + UndoLayerChange(RenderableEditableObject *o, int old_l, int new_l) : obj(o), oldLayerIdx(old_l), newLayerIdx(new_l) {} + + virtual void restore(bool /*save_redo*/) + { + if (LandscapeEntityObject *o = RTTI_cast(obj)) + o->setEditLayerIdx(oldLayerIdx); + else if (SplineObject *o = RTTI_cast(obj)) + o->setEditLayerIdx(oldLayerIdx); + } + virtual void redo() + { + if (LandscapeEntityObject *o = RTTI_cast(obj)) + o->setEditLayerIdx(newLayerIdx); + else if (SplineObject *o = RTTI_cast(obj)) + o->setEditLayerIdx(newLayerIdx); + } + + virtual size_t size() { return sizeof(*this); } + virtual void accepted() {} + virtual void get_description(String &s) { s = "UndoEditLayerIdxChange"; } + }; + + objEd.getUndoSystem()->begin(); + if (EditLayerProps::layerProps[lidx].type == EditLayerProps::ENT) + { + for (int i = 0; i < objEd.selectedCount(); i++) + if (LandscapeEntityObject *o = RTTI_cast(objEd.getSelected(i))) + { + objEd.getUndoSystem()->put(new UndoLayerChange(o, o->getEditLayerIdx(), lidx)); + o->setEditLayerIdx(lidx); + } + } + else if (EditLayerProps::layerProps[lidx].type == EditLayerProps::SPL) + { + for (int i = 0; i < objEd.selectedCount(); i++) + if (SplineObject *o = RTTI_cast(objEd.getSelected(i))) + if (!o->isPoly()) + { + objEd.getUndoSystem()->put(new UndoLayerChange(o, o->getEditLayerIdx(), lidx)); + o->setEditLayerIdx(lidx); + } + } + else if (EditLayerProps::layerProps[lidx].type == EditLayerProps::PLG) + { + for (int i = 0; i < objEd.selectedCount(); i++) + if (SplineObject *o = RTTI_cast(objEd.getSelected(i))) + if (o->isPoly()) + { + objEd.getUndoSystem()->put(new UndoLayerChange(o, o->getEditLayerIdx(), lidx)); + o->setEditLayerIdx(lidx); + } + } + objEd.getUndoSystem()->accept(String(0, "Move objects to layer \"%s\"", EditLayerProps::layerProps[lidx].name())); +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlImport.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlImport.cpp new file mode 100644 index 000000000..68b54b77e --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlImport.cpp @@ -0,0 +1,382 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "hmlPlugin.h" +#include + + +class HeightmapImporter +{ +public: + float hMin, hScale; + + HeightmapImporter() { hMin = 0, hScale = 1; } + + virtual bool importHeightmap(const char *filename, HeightMapStorage &heightmap, CoolConsole &con, HmapLandPlugin &plugin, int x0, + int y0, int x1, int y1) = 0; +}; + + +class Raw32fHeightmapImporter : public HeightmapImporter +{ + bool sizesHeader; +#pragma pack(push) +#pragma pack(1) + struct Header + { + int w, h; + } header; +#pragma pack(pop) +public: + Raw32fHeightmapImporter(bool sizes_header) : sizesHeader(sizes_header) {} + virtual bool importHeightmap(const char *filename, HeightMapStorage &heightmap, CoolConsole &con, HmapLandPlugin &plugin, int x0, + int y0, int x1, int y1) + { + file_ptr_t handle = ::df_open(filename, DF_READ); + + if (!handle) + { + con.addMessage(ILogWriter::ERROR, "Can't open file '%s'", filename); + return false; + } + + int length = ::df_length(handle); + if (sizesHeader) + { + if (::df_read(handle, &header, sizeof(header)) != sizeof(header)) + { + con.addMessage(ILogWriter::ERROR, "Error reading file '%s'", filename); + ::df_close(handle); + return false; + } + length -= sizeof(header); + } + int mapSizeX = int(floor(sqrt((double)(length / 4)) + 0.0001)); + int mapSizeY = mapSizeX; + if (sizesHeader) + { + if (header.w * header.h * 4 != length) + con.addMessage(ILogWriter::WARNING, "File's header (%d, %d) doesn't match file size=%d '%s'", header.w, header.h, + length - sizeof(header), filename); + mapSizeX = header.w; + mapSizeY = header.h; + } + else + { + header.w = mapSizeX; + header.h = mapSizeY; + } + if (mapSizeX != x1 - x0 || mapSizeY != y1 - y0) + con.addMessage(ILogWriter::WARNING, "File dim (%d, %d) doesn't match destination %dx%d '%s'", header.w, header.h, x1 - x0, + y1 - y0, filename); + + SmallTab buf; + clear_and_resize(buf, mapSizeX); + + con.startProgress(); + con.setActionDesc("importing heightmap..."); + con.setTotal(mapSizeY); + + for (int y = mapSizeY - 1, cnt = 0; y >= 0; --y) + { + if (::df_read(handle, buf.data(), data_size(buf)) != data_size(buf)) + { + con.addMessage(ILogWriter::ERROR, "Error reading file '%s'", filename); + ::df_close(handle); + return false; + } + + if (y >= y1 - y0) + continue; + for (int x = 0; x < mapSizeX && x < x1 - x0; ++x) + { + heightmap.setInitialData(x + x0, y + y0, buf[x]); + heightmap.setFinalData(x + x0, y + y0, buf[x]); + } + + con.incDone(); + } + + heightmap.flushData(); + + con.endProgress(); + + ::df_close(handle); + + return true; + } +}; + + +class Raw16HeightmapImporter : public HeightmapImporter +{ +public: + virtual bool importHeightmap(const char *filename, HeightMapStorage &heightmap, CoolConsole &con, HmapLandPlugin &plugin, int x0, + int y0, int x1, int y1) + { + file_ptr_t handle = ::df_open(filename, DF_READ); + + if (!handle) + { + con.addMessage(ILogWriter::ERROR, "Can't open file '%s'", filename); + return false; + } + + int length = ::df_length(handle); + + int mapSizeX = int(floor(sqrt((double)(length / 2)) + 0.0001)); + int mapSizeY = mapSizeX; + + if (mapSizeX != x1 - x0 || mapSizeY != y1 - y0) + con.addMessage(ILogWriter::WARNING, "File dim (%d, %d) doesn't match destination %dx%d '%s'", mapSizeX, mapSizeY, x1 - x0, + y1 - y0, filename); + + SmallTab buf; + clear_and_resize(buf, mapSizeX); + + con.startProgress(); + con.setActionDesc("importing heightmap..."); + con.setTotal(mapSizeY); + + for (int y = mapSizeY - 1, cnt = 0; y >= 0; --y) + { + if (::df_read(handle, buf.data(), data_size(buf)) != data_size(buf)) + { + con.addMessage(ILogWriter::ERROR, "Error reading file '%s'", filename); + ::df_close(handle); + return false; + } + + if (y >= y1 - y0) + continue; + for (int x = 0; x < mapSizeX && x < x1 - x0; ++x) + { + float v = buf[x] / float((1 << 16) - 1) * hScale + hMin; + heightmap.setInitialData(x + x0, y + y0, v); + heightmap.setFinalData(x + x0, y + y0, v); + } + + con.incDone(); + } + + heightmap.flushData(); + heightmap.unloadAllUnchangedData(); + + con.endProgress(); + + ::df_close(handle); + + return true; + } +}; + + +class TgaHeightmapImporter : public HeightmapImporter +{ +public: + virtual bool importHeightmap(const char *filename, HeightMapStorage &heightmap, CoolConsole &con, HmapLandPlugin &plugin, int x0, + int y0, int x1, int y1) + { + con.startProgress(); + con.setActionDesc("loading TGA image..."); + con.setTotal(2); + con.incDone(); + + TexImage8 *img = load_tga8(filename, tmpmem); + + if (!img) + { + con.endProgress(); + con.addMessage(ILogWriter::ERROR, "Can't load TGA file '%s'", filename); + return false; + } + + int mapSizeX = img->w; + int mapSizeY = img->h; + + if (mapSizeX != x1 - x0 || mapSizeY != y1 - y0) + con.addMessage(ILogWriter::WARNING, "File dim (%d, %d) doesn't match destination %dx%d '%s'", mapSizeX, mapSizeY, x1 - x0, + y1 - y0, filename); + + uint8_t *ptr = (uint8_t *)(img + 1); + + con.setActionDesc("importing heightmap..."); + con.setTotal(mapSizeY); + + for (int y = 0, cnt = 0; y < mapSizeY; y++) + { + if (y >= y1 - y0) + break; + for (int x = 0; x < mapSizeX && x < x1 - x0; ++x, ++ptr) + { + float v = *ptr / float((1 << 8) - 1) * hScale + hMin; + heightmap.setInitialData(x + x0, y + y0, v); + heightmap.setFinalData(x + x0, y + y0, v); + } + + con.incDone(); + } + + heightmap.flushData(); + + con.endProgress(); + + memfree(img, tmpmem); + + return true; + } +}; + + +class TiffHeightmapImporter : public HeightmapImporter +{ +public: + virtual bool importHeightmap(const char *filename, HeightMapStorage &heightmap, CoolConsole &con, HmapLandPlugin &plugin, int x0, + int y0, int x1, int y1) + { + con.startProgress(); + con.setActionDesc("loading TIFF image..."); + con.setTotal(2); + con.incDone(); + + IBitMaskImageMgr::BitmapMask bm; + if (!HmapLandPlugin::bitMaskImgMgr->loadImage(bm, NULL, filename)) + { + con.endProgress(); + con.addMessage(ILogWriter::ERROR, "Can't load TIFF file '%s'", filename); + return false; + } + if (bm.getBitsPerPixel() < 4) + { + con.endProgress(); + con.addMessage(ILogWriter::ERROR, "TIFF file '%s' has too low BPP=%d", filename, bm.getBitsPerPixel()); + return false; + } + + + int mapSizeX = bm.getWidth(); + int mapSizeY = bm.getHeight(); + + if (mapSizeX != x1 - x0 || mapSizeY != y1 - y0) + con.addMessage(ILogWriter::WARNING, "File dim (%d, %d) doesn't match destination %dx%d '%s'", mapSizeX, mapSizeY, x1 - x0, + y1 - y0, filename); + + con.setActionDesc("importing heightmap (%dx%d %dbpp)...", bm.getWidth(), bm.getHeight(), bm.getBitsPerPixel()); + con.setTotal(mapSizeY); + + double mScale = 0xFFu; + if (bm.getBitsPerPixel() == 4) + mScale = 0xFu; + else if (bm.getBitsPerPixel() == 16) + mScale = 0xFFFFu; + else if (bm.getBitsPerPixel() == 32) + mScale = 0xFFFFFFFFu; + for (int y = 0, cnt = 0; y < mapSizeY; y++) + { + if (y >= y1 - y0) + break; + for (int x = 0; x < mapSizeX && x < x1 - x0; ++x) + { + unsigned pix = bm.getMaskPixelAnyBpp(x, mapSizeY - 1 - y); + float v = pix / mScale * hScale + hMin; + heightmap.setInitialData(x + x0, y + y0, v); + heightmap.setFinalData(x + x0, y + y0, v); + } + + con.incDone(); + } + + heightmap.flushData(); + HmapLandPlugin::bitMaskImgMgr->destroyImage(bm); + + con.endProgress(); + + return true; + } +}; + + +bool HmapLandPlugin::importHeightmap(String &filename, HeightmapTypes type) +{ + const char *ext = get_file_ext(filename); + if (!ext) + return false; + + CoolConsole &con = DAGORED2->getConsole(); + con.startLog(); + + HeightmapImporter *importer = NULL; + + if (stricmp(ext, "r32") == 0) + importer = new Raw32fHeightmapImporter(false); + else if (stricmp(ext, "height") == 0) + importer = new Raw32fHeightmapImporter(true); + else if (stricmp(ext, "r16") == 0 || stricmp(ext, "raw") == 0) + importer = new Raw16HeightmapImporter; + else if (stricmp(ext, "tif") == 0) + importer = new TiffHeightmapImporter; + else + { + // importer=new TgaHeightmapImporter; + return false; + } + + HeightMapStorage *hms = &heightMap; + float hMin = lastMinHeight[0]; + float hScale = lastHeightRange[0]; + IBBox2 importRect(IPoint2(0, 0), IPoint2(heightMap.getMapSizeX(), heightMap.getMapSizeY())); + bool importWater = false; + if (type == HeightmapTypes::HEIGHTMAP_DET) + { + hms = &heightMapDet; + hMin = lastMinHeight[1]; + hScale = lastHeightRange[1]; + importRect = detRectC; + } + else if (type == HeightmapTypes::HEIGHTMAP_WATER_DET) + { + hms = &waterHeightmapDet; + importWater = true; + } + else if (type == HeightmapTypes::HEIGHTMAP_WATER_MAIN) + { + hms = &waterHeightmapMain; + importWater = true; + importRect[1] = IPoint2(hms->getMapSizeX(), hms->getMapSizeY()); + } + if (importWater) + { + hMin = 0.0f; + hScale = 1.0f; + } + + importer->hMin = hMin; + importer->hScale = hScale; + + bool useDetRect = type == HeightmapTypes::HEIGHTMAP_DET; + if (!importer->importHeightmap(filename, *hms, con, *this, importRect[0].x, importRect[0].y, importRect[1].x, importRect[1].y)) + { + con.endLog(); + return false; + } + + con.addMessage(ILogWriter::NOTE, "Imported heightmap from '%s'", (const char *)filename); + + if (!hms->flushData()) + { + con.addMessage(ILogWriter::ERROR, "Error saving heightmap data"); + con.endLog(); + return false; + } + if (importWater) + applyHmModifiers(false); + + con.endLog(); + + return true; +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlImportExport.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlImportExport.cpp new file mode 100644 index 000000000..fb43c00e1 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlImportExport.cpp @@ -0,0 +1,721 @@ +#include "hmlObjectsEditor.h" +#include "hmlSplineObject.h" +#include "hmlSplinePoint.h" +#include "hmlEntity.h" +#include "hmlSnow.h" +#include "hmlLight.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using hdpi::_pxScaled; + +enum +{ + PID_STATIC = 1, + PID_APPLYFORALL, + PID_CHOISE, + PID_CHOISE_1, + PID_CHOISE_2, + PID_CHOISE_3, + + PID_SEL_ONLY, + PID_SPLINES, + PID_POLYGONS, + PID_ENTITIES, + PID_GEOM, + PID_PLUGINS, +}; + + +class ExportImportDlg : public ControlEventHandler // : public IPropertyPanelDlgClient +{ +public: + ExportImportDlg(Tab &sel_names, bool exp_) : selNames(sel_names), exp(exp_), selOnly(false), plugs(tmpmem) + { + geoms = 0; + + mDlg = DAGORED2->createDialog(_pxScaled(320), _pxScaled(exp ? 350 : 200), exp ? "Export objects" : "Import objects"); + mPanel = mDlg->getPanel(); + mPanel->setEventHandler(this); + + fillPanel(); + } + + ExportImportDlg::~ExportImportDlg() { DAGORED2->deleteDialog(mDlg); } + + bool showDialog() + { + // int ret = dlg->execute(); + // dagGui->deletePropPanelDlg(dlg); + // return ret == CTL_IDOK; + if (mDlg->showDialog() == DIALOG_ID_OK) + onOkPressed(); + else + return false; + + return true; + } + + void fillPanel() + { + mPanel->createCheckBox(PID_SEL_ONLY, "Selected objects only", false); + mPanel->createSeparator(); + mPanel->createCheckBox(PID_SPLINES, "Splines", true); + mPanel->createCheckBox(PID_POLYGONS, "Polygons", true); + mPanel->createCheckBox(PID_ENTITIES, "Entities", true); + + if (!exp) + return; + + mPanel->createIndent(); + mPanel->createCheckBox(PID_GEOM, "Geometry:", true); + + IDaEditor3Engine::get().setEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_EXPORT, 0); + int i; + for (i = 0; i < DAGORED2->getPluginCount(); ++i) + { + IGenEditorPlugin *plugin = DAGORED2->getPlugin(i); + if (plugin->queryInterface()) + continue; + + IObjEntityFilter *filter = plugin->queryInterface(); + + if (filter && filter->allowFiltering(IObjEntityFilter::STMASK_TYPE_EXPORT)) + filter->applyFiltering(IObjEntityFilter::STMASK_TYPE_EXPORT, true); + } + + for (i = 0; i < DAGORED2->getPluginCount(); ++i) + { + IGenEditorPlugin *plugin = DAGORED2->getPlugin(i); + + IGatherStaticGeometry *geom = plugin->queryInterface(); + if (!geom) + continue; + + mPanel->createCheckBox(PID_PLUGINS + geoms, plugin->getMenuCommandName(), true); + plugs.push_back(i); + geoms++; + } + } + + void onChange(int pcb_id, PropPanel2 *panel) + { + if (!exp) + return; + + if (pcb_id == PID_GEOM) + { + bool chck = panel->getBool(pcb_id); + for (int i = 0; i < geoms; i++) + { + panel->setBool(PID_PLUGINS + i, chck); + panel->setEnabledById(PID_PLUGINS + i, chck); + } + } + } + + void onOkPressed() + { + if (mPanel->getBool(PID_SPLINES)) + selNames.push_back() = "Splines"; + + if (mPanel->getBool(PID_POLYGONS)) + selNames.push_back() = "Polygons"; + + if (mPanel->getBool(PID_ENTITIES)) + selNames.push_back() = "Entities"; + + selOnly = mPanel->getBool(PID_SEL_ONLY); + + if (exp) + for (int i = 0; i < geoms; i++) + if (mPanel->getBool(PID_PLUGINS + i) || mPanel->getBool(PID_GEOM)) // huck, without onPPChange + selNames.push_back() = DAGORED2->getPlugin(plugs[i])->getMenuCommandName(); + } + +public: + bool selOnly; + +private: + Tab &selNames; + int geoms; + bool exp; + Tab plugs; + + CDialogWindow *mDlg; + PropertyContainerControlBase *mPanel; +}; + + +void HmapLandObjectEditor::exportAsComposit() +{ + CoolConsole &con = DAGORED2->getConsole(); + con.startLog(); + + DataBlock compositBlk; + compositBlk.setStr("className", "composit"); + DataBlock &blk = *compositBlk.addBlock("node"); + blk.addTm("tm", TMatrix::IDENT); + + Point3 center; + bool centerSetted = false; + int exportedCnt = 0; + + int cnt = selection.size(); + for (int i = 0; i < cnt; i++) + { + LandscapeEntityObject *o = RTTI_cast(selection[i]); + if (!o) + continue; + + IObjEntity *entity = o->getEntity(); + int etype = entity ? entity->getAssetTypeId() : -1; + + if (etype == -1) + { + con.addMessage(ILogWriter::ERROR, "unauthorized entity type '%s'... skipping", o->getName()); + continue; + } + + TMatrix tm = o->getTm(); + if (o->getProps().placeType) + if (IObjEntity *e = o->getEntity()) + e->getTm(tm); + if (!centerSetted) + { + center = tm.getcol(3); + centerSetted = true; + } + + DataBlock &sblk = *blk.addNewBlock("node"); + if (strchr(o->getProps().entityName, ':')) + sblk.setStr("name", o->getProps().entityName); + else + sblk.setStr("name", String(0, "%s:%s", o->getProps().entityName, IDaEditor3Engine::get().getAssetTypeName(etype))); + + tm.setcol(3, tm.getcol(3) - center); + sblk.setTm("tm", tm); + if (o->getProps().placeType) + sblk.setInt("place_type", o->getProps().placeType); + + exportedCnt++; + } + + Tab orig_pts; + for (int i = 0; i < cnt; i++) + { + SplineObject *s = RTTI_cast(selection[i]); + if (!s) + continue; + if (!centerSetted) + { + center = s->points[0]->getPt(); + centerSetted = true; + } + int pt_cnt = s->points.size() - (s->isClosed() ? 1 : 0); + orig_pts.resize(pt_cnt); + for (int j = 0; j < pt_cnt; j++) + { + orig_pts[j] = s->points[j]->getPt(); + s->points[j]->setPos(s->points[j]->getPt() - center); + } + s->save(*blk.addNewBlock("node")); + for (int j = 0; j < pt_cnt; j++) + s->points[j]->setPos(orig_pts[j]); + } + + if (!centerSetted) + { + wingw::message_box(wingw::MBS_EXCL, "Error", "No entities selected!"); + con.endLog(); + return; + } + + if (lastAsCompositExportPath.length() <= 0) + lastAsCompositExportPath.printf(256, "%s/assets/", DAGORED2->getSdkDir()); + + String path = wingw::file_save_dlg(NULL, "Select composit file to export", + "composit files (*.composit.blk)|*.composit.blk|All files (*.*)|*.*", "blk", lastAsCompositExportPath); + + if (path.length()) + { + lastAsCompositExportPath = path; + ::dd_mkpath(path); + + if (!compositBlk.saveToTextFile(path)) + con.addMessage(ILogWriter::ERROR, "error while saving file '%s'", path.str()); + else + con.addMessage(ILogWriter::NOTE, "created composit with %d entities", exportedCnt); + } + + con.endLog(); +} + +void HmapLandObjectEditor::exportToDag() +{ + Tab exps(tmpmem); + + ExportImportDlg exportDlg(exps, true); + if (!exportDlg.showDialog()) + return; + + if (!exps.size()) + return; + + static const int ST_EXPORTABLE = 30; + PtrTab sel_obj; + Tab sel_spl; + bool exp_selected = exportDlg.selOnly; + if (exp_selected) + { + for (int i = 0; i < splines.size(); ++i) + if (splines[i] && splines[i]->isSelected()) + sel_spl.push_back(splines[i]); + sel_obj = selection; + if (!sel_obj.size() && !sel_spl.size()) + { + wingw::message_box(wingw::MBS_EXCL, "Error", "No entities selected!"); + return; + } + } + + String path = wingw::file_save_dlg(NULL, "Select DAG file to export", "DAG files (*.dag)|*.dag|All files (*.*)|*.*", "dag", + lastExportPath.length() > 0 ? lastExportPath : DAGORED2->getSdkDir()); + + if (path.length()) + { + ::dd_mkpath(path); + lastExportPath = path; + + DagSaver *save = dagGeom->newDagSaver(tmpmem); + + if (dagGeom->dagSaverStartSaveDag(*save, path) && dagGeom->dagSaverStartSaveNodes(*save)) + { + StaticGeometryContainer *cont = dagGeom->newStaticGeometryContainer(); + + PtrTab &exp_obj = exp_selected ? sel_obj : objects; + dag::ConstSpan exp_spl = exp_selected ? sel_spl : splines; + Tab sel_obj_st(tmpmem); + int st_mask_exp = DAEDITOR3.getEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_EXPORT); + int st_mask_ren = DAEDITOR3.getEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_RENDER); + if (exp_selected) + { + DAEDITOR3.setEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_EXPORT, 1 << ST_EXPORTABLE); + DAEDITOR3.setEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_RENDER, 1 << ST_EXPORTABLE); + sel_obj_st.resize(exp_obj.size()); + mem_set_0(sel_obj_st); + for (int i = 0; i < exp_obj.size(); i++) + if (LandscapeEntityObject *ent_obj = RTTI_cast(exp_obj[i])) + if (IObjEntity *e = ent_obj ? ent_obj->getEntity() : NULL) + { + sel_obj_st[i] = e->getSubtype(); + e->setSubtype(ST_EXPORTABLE); + } + } + + for (int expid = 0; expid < exps.size(); expid++) + { + if (exps[expid] == "Splines" || exps[expid] == "Polygons") + { + for (int i = 0; i < exp_spl.size(); ++i) + { + SplineObject *spline = exp_spl[i]; + if (!spline || spline->points.size() < 1 || !spline->isCreated()) + continue; + + if ((exp_spl[i]->isPoly() && exps[expid] == "Splines") || (!exp_spl[i]->isPoly() && exps[expid] == "Polygons")) + continue; + + if (dagGeom->dagSaverStartSaveNode(*save, spline->getName(), TMatrix::IDENT)) + { + DagSpline dagSpline; + DagSpline *dagSplinePtr = &dagSpline; + + spline->getSpline(dagSpline); + + dagGeom->dagSaverSaveDagSpline(*save, &dagSplinePtr, 1); + + DataBlock blk; + blk.addBool("isPoly", exp_spl[i]->isPoly()); + blk.addStr("blkGenName", exp_spl[i]->getBlkGenName()); + blk.addInt("modifType", exp_spl[i]->getModifType()); + blk.addBool("polyHmapAlign", exp_spl[i]->isPolyHmapAlign()); + blk.addPoint2("polyObjOffs", exp_spl[i]->getPolyObjOffs()); + blk.addReal("polyObjRot", exp_spl[i]->getPolyObjRot()); + blk.addBool("exportable", exp_spl[i]->isExportable()); + blk.addBool("altGeom", exp_spl[i]->polyGeom.altGeom); + blk.addReal("bboxAlignStep", exp_spl[i]->polyGeom.bboxAlignStep); + blk.addInt("cornerType", exp_spl[i]->getProps().cornerType); + + DataBlock *mblk = blk.addNewBlock("modifParams"); + mblk->addReal("width", exp_spl[i]->getProps().modifParams.width); + mblk->addReal("smooth", exp_spl[i]->getProps().modifParams.smooth); + mblk->addReal("offsetPow", exp_spl[i]->getProps().modifParams.offsetPow); + mblk->addPoint2("offset", exp_spl[i]->getProps().modifParams.offset); + + DynamicMemGeneralSaveCB cb(tmpmem); + if (blk.saveToTextStream(cb)) + { + Tab splineScript(tmpmem); + const int buffSize = cb.size(); + + append_items(splineScript, buffSize, (const char *)cb.data()); + splineScript.push_back(0); + + save->save_node_script(splineScript.data()); + } + + dagGeom->dagSaverEndSaveNode(*save); + } + } + } + else if (exps[expid] == "Entities") + { + for (int i = 0; i < exp_obj.size(); i++) + { + RenderableEditableObject *o = exp_obj[i]; + + LandscapeEntityObject *ent_obj = RTTI_cast(o); + SnowSourceObject *snow_obj = RTTI_cast(o); + SphereLightObject *light_obj = RTTI_cast(o); + + if (!ent_obj && !snow_obj && !light_obj) + continue; + + if (dagGeom->dagSaverStartSaveNode(*save, o->getName(), o->getWtm())) + { + DataBlock blk; + + if (ent_obj) + { + blk.addStr("entity_name", ent_obj->getProps().entityName); + blk.addInt("place_type", ent_obj->getProps().placeType); + } + else + { + DataBlock *props = blk.addBlock("props"); + + if (snow_obj) + { + blk.addStr("object_type", "snow"); + snow_obj->save(*props); + } + else if (light_obj) + { + blk.addStr("object_type", "light"); + light_obj->save(*props); + } + + props->removeParam("name"); + props->removeParam("tm"); + } + + DynamicMemGeneralSaveCB cb(tmpmem); + if (blk.saveToTextStream(cb)) + { + Tab entScript(tmpmem); + const int buffSize = cb.size(); + + append_items(entScript, buffSize, (const char *)cb.data()); + entScript.push_back(0); + + save->save_node_script(entScript.data()); + } + + dagGeom->dagSaverEndSaveNode(*save); + } + } + } + else + { + for (int i = 0; i < DAGORED2->getPluginCount(); ++i) + { + IGenEditorPlugin *plugin = DAGORED2->getPlugin(i); + if (strcmp(plugin->getMenuCommandName(), exps[expid]) == 0) + { + IExportToDag *exportToDag = plugin->queryInterface(); + if (exportToDag) + { + exportToDag->gatherExportToDagGeometry(*cont); + break; + } + + IGatherStaticGeometry *geom = plugin->queryInterface(); + if (!geom) + continue; + + geom->gatherStaticVisualGeometry(*cont); + break; + } + } + } + } + + DAEDITOR3.setEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_EXPORT, st_mask_exp); + DAEDITOR3.setEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_RENDER, st_mask_ren); + if (exp_selected && sel_obj_st.size()) + for (int i = 0; i < exp_obj.size(); i++) + if (LandscapeEntityObject *ent_obj = RTTI_cast(exp_obj[i])) + if (IObjEntity *e = ent_obj ? ent_obj->getEntity() : NULL) + e->setSubtype(sel_obj_st[i]); + + cont->writeNodes(save); + + dagGeom->dagSaverEndSaveNodes(*save); + + cont->writeMaterials(save, true); + + dagGeom->deleteStaticGeometryContainer(cont); + dagGeom->dagSaverEndSaveDag(*save); + } + + dagGeom->deleteDagSaver(save); + } +} + + +void HmapLandObjectEditor::importFromDag() +{ + Tab imps(tmpmem); + + ExportImportDlg importDlg(imps, false); + if (!importDlg.showDialog()) + return; + + if (!imps.size()) + return; + + + String filename = wingw::file_open_dlg(NULL, "Open DAG file", "DAG files (*.dag)|*.dag|All files (*.*)|*.*", "dag", + lastImportPath.length() > 0 ? lastImportPath : DAGORED2->getSdkDir()); + + + if (filename.length()) + { + lastImportPath = filename; + + AScene *sc = dagGeom->newAScene(tmpmem); + + if (dagGeom->loadAscene((char *)filename, *sc, LASF_MATNAMES | LASF_NOMATS | LASF_NOMESHES | LASF_NOLIGHTS, false)) + { + dagGeom->nodeCalcWtm(*sc->root); + bool applyForAll = false; + int choosed = 0; + getUndoSystem()->begin(); + importFromNode(sc->root, applyForAll, choosed, imps); + getUndoSystem()->accept("Import splines"); + } + else + wingw::message_box(wingw::MBS_EXCL, "Couldn't open DAG file", "Couldn't open file\n\"%s\"", (const char *)filename); + + dagGeom->deleteAScene(sc); + DAGORED2->repaint(); + } +} + + +void HmapLandObjectEditor::importFromNode(const Node *node, bool &for_all, int &choosed, Tab &imps) +{ + if (node) + { + String newName(node->name); + bool needToImport = true; + + DataBlock blk; + blk.loadText(node->script, node->script.length()); + + if (node->obj && node->obj->isSubOf(OCID_SHAPEHOLDER)) + { + const char *typeName = blk.getBool("isPoly", false) ? "Polygons" : "Splines"; + bool is = false; + for (int i = 0; i < imps.size(); i++) + if (strcmp(imps[i], typeName) == 0) + { + is = true; + break; + } + + if (!is) + needToImport = false; + } + else + { + bool is = false; + for (int i = 0; i < imps.size(); i++) + if (strcmp(imps[i], "Entities") == 0) + { + is = true; + break; + } + + if (!is) + needToImport = false; + } + + if (needToImport && getObjectByName(node->name)) + { + newName = node->name; + + if (!for_all) + { + // ImportDlg importDlg(this, newName, choosed, for_all); + // if (!importDlg.execute(DAGORED2->getMainWnd())) + // needToImport = false; + CDialogWindow *myDlg = DAGORED2->createDialog(_pxScaled(320), _pxScaled(250), "Import objects"); + PropertyContainerControlBase *myPanel = myDlg->getPanel(); + + // fill panel + String text(260, "Spline object \"%s\" is already exists.", newName.str()); + myPanel->createIndent(); + myPanel->createStatic(PID_STATIC, text); + + PropertyContainerControlBase *gtRadio = myPanel->createRadioGroup(PID_CHOISE, "What do you want?"); + + myPanel->createIndent(); + myPanel->createCheckBox(PID_APPLYFORALL, "Apply for all", false); + + + String renTo(newName); + while (getObjectByName(renTo)) + ::make_next_numbered_name(renTo, 3); + + String renToStr(260, "Rename new object to %s", (char *)renTo); + gtRadio->createRadio(PID_CHOISE_1, renToStr); + gtRadio->createRadio(PID_CHOISE_2, "Replace old object"); + gtRadio->createRadio(PID_CHOISE_3, "Skip"); + gtRadio->setInt(PID_CHOISE, PID_CHOISE_1); + + if (myDlg->showDialog() == DIALOG_ID_OK) + { + for_all = myPanel->getBool(PID_APPLYFORALL); + choosed = myPanel->getInt(PID_CHOISE) - PID_CHOISE; + } + + DAGORED2->deleteDialog(myDlg); + } + + if (needToImport) + { + if (choosed == 1) + { + while (getObjectByName(newName)) + ::make_next_numbered_name(newName, 2); + } + if (choosed == 2) + removeObject(getObjectByName(node->name)); + else if (choosed == 3) + needToImport = false; + } + } + + if (needToImport) + { + if (node->obj && node->obj->isSubOf(OCID_SHAPEHOLDER)) + { + SplineShape *spline = ((ShapeHolderObj *)node->obj)->shp; + for (int si = 0; si < spline->spl.size(); ++si) + { + DagSpline *dagSpline = spline->spl[si]; + SplineObject *so = new SplineObject(blk.getBool("isPoly", false)); + so->setEditLayerIdx(EditLayerProps::activeLayerIdx[so->lpIndex()]); + + if (dagSpline) + { + so->setBlkGenName(blk.getStr("blkGenName", "")); + so->setModifType(blk.getInt("modifType", 0)); + so->setPolyHmapAlign(blk.getBool("polyHmapAlign", false)); + so->setPolyObjOffs(blk.getPoint2("polyObjOffs", Point2(0, 0))); + so->setPolyObjRot(blk.getReal("polyObjRot", 0)); + so->setExportable(blk.getBool("exportable", false)); + so->polyGeom.altGeom = blk.getBool("altGeom", false); + so->polyGeom.bboxAlignStep = blk.getReal("bboxAlignStep", blk.getReal("minGridStep", 1.0f)); + so->setCornerType(blk.getInt("cornerType", 0)); + + DataBlock *mblk = blk.getBlockByName("modifParams"); + if (mblk) + so->loadModifParams(*mblk); + + so->setName(newName); + addObject(so); + + for (int i = 0; i < dagSpline->knot.size(); ++i) + { + const DagSpline::SplineKnot &knot = dagSpline->knot[i]; + + SplinePointObject *p = new SplinePointObject; + + Point3 sppoint = knot.p * node->tm; + Point3 spin = knot.i * node->tm; + Point3 spout = knot.o * node->tm; + + p->setPos(sppoint); + p->setRelBezierIn(spin - sppoint); + p->setRelBezierOut(spout - sppoint); + + p->arrId = i; + p->spline = so; + + addObject(p); + } + + so->onCreated(false); + } + } + } + else + { + { + const char *objType = blk.getStr("object_type", NULL); + + if (!objType) + { + const char *entName = blk.getStr("entity_name", ""); + int coll = blk.getInt("place_type", LandscapeEntityObject::Props::PT_coll); + + LandscapeEntityObject *o = new LandscapeEntityObject(entName); + o->setEditLayerIdx(EditLayerProps::activeLayerIdx[o->lpIndex()]); + o->setWtm(node->wtm); + LandscapeEntityObject::Props pr = o->getProps(); + pr.placeType = coll; + o->setProps(pr); + addObject(o); + } + else + { + DataBlock *props = blk.addBlock("props"); + props->setStr("name", node->name); + props->setTm("tm", node->wtm); + + if (stricmp(objType, "snow") == 0) + { + SnowSourceObject *snow_obj = new SnowSourceObject(); + addObject(snow_obj); + snow_obj->load(*props); + } + else if (stricmp(objType, "light") == 0) + { + SphereLightObject *light_obj = new SphereLightObject(); + addObject(light_obj); + light_obj->load(*props); + } + } + } + } + } + + for (int i = 0; i < node->child.size(); ++i) + importFromNode(node->child[i], for_all, choosed, imps); + } +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlLayers.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlLayers.cpp new file mode 100644 index 000000000..265babef3 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlLayers.cpp @@ -0,0 +1,421 @@ +#include "hmlObjectsEditor.h" +#include "hmlPlugin.h" +#include +#include +#include +#include +#include +#include +#undef ERROR +#include "hmlCm.h" +#include + +using hdpi::_pxScaled; + +enum +{ + PIDSTEP_LAYER_PROPS = 7, + MAX_LAYER_COUNT = EditLayerProps::MAX_LAYERS, +}; + +enum +{ + PID_ENT_GRP = 1000, + PID_SPL_GRP, + PID_PLG_GRP, + PID_ENT_LAYER, + PID_SPL_LAYER, + PID_PLG_LAYER, + + PID_ADD_ENT_LAYER, + PID_ADD_SPL_LAYER, + PID_ADD_PLG_LAYER, + + PID_ENT_LAYER_NAME, + PID_ENT_LAYER_ACTIVE, + PID_ENT_LAYER_LOCK, + PID_ENT_LAYER_HIDE, + PID_ENT_LAYER_RTM, + PID_ENT_LAYER_SEL, + PID_ENT_LAYER_ADD, + + PID_SPL_LAYER_NAME = PID_ENT_LAYER_NAME + PIDSTEP_LAYER_PROPS * MAX_LAYER_COUNT, + PID_SPL_LAYER_ACTIVE, + PID_SPL_LAYER_LOCK, + PID_SPL_LAYER_HIDE, + PID_SPL_LAYER_RTM, + PID_SPL_LAYER_SEL, + PID_SPL_LAYER_ADD, + + PID_PLG_LAYER_NAME = PID_SPL_LAYER_NAME + PIDSTEP_LAYER_PROPS * MAX_LAYER_COUNT, + PID_PLG_LAYER_ACTIVE, + PID_PLG_LAYER_LOCK, + PID_PLG_LAYER_HIDE, + PID_PLG_LAYER_RTM, + PID_PLG_LAYER_SEL, + PID_PLG_LAYER_ADD, +}; + +HmapLandObjectEditor::LayersDlg::LayersDlg() +{ + G_STATIC_ASSERT(sizeof(wr) == sizeof(RECT)); + dlg = EDITORCORE->createDialog(_pxScaled(1000), _pxScaled(1080), "Object Layers"); + ::GetWindowRect((HWND)dlg->getHandle(), (RECT *)&wr); + dlg->setCloseHandler(this); + dlg->showButtonPanel(false); +} +HmapLandObjectEditor::LayersDlg::~LayersDlg() +{ + EDITORCORE->deleteDialog(dlg); + dlg = NULL; +} + +bool HmapLandObjectEditor::LayersDlg::isVisible() const { return dlg->isVisible(); }; +void HmapLandObjectEditor::LayersDlg::show() +{ + const FastNameMapEx &layerNames = EditLayerProps::layerNames; + const Tab &layerProps = EditLayerProps::layerProps; + const int *activeLayerIdx = EditLayerProps::activeLayerIdx; + + ::SetWindowPos((HWND)dlg->getHandle(), NULL, wr[0], wr[1], 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE); + dlg->show(); + PropertyContainerControlBase &panel = *dlg->getPanel(); + panel.setEventHandler(this); + +#define BUILD_LP_CONTROLS(GRP, LPTYPE, PIDPREFIX) \ + for (int i = 0; i < layerProps.size(); i++) \ + { \ + if (layerProps[i].type != LPTYPE) \ + continue; \ + GRP.createStatic(PIDPREFIX##LAYER_NAME + i * PIDSTEP_LAYER_PROPS, layerProps[i].name()); \ + GRP.createRadio(PIDPREFIX##LAYER_ACTIVE + i * PIDSTEP_LAYER_PROPS, "active", true, false); \ + if (activeLayerIdx[LPTYPE] == i) \ + panel.setInt(PIDPREFIX##LAYER, PIDPREFIX##LAYER_ACTIVE + i * PIDSTEP_LAYER_PROPS); \ + GRP.createCheckBox(PIDPREFIX##LAYER_LOCK + i * PIDSTEP_LAYER_PROPS, "lock", layerProps[i].lock, true, false); \ + GRP.createCheckBox(PIDPREFIX##LAYER_HIDE + i * PIDSTEP_LAYER_PROPS, "hide", layerProps[i].hide, true, false); \ + GRP.createCheckBox(PIDPREFIX##LAYER_RTM + i * PIDSTEP_LAYER_PROPS, "to mask", layerProps[i].renderToMask, true, false); \ + GRP.createButton(PIDPREFIX##LAYER_SEL + i * PIDSTEP_LAYER_PROPS, "select objects", true, false); \ + GRP.createButton(PIDPREFIX##LAYER_ADD + i * PIDSTEP_LAYER_PROPS, "add to layer", true, false); \ + for (; i + 1 < layerProps.size(); i++) \ + if (layerProps[i + 1].type == LPTYPE) \ + { \ + GRP.createSeparator(-1); \ + break; \ + } \ + } + + PropertyContainerControlBase &pEntM = *panel.createGroup(PID_ENT_GRP, "Entities"); + PropertyContainerControlBase &pEnt = *pEntM.createRadioGroup(PID_ENT_LAYER, ""); + BUILD_LP_CONTROLS(pEnt, EditLayerProps::ENT, PID_ENT_); + pEntM.createButton(PID_ADD_ENT_LAYER, "add new layer"); + + PropertyContainerControlBase &pSplM = *panel.createGroup(PID_SPL_GRP, "Spline"); + PropertyContainerControlBase &pSpl = *pSplM.createRadioGroup(PID_SPL_LAYER, ""); + BUILD_LP_CONTROLS(pSpl, EditLayerProps::SPL, PID_SPL_); + pSplM.createButton(PID_ADD_SPL_LAYER, "add new layer"); + + PropertyContainerControlBase &pPlgM = *panel.createGroup(PID_PLG_GRP, "Polygons"); + PropertyContainerControlBase &pPlg = *pPlgM.createRadioGroup(PID_PLG_LAYER, ""); + BUILD_LP_CONTROLS(pPlg, EditLayerProps::PLG, PID_PLG_); + pPlgM.createButton(PID_ADD_PLG_LAYER, "add new layer"); + +#undef BUILD_LP_CONTROLS +} +void HmapLandObjectEditor::LayersDlg::hide() +{ + if (dlg->getPanel()->getChildCount()) + { + panelState.reset(); + dlg->getPanel()->saveState(panelState); + panelState.setInt("pOffset", dlg->getScrollPos()); + dlg->getPanel()->clear(); + } + dlg->hide(); +} +void HmapLandObjectEditor::LayersDlg::refillPanel() +{ + if (dlg->isVisible()) + { + ::GetWindowRect((HWND)dlg->getHandle(), (RECT *)&wr); + panelState.reset(); + dlg->getPanel()->saveState(panelState); + panelState.setInt("pOffset", dlg->getScrollPos()); + + dlg->getPanel()->clear(); + show(); + } +} + +static void change_active(dag::ConstSpan layerProps, int *activeLayerIdx, int active_idx, unsigned lptype) +{ + if (active_idx < 0 || active_idx >= layerProps.size() || layerProps[active_idx].type != lptype) + active_idx = lptype; + activeLayerIdx[lptype] = active_idx; +} + +void HmapLandObjectEditor::LayersDlg::onChange(int pid, PropertyContainerControlBase *panel) +{ + int lidx = -1; + int pid0 = 0; + + if (pid >= PID_ENT_LAYER_ACTIVE && pid < PID_ENT_LAYER_ACTIVE + PIDSTEP_LAYER_PROPS * MAX_LAYER_COUNT) + { + lidx = (pid - PID_ENT_LAYER_ACTIVE) / PIDSTEP_LAYER_PROPS; + pid0 = pid - lidx * PIDSTEP_LAYER_PROPS; + } + else if (pid >= PID_SPL_LAYER_ACTIVE && pid < PID_SPL_LAYER_ACTIVE + PIDSTEP_LAYER_PROPS * MAX_LAYER_COUNT) + { + lidx = (pid - PID_SPL_LAYER_ACTIVE) / PIDSTEP_LAYER_PROPS; + pid0 = pid - lidx * PIDSTEP_LAYER_PROPS; + } + else if (pid >= PID_PLG_LAYER_ACTIVE && pid < PID_PLG_LAYER_ACTIVE + PIDSTEP_LAYER_PROPS * MAX_LAYER_COUNT) + { + lidx = (pid - PID_PLG_LAYER_ACTIVE) / PIDSTEP_LAYER_PROPS; + pid0 = pid - lidx * PIDSTEP_LAYER_PROPS; + } + else if (pid == PID_ENT_LAYER) + { + lidx = (panel->getInt(pid) - PID_ENT_LAYER_ACTIVE) / PIDSTEP_LAYER_PROPS; + change_active(EditLayerProps::layerProps, EditLayerProps::activeLayerIdx, lidx, EditLayerProps::ENT); + } + else if (pid == PID_SPL_LAYER) + { + lidx = (panel->getInt(pid) - PID_SPL_LAYER_ACTIVE) / PIDSTEP_LAYER_PROPS; + change_active(EditLayerProps::layerProps, EditLayerProps::activeLayerIdx, lidx, EditLayerProps::SPL); + } + else if (pid == PID_PLG_LAYER) + { + lidx = (panel->getInt(pid) - PID_PLG_LAYER_ACTIVE) / PIDSTEP_LAYER_PROPS; + Tab &layerProps = EditLayerProps::layerProps; + change_active(EditLayerProps::layerProps, EditLayerProps::activeLayerIdx, lidx, EditLayerProps::PLG); + } + + if (lidx != -1) + { + Tab &layerProps = EditLayerProps::layerProps; + EditLayerProps &l = layerProps[lidx]; + switch (pid0) + { + case PID_ENT_LAYER_ACTIVE: + case PID_SPL_LAYER_ACTIVE: + case PID_PLG_LAYER_ACTIVE: break; + + case PID_ENT_LAYER_LOCK: + case PID_SPL_LAYER_LOCK: + case PID_PLG_LAYER_LOCK: + if (panel->getBool(pid)) + { + l.lock = 1; + HmapLandPlugin::self->selectLayerObjects(lidx, false); + } + else + l.lock = 0; + break; + + case PID_ENT_LAYER_HIDE: + case PID_SPL_LAYER_HIDE: + case PID_PLG_LAYER_HIDE: + if (panel->getBool(pid)) + { + l.hide = 1; + DAEDITOR3.setEntityLayerHiddenMask(DAEDITOR3.getEntityLayerHiddenMask() | (1ull << lidx)); + } + else + { + l.hide = 0; + DAEDITOR3.setEntityLayerHiddenMask(DAEDITOR3.getEntityLayerHiddenMask() & ~(1ull << lidx)); + } + HmapLandPlugin::hmlService->invalidateClipmap(false); + break; + + case PID_ENT_LAYER_RTM: + case PID_SPL_LAYER_RTM: + case PID_PLG_LAYER_RTM: l.renderToMask = panel->getBool(pid) ? 1 : 0; break; + } + } +} +void HmapLandObjectEditor::LayersDlg::onClick(int pid, PropertyContainerControlBase *panel) +{ + FastNameMapEx &layerNames = EditLayerProps::layerNames; + Tab &layerProps = EditLayerProps::layerProps; + + if (pid == -DIALOG_ID_CLOSE) + { + ::GetWindowRect((HWND)dlg->getHandle(), (RECT *)&wr); + HmapLandPlugin::self->onLayersDlgClosed(); + if (dlg->getPanel()->getChildCount()) + { + panelState.reset(); + dlg->getPanel()->saveState(panelState); + panelState.setInt("pOffset", dlg->getScrollPos()); + dlg->getPanel()->clear(); + } + } + else if (pid == PID_ADD_ENT_LAYER || pid == PID_ADD_SPL_LAYER || pid == PID_ADD_PLG_LAYER) + { + if (EditLayerProps::layerProps.size() >= EditLayerProps::MAX_LAYERS) + { + wingw::message_box(wingw::MBS_OK, "Add new layer", "Too many layers created (%d), cannot create one more", + EditLayerProps::layerProps.size()); + return; + } + int lptype = 0; + if (pid == PID_ADD_ENT_LAYER) + lptype = EditLayerProps::ENT; + else if (pid == PID_ADD_SPL_LAYER) + lptype = EditLayerProps::SPL; + else if (pid == PID_ADD_PLG_LAYER) + lptype = EditLayerProps::PLG; + + CDialogWindow *dialog = DAGORED2->createDialog(_pxScaled(250), _pxScaled(135), "Add layer"); + PropPanel2 *dpan = dialog->getPanel(); + dpan->createEditBox(1, "Enter layer name:"); + dpan->setFocusById(1); + dpan->createSeparator(-1); + for (;;) // infinite cycle with explicit break + { + int ret = dialog->showDialog(); + if (ret == DIALOG_ID_OK) + { + String nm(dpan->getText(1)); + bool bad_name = false; + if (!nm.length()) + bad_name = true; + for (const char *p = nm.str(); *p != 0; p++) + if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || *p == '_') + continue; + else + { + bad_name = true; + break; + } + if (bad_name) + { + wingw::message_box(wingw::MBS_OK, "Add new layer", + "Bad layer name <%s>\n" + "Name must not be empty and is allowed to content only latin letters, digits or _", + dpan->getText(1)); + continue; + } + + int lidx = EditLayerProps::findLayerOrCreate(lptype, layerNames.addNameId(dpan->getText(1))); + change_active(layerProps, EditLayerProps::activeLayerIdx, lidx, lptype); + panel->setPostEvent(1); + } + break; + } + DAGORED2->deleteDialog(dialog); + } + else if (pid >= PID_ENT_LAYER_ACTIVE && pid < PID_ENT_LAYER_ACTIVE + PIDSTEP_LAYER_PROPS * MAX_LAYER_COUNT) + { + int lidx = (pid - PID_ENT_LAYER_ACTIVE) / PIDSTEP_LAYER_PROPS; + if (pid == PID_ENT_LAYER_SEL + lidx * PIDSTEP_LAYER_PROPS && !(EditLayerProps::layerProps[lidx].lock)) + HmapLandPlugin::self->selectLayerObjects(lidx); + else if (pid == PID_ENT_LAYER_ADD + lidx * PIDSTEP_LAYER_PROPS) + HmapLandPlugin::self->moveObjectsToLayer(lidx); + } + else if (pid >= PID_SPL_LAYER_ACTIVE && pid < PID_SPL_LAYER_ACTIVE + PIDSTEP_LAYER_PROPS * MAX_LAYER_COUNT) + { + int lidx = (pid - PID_SPL_LAYER_ACTIVE) / PIDSTEP_LAYER_PROPS; + if (pid == PID_SPL_LAYER_SEL + lidx * PIDSTEP_LAYER_PROPS && !(EditLayerProps::layerProps[lidx].lock)) + HmapLandPlugin::self->selectLayerObjects(lidx); + else if (pid == PID_SPL_LAYER_ADD + lidx * PIDSTEP_LAYER_PROPS) + HmapLandPlugin::self->moveObjectsToLayer(lidx); + } + else if (pid >= PID_PLG_LAYER_ACTIVE && pid < PID_PLG_LAYER_ACTIVE + PIDSTEP_LAYER_PROPS * MAX_LAYER_COUNT) + { + int lidx = (pid - PID_PLG_LAYER_ACTIVE) / PIDSTEP_LAYER_PROPS; + if (pid == PID_PLG_LAYER_SEL + lidx * PIDSTEP_LAYER_PROPS && !(EditLayerProps::layerProps[lidx].lock)) + HmapLandPlugin::self->selectLayerObjects(lidx); + else if (pid == PID_PLG_LAYER_ADD + lidx * PIDSTEP_LAYER_PROPS) + HmapLandPlugin::self->moveObjectsToLayer(lidx); + } +} +void HmapLandObjectEditor::LayersDlg::onDoubleClick(int pid, PropertyContainerControlBase *panel) {} + +void HmapLandPlugin::onLayersDlgClosed() { objEd.setButton(CM_LAYERS_DLG, false); } + + +FastNameMapEx EditLayerProps::layerNames; +Tab EditLayerProps::layerProps; +int EditLayerProps::activeLayerIdx[EditLayerProps::TYPENUM]; + +void EditLayerProps::resetLayersToDefauls() +{ + layerNames.reset(); + layerNames.addNameId("default"); + + layerProps.resize(EditLayerProps::TYPENUM); + mem_set_0(layerProps); + + for (int i = 0; i < EditLayerProps::TYPENUM; i++) + { + layerProps[i].nameId = 0; + layerProps[i].type = i; + layerProps[i].renderToMask = 1; + + activeLayerIdx[i] = i; + } +} + +static const char *lptype_name[] = {"ent", "spl", "plg"}; +void EditLayerProps::loadLayersConfig(const DataBlock &blk, const DataBlock &local_data) +{ + const DataBlock *layersBlk = blk.getBlockByName("layers"); + const DataBlock &layersBlk_local = *local_data.getBlockByNameEx("layers"); + for (int i = 0; i < layersBlk->blockCount(); i++) + { + const DataBlock &b = *layersBlk->getBlock(i); + int nid = layerNames.addNameId(b.getBlockName()); + if (nid < 0) + { + DAEDITOR3.conError("bad layer name <%s> in %s", b.getBlockName(), "heightmapLand.plugin.blk"); + continue; + } + int lidx = findLayerOrCreate(b.getInt("type", 0), nid); + + const DataBlock &b_local = + *layersBlk_local.getBlockByNameEx(lptype_name[layerProps[lidx].type])->getBlockByNameEx(b.getBlockName()); + layerProps[lidx].lock = b_local.getBool("lock", false); + layerProps[lidx].hide = b_local.getBool("hide", false); + layerProps[lidx].renderToMask = b_local.getBool("renderToMask", true); + } + + activeLayerIdx[0] = findLayer(ENT, layerNames.getNameId(layersBlk_local.getStr("ENT_active", "default"))); + activeLayerIdx[1] = findLayer(SPL, layerNames.getNameId(layersBlk_local.getStr("SPL_active", "default"))); + activeLayerIdx[2] = findLayer(PLG, layerNames.getNameId(layersBlk_local.getStr("PLG_active", "default"))); + for (int i = 0; i < EditLayerProps::TYPENUM; i++) + if (activeLayerIdx[i] < 0) + activeLayerIdx[i] = i; + + uint64_t lh_mask = 0; + for (int i = 0; i < layerProps.size(); i++) + if (layerProps[i].hide) + lh_mask |= 1ull << i; + DAEDITOR3.setEntityLayerHiddenMask(lh_mask); +} +void EditLayerProps::saveLayersConfig(DataBlock &blk, DataBlock &local_data) +{ + if (layerProps.size() != EditLayerProps::TYPENUM || + (layerProps[0].renderToMask & layerProps[1].renderToMask & layerProps[2].renderToMask) != 1 || + (layerProps[0].lock | layerProps[1].lock | layerProps[2].lock) != 0 || + (layerProps[0].hide | layerProps[1].hide | layerProps[2].hide) != 0) + { + DataBlock &layersBlk = *blk.addBlock("layers"); + DataBlock &layersBlk_local = *local_data.addBlock("layers"); + for (int i = 0; i < layerProps.size(); i++) + { + DataBlock &b = *layersBlk.addNewBlock(layerProps[i].name()); + DataBlock &b_local = *layersBlk_local.addBlock(lptype_name[layerProps[i].type])->addBlock(b.getBlockName()); + + b.setInt("type", layerProps[i].type); + b_local.setBool("lock", layerProps[i].lock); + b_local.setBool("hide", layerProps[i].hide); + b_local.setBool("renderToMask", layerProps[i].renderToMask); + } + + layersBlk_local.setStr("ENT_active", layerProps[activeLayerIdx[0]].name()); + layersBlk_local.setStr("SPL_active", layerProps[activeLayerIdx[1]].name()); + layersBlk_local.setStr("PLG_active", layerProps[activeLayerIdx[2]].name()); + } +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlLayers.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlLayers.h new file mode 100644 index 000000000..67ba62491 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlLayers.h @@ -0,0 +1,51 @@ +#pragma once + +#include +class DataBlock; + +struct EditLayerProps +{ + enum + { + ENT = 0, + SPL, + PLG, + TYPENUM + }; + static const int MAX_LAYERS = 60; + + unsigned lock : 1, hide : 1, renderToMask : 1; + unsigned type : 3; + unsigned nameId : 10; + + EditLayerProps() : lock(0), hide(0), renderToMask(0), type(TYPENUM), nameId(0) {} + EditLayerProps(unsigned t, unsigned nid) : lock(0), hide(0), renderToMask(0), type(t), nameId(nid) {} + const char *name() const { return layerNames.getName(nameId); } + +public: + static FastNameMapEx layerNames; + static Tab layerProps; + static int activeLayerIdx[TYPENUM]; + + static void resetLayersToDefauls(); + static void loadLayersConfig(const DataBlock &blk, const DataBlock &local_data); + static void saveLayersConfig(DataBlock &blk, DataBlock &local_data); + static int findLayer(unsigned t, unsigned nid) + { + for (int i = 0; i < layerProps.size(); i++) + if (layerProps[i].type == t && layerProps[i].nameId == nid) + return i; + return -1; + } + static int findLayerOrCreate(unsigned t, unsigned nid) + { + int lidx = findLayer(t, nid); + if (lidx < 0) + { + lidx = layerProps.size(); + layerProps.push_back(EditLayerProps(t, nid)); + } + return lidx; + } + static const char *layerName(int idx) { return layerProps[idx].name(); } +}; diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlLight.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlLight.cpp new file mode 100644 index 000000000..603510be2 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlLight.cpp @@ -0,0 +1,735 @@ +#include "hmlLight.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hmlObjectsEditor.h" + +enum +{ + PID_DIRECTIONAL = 1, + PID_GEOM_POS, + PID_GEOM_SIZE, + PID_GEOM_DIR, + PID_GEOM_SEGMENTS, + PID_ANGLE_SIZE, + PID_LT_COLOR, + PID_LT_BRIGHTNESS, + PID_AMB_COLOR, + PID_AMB_BRIGHTNESS, +}; + +static void generateSphereMesh(MeshData &mesh, int segments, const Color4 &col); +static int get_cos_power_from_ang(real alfa, real part, real &real_part); +static real square_rec(int iter_no, real val, real *hashed_iter); + +int SphereLightObject::lightGeomSubtype = -1; + +void SphereLightObject::Props::defaults() +{ + color = E3DCOLOR(220, 220, 220); + brightness = 300; + ambColor = E3DCOLOR(220, 220, 220); + ambBrightness = 0; + ang = 30 * DEG_TO_RAD; + directional = false; + segments = 8; +} + +SphereLightObject::SphereLightObject() : ltGeom(NULL) +{ + props.defaults(); + if (lightGeomSubtype == -1) + lightGeomSubtype = 1 << IDaEditor3Engine::get().registerEntitySubTypeId("lt_geom"); +} +SphereLightObject::~SphereLightObject() { dagGeom->deleteGeomObject(ltGeom); } + +bool SphereLightObject::isSelectedByRectangle(IGenViewportWnd *vp, const EcRect &rect) const +{ + Point2 cp[8]; + BBox3 box(Point3(-0.5, -0.5, -0.5), Point3(0.5, 0.5, 0.5)); + BBox2 box2; + real z; + bool in_frustum = false; + +#define TEST_POINT(i, P) \ + in_frustum |= vp->worldToClient(matrix * P, cp[i], &z) && z > 0; \ + if (z > 0 && rect.l <= cp[i].x && rect.t <= cp[i].y && cp[i].x <= rect.r && cp[i].y <= rect.b) \ + return true; \ + else \ + box2 += cp[i]; + +#define TEST_SEGMENT(i, j) \ + if (::isect_line_segment_box(cp[i], cp[j], rbox)) \ + return true + + for (int i = 0; i < 8; i++) + { + TEST_POINT(i, box.point(i)); + } + + if (!in_frustum) + return false; + BBox2 rbox(Point2(rect.l, rect.t), Point2(rect.r, rect.b)); + if (!(box2 & rbox)) + return false; + + TEST_SEGMENT(0, 4); + TEST_SEGMENT(4, 5); + TEST_SEGMENT(5, 1); + TEST_SEGMENT(1, 0); + TEST_SEGMENT(2, 6); + TEST_SEGMENT(6, 7); + TEST_SEGMENT(7, 3); + TEST_SEGMENT(3, 2); + TEST_SEGMENT(0, 2); + TEST_SEGMENT(1, 3); + TEST_SEGMENT(4, 6); + TEST_SEGMENT(5, 7); + +#undef TEST_POINT +#undef TEST_SEGMENT + + return isSelectedByPointClick(vp, rect.l, rect.t); + return false; +} +bool SphereLightObject::isSelectedByPointClick(IGenViewportWnd *vp, int x, int y) const +{ + Point3 dir, p0; + float out_t; + + vp->clientToWorld(Point2(x, y), p0, dir); + float wtm_det = getWtm().det(); + if (fabsf(wtm_det) < 1e-12) + return false; + TMatrix iwtm = inverse(getWtm(), wtm_det); + return rayIntersectSphere(iwtm * p0, normalize(iwtm % dir), Point3(0, 0, 0), 0.5 * 0.5); +} +bool SphereLightObject::getWorldBox(BBox3 &box) const +{ + box = matrix * BSphere3(Point3(0, 0, 0), 0.5); + return true; +} + +void SphereLightObject::render() +{ + if (ltGeom) + { + ltGeom->setTm(getWtm()); + dagGeom->geomObjectRender(*ltGeom); + } +} +void SphereLightObject::renderTrans() +{ + if (ltGeom) + { + ltGeom->setTm(getWtm()); + dagGeom->geomObjectRenderTrans(*ltGeom); + } +} + +void SphereLightObject::renderObject() +{ + TMatrix tm = getWtm(); + Point3 sz(matrix.getcol(0).length(), matrix.getcol(1).length(), matrix.getcol(2).length()); + bool sel = isSelected(); + E3DCOLOR c = props.directional ? props.ambColor : props.color; + float br = props.directional ? props.ambBrightness : props.brightness; + float br_scale = 0.5; // toneMapper.hdrScaleMul*toneMapper.postScaleMul + E3DCOLOR dc = sel ? E3DCOLOR(200, 200, 200, 255) : E3DCOLOR(128, 160, 128, 255); + + dagRender->setLinesTm(tm); + dagRender->renderSphere(Point3(0, 0, 0), 0.5, dc); + + if (sel && !props.directional) + { + real fallof = sqrt(PI * sz.lengthSq() * max(c.r, max(c.g, c.b)) * br * br_scale); + + TMatrix tm = TMatrix::IDENT; + tm.setcol(3, getPos()); + + dagRender->setLinesTm(tm); + dagRender->renderSphere(Point3(0, 0, 0), fallof, c); + // dagRender->renderSphere(Point3(0, 0, 0), visRad, dc); + } + + if (props.directional) + { + real dirFallof = + sqrt(props.ang * (sz / 2).lengthSq() * max(props.color.r, max(props.color.g, props.color.b)) * props.brightness * br_scale); + + Point3 top = Point3(0, 1, 0) * dirFallof; + + Tab points(tmpmem); + Tab points1(tmpmem); + TMatrix scaleTm = TMatrix::IDENT; + scaleTm[0][0] = getSize().x / 2; + scaleTm[2][2] = getSize().z / 2; + TMatrix tM = getRotTm(); + tM.setcol(3, getPos()); + int pointsNum; + points1.push_back(-Point3(0, 0, 1)); + pointsNum = 8; + const float STEP = PI * 2 / ((float)pointsNum); + for (int i = 1; i < pointsNum; i++) + points1.push_back(rotyTM(STEP) * points1[i - 1]); + + for (int i = 0; i < pointsNum; i++) + { + Point3 side = points1[i]; + side.normalize(); + points1[i] = scaleTm * points1[i]; + points.push_back(points1[i] + sin(props.ang) * side * dirFallof + cos(props.ang) * top); + points[i] = tM * points[i]; + points1[i] = tM * points1[i]; + } + + dagRender->setLinesTm(TMatrix::IDENT); + E3DCOLOR dirc(props.color.r, props.color.g, props.color.b); + for (int i = 0; i < points.size(); i++) + { + dagRender->renderLine(points[i], points1[i], dirc); + if (i > 0) + dagRender->renderLine(points[i - 1], points[i], dirc); + else + dagRender->renderLine(points.back(), points[i], dirc); + } + } +} + +void SphereLightObject::fillProps(PropPanel2 &op, DClassID for_class_id, dag::ConstSpan objects) +{ + bool one_type = true; + + for (int i = 0; i < objects.size(); ++i) + { + SphereLightObject *o = RTTI_cast(objects[i]); + if (!o) + { + one_type = false; + continue; + } + } + + if (one_type) + { + op.createIndent(-1); + + op.createCheckBox(PID_DIRECTIONAL, "Directional", props.directional); + // op.createCheckBox(PID_SPHERICAL, "Spherical", props.spherical); + + op.createPoint3(PID_GEOM_POS, "Position", getPos(), false); + op.createPoint3(PID_GEOM_SIZE, "Size", getSize(), false); + op.createPoint3(PID_GEOM_DIR, "Direction", getWtm().getcol(1), false); + op.createEditInt(PID_GEOM_SEGMENTS, "Segments", props.segments); + + op.createEditFloat(PID_ANGLE_SIZE, "Angle size", props.ang, 2, props.directional); + + op.createColorBox(PID_LT_COLOR, "Color", props.color); + op.createEditFloat(PID_LT_BRIGHTNESS, "Brightness", props.brightness); + + op.createColorBox(PID_AMB_COLOR, "Amb color", props.ambColor, props.directional); + op.createEditFloat(PID_AMB_BRIGHTNESS, "Amb brightness", props.ambBrightness, 2, props.directional); + + for (int i = 0; i < objects.size(); ++i) + { + SphereLightObject *o = RTTI_cast(objects[i]); + if (o->props.directional != props.directional) + op.resetById(PID_DIRECTIONAL); + if (lengthSq(o->getPos() - getPos()) > 1e-6) + op.resetById(PID_GEOM_POS); + if (lengthSq(o->getSize() - getSize()) > 1e-6) + op.resetById(PID_GEOM_SIZE); + if (lengthSq(o->getWtm().getcol(1) - getWtm().getcol(1)) > 1e-6) + op.resetById(PID_GEOM_DIR); + if (o->props.segments != props.segments) + op.resetById(PID_GEOM_SEGMENTS); + if (o->props.ang != props.ang) + op.resetById(PID_ANGLE_SIZE); + if (o->props.color != props.color) + op.resetById(PID_LT_COLOR); + if (o->props.brightness != props.brightness) + op.resetById(PID_LT_BRIGHTNESS); + if (o->props.ambColor != props.ambColor) + op.resetById(PID_AMB_COLOR); + if (o->props.ambBrightness != props.ambBrightness) + op.resetById(PID_AMB_BRIGHTNESS); + } + } +} + +void SphereLightObject::onPPChange(int pid, bool edit_finished, PropPanel2 &panel, dag::ConstSpan objects) +{ +#define CHANGE_VAL(type, pname, getfunc) \ + { \ + type val = panel.getfunc(pid); \ + for (int i = 0; i < objects.size(); ++i) \ + { \ + SphereLightObject *o = RTTI_cast(objects[i]); \ + if (!o || o->pname == val) \ + continue; \ + getObjEditor()->getUndoSystem()->put(new UndoPropsChange(o)); \ + o->pname = val; \ + o->propsChanged(); \ + } \ + } + if (!edit_finished) + return; + + if (pid == PID_DIRECTIONAL) + { + CHANGE_VAL(bool, props.directional, getBool) + + panel.setEnabledById(PID_ANGLE_SIZE, props.directional); + panel.setEnabledById(PID_AMB_COLOR, props.directional); + panel.setEnabledById(PID_AMB_BRIGHTNESS, props.directional); + } + else if (pid == PID_GEOM_SEGMENTS) + { + CHANGE_VAL(int, props.segments, getInt) + } + else if (pid == PID_ANGLE_SIZE) + { + CHANGE_VAL(float, props.ang, getFloat) + } + else if (pid == PID_LT_BRIGHTNESS) + { + CHANGE_VAL(float, props.brightness, getFloat) + } + else if (pid == PID_AMB_BRIGHTNESS) + { + CHANGE_VAL(float, props.ambBrightness, getFloat) + } + else if (pid == PID_LT_COLOR) + { + CHANGE_VAL(E3DCOLOR, props.color, getColor) + } + else if (pid == PID_AMB_COLOR) + { + CHANGE_VAL(E3DCOLOR, props.ambColor, getColor) + } + DAGORED2->repaint(); + +#undef CHANGE_VAL +} + +void SphereLightObject::save(DataBlock &blk) +{ + blk.setStr("name", getName()); + blk.setE3dcolor("color", props.color); + blk.setReal("output", props.brightness); + blk.setBool("directional", props.directional); + blk.setReal("ambBrightness", props.ambBrightness); + blk.setE3dcolor("ambColor", props.ambColor); + blk.setReal("ang", props.ang); + blk.setTm("tm", matrix); + blk.setInt("segments", props.segments); +} +void SphereLightObject::load(const DataBlock &blk) +{ + String uniqName(blk.getStr("name", "")); + if (uniqName == "") + uniqName = "Sph_Light_Source_001"; + getObjEditor()->setUniqName(this, uniqName); + setWtm(blk.getTm("tm", TMatrix::IDENT)); + + props.color = blk.getE3dcolor("color", E3DCOLOR(220, 220, 220, 255)); + props.brightness = blk.getReal("output", 220); + props.directional = blk.getBool("directional", false); + props.ambBrightness = blk.getReal("ambBrightness", 0); + props.ambColor = blk.getE3dcolor("ambColor", E3DCOLOR(220, 220, 220, 255)); + + props.ang = blk.getReal("ang", 30 * DEG_TO_RAD); + props.segments = blk.getInt("segments", 8); + + propsChanged(); +} + +void SphereLightObject::setWtm(const TMatrix &wtm) { __super::setWtm(wtm); } + +void SphereLightObject::onRemove(ObjectEditor *) {} +void SphereLightObject::onAdd(ObjectEditor *objEditor) { propsChanged(); } + +bool SphereLightObject::setPos(const Point3 &p) +{ + if (!__super::setPos(p)) + return false; + return true; +} + +void SphereLightObject::propsChanged() { buildGeom(); } + +SphereLightObject *SphereLightObject::clone() +{ + SphereLightObject *obj = new SphereLightObject; + + getObjEditor()->setUniqName(obj, getName()); + + obj->setProps(getProps()); + + TMatrix tm = getWtm(); + obj->setWtm(tm); + + return obj; +} + +void SphereLightObject::putMoveUndo() +{ + HmapLandObjectEditor *ed = (HmapLandObjectEditor *)getObjEditor(); + if (!ed->isCloneMode()) + __super::putMoveUndo(); +} + +void SphereLightObject::buildGeom() +{ + if (!ltGeom) + { + ltGeom = dagGeom->newGeomObject(midmem); + ltGeom->notChangeVertexColors(true); + } + else + dagGeom->geomObjectClear(*ltGeom); + + StaticGeometryContainer *cont = ltGeom->getGeometryContainer(); + int seg = props.segments < 5 ? 5 : props.segments; + + Color4 col = color4(props.color); + Color4 ambCol = color4(props.ambColor); + + Ptr matMain = + SphereLightObject::makeMat("editor_helper_no_tex_blend", props.directional ? ambCol : col, Color4(0, 0, 0, 0), 0); + + Mesh *mesh = new Mesh; + MaterialDataList mat; + mat.addSubMat(matMain); + + generateSphereMesh(mesh->getMeshData(), seg, props.directional ? ambCol : col); + dagGeom->objCreator3dAddNode(name, mesh, &mat, *cont); + + if (!cont->nodes.size()) + return; + + StaticGeometryNode *node = cont->nodes[0]; + + if (node) + { + node->visRange = -1; + node->name = name; + + node->wtm = TMatrix::IDENT; + + node->flags = StaticGeometryNode::FLG_RENDERABLE | StaticGeometryNode::FLG_CASTSHADOWS_ON_SELF | + StaticGeometryNode::FLG_CASTSHADOWS | StaticGeometryNode::FLG_AUTOMATIC_VISRANGE; + + if (props.directional) + { + node->normalsDir = matrix.getcol(1); + node->flags |= StaticGeometryNode::FLG_FORCE_WORLD_NORMALS; + } + + node->lighting = StaticGeometryNode::LIGHT_NONE; + } + + ltGeom->setTm(getWtm()); + ltGeom->setUseNodeVisRange(true); + dagGeom->geomObjectSetDefNodeVis(*ltGeom); + + dagGeom->geomObjectRecompile(*ltGeom); +} +void SphereLightObject::gatherGeom(StaticGeometryContainer &container) const +{ + const StaticGeometryContainer *cont = ltGeom->getGeometryContainer(); + + if (cont) + { + Color4 col = color4(props.color) * props.brightness; + Color4 ambCol = color4(props.ambColor) * props.ambBrightness; + + StaticGeometryMaterial *matMain = NULL; + + if (props.directional) + { + real eps; + real power = ::get_cos_power_from_ang(props.ang, 0.9, eps); + matMain = makeMat2("hdr_dir_light", col, ambCol, power); + } + else + matMain = makeMat2("hdr_envi", col, Color4(0, 0, 0, 0), 0); + + for (int i = 0; i < cont->nodes.size(); ++i) + { + const StaticGeometryNode *srcNode = cont->nodes[i]; + + if (srcNode && srcNode->mesh) + { + StaticGeometryNode *node = new StaticGeometryNode(*srcNode); + + node->wtm = getWtm(); + node->mesh->mesh.cvert[0] = col; + + for (int mi = 0; mi < node->mesh->mats.size(); ++mi) + node->mesh->mats[mi] = matMain; + + container.addNode(node); + } + } + } +} + + +static PtrTab sharedMats(tmpmem); +static PtrTab sharedMats2(tmpmem); + +void SphereLightObject::clearMats() +{ + clear_and_shrink(sharedMats); + clear_and_shrink(sharedMats2); +} + +MaterialData *SphereLightObject::makeMat(const char *class_name, const Color4 &emis, const Color4 &amb_emis, real power) +{ + for (int i = 0; i < sharedMats.size(); i++) + if (sharedMats[i] && stricmp(sharedMats[i]->className, class_name) == NULL && sharedMats[i]->mat.emis == emis && + sharedMats[i]->mat.amb == amb_emis && sharedMats[i]->mat.power == power) + return sharedMats[i]; + + MaterialData *gm = new MaterialData; + gm->matName = "light_material"; + gm->className = class_name; + gm->matScript = "emission=1000"; + gm->mat.diff = emis; + gm->mat.amb = amb_emis; + gm->mat.emis = emis; + gm->mat.spec = emis; + gm->mat.power = power; + // gm->mat.cosPower = power; + gm->flags = MatFlags::FLG_USE_IN_GI; + + sharedMats.push_back(gm); + return gm; +} + +StaticGeometryMaterial *SphereLightObject::makeMat2(const char *class_name, const Color4 &emis, const Color4 &amb_emis, real power) +{ + for (int i = 0; i < sharedMats2.size(); i++) + if (sharedMats2[i] && stricmp(sharedMats2[i]->className, class_name) == NULL && sharedMats2[i]->emis == emis && + sharedMats2[i]->amb == amb_emis && sharedMats2[i]->power == power) + return sharedMats2[i]; + + StaticGeometryMaterial *gm = new StaticGeometryMaterial; + gm->name = "light_material"; + gm->className = class_name; + gm->scriptText = "emission=1000"; + gm->diff = emis; + gm->amb = amb_emis; + gm->emis = emis; + gm->spec = emis; + gm->power = power; + gm->cosPower = power; + gm->flags = MatFlags::FLG_USE_IN_GI; + + sharedMats2.push_back(gm); + return gm; +} + +static void generateRing(Tab &vert, Tab &tvert, int segments, real y) +{ + const real radius = 0.5 * sqrtf(1 - y * y * 4); + + vert.resize(segments); + tvert.resize(segments + 1); + + const real step = TWOPI / segments; + const real ty = acos(y * 2) / PI; + real angle = 0; + + for (int i = 0; i < segments; ++i, angle += step) + { + vert[i] = Point3(radius * cos(angle), y, radius * sin(angle)); + tvert[i] = Point2(angle / TWOPI, ty); + } + + tvert[segments] = Point2(angle / TWOPI, ty); +} + +static void generateSphereMesh(MeshData &mesh, int segments, const Color4 &col) +{ + const int resizeStep = segments * 10; + const int endRing = segments / 2 + 1; + const real dy = 2.0 / segments; + + const real segAngle = PI / (endRing - 1); + + real y = 0.5; + Tab vert(tmpmem); + Tab tvert(tmpmem); + + Face face; + face.smgr = 1; + + TFace tface; + + for (int ring = 0; ring < endRing; y = 0.5 * cosf(segAngle * ++ring)) + { + // north pole + if (!ring) + { + mesh.vert.push_back(Point3(0, 0.5, 0)); + mesh.tvert[0].push_back(Point2(0, 1)); + + continue; + } + + // south pole + if (ring == endRing - 1) + { + mesh.vert.push_back(Point3(0, -0.5, 0)); + mesh.tvert[0].push_back(Point2(0, 0)); + + continue; + } + + // add ring vertexes + generateRing(vert, tvert, segments, y); + append_items(mesh.vert, segments, vert.data()); + append_items(mesh.tvert[0], segments + 1, tvert.data()); + + if (ring > 1 && ring < endRing - 1) + { + for (int vi = mesh.vert.size() - segments, ti = mesh.tvert[0].size() - segments - 1; vi < mesh.vert.size(); ++vi, ++ti) + { + face.v[0] = vi; + face.v[1] = vi - segments; + face.v[2] = vi + 1; + + tface.t[0] = ti; + tface.t[1] = ti - segments - 1; + tface.t[2] = ti + 1; + + if (vi == mesh.vert.size() - 1) + face.v[2] = mesh.vert.size() - segments; + + mesh.face.push_back(face); + mesh.tface[0].push_back(tface); + + face.v[0] = vi - segments; + face.v[1] = vi - segments + 1; + face.v[2] = vi + 1; + + tface.t[0] = ti - segments - 1; + tface.t[1] = ti - segments; + tface.t[2] = ti + 1; + + if (vi == mesh.vert.size() - 1) + { + face.v[1] = mesh.vert.size() - segments * 2; + face.v[2] = mesh.vert.size() - segments; + } + + mesh.face.push_back(face); + mesh.tface[0].push_back(tface); + } + } + + // next ring after north pole + if (ring == 1) + { + for (int vi = 1; vi <= segments; ++vi) + { + face.v[0] = tface.t[0] = vi; + face.v[1] = tface.t[1] = 0; + face.v[2] = tface.t[2] = vi + 1; + + if (vi == segments) + face.v[2] = 1; + + mesh.face.push_back(face); + mesh.tface[0].push_back(tface); + } + } + + // ring before south pole + if (ring == endRing - 2) + { + for (int vi = mesh.vert.size() - segments, ti = mesh.tvert[0].size() - segments - 1; vi < mesh.vert.size(); ++vi, ++ti) + { + face.v[0] = mesh.vert.size(); + face.v[1] = vi; + face.v[2] = vi + 1; + + if (vi == mesh.vert.size() - 1) + face.v[2] = mesh.vert.size() - segments; + + tface.t[0] = mesh.tvert[0].size(); + tface.t[1] = ti; + tface.t[2] = ti + 1; + + mesh.face.push_back(face); + mesh.tface[0].push_back(tface); + } + } + } + + // set colors + mesh.cvert.resize(1); + mesh.cvert[0] = col; + + mesh.cface.resize(mesh.face.size()); + for (int fi = 0; fi < mesh.face.size(); ++fi) + { + mesh.cface[fi].t[0] = 0; + mesh.cface[fi].t[1] = 0; + mesh.cface[fi].t[2] = 0; + } + + mesh.vert.shrink_to_fit(); + mesh.face.shrink_to_fit(); + mesh.tface[0].shrink_to_fit(); + mesh.facenorm.shrink_to_fit(); + + mesh.calc_ngr(); + mesh.calc_vertnorms(); +} + +static int get_cos_power_from_ang(real alfa, real part, real &real_part) +{ + const int maxDegree = 100000; + real alfaIters[(maxDegree - 1) / 2], oneIters[(maxDegree - 1) / 2], zeroIters[(maxDegree - 1) / 2]; + int d = 0; + int k = 0; + for (d = 1; d < maxDegree; d += 2) + { + real zeroIter = 0; + real oneIter = square_rec(d, 1, d > 1 ? &oneIters[(d - 3) / 2] : NULL); + real alfaIter = square_rec(d, sin(alfa), d > 1 ? &alfaIters[(d - 3) / 2] : NULL); + alfaIters[k] = alfaIter; + oneIters[k] = oneIter; + zeroIters[k] = zeroIter; + k++; + real_part = (alfaIter - zeroIter) / (oneIter - zeroIter); + if (real_part > part) + break; + } + return d; +} +static real square_rec(int iter_no, real val, real *hashed_iter) +{ + if (iter_no == 1) + return val; + real mulRez = 1; + real mul = 1 - val * val; + for (int i = 0; i < (iter_no - 1) / 2; i++) + mulRez *= mul; + if (hashed_iter) + return (val * mulRez - (1 - iter_no) * (*hashed_iter)) / iter_no; + else + return (val * mulRez - (1 - iter_no) * square_rec(iter_no - 2, val, NULL)) / iter_no; +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlLight.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlLight.h new file mode 100644 index 000000000..719ecefcf --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlLight.h @@ -0,0 +1,117 @@ +#pragma once + +#include + +class HmapLandObjectEditor; +class GeomObject; +class MaterialData; +class StaticGeometryContainer; +class StaticGeometryMaterial; +struct Color4; + +static constexpr unsigned CID_SphereLightObject = 0xD04E90D9u; // SphereLightObject + +// +// Entity object placed on landscape +// +class SphereLightObject : public RenderableEditableObject +{ +public: + SphereLightObject(); + + virtual void update(float) {} + virtual void beforeRender() {} + virtual void render(); + virtual void renderTrans(); + + virtual bool isSelectedByRectangle(IGenViewportWnd *vp, const EcRect &rect) const; + virtual bool isSelectedByPointClick(IGenViewportWnd *vp, int x, int y) const; + virtual bool getWorldBox(BBox3 &box) const; + + virtual void fillProps(PropPanel2 &op, DClassID for_class_id, dag::ConstSpan objects); + + virtual void onPPChange(int pid, bool edit_finished, PropPanel2 &panel, dag::ConstSpan objects); + + virtual void save(DataBlock &blk); + virtual void load(const DataBlock &blk); + + virtual bool mayRename() { return true; } + virtual bool mayDelete() { return true; } + virtual void setWtm(const TMatrix &wtm); + + virtual void onRemove(ObjectEditor *); + virtual void onAdd(ObjectEditor *objEditor); + + virtual bool setPos(const Point3 &p); + + virtual void putMoveUndo(); + + virtual void onObjectNameChange(RenderableEditableObject *obj, const char *old_name, const char *new_name) {} + + EO_IMPLEMENT_RTTI(CID_SphereLightObject) + + UndoRedoObject *makePropsUndoObj() { return new UndoPropsChange(this); } + SphereLightObject *clone(); + + struct Props + { + E3DCOLOR color; + real brightness; + E3DCOLOR ambColor; + real ambBrightness; + real ang; + bool directional; + + int segments; + + void defaults(); + }; + + const Props &getProps() const { return props; } + void setProps(const Props &p) + { + props = p; + propsChanged(); + } + + void propsChanged(); + void renderObject(); + + void buildGeom(); + void gatherGeom(StaticGeometryContainer &container) const; + + + static int lightGeomSubtype; + + static void clearMats(); + static MaterialData *makeMat(const char *class_name, const Color4 &emis, const Color4 &amb_emis, real power); + static StaticGeometryMaterial *makeMat2(const char *class_name, const Color4 &emis, const Color4 &amb_emis, real power); + +protected: + Props props; + GeomObject *ltGeom; + + ~SphereLightObject(); + + class UndoPropsChange : public UndoRedoObject + { + Ptr obj; + SphereLightObject::Props oldProps, redoProps; + + public: + UndoPropsChange(SphereLightObject *o) : obj(o) { oldProps = redoProps = obj->props; } + + virtual void restore(bool save_redo) + { + if (save_redo) + redoProps = obj->props; + obj->setProps(oldProps); + } + + virtual void redo() { obj->setProps(redoProps); } + + virtual size_t size() { return sizeof(*this); } + virtual void accepted() {} + virtual void get_description(String &s) { s = "UndoLightPropsChange"; } + }; +}; diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlLmeshHtConstrMask.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlLmeshHtConstrMask.cpp new file mode 100644 index 000000000..2712a9210 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlLmeshHtConstrMask.cpp @@ -0,0 +1,219 @@ +#include "hmlPlugin.h" +#include +#include +#include "hmlSplineObject.h" +#include "hmlSplinePoint.h" +// #include +#include +#include +#include +#include "editorLandRayTracer.h" + +static const float BITMASK_SCALE = 0.25; + +typedef HierBitMap2d>> HugeBitmask; +static HugeBitmask *bmLmeshHtConstr = NULL; + +static bool replaceBitmask(HugeBitmask *&dest, HugeBitmask *bm, IBBox2 &out_bb) +{ + if (!bm && !dest) + return false; + + int w = bm ? bm->getW() : 0, h = bm ? bm->getH() : 0; + if (dest && dest->getW() == w && dest->getH() == h) + { + IBBox2 bb; + if (!bm->compare(*dest, 0, 0, bb[0].x, bb[0].y, bb[1].x, bb[1].y)) + return false; + + out_bb = bb; + } + else if (!dest && bm) + { + IBBox2 bb; + bm->addSetBitsMinMax(0, 0, bb[0].x, bb[0].y, bb[1].x, bb[1].y); + out_bb = bb; + } + else + { + out_bb[0].x = 0; + out_bb[0].y = 0; + out_bb[1].x = w - 1; + out_bb[1].y = h - 1; + } + + del_it(dest); + dest = bm; + return true; +} + +bool HmapLandPlugin::rebuildHtConstraintBitmask() +{ + if (exportType != EXPORT_LANDMESH) + { + del_it(bmLmeshHtConstr); + return false; + } + + int t0 = get_time_msec(); + BezierSpline2d s2d_src; + float sx = BITMASK_SCALE, sy = BITMASK_SCALE; + int w = sx * gridCellSize * heightMap.getMapSizeX(); + int h = sy * gridCellSize * heightMap.getMapSizeY(); + HugeBitmask *bm = new HugeBitmask(w, h); + bool any_spline = false; + int spl_count = 0; + + for (int i = 0; i < objEd.splinesCount(); i++) + { + SplineObject *sobj = objEd.getSpline(i); + if (sobj->isPoly()) + continue; + + sobj->getSplineXZ(s2d_src); + BezierSplinePrec2d &s2d = toPrecSpline(s2d_src); + + const splineclass::AssetData *a = sobj->points[0]->getSplineClass(); + int seg = 0; + int hw = (a && a->lmeshHtConstrSweepWidth > 0) ? int(a->lmeshHtConstrSweepWidth / 2 / sx) : -1; + + float splineLen = s2d.getLength(), st; + bool has_width = false; + + for (float s = 0.0; s < splineLen; s += 0.5 / sx) + { + float st; + int n_seg = s2d.findSegment(s, st); + if (seg != n_seg) + { + a = sobj->points[n_seg]->getSplineClass(); + hw = (a && a->lmeshHtConstrSweepWidth > 0) ? int(a->lmeshHtConstrSweepWidth / 2 / sx) : -1; + seg = n_seg; + if (hw >= 0) + has_width = true; + } + if (hw < 0) + continue; + + Point2 p = s2d.segs[n_seg].point(st); + Point2 t = normalize(s2d.segs[n_seg].tang(st)); + Point2 n(t.y * sx * 0.5, -t.x * sy * 0.5); + for (int i = -hw; i <= hw; i++) + { + int px = (p.x - heightMapOffset.x) * sx + n.x * i; + int py = (p.y - heightMapOffset.y) * sy + n.y * i; + if (px >= 0 && py >= 0 && px < w && py < h) + bm->set(px, py); + } + } + if (has_width) + { + spl_count++; + any_spline = true; + } + } + t0 = get_time_msec() - t0; + DAEDITOR3.conRemark("rebuilt map %dx%d of %d/%d splines for %dms", bm->getW(), bm->getH(), spl_count, objEd.splinesCount(), t0); + + if (!any_spline) + del_it(bm); + + t0 = get_time_msec(); + IBBox2 b; + if (replaceBitmask(bmLmeshHtConstr, bm, b)) + { + DAEDITOR3.conRemark("new lmesh ht constr map differs (%d,%d)-(%d,%d), compared for %dms", b[0].x, b[0].y, b[1].x, b[1].y, + get_time_msec() - t0); + + if (bm) + { + b[0].x = b[0].x * landClsMap.getMapSizeX() / (sx * gridCellSize * heightMap.getMapSizeX()); + b[0].y = b[0].y * landClsMap.getMapSizeY() / (sy * gridCellSize * heightMap.getMapSizeY()); + b[1].x = b[1].x * landClsMap.getMapSizeX() / (sx * gridCellSize * heightMap.getMapSizeX()); + b[1].y = b[1].y * landClsMap.getMapSizeY() / (sy * gridCellSize * heightMap.getMapSizeY()); + } + else + { + b[0].x = 0; + b[0].y = 0; + b[1].x = landClsMap.getMapSizeX(); + b[1].y = landClsMap.getMapSizeY(); + } + return true; + } + + DAEDITOR3.conRemark("new lmesh ht constr map is the same, compared for %dms", get_time_msec() - t0); + return false; +} + +bool HmapLandPlugin::applyHtConstraintBitmask(Mesh &mesh) +{ + if (!bmLmeshHtConstr) + return false; + + int t0 = get_time_msec(); + + float sx = BITMASK_SCALE, sy = BITMASK_SCALE; + int w = sx * gridCellSize * heightMap.getMapSizeX(); + int h = sy * gridCellSize * heightMap.getMapSizeY(); + float aboveHt = meshErrorThreshold * 4; + Tab vshift(tmpmem); + vshift.resize(mesh.vert.size()); + mem_set_0(vshift); + bool changed = false; + exportType = -1; + for (int y = 0; y < h; y++) + for (int x = 0; x < w; x++) + if (bmLmeshHtConstr->get(x, y)) + { + Point3 p(heightMapOffset.x + x / sx, 0, heightMapOffset.y + y / sy); + float t = aboveHt; + getHeightmapPointHt(p, NULL); + p.y += t; + + // int fi = rt.traceray(p, Point3(0,-1,0), t); + + float htOther; + int fi = landMeshMap.getEditorLandRayTracer()->traceDownFaceVec(p, htOther, NULL); + + if (fi < 0) + continue; + if (htOther > p.y || htOther < p.y - aboveHt) + continue; + fi /= 3; + + // compute barycentric coordinates + const uint32_t *vi = mesh.face[fi].v; + Point3 &v1 = mesh.vert[vi[0]], &v2 = mesh.vert[vi[1]], &v3 = mesh.vert[vi[2]]; + + float dx = p.x - v3.x, dz = p.z - v3.z; + float m11 = v1.x - v3.x, m12 = v2.x - v3.x, m21 = v1.z - v3.z, m22 = v2.z - v3.z; + float invdet = 1.0 / (m11 * m22 - m12 * m21); + float l1 = invdet * (m22 * dx - m12 * dz); + float l2 = invdet * (-m21 * dx + m11 * dz); + float l3 = 1 - l1 - l2; + + float lsq = l1 * l1 + l2 * l2 + l3 * l3; + + float dy1 = (t - aboveHt) * l1 / lsq; + float dy2 = (t - aboveHt) * l2 / lsq; + float dy3 = (t - aboveHt) * l3 / lsq; + if (vshift[vi[0]] > dy1) + vshift[vi[0]] = dy1; + if (vshift[vi[1]] > dy2) + vshift[vi[1]] = dy2; + if (vshift[vi[2]] > dy3) + vshift[vi[2]] = dy3; + changed = true; + // debug("diff %.2f at (%d,%d), " FMT_P3 " " FMT_P3 "", + // t-aboveHt, x, y, l1, l2, l3, vshift[vi[0]], vshift[vi[1]], vshift[vi[2]]); + } + exportType = EXPORT_LANDMESH; + DAEDITOR3.conRemark("height constraints applied to landmesh for %dms", get_time_msec() - t0); + if (!changed) + return false; + for (int i = 0; i < mesh.vert.size(); i++) + mesh.vert[i].y += vshift[i]; + + return true; +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlMain.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlMain.cpp new file mode 100644 index 000000000..14fd22a50 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlMain.cpp @@ -0,0 +1,59 @@ +#include "hmlPlugin.h" +#include +#include +#include +#include + +bool HmapLandPlugin::defMipOrdRev = false; +bool HmapLandPlugin::preferZstdPacking = false; +bool HmapLandPlugin::allowOodlePacking = false; + +//================================================================================================== +BOOL __stdcall DllMain(HINSTANCE instance, DWORD reason, void *) +{ + if (reason == DLL_PROCESS_DETACH && HmapLandPlugin::self) + delete HmapLandPlugin::self; + + return TRUE; +} + + +//================================================================================================== +extern "C" int __fastcall get_plugin_version() { return IGenEditorPlugin::VERSION_1_1; } + + +//================================================================================================== +extern "C" IGenEditorPlugin *__fastcall register_plugin(IDagorEd2Engine &editor) +{ + daeditor3_init_globals(editor); + + DataBlock app_blk(DAGORED2->getWorkspace().getAppPath()); + const char *mgr_type = app_blk.getBlockByNameEx("projectDefaults")->getBlockByNameEx("hmap")->getStr("type", NULL); +#if defined(USE_HMAP_ACES) + if (!mgr_type || strcmp(mgr_type, "aces") != 0) + return NULL; +#else + if (mgr_type && strcmp(mgr_type, "classic") != 0) + return NULL; +#endif + + if (!HmapLandPlugin::prepareRequiredServices()) + return NULL; + + if (DAGORED2->getPluginByName("bin_scene_view")) + { + DAEDITOR3.conError("\"%s\" is not compatible with already inited \"%s\", skipped", "Landscape", "Scene view"); + return NULL; + } + + ddsx::ConvertParams cp; + HmapLandPlugin::defMipOrdRev = app_blk.getBlockByNameEx("projectDefaults")->getBool("defDDSxMipOrdRev", cp.mipOrdRev); + HmapLandPlugin::preferZstdPacking = app_blk.getBlockByNameEx("projectDefaults")->getBool("preferZSTD", false); + if (HmapLandPlugin::preferZstdPacking) + debug("landscape prefers ZSTD"); + HmapLandPlugin::allowOodlePacking = app_blk.getBlockByNameEx("projectDefaults")->getBool("allowOODLE", false); + if (HmapLandPlugin::allowOodlePacking) + debug("landscape allows OODLE"); + + return ::new (inimem) HmapLandPlugin; +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlModifiers.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlModifiers.cpp new file mode 100644 index 000000000..36e3caa68 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlModifiers.cpp @@ -0,0 +1,334 @@ +#include "hmlPlugin.h" +#include "hmlSplineObject.h" + +#include +#include +#include +#include + +bool guard_det_border = false; + +bool HmapLandPlugin::applyHmModifiers1(HeightMapStorage &hm, float gc_sz, bool gen_colors, bool reset_final, IBBox2 *out_dirty_clip, + IBBox2 *out_sum_dirty, bool *out_colors_changed) +{ + if (!hm.changed && hm.srcChanged.isEmpty()) + return false; + + IBBox2 dirty_clip = hm.srcChanged; + int mapSizeX = hm.getMapSizeX(); + int mapSizeY = hm.getMapSizeY(); + bool colors_changed = false; + + if (hm.changed) + { + dirty_clip += IPoint2(0, 0); + dirty_clip += IPoint2(mapSizeX - 1, mapSizeY - 1); + } + if (&hm == &heightMapDet) + { + detRectC.clipBox(dirty_clip); + if (reset_final && guard_det_border) + { + IBBox2 detRectCI; + detRectCI = detRectC; + detRectCI[0].x += detDivisor * 2; + detRectCI[0].y += detDivisor * 2; + detRectCI[1].x -= detDivisor * 2; + detRectCI[1].y -= detDivisor * 2; + detRectCI.clipBox(dirty_clip); + } + } + + if (dirty_clip[0].x < 0) + dirty_clip[0].x = 0; + if (dirty_clip[0].y < 0) + dirty_clip[0].y = 0; + if (dirty_clip[1].x > mapSizeX - 1) + dirty_clip[1].x = mapSizeX - 1; + if (dirty_clip[1].y > mapSizeY - 1) + dirty_clip[1].y = mapSizeY - 1; + if (dirty_clip.isEmpty()) + return false; + + hm.changed = false; + hm.srcChanged.setEmpty(); + + int x, y; + int wss = waterMaskScale, wsd = &hm == &heightMapDet ? detDivisor : 1; + + if (reset_final && hasWaterSurface && waterMask.getW() && waterMask.getH()) + { + float max_bottom_h = waterSurfaceLevel - minUnderwaterBottomDepth; + for (y = dirty_clip[1].y; y >= dirty_clip[0].y; --y) + { + for (x = dirty_clip[0].x; x <= dirty_clip[1].x; ++x) + { + float h = hm.getInitialData(x, y); + hm.setFinalData(x, y, waterMask.get(x * wss / wsd, y * wss / wsd) && h > max_bottom_h ? max_bottom_h : h); + } + } + } + else if (reset_final) + for (y = dirty_clip[1].y; y >= dirty_clip[0].y; --y) + for (x = dirty_clip[0].x; x <= dirty_clip[1].x; ++x) + hm.resetFinalData(x, y); + + IBBox2 sum_dirty; + for (x = 0; x < objEd.splinesCount(); x++) + { + SplineObject *spline = objEd.getSpline(x); + if (spline->isAffectingHmap()) + { + IBBox2 dirty; + + spline->applyHmapModifier(hm, heightMapOffset, gc_sz, dirty, dirty_clip); + + if (!gen_colors) + continue; + + dirty_clip.clipBox(dirty); + if (dirty.isEmpty()) + continue; + + sum_dirty += dirty; + colors_changed = true; + } + } + + if (hasWaterSurface && waterMask.getW() && waterMask.getH()) + { + float max_bottom_h = waterSurfaceLevel - minUnderwaterBottomDepth; + for (y = dirty_clip[1].y; y >= dirty_clip[0].y; --y) + { + for (x = dirty_clip[0].x; x <= dirty_clip[1].x; ++x) + { + float h = heightMap.getFinalData(x, y); + if (waterMask.get(x * wss / wsd, y * wss / wsd) && h > max_bottom_h) + heightMap.setFinalData(x, y, max_bottom_h); + } + } + } + updateHeightMapTex(&hm == &heightMapDet, &dirty_clip); + + if (out_colors_changed) + *out_colors_changed = colors_changed; + if (out_dirty_clip) + *out_dirty_clip = dirty_clip; + if (out_sum_dirty) + *out_sum_dirty = sum_dirty; + return true; +} + +void HmapLandPlugin::applyHmModifiers(bool gen_colors, bool reset_final, bool finished) +{ + bool colors_changed = false; + IBBox2 dirty_clip, sum_dirty; + int64_t reft = ref_time_ticks_qpc(); + + bool changed_main = applyHmModifiers1(heightMap, gridCellSize, gen_colors, reset_final, &dirty_clip, &sum_dirty, &colors_changed); + bool changed_det = + !detDivisor ? false : applyHmModifiers1(heightMapDet, gridCellSize / detDivisor, false, reset_final, NULL, NULL, NULL); + + if (get_time_usec_qpc(reft) > 1000000) + DAEDITOR3.conWarning("applyHmModifiers(gen_colors=%d, reset_final=%d, finished=%d) took %.1f sec to process %@", (int)gen_colors, + (int)reset_final, (int)finished, get_time_usec_qpc(reft) / 1e6, sum_dirty); + if (!changed_main && !changed_det) + return; + + if (colors_changed) + { + generateLandColors(&sum_dirty); + recalcLightingInRect(sum_dirty); + // resetRenderer(); + hmlService->invalidateClipmap(false); + DAGORED2->invalidateViewportCache(); + } + if (finished) + onLandRegionChanged(dirty_clip[0].x * lcmScale, dirty_clip[0].y * lcmScale, dirty_clip[1].x * lcmScale, dirty_clip[1].y * lcmScale, + false, finished); +} + +void HmapLandPlugin::invalidateFinalBox(const BBox3 &box) +{ + IBBox2 box2(IPoint2(floor((box[0].x - heightMapOffset.x) / gridCellSize), floor((box[0].z - heightMapOffset.y) / gridCellSize)), + IPoint2(ceil((box[1].x - heightMapOffset.x) / gridCellSize), ceil((box[1].z - heightMapOffset.y) / gridCellSize))); + heightMap.srcChanged += box2; + if (detDivisor) + { + box2[0] *= detDivisor; + box2[1] *= detDivisor; + detRectC.clipBox(box2); + heightMapDet.srcChanged += box2; + } +} + +struct UndoCollapse : public UndoRedoObject +{ + PtrTab spl; + struct HmapHeights + { + HmapBitmap bmp; + Tab oldHt, newHt; + HeightMapStorage *stor; + } hmap[2]; + + UndoCollapse(HeightMapStorage *hmap_main, HeightMapStorage *hmap_det, dag::ConstSpan _spl) + { + spl.Tab>::operator=(make_span_const((const Ptr *)_spl.data(), _spl.size())); + hmap[0].stor = hmap_main; + hmap[1].stor = hmap_det; + for (int i = 0; i < 2; i++) + if (hmap[i].stor) + hmap[i].bmp.resize(hmap[i].stor->getMapSizeX(), hmap[i].stor->getMapSizeY()); + } + void finalizeChanges(const IBBox2 coll_area[2], bool use_bmp) + { + for (int i = 0; i < 2; i++) + { + HmapHeights &hh = hmap[i]; + if (!hh.stor) + continue; + int map_x = hh.stor->getMapSizeX(), map_y = hh.stor->getMapSizeY(); + IBBox2 bb = coll_area[i]; + if (bb[1].x + 1 < map_x) + bb[1].x++; + if (bb[1].y + 1 < map_y) + bb[1].y++; + + hh.oldHt.reserve(bb.width().x * bb.width().y); + hh.newHt.reserve(bb.width().x * bb.width().y); + for (int y = bb[0].y; y < bb[1].y; y++) + for (int x = bb[0].x; x < bb[1].x; x++) + { + if (use_bmp && !hh.bmp.get(x, y)) + continue; + if (!use_bmp && hh.stor->getInitialData(x, y) == hh.stor->getFinalData(x, y)) + continue; + + hh.bmp.set(x, y); + hh.oldHt.push_back(hh.stor->getInitialData(x, y)); + hh.newHt.push_back(hh.stor->getFinalData(x, y)); + hh.stor->setInitialData(x, y, hh.stor->getFinalData(x, y)); + } + hh.oldHt.shrink_to_fit(); + hh.newHt.shrink_to_fit(); + } + + for (int i = 0; i < spl.size(); i++) + { + if (spl[i]->isPoly()) + spl[i]->setPolyHmapAlign(false); + else + spl[i]->setModifType(MODIF_NONE); + } + } + + virtual void restore(bool save_redo) + { + for (int i = 0; i < 2; i++) + { + HmapHeights &hh = hmap[i]; + if (!hh.stor) + continue; + for (int y = 0, ord = 0; y < hh.stor->getMapSizeY(); y++) + for (int x = 0; x < hh.stor->getMapSizeX(); x++) + if (hh.bmp.get(x, y)) + hh.stor->setInitialData(x, y, hh.oldHt[ord++]); + } + for (int i = 0; i < spl.size(); i++) + { + if (spl[i]->isPoly()) + spl[i]->setPolyHmapAlign(true); + else + spl[i]->setModifType(MODIF_HMAP); + } + HmapLandPlugin::self->invalidateObjectProps(); + } + + virtual void redo() + { + for (int i = 0; i < 2; i++) + { + HmapHeights &hh = hmap[i]; + if (!hh.stor) + continue; + for (int y = 0, ord = 0; y < hh.stor->getMapSizeY(); y++) + for (int x = 0; x < hh.stor->getMapSizeX(); x++) + if (hh.bmp.get(x, y)) + hh.stor->setInitialData(x, y, hh.newHt[ord++]); + } + for (int i = 0; i < spl.size(); i++) + { + if (spl[i]->isPoly()) + spl[i]->setPolyHmapAlign(false); + else + spl[i]->setModifType(MODIF_NONE); + } + HmapLandPlugin::self->invalidateObjectProps(); + } + + virtual size_t size() + { + return data_size(spl) + data_size(hmap[0].oldHt) + data_size(hmap[0].newHt) + data_size(hmap[1].oldHt) + data_size(hmap[1].newHt); + } + virtual void accepted() {} + virtual void get_description(String &s) { s = "UndoCollapse"; } +}; + +void HmapLandPlugin::copyFinalHmapToInitial() +{ + Tab spl; + for (int i = 0; i < objEd.objectCount(); i++) + if (SplineObject *o = RTTI_cast(objEd.getObject(i))) + if (o->isAffectingHmap()) + spl.push_back(o); + + objEd.getUndoSystem()->begin(); + UndoCollapse *undo = new UndoCollapse(&heightMap, &heightMapDet, spl); + + IBBox2 collArea[2]; + collArea[0][0].set(0, 0); + collArea[0][1].set(heightMap.getMapSizeX(), heightMap.getMapSizeY()); + collArea[1] = detRectC; + undo->finalizeChanges(collArea, false); + + objEd.getUndoSystem()->put(undo); + objEd.getUndoSystem()->accept("Copy final HMAP to initial"); + + updateHeightMapTex(false); + if (detDivisor) + updateHeightMapTex(true); +} + +void HmapLandPlugin::collapseModifiers(dag::ConstSpan collapse_splines) +{ + UndoCollapse *undo = new UndoCollapse(&heightMap, &heightMapDet, collapse_splines); + objEd.getUndoSystem()->begin(); + + IBBox2 collArea[2]; + int hw = heightMap.getMapSizeX(); + int hh = heightMap.getMapSizeY(); + + for (int i = 0; i < collapse_splines.size(); i++) + { + IBBox2 dirty; + collapse_splines[i]->applyHmapModifier(heightMap, heightMapOffset, gridCellSize, dirty, + IBBox2(IPoint2(0, 0), IPoint2(hw - 1, hh - 1)), &undo->hmap[0].bmp); + collArea[0] += dirty; + + if (detDivisor) + { + collapse_splines[i]->applyHmapModifier(heightMapDet, heightMapOffset, gridCellSize / detDivisor, dirty, detRectC, + &undo->hmap[1].bmp); + collArea[1] += dirty; + } + } + + undo->finalizeChanges(collArea, true); + objEd.getUndoSystem()->put(undo); + objEd.getUndoSystem()->accept("Collapse modifier(s)"); + + updateHeightMapTex(false, &collArea[0]); + if (detDivisor) + updateHeightMapTex(true, &collArea[1]); +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlObject.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlObject.cpp new file mode 100644 index 000000000..34890b290 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlObject.cpp @@ -0,0 +1,2234 @@ +#include "hmlPlugin.h" +#include "hmlSplineObject.h" +#include "hmlSplinePoint.h" +#include "hmlEntity.h" +#include "hmlLight.h" +#include "hmlSnow.h" +#include "entityCopyDlg.h" + +#include "hmlObjectsEditor.h" +#include "hmlHoleObject.h" +#include "roadUtil.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include <3d/dag_drv3d.h> +#include +#include +#include + +#include "crossRoad.h" +#include "hmlCm.h" +#include "common.h" + +#include +#include + +#include +#include + +#define OBJECT_SPLINE "Splines" +#define OBJECT_POLYGON "Polygons" +#define OBJECT_ENTITY "Entities" +#define OBJECT_LIGHT "Sphere lights" +#define OBJECT_SNOW "Snow sources" + +int HmapLandObjectEditor::geomBuildCntLoft = 0; +int HmapLandObjectEditor::geomBuildCntPoly = 0; +int HmapLandObjectEditor::geomBuildCntRoad = 0; +int HmapLandObjectEditor::waterSurfSubtypeMask = -1; + + +extern objgenerator::WorldHugeBitmask bm_loft_mask[LAYER_ORDER_MAX], bm_poly_mask; + +static TEXTUREID signTexPt = BAD_TEXTUREID; + + +#define CROSSROADS_TRACE_GEOM 0 + +#define TRACE_CACHE_CELL_SIZE 256 +#define TRACE_CACHE_CELL_SIZE_INV (1.f / TRACE_CACHE_CELL_SIZE) +#define TRACE_CACHE_EXTENSION (TRACE_CACHE_CELL_SIZE / 4) + +struct TraceSplineCache +{ + void *arrayPtr; + int arrayCount; + Tab cached; + int ix, iz; + float dist; + + TraceSplineCache() { reset(); } + + void reset() + { + arrayPtr = nullptr; + arrayCount = VERY_BIG_NUMBER; + cached.clear(); + ix = VERY_BIG_NUMBER; + iz = VERY_BIG_NUMBER; + } + + bool build(const Tab &splines, const Point3 &p, const Point3 &dir) + { + if (splines.size() < 50) + return false; + + bool valid = SplineObject::isSplineCacheValid && ((void *)splines.data() == arrayPtr && splines.size() == arrayCount); + int x = 0; + int z = 0; + if (valid) + { + x = int(floorf(p.x * TRACE_CACHE_CELL_SIZE_INV)); + z = int(floorf(p.z * TRACE_CACHE_CELL_SIZE_INV)); + valid = (x == ix && z == iz); + } + + if (valid) + return true; + + reset(); + + BBox3 cellBox( + Point3(x * TRACE_CACHE_CELL_SIZE - TRACE_CACHE_EXTENSION, -VERY_BIG_NUMBER, z * TRACE_CACHE_CELL_SIZE - TRACE_CACHE_EXTENSION), + Point3((x + 1) * TRACE_CACHE_CELL_SIZE + TRACE_CACHE_EXTENSION, VERY_BIG_NUMBER, + (z + 1) * TRACE_CACHE_CELL_SIZE + TRACE_CACHE_EXTENSION)); + + ix = x; + iz = z; + arrayPtr = (void *)splines.data(); + arrayCount = splines.size(); + + for (int i = 0; i < splines.size(); i++) + if (splines[i]->isCreated()) + { + if (splines[i]->getSplineBox() & cellBox) + cached.push_back(splines[i]); + } + + SplineObject::isSplineCacheValid = true; + return true; + } +} spline_cache; + + +HmapLandObjectEditor::HmapLandObjectEditor() : + inGizmo(false), + splines(midmem_ptr()), + cloneMode(false), + crossRoads(midmem), + loftGeomCollider(true, *this), + polyGeomCollider(false, *this), + nearSources(tmpmem), + cloneObjs(midmem) +{ + waterGeom = NULL; + objCreator = NULL; + areLandHoleBoxesVisible = true; + hideSplines = false; + autoUpdateSpline = true; + maxPointVisDist = 5000.0; + + memset(catmul, 0, sizeof(catmul)); + clear_and_shrink(splines); + ptDynBuf = dagRender->newDynRenderBuffer("editor_rhv_tex", midmem); + + SplinePointObject::initStatics(); + if (signTexPt == BAD_TEXTUREID) + { + signTexPt = dagRender->addManagedTexture(::make_full_start_path("../commonData/tex/sign.tga")); + dagRender->acquireManagedTex(signTexPt); + } + + curPt = NULL; + curSpline = NULL; + generationCount = 0; + + selectMode = -1; + __super::setEditMode(CM_OBJED_MODE_SELECT); + + debugP1 = debugP2 = NULL; + + crossRoadsChanged = true; + + IAssetService *assetSrv = DAGORED2->queryEditorInterface(); + if (assetSrv) + assetSrv->subscribeUpdateNotify(this, true, true); + + setSuffixDigitsCount(3); + nearSources.reserve(SnowSourceObject::NEAR_SRC_COUNT); + + if (waterSurfSubtypeMask == -1) + waterSurfSubtypeMask = 1 << IDaEditor3Engine::get().registerEntitySubTypeId("water_surf"); + + shaders::OverrideState zFuncLessState; + zFuncLessState.set(shaders::OverrideState::Z_FUNC); + zFuncLessState.zFunc = CMPF_LESS; + zFuncLessStateId = dagGeom->create(zFuncLessState); +} + + +HmapLandObjectEditor::~HmapLandObjectEditor() +{ + IAssetService *assetSrv = DAGORED2->queryEditorInterface(); + if (assetSrv) + assetSrv->unsubscribeUpdateNotify(this, true, true); + + dagGeom->deleteGeomObject(waterGeom); + dagRender->deleteDynRenderBuffer(ptDynBuf); + setCreateBySampleMode(NULL); + selectNewObjEntity(NULL); + + dagGeom->destroy(zFuncLessStateId); +} + +void HmapLandObjectEditor::clearToDefaultState() +{ + setCreateBySampleMode(NULL); + selectNewObjEntity(NULL); + del_it(objCreator); + + inGizmo = false; + areLandHoleBoxesVisible = true; + + memset(catmul, 0, sizeof(catmul)); + + SplinePointObject::initStatics(); + SphereLightObject::clearMats(); + SnowSourceObject::clearMats(); + + curPt = NULL; + curSpline = NULL; + + selectMode = -1; +} + +CPanelWindow *HmapLandObjectEditor::getCurrentPanelFor(RenderableEditableObject *obj) +{ + if (selectedCount() != 1 || getSelected(0) != obj || !objectPropBar) + return NULL; + return objectPropBar->getPanel(); +} + +void HmapLandObjectEditor::fillToolBar(PropertyContainerControlBase *toolbar) +{ + PropertyContainerControlBase *tb1 = toolbar->createToolbarPanel(0, ""); + + addButton(tb1, CM_SHOW_PANEL, "show_hml_panel", "Show properties panel (P)", true); + // addButton(tb1, CM_SHOW_LAND_OBJECTS, "show_bounds", "Show land hole boxes", true); + tb1->createSeparator(); + + addButton(tb1, CM_HILL_UP, "terr_up_vertex", "Hill up mode (1)", true); + addButton(tb1, CM_HILL_DOWN, "terr_down_vertex", "Hill down mode (2)", true); + addButton(tb1, CM_ALIGN, "terr_align", "Align mode (3)", true); + addButton(tb1, CM_SMOOTH, "terr_smooth", "Smooth mode (4)", true); + if (hasLightmapTex) + addButton(tb1, CM_SHADOWS, "terr_light", "Calculate lighting mode (5)", true); + addButton(tb1, CM_SCRIPT, "terr_script", "Apply script (6)", true); + tb1->createSeparator(); + + __super::fillToolBar(toolbar); + + PropertyContainerControlBase *tb2 = toolbar->createToolbarPanel(0, ""); + + tb2->createSeparator(); + addButton(tb2, CM_LAYERS_DLG, "layers", "Show/hide layers dialog", true); + addButton(tb2, CM_HIDE_SPLINES, "hide_splines", "Hide splines (Ctrl+0)", true); + tb2->createSeparator(); + addButton(tb2, CM_SELECT_PT, "select_vertex", "Select only points (Ctrl+1)", true); + addButton(tb2, CM_SELECT_SPLINES, "select_spline", "Select only splines (Ctrl+2)", true); + addButton(tb2, CM_SELECT_ENT, "select_entity", "Select only entities (Ctrl+3)", true); + addButton(tb2, CM_SELECT_SPL_ENT, "select_spl_ent", "Select only splines and entities (Ctrl+7)", true); + // addButton(tb2, CM_SELECT_LT, "select_lt", "Select only light spheres (Ctrl+4)", true); + if (HmapLandPlugin::self->isSnowAvailable()) + addButton(tb2, CM_SELECT_SNOW, "hide_multi_objects", "Select only snow sources (Ctrl+5)", true); + tb2->createSeparator(); + + // addButton(tb2, CM_CREATE_HOLEBOX_MODE, "create_holebox", "Create land hole box", true); + addButton(tb2, CM_CREATE_ENTITY, "create_lib_ent", "Create entity", true); + addButton(tb2, CM_ROTATION_NONE, "rotation_none", "No rotation", true); + addButton(tb2, CM_ROTATION_X, "rotation_x", "X to normal", true); + addButton(tb2, CM_ROTATION_Y, "rotation_y", "Y to normal", true); + addButton(tb2, CM_ROTATION_Z, "rotation_z", "Z to normal", true); + addButton(tb2, CM_CREATE_SPLINE, "create_spline", "Create spline (hold shift to place on RI)", true); + addButton(tb2, CM_CREATE_POLYGON, "create_poly", "Create polygon", true); + // addButton(tb2, CM_CREATE_LT, "create_lt", "Create light sphere", true); + if (HmapLandPlugin::self->isSnowAvailable()) + addButton(tb2, CM_CREATE_SNOW_SOURCE, "create_multi_object", "Create snow source", true); + tb2->createSeparator(); + + addButton(tb2, CM_REFINE_SPLINE, "spline_refine", "Refine spline", true); + addButton(tb2, CM_SPLIT_SPLINE, "split_spline", "Split spline", true); + addButton(tb2, CM_SPLIT_POLY, "split_poly", "Split poly", true); + + addButton(tb2, CM_REVERSE_SPLINE, "spline_reverse", "Reverse spline(s)"); + addButton(tb2, CM_CLOSE_SPLINE, "spline_close", "Close selected spline(s)"); + addButton(tb2, CM_OPEN_SPLINE, "spline_break", "Un-close spline at selected point"); + tb2->createSeparator(); + + addButton(tb2, CM_MANUAL_SPLINE_REGEN_MODE, "offline", "Use manual obj/geom update for spline/poly", true); + addButton(tb2, CM_SPLINE_REGEN, "compile", "Manual spline/poly obj/geom update (F1)"); + + setButton(CM_MANUAL_SPLINE_REGEN_MODE, !autoUpdateSpline); + enableButton(CM_SPLINE_REGEN, !autoUpdateSpline); + + addButton(tb2, CM_REBUILD_SPLINES_BITMASK, "splinemask", "Rebuild splines bitmask (F2)"); +} + +void HmapLandObjectEditor::updateToolbarButtons() +{ + __super::updateToolbarButtons(); + + setRadioButton(CM_SMOOTH, getEditMode()); + setRadioButton(CM_ALIGN, getEditMode()); + setRadioButton(CM_HILL_UP, getEditMode()); + setRadioButton(CM_HILL_DOWN, getEditMode()); + setRadioButton(CM_SHADOWS, getEditMode()); + setRadioButton(CM_SCRIPT, getEditMode()); + setRadioButton(CM_CREATE_SPLINE, getEditMode()); + setRadioButton(CM_REFINE_SPLINE, getEditMode()); + setRadioButton(CM_SPLIT_SPLINE, getEditMode()); + setRadioButton(CM_SPLIT_POLY, getEditMode()); + setRadioButton(CM_CREATE_POLYGON, getEditMode()); + setRadioButton(CM_CREATE_ENTITY, getEditMode()); + setButton(CM_ROTATION_NONE, buttonIdToPlacementRotation(CM_ROTATION_NONE) == selectedPlacementRotation); + setButton(CM_ROTATION_X, buttonIdToPlacementRotation(CM_ROTATION_X) == selectedPlacementRotation); + setButton(CM_ROTATION_Y, buttonIdToPlacementRotation(CM_ROTATION_Y) == selectedPlacementRotation); + setButton(CM_ROTATION_Z, buttonIdToPlacementRotation(CM_ROTATION_Z) == selectedPlacementRotation); + setRadioButton(CM_CREATE_HOLEBOX_MODE, getEditMode()); + setRadioButton(CM_CREATE_LT, getEditMode()); + setRadioButton(CM_CREATE_SNOW_SOURCE, getEditMode()); + setButton(CM_SHOW_LAND_OBJECTS, areLandHoleBoxesVisible); + setButton(CM_HIDE_SPLINES, hideSplines); + setButton(CM_MANUAL_SPLINE_REGEN_MODE, !autoUpdateSpline); + setButton(CM_LAYERS_DLG, layersDlg.isVisible()); + + if (HmapLandPlugin::self) + enableButton(CM_SPLINE_REGEN, !autoUpdateSpline); +} + + +void HmapLandObjectEditor::beforeRender() +{ + __super::beforeRender(); + + if (autoUpdateSpline) + updateSplinesGeom(); + else if (splinesChanged) + { + bool changed = false; + for (int i = 0; i < splines.size(); ++i) + if (splines[i]->modifChanged) + { + splines[i]->reApplyModifiers(false); + changed = true; + } + if (changed) + { + SplineObject::isSplineCacheValid = false; + HmapLandPlugin::self->applyHmModifiers(false, true, false); + HmapLandPlugin::hmlService->invalidateClipmap(false); + DAGORED2->invalidateViewportCache(); + } + } +} + +void HmapLandObjectEditor::updateSplinesGeom() +{ + static Tab chSpl(tmpmem); + + if (!splinesChanged && !crossRoadsChanged) + return; + + SplineObject::isSplineCacheValid = false; + HmapLandPlugin::hmlService->invalidateClipmap(false, false); + if (HmapLandPlugin::gpuGrassService) + HmapLandPlugin::gpuGrassService->invalidate(); + if (HmapLandPlugin::grassService) + HmapLandPlugin::grassService->forceUpdate(); + generationCount++; + geomBuildCntLoft = geomBuildCntPoly = geomBuildCntRoad = 0; + // DAEDITOR3.conNote("update %d", generationCount); + + if (crossRoadsChanged) + for (int i = 0; i < crossRoads.size(); ++i) + if (crossRoads[i]->checkCrossRoad()) + splinesChanged = true; + + if (splinesChanged) + { + for (int i = 0; i < splines.size(); ++i) + if (splines[i]->modifChanged) + splines[i]->reApplyModifiers(false); + HmapLandPlugin::self->applyHmModifiers(true, true, false); + + // first spline update stage: generate geometry + for (int i = 0; i < splines.size(); ++i) + if (splines[i]->splineChanged) + { + // DAEDITOR3.conNote("update spline %s, first pass", splines[i]->getName()); + chSpl.push_back(splines[i]); + splines[i]->updateSpline(SplineObject::STAGE_START); + } + + splinesChanged = false; + } + + if (crossRoadsChanged) + { + updateCrossRoadGeom(); + crossRoadsChanged = false; + } + + // last spline update stage: generate entities + for (int j = SplineObject::STAGE_START + 1; j <= SplineObject::STAGE_FINISH; j++) + { + if (j == SplineObject::STAGE_GEN_LOFT) + { + for (int layer = 0; layer < LAYER_ORDER_MAX; ++layer) + { + loftGeomCollider.setLoftLayer(layer); + for (int i = 0; i < chSpl.size(); ++i) + if (chSpl[i]->getLayer() == layer) + chSpl[i]->updateSpline(j); + } + loftGeomCollider.setLoftLayer(-1); + } + else + for (int i = 0; i < chSpl.size(); ++i) + chSpl[i]->updateSpline(j); + } + + BBox3 changedRegion; + + for (int i = 0; i < chSpl.size(); ++i) + changedRegion += chSpl[i]->getGeomBoxChanges(); + + chSpl.clear(); + + LandscapeEntityObject::rePlaceAllEntitiesOnCollision(*this, geomBuildCntLoft > 0, geomBuildCntPoly > 0, geomBuildCntRoad > 0, + changedRegion); +} + +void HmapLandObjectEditor::render() +{ + bool curPlugin = DAGORED2->curPlugin() == HmapLandPlugin::self; + int st_mask = IDaEditor3Engine::get().getEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_RENDER); + + TMatrix4 gtm; + d3d::getglobtm(gtm); + Frustum frustum; + frustum.construct(gtm); + int w, h; + d3d::get_target_size(w, h); + Point2 scale; + scale.x = 2.0 / w; + scale.y = 2.0 / h; + + if (curPlugin) + { + bool all = !hideSplines; + SplineObject *spl_of_sel_pt = NULL; + if (hideSplines) + for (int i = 0; i < selection.size(); ++i) + if (SplinePointObject *p = RTTI_cast(selection[i])) + { + spl_of_sel_pt = p->spline; + break; + } + + if ((st_mask & SphereLightObject::lightGeomSubtype) && all) + for (int i = 0; i < objects.size(); ++i) + { + SphereLightObject *l = RTTI_cast(objects[i]); + if (l) + l->render(); + } + + dagRender->startLinesRender(true, false, true); + dagRender->setLinesTm(TMatrix::IDENT); + for (int i = 0; i < splines.size(); ++i) + if (all || splines[i]->isSelected() || splines[i] == spl_of_sel_pt) + splines[i]->renderLines(false, frustum); + dagRender->endLinesRender(); + + dagRender->startLinesRender(); + for (int i = 0; i < splines.size(); ++i) + if (all || splines[i]->isSelected() || splines[i] == spl_of_sel_pt) + splines[i]->renderLines(true, frustum); + + if (debugP1 && debugP2) + dagRender->renderLine(*debugP1, *debugP2, E3DCOLOR(255, 0, 0)); + dagRender->endLinesRender(); + + dagRender->dynRenderBufferClearBuf(*ptDynBuf); + + + int cnt = 0; + for (int i = 0; i < splines.size(); ++i) + if (all || splines[i]->isSelected() || splines[i] == spl_of_sel_pt) + splines[i]->render(ptDynBuf, gtm, scale, frustum, cnt); + + if (curPt && curPt->visible) + SplinePointObject::renderPoint(*ptDynBuf, toPoint4(curPt->getPt(), 1) * gtm, scale * SplinePointObject::ptScreenRad, + E3DCOLOR(200, 200, 10)); + + dagGeom->set(zFuncLessStateId); + dagGeom->shaderGlobalSetInt(SplinePointObject::ptRenderPassId, 0); + dagRender->dynRenderBufferFlushToBuffer(*ptDynBuf, SplinePointObject::texPt); + dagGeom->reset_override(); + + dagGeom->shaderGlobalSetInt(SplinePointObject::ptRenderPassId, 1); + dagRender->dynRenderBufferFlushToBuffer(*ptDynBuf, SplinePointObject::texPt); + dagRender->dynRenderBufferFlush(*ptDynBuf); + + // render note signs + dagRender->dynRenderBufferClearBuf(*ptDynBuf); + if (!all) + goto end; + for (int i = 0; i < objects.size(); ++i) + { + LandscapeEntityObject *p = RTTI_cast(objects[i]); + if (p && !p->getProps().notes.empty()) + SplinePointObject::renderPoint(*ptDynBuf, toPoint4(p->getPos(), 1) * gtm, 3 * scale * SplinePointObject::ptScreenRad, + E3DCOLOR(50, 60, 255)); + } + for (int i = 0; i < splines.size(); ++i) + if (!splines[i]->getProps().notes.empty()) + SplinePointObject::renderPoint(*ptDynBuf, toPoint4(splines[i]->points[0]->getPos(), 1) * gtm, + 3 * scale * SplinePointObject::ptScreenRad, E3DCOLOR(50, 160, 255)); + + dagGeom->set(zFuncLessStateId); + dagGeom->shaderGlobalSetInt(SplinePointObject::ptRenderPassId, 0); + dagRender->dynRenderBufferFlushToBuffer(*ptDynBuf, signTexPt); + dagGeom->reset_override(); + + dagGeom->shaderGlobalSetInt(SplinePointObject::ptRenderPassId, 1); + dagRender->dynRenderBufferFlushToBuffer(*ptDynBuf, signTexPt); + dagRender->dynRenderBufferFlush(*ptDynBuf); + } + else if ((HmapLandPlugin::self->renderAllSplinesAlways || HmapLandPlugin::self->renderSelSplinesAlways)) + { + bool all = HmapLandPlugin::self->renderAllSplinesAlways && !hideSplines; + + dagRender->startLinesRender(true, false, true); + dagRender->setLinesTm(TMatrix::IDENT); + for (int i = 0; i < splines.size(); ++i) + if (all || splines[i]->isSelected()) + splines[i]->renderLines(false, frustum); + dagRender->endLinesRender(); + + dagRender->startLinesRender(); + + for (int i = 0; i < splines.size(); ++i) + if (all || splines[i]->isSelected()) + splines[i]->renderLines(true, frustum); + + if (debugP1 && debugP2) + dagRender->renderLine(*debugP1, *debugP2, E3DCOLOR(255, 0, 0)); + + dagRender->endLinesRender(); + + dagRender->dynRenderBufferClearBuf(*ptDynBuf); + + + int cnt = 0; + for (int i = 0; i < splines.size(); ++i) + if (all || splines[i]->isSelected()) + splines[i]->render(ptDynBuf, gtm, scale, frustum, cnt); + + dagGeom->set(zFuncLessStateId); + dagGeom->shaderGlobalSetInt(SplinePointObject::ptRenderPassId, 0); + dagRender->dynRenderBufferFlushToBuffer(*ptDynBuf, SplinePointObject::texPt); + dagGeom->reset_override(); + + dagGeom->shaderGlobalSetInt(SplinePointObject::ptRenderPassId, 1); + dagRender->dynRenderBufferFlushToBuffer(*ptDynBuf, SplinePointObject::texPt); + dagRender->dynRenderBufferFlush(*ptDynBuf); + } + +end: + if (objCreator) + objCreator->render(); +} + + +void HmapLandObjectEditor::renderTrans() +{ + bool curPlugin = DAGORED2->curPlugin() == HmapLandPlugin::self; + int st_mask = IDaEditor3Engine::get().getEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_RENDER); + + if (!curPlugin) + return; + + // render object boxes + if (1) + { + if (st_mask & SphereLightObject::lightGeomSubtype) + for (int i = 0; i < objects.size(); ++i) + { + SphereLightObject *l = RTTI_cast(objects[i]); + if (l) + l->renderTrans(); + } + + dagRender->startLinesRender(); + dagRender->setLinesTm(TMatrix::IDENT); + for (int i = 0; i < objects.size(); ++i) + { + if (LandscapeEntityObject *p = RTTI_cast(objects[i])) + { + p->renderBox(); + continue; + } + + if (areLandHoleBoxesVisible) + { + if (HmapLandHoleObject *o = RTTI_cast(objects[i])) + o->render(); + } + + if (st_mask & SphereLightObject::lightGeomSubtype) + { + if (SphereLightObject *l = RTTI_cast(objects[i])) + l->renderObject(); + } + if (st_mask & SnowSourceObject::showSubtypeId) + { + if (SnowSourceObject *sn = RTTI_cast(objects[i])) + sn->renderObject(); + } + } + + dagRender->endLinesRender(); + } +} + +void HmapLandObjectEditor::renderGrassMask() +{ + d3d::settm(TM_WORLD, TMatrix::IDENT); + TMatrix4 globtm; + d3d::getglobtm(globtm); + Frustum frustum; + frustum.construct(globtm); + + ISplineGenService *splSrv = EDITORCORE->queryEditorInterface(); + if (splSrv) + { + FastIntList loft_layers; + loft_layers.addInt(0); + splSrv->gatherLoftLayers(loft_layers, true); + bool opaque = true; + for (int lli = 0; lli < loft_layers.size(); lli++) + { + int ll = loft_layers.getList()[lli]; + splSrv->renderLoftGeom(ll, opaque, frustum, 0); + } + } + + IRenderingService *prefabMgr = nullptr; + for (int i = 0, plugin_cnt = IEditorCoreEngine::get()->getPluginCount(); i < plugin_cnt; ++i) + { + IGenEditorPlugin *p = IEditorCoreEngine::get()->getPlugin(i); + IRenderingService *iface = p->queryInterface(); + if (stricmp(p->getInternalName(), "_prefabEntMgr") == 0) + prefabMgr = iface; + } + if (prefabMgr) + { + prefabMgr->renderGeometry(IRenderingService::STG_RENDER_GRASS_MASK); + // prefabs rendering can modify TM_WORLD, so we restore default + d3d::settm(TM_WORLD, TMatrix::IDENT); + } +} + +void HmapLandObjectEditor::renderGeometry(bool opaque) +{ + static int landCellShortDecodeXZ = dagGeom->getShaderVariableId("landCellShortDecodeXZ"); + static int landCellShortDecodeY = dagGeom->getShaderVariableId("landCellShortDecodeY"); + static Color4 dec_xz_0(0, 0, 0, 0), dec_y_0(0, 0, 0, 0); + if (landCellShortDecodeXZ != -1) + { + dec_xz_0 = dagGeom->shaderGlobalGetColor4(landCellShortDecodeXZ); + dagGeom->shaderGlobalSetColor4(landCellShortDecodeXZ, Color4(1.0f / 32767.f, 0, 0, 0)); + } + if (landCellShortDecodeY != -1) + { + dec_y_0 = dagGeom->shaderGlobalGetColor4(landCellShortDecodeY); + dagGeom->shaderGlobalSetColor4(landCellShortDecodeY, Color4(1.0f / 32767.f, 0, 0, 0)); + } + + ISplineGenService *splSrv = EDITORCORE->queryEditorInterface(); + d3d::settm(TM_WORLD, TMatrix::IDENT); + TMatrix4 globtm; + d3d::getglobtm(globtm); + Frustum frustum; + frustum.construct(globtm); + int st_mask = IDaEditor3Engine::get().getEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_RENDER); + if (waterGeom && (st_mask & waterSurfSubtypeMask)) + { + if (opaque) + dagGeom->geomObjectRender(*waterGeom); + else + dagGeom->geomObjectRenderTrans(*waterGeom); + } + + FastIntList loft_layers; + loft_layers.addInt(0); + Tab renderSplines; + renderSplines.reserve(splines.size()); + for (int i = 0; i < splines.size(); ++i) + { + if (frustum.testBoxB(splines[i]->getGeomBox())) + renderSplines.push_back(splines[i]); + } + if (splSrv && (st_mask & SplineObject::splineSubtypeMask)) + splSrv->gatherLoftLayers(loft_layers, true); + + for (int lli = 0; lli < loft_layers.size(); lli++) + { + int max_layer = 0, ll = loft_layers.getList()[lli]; + for (int i = 0; i < renderSplines.size(); ++i) + { + int l = renderSplines[i]->getLayer(); + if (!l) + renderSplines[i]->renderGeom(opaque, ll, frustum); + else if (max_layer < l) + max_layer = l; + } + if (splSrv) + splSrv->renderLoftGeom(ll, opaque, frustum, 0); + for (int l = 1; l <= max_layer; l++) + { + for (int i = 0; i < renderSplines.size(); ++i) + if (renderSplines[i]->getLayer() == l) + renderSplines[i]->renderGeom(opaque, ll, frustum); + if (splSrv) + splSrv->renderLoftGeom(ll, opaque, frustum, l); + } + } + + if (st_mask & SplineObject::roadsSubtypeMask) + for (int i = 0; i < crossRoads.size(); i++) + { + GeomObject *geom = crossRoads[i]->getRoadGeom(); + if (!geom) + continue; + if (!frustum.testBoxB(dagGeom->geomObjectGetBoundBox(*geom))) + continue; + if (opaque) + dagGeom->geomObjectRender(*geom); + else + dagGeom->geomObjectRenderTrans(*geom); + } + + if (landCellShortDecodeXZ != -1) + dagGeom->shaderGlobalSetColor4(landCellShortDecodeXZ, dec_xz_0); + if (landCellShortDecodeY != -1) + dagGeom->shaderGlobalSetColor4(landCellShortDecodeY, dec_y_0); +} + +void HmapLandObjectEditor::onBrushPaintEnd() +{ + /*== too brute force; these should be updated locally in onLandRegionChanged() + for (int i = 0; i < splines.size(); i++) + if (!splines[i]->isPoly()) + splines[i]->updateFullLoft(); + */ +} + +void HmapLandObjectEditor::setSelectionGizmoTranformMode(bool enable) +{ + for (int i = 0; i < selection.size(); ++i) + if (auto *obj = RTTI_cast(selection[i])) + obj->setGizmoTranformMode(enable); +} + +void HmapLandObjectEditor::gizmoStarted() +{ + __super::gizmoStarted(); + inGizmo = false; + getAxes(locAx[0], locAx[1], locAx[2]); + inGizmo = true; + + setSelectionGizmoTranformMode(true); + + for (int i = 0; i < selection.size(); ++i) + if (!RTTI_cast(selection[i]) && !RTTI_cast(selection[i]) && + !RTTI_cast(selection[i]) && !RTTI_cast(selection[i])) + return; + + if ((wingw::is_key_pressed(wingw::V_SHIFT)) && getEditMode() == CM_OBJED_MODE_MOVE) + { + if (!cloneMode) + cloneMode = true; + + cloneDelta = getPt(); + } + + if (cloneMode) + { + clear_and_shrink(cloneObjs); + clone(true); + } +} + +static void renameObjects(PtrTab &objs, const char *new_prefix, HmapLandObjectEditor &ed) +{ + String fn; + + for (int i = 0; i < objs.size(); ++i) + { + if (new_prefix && *new_prefix) + fn = new_prefix; + else + fn = objs[i]->getName(); + + ed.setUniqName(objs[i], fn); + } +} + +void HmapLandObjectEditor::gizmoEnded(bool apply) +{ + setSelectionGizmoTranformMode(false); + + HmapLandPlugin::hmlService->invalidateClipmap(false); + if (cloneMode && selection.size()) + { + int cloneCount; + bool cloneSeed = false; + + CopyDlg copyDlg(cloneName, cloneCount, cloneSeed); + + if (copyDlg.execute()) + { + const Point3 delta = getPt() - cloneDelta; + + if (!cloneSeed) + for (int i = 0; i < selection.size(); ++i) + { + if (LandscapeEntityObject *l = RTTI_cast(selection[i])) + l->setRndSeed(grnd()); + else if (SplineObject *s = RTTI_cast(selection[i])) + s->setRandomSeed(grnd()); + } + + for (int cloneId = 2; cloneId <= cloneCount; ++cloneId) + { + renameObjects(selection, cloneName, *this); + + cloneDelta = getPt(); + clone(cloneSeed); + for (int i = 0; i < selection.size(); ++i) + selection[i]->moveObject(delta, IEditorCoreEngine::BASIS_World); + } + + renameObjects(selection, cloneName, *this); + getUndoSystem()->accept("Clone object(s)"); + updateSelection(); + } + else + { + for (int i = 0; i < cloneObjs.size(); ++i) + removeObject(cloneObjs[i]); + + getUndoSystem()->cancel(); + } + + cloneMode = false; + + gizmoRotO = gizmoRot; + gizmoSclO = gizmoScl; + isGizmoStarted = false; + } + else + __super::gizmoEnded(apply); + inGizmo = false; +} + +void HmapLandObjectEditor::_addObjects(RenderableEditableObject **obj, int num, bool use_undo) +{ + Tab objs(tmpmem); + objs.resize(num); + for (int i = 0; i < num; i++) + objs[num - i - 1] = obj[i]; + + __super::_addObjects(objs.data(), num, use_undo); + + for (int i = 0; i < num; ++i) + if (RTTI_cast(objs[i])) + { + HmapLandPlugin::self->updateSnowSources(); + break; + } + + clear_and_shrink(splines); + for (int i = 0; i < objects.size(); i++) + { + SplineObject *o = RTTI_cast(objects[i]); + if (o && !o->splineInactive) + splines.push_back(o); + } +} + +void HmapLandObjectEditor::_removeObjects(RenderableEditableObject **obj, int num, bool use_undo) +{ + Tab remSplines(tmpmem); + Tab remPt0(tmpmem); + PtrTab remPoints(tmpmem); + Tab remObjs(tmpmem); + bool rebuild_hmap_modif = false; + + // splitting objects on groops + for (int i = 0; i < num; i++) + { + if (SplineObject *o = RTTI_cast(obj[i])) + remSplines.push_back(o); + else if (SplinePointObject *p = RTTI_cast(obj[i])) + remPt0.push_back(p); + else + remObjs.push_back(obj[i]); + } + + // add points of rem-splines to remove-list + for (int i = 0; i < remSplines.size(); i++) + { + for (int j = remSplines[i]->points.size() - (remSplines[i]->isClosed() ? 2 : 1); j >= 0; j--) + { + remPoints.push_back(remSplines[i]->points[j]); + erase_item_by_value(remPt0, remSplines[i]->points[j]); + } + if (remSplines[i]->isAffectingHmap()) + { + remSplines[i]->reApplyModifiers(false); + rebuild_hmap_modif = true; + } + if (remSplines[i]->isClosed()) + getUndoSystem()->put(remSplines[i]->makePointListUndo()); + remSplines[i]->points.clear(); + } + + if (use_undo) + { + Tab undoPointsListSplines(tmpmem); + for (int i = 0; i < remPoints.size(); i++) + if (remPoints[i]->arrId == 0 && remPoints[i]->spline->isClosed()) + if (find_value_idx(undoPointsListSplines, remPoints[i]->spline) == -1) + undoPointsListSplines.push_back(remPoints[i]->spline); + + for (int i = 0; i < undoPointsListSplines.size(); i++) + getUndoSystem()->put(undoPointsListSplines[i]->makePointListUndo()); + } + + __super::_removeObjects((RenderableEditableObject **)remPoints.data(), remPoints.size(), use_undo); + __super::_removeObjects((RenderableEditableObject **)remSplines.data(), remSplines.size(), use_undo); + __super::_removeObjects((RenderableEditableObject **)remPt0.data(), remPt0.size(), use_undo); + __super::_removeObjects(remObjs.data(), remObjs.size(), use_undo); + + + // synchronize our splines array with real splines array + clear_and_shrink(splines); + for (int i = 0; i < objects.size(); i++) + { + SplineObject *o = RTTI_cast(objects[i]); + if (o) + { + if ((o->isPoly() && o->points.size() < 3) || (!o->isPoly() && o->points.size() < 2)) + _removeObjects((RenderableEditableObject **)&o, 1, use_undo); + else if (!o->splineInactive) + splines.push_back(o); + } + } + if (rebuild_hmap_modif) + HmapLandPlugin::self->applyHmModifiers(); +} + + +bool HmapLandObjectEditor::canSelectObj(RenderableEditableObject *o) +{ + if (!__super::canSelectObj(o)) + return false; + + if (o == curPt) + return false; + + if (LandscapeEntityObject *e = RTTI_cast(o)) + { + if (EditLayerProps::layerProps[e->getEditLayerIdx()].lock) + return false; + } + else if (SplineObject *s = RTTI_cast(o)) + { + if (EditLayerProps::layerProps[s->getEditLayerIdx()].lock) + return false; + } + else if (SplinePointObject *p = RTTI_cast(o)) + { + if (SplineObject *s = p->spline) + if (EditLayerProps::layerProps[s->getEditLayerIdx()].lock) + return false; + } + + switch (selectMode) + { + case CM_SELECT_PT: return RTTI_cast(o) != NULL; + case CM_SELECT_SPLINES: return RTTI_cast(o) != NULL; + case CM_SELECT_ENT: return RTTI_cast(o) != NULL; + case CM_SELECT_SPL_ENT: return RTTI_cast(o) || RTTI_cast(o); + case CM_SELECT_LT: return RTTI_cast(o) != NULL; + case CM_SELECT_SNOW: return RTTI_cast(o) != NULL; + + default: return true; + } + + return false; +} + + +void HmapLandObjectEditor::removeSpline(SplineObject *s) +{ + for (int i = 0; i < splines.size(); i++) + if (splines[i] == s) + erase_items(splines, i, 1); +} + + +void HmapLandObjectEditor::save(DataBlock &blk) +{ + blk.setBool("areLandHoleBoxesVisible", areLandHoleBoxesVisible); + + for (int i = 0; i < objectCount(); ++i) + if (HmapLandHoleObject *obj = RTTI_cast(getObject(i))) + obj->save(*blk.addNewBlock("hole")); +} + +void HmapLandObjectEditor::save(DataBlock &splBlk, DataBlock &polBlk, DataBlock &entBlk, DataBlock <Blk, int layer) +{ + for (int i = 0; i < objects.size(); ++i) + if (SplineObject *s = RTTI_cast(objects[i])) + { + if (s && s->getEditLayerIdx() == (layer < 0 ? s->lpIndex() : layer)) + { + if (s->isPoly()) + s->save(polBlk); + else + s->save(splBlk); + } + } + else + { + LandscapeEntityObject *p = RTTI_cast(objects[i]); + if (p && (p != newObj) && p->getEditLayerIdx() == (layer < 0 ? p->lpIndex() : layer)) + p->save(*entBlk.addNewBlock("entity")); + + if (layer >= 0) + continue; + + if (SphereLightObject *l = RTTI_cast(objects[i])) + l->save(*ltBlk.addNewBlock("SphereLightSource")); + else if (SnowSourceObject *s = RTTI_cast(objects[i])) + s->save(*ltBlk.addNewBlock("SnowSource")); + } + + if (layer < 0) + LandscapeEntityObject::saveColliders(entBlk); +} + + +void HmapLandObjectEditor::load(const DataBlock &main_blk) +{ + areLandHoleBoxesVisible = main_blk.getBool("areLandHoleBoxesVisible", areLandHoleBoxesVisible); + + int holeNameId = main_blk.getNameId("hole"); + + for (int bi = 0; bi < main_blk.blockCount(); ++bi) + { + const DataBlock &blk = *main_blk.getBlock(bi); + + if (blk.getBlockNameId() == holeNameId) + { + HmapLandHoleObject *obj = new HmapLandHoleObject; + addObject(obj, false); + obj->load(blk); + } + } +} + +void HmapLandObjectEditor::load(const DataBlock &splBlk, const DataBlock &polBlk, const DataBlock &entBlk, const DataBlock <Blk, + int layer) +{ + if (layer < 0) + splines.clear(); + + int nid = splBlk.getNameId("spline"); + for (int i = 0; i < splBlk.blockCount(); i++) + if (splBlk.getBlock(i)->getBlockNameId() == nid) + { + const DataBlock &cb = *splBlk.getBlock(i); + + SplineObject *s = new SplineObject(false); + s->setEditLayerIdx(layer < 0 ? s->lpIndex() : layer); + addObject(s, false); + s->load(cb, false); + s->onCreated(false); + } + + nid = polBlk.getNameId("polygon"); + for (int i = 0; i < polBlk.blockCount(); i++) + if (polBlk.getBlock(i)->getBlockNameId() == nid) + { + const DataBlock &cb = *polBlk.getBlock(i); + + SplineObject *s = new SplineObject(true); + s->setEditLayerIdx(layer < 0 ? s->lpIndex() : layer); + addObject(s, false); + s->load(cb, false); + s->onCreated(false); + } + + nid = entBlk.getNameId("entity"); + if (layer < 0) + LandscapeEntityObject::loadColliders(entBlk); + + for (int i = 0; i < entBlk.blockCount(); i++) + if (entBlk.getBlock(i)->getBlockNameId() == nid) + { + const DataBlock &cb = *entBlk.getBlock(i); + + LandscapeEntityObject *o = new LandscapeEntityObject(NULL); + o->setEditLayerIdx(layer < 0 ? o->lpIndex() : layer); + addObject(o, false); + o->load(cb); + } + + if (layer >= 0) + return; + + nid = ltBlk.getNameId("SphereLightSource"); + int nids = ltBlk.getNameId("SnowSource"); + + for (int i = 0; i < ltBlk.blockCount(); i++) + if (ltBlk.getBlock(i)->getBlockNameId() == nid) + { + const DataBlock &cb = *ltBlk.getBlock(i); + + SphereLightObject *o = new SphereLightObject; + addObject(o, false); + o->load(cb); + } + else if (ltBlk.getBlock(i)->getBlockNameId() == nids) + { + const DataBlock &cb = *ltBlk.getBlock(i); + + SnowSourceObject *o = new SnowSourceObject; + addObject(o, false); + o->load(cb); + } +} + + +void HmapLandObjectEditor::getObjNames(Tab &names, Tab &sel_names, const Tab &types) +{ + names.clear(); + + if (types.empty()) + return; + + bool showSplines = false; + bool showPolys = false; + bool showEnt = false; + bool showLt = false; + bool showSnow = false; + + for (int ti = 0; ti < types.size(); ++ti) + { + if (types[ti] == 0) + showSplines = true; + + if (types[ti] == 1) + showPolys = true; + + if (types[ti] == 2) + showEnt = true; + + if (types[ti] == 3) + showLt = true; + + if (types[ti] == 4) + showSnow = true; + } + + for (int i = 0; i < splines.size(); ++i) + { + SplineObject *so = splines[i]; + if (so && so->isCreated()) + { + if ((so->isPoly() && showPolys) || (!so->isPoly() && showSplines)) + { + names.push_back() = so->getName(); + + if (so->isSelected()) + sel_names.push_back() = so->getName(); + } + } + } + + if (showEnt || showLt || showSnow) + for (int i = 0; i < objects.size(); i++) + { + RenderableEditableObject *o; + + o = showEnt ? RTTI_cast(objects[i]) : NULL; + if (o) + { + names.push_back() = o->getName(); + + if (o->isSelected()) + sel_names.push_back() = o->getName(); + } + + o = showLt ? RTTI_cast(objects[i]) : NULL; + if (o) + { + names.push_back() = o->getName(); + + if (o->isSelected()) + sel_names.push_back() = o->getName(); + } + + o = showSnow ? RTTI_cast(objects[i]) : NULL; + if (o) + { + names.push_back() = o->getName(); + + if (o->isSelected()) + sel_names.push_back() = o->getName(); + } + } +} + + +void HmapLandObjectEditor::getTypeNames(Tab &names) +{ + bool has_snow = HmapLandPlugin::self->isSnowAvailable(); + + names.resize(has_snow ? 5 : 4); + names[0] = OBJECT_SPLINE; + names[1] = OBJECT_POLYGON; + names[2] = OBJECT_ENTITY; + names[3] = OBJECT_LIGHT; + if (has_snow) + names[4] = OBJECT_SNOW; +} + + +void HmapLandObjectEditor::onSelectedNames(const Tab &names) +{ + getUndoSystem()->begin(); + unselectAll(); + + Tab points(tmpmem); + + for (int ni = 0; ni < names.size(); ++ni) + { + RenderableEditableObject *o = getObjectByName(names[ni]); + if (canSelectObj(o)) + o->selectObject(); + } + + getUndoSystem()->accept("Select"); + updateGizmo(); +} + + +bool HmapLandObjectEditor::findTargetPos(IGenViewportWnd *wnd, int x, int y, Point3 &out, bool place_on_ri_collision) +{ + Point3 dir, world; + real dist = DAGORED2->getMaxTraceDistance(); + + wnd->clientToWorld(Point2(x, y), world, dir); + + if (place_on_ri_collision) + EDITORCORE->setupColliderParams(1, BBox3()); + + bool hasTarget = IEditorCoreEngine::get()->traceRay(world, dir, dist, NULL); + + if (place_on_ri_collision) + EDITORCORE->setupColliderParams(0, BBox3()); + + if (hasTarget) + { + out = world + dir * dist; + // out.y += 0.2; + return true; + } + + return false; +} + + +bool HmapLandPlugin::getSelectionBox(BBox3 &box) const { return objEd.getSelectionBox(box); } + + +void HmapLandObjectEditor::prepareCatmul(SplinePointObject *p1, SplinePointObject *p2) +{ + if (p1->linkCount() == 2) + catmul[0] = p1->getLinkedPt(0) == p2 ? p1->getLinkedPt(1) : p1->getLinkedPt(0); + else + catmul[0] = p1; + + catmul[1] = p1; + catmul[2] = p2; + + if (p2->linkCount() == 2) + catmul[3] = p2->getLinkedPt(0) == p1 ? p2->getLinkedPt(1) : p2->getLinkedPt(0); + else + catmul[3] = p2; + + recalcCatmul(); +} + + +void HmapLandObjectEditor::recalcCatmul() +{ + if (catmul[1]) + { + BezierSplineInt sp; + Point3 v[4]; + + for (int i = 0; i < 4; i++) + v[i] = catmul[i]->getPt(); + sp.calculateCatmullRom(v); + sp.calculateBack(v); + + catmul[1]->setRelBezierIn(v[0] - v[1]); + catmul[1]->setRelBezierOut(v[1] - v[0]); + catmul[1]->markChanged(); + catmul[2]->setRelBezierIn(v[2] - v[3]); + catmul[2]->setRelBezierOut(v[3] - v[2]); + catmul[2]->markChanged(); + } +} + +void HmapLandObjectEditor::setEditMode(int cm) +{ + memset(catmul, 0, sizeof(catmul)); + + DAGORED2->endBrushPaint(); + + if (getUndoSystem()->is_holding()) + DAGORED2->setGizmo(NULL, IDagorEd2Engine::MODE_None); + + if (curPt) + { + curPt->visible = false; + curPt->spline = NULL; + } + curPt = NULL; + curSpline = NULL; + + setCreateBySampleMode(NULL); + del_it(objCreator); + selectNewObjEntity(NULL); + + if (cm == CM_CREATE_HOLEBOX_MODE) + { + objCreator = dagGeom->newBoxCreator(); + + areLandHoleBoxesVisible = true; + updateToolbarButtons(); + DAGORED2->repaint(); + } + else if (cm == CM_CREATE_LT) + { + objCreator = dagGeom->newSphereCreator(); + + updateToolbarButtons(); + DAGORED2->repaint(); + } + else if (cm == CM_CREATE_SNOW_SOURCE) + { + objCreator = dagGeom->newSphereCreator(); + + updateToolbarButtons(); + DAGORED2->repaint(); + } + + __super::setEditMode(cm); + if (getEditMode() != CM_CREATE_ENTITY) + DAEDITOR3.hideAssetWindow(); + DAGORED2->repaint(); +} + +void HmapLandObjectEditor::gatherStaticGeometry(StaticGeometryContainer &cont, int flags, bool collision, int stage) +{ + ISplineGenService *splSrv = EDITORCORE->queryEditorInterface(); + int st_mask = + DAEDITOR3.getEntitySubTypeMask(collision ? IObjEntityFilter::STMASK_TYPE_COLLISION : IObjEntityFilter::STMASK_TYPE_EXPORT); + + updateSplinesGeom(); + + if (collision) + flags |= StaticGeometryNode::FLG_COLLIDABLE; + + FastIntList loft_layers; + loft_layers.addInt(0); + if (splSrv && (st_mask & SplineObject::splineSubtypeMask)) + splSrv->gatherLoftLayers(loft_layers, false); + + for (int lli = 0; lli < loft_layers.size(); lli++) + { + int max_layer = 0, ll = loft_layers.getList()[lli]; + for (int i = 0; i < splines.size(); ++i) + { + int l = splines[i]->getLayer(); + if (max_layer < l) + max_layer = l; + } + for (int l = 0; l <= max_layer; l++) + { + if (splSrv) + splSrv->gatherStaticGeometry(cont, flags, collision, ll, stage, l); + for (int i = 0; i < splines.size(); ++i) + if (splines[i]->getLayer() == l) + { + StaticGeometryContainer splineNodes; + splines[i]->gatherStaticGeometry(splineNodes, flags, collision, ll, stage); + for (int nodeNo = 0; nodeNo < splineNodes.nodes.size(); nodeNo++) + { + splineNodes.nodes[nodeNo]->script.setInt("splineLayer", l); // Use this and layer:i from loft to split materials by layers. + cont.addNode(splineNodes.nodes[nodeNo]); + } + clear_and_shrink(splineNodes.nodes); + } + } + } + + if (st_mask & SplineObject::roadsSubtypeMask) + for (int i = 0; i < crossRoads.size(); i++) + { + GeomObject *geom = crossRoads[i]->getRoadGeom(); + if (geom) + SplineObject::gatherStaticGeom(cont, *geom->getGeometryContainer(), flags, 0, i, stage); + } + + if (waterGeom && (st_mask & waterSurfSubtypeMask)) + SplineObject::gatherStaticGeom(cont, *waterGeom->getGeometryContainer(), flags, 7, 0, stage); + + if (st_mask & SphereLightObject::lightGeomSubtype) + for (int i = 0; i < objects.size(); ++i) + { + SphereLightObject *l = RTTI_cast(objects[i]); + if (l) + l->gatherGeom(cont); + } +} +void HmapLandObjectEditor::gatherLoftLandPts(Tab &loft_pt_cloud, Tab &water_border_polys, + Tab &hmap_sweep_polys) +{ + for (int i = 0; i < splines.size(); i++) + splines[i]->gatherLoftLandPts(loft_pt_cloud, water_border_polys, hmap_sweep_polys); +} + +void HmapLandObjectEditor::setSelectMode(int cm) +{ + if (selectMode == cm) + return; + int old_mode = selectMode; + selectMode = cm; + setRadioButton(CM_SELECT_PT, selectMode); + setRadioButton(CM_SELECT_SPLINES, selectMode); + setRadioButton(CM_SELECT_ENT, selectMode); + setRadioButton(CM_SELECT_SPL_ENT, selectMode); + setRadioButton(CM_SELECT_LT, selectMode); + setRadioButton(CM_SELECT_SNOW, selectMode); + + if (selectMode != -1) + { + bool desel = false; + + getUndoSystem()->begin(); + for (int i = selection.size() - 1; i >= 0; i--) + if (!canSelectObj(selection[i])) + { + selection[i]->selectObject(false); + desel = true; + } + updateSelection(); + + class UndoSelModeChange : public UndoRedoObject + { + HmapLandObjectEditor *ed; + int oldMode, redoMode; + + public: + UndoSelModeChange(HmapLandObjectEditor *e, int mode) : ed(e) + { + oldMode = mode; + redoMode = ed->selectMode; + } + + virtual void restore(bool save_redo) + { + if (save_redo) + redoMode = ed->selectMode; + ed->setSelectMode(oldMode); + } + + virtual void redo() { ed->setSelectMode(redoMode); } + + virtual size_t size() { return sizeof(*this); } + virtual void accepted() {} + virtual void get_description(String &s) { s = "UndoEdSelectModeChange"; } + }; + + if (desel) + { + getUndoSystem()->put(new UndoSelModeChange(this, old_mode)); + getUndoSystem()->accept("Change select mode"); + } + else + getUndoSystem()->cancel(); + + invalidateObjectProps(); + } +} + + +float HmapLandObjectEditor::screenDistBetweenPoints(IGenViewportWnd *wnd, SplinePointObject *p1, SplinePointObject *p2) +{ + if (!wnd || !p1 || !p2) + return -1; + + Point2 pt1, pt2; + + if (!wnd->worldToClient(p1->getPt(), pt1)) + return -1; + + if (!wnd->worldToClient(p2->getPt(), pt2)) + return -1; + + float dx = pt2.x - pt1.x; + float dy = pt2.y - pt1.y; + + return sqrt(dx * dx + dy * dy); +} + + +float HmapLandObjectEditor::screenDistBetweenCursorAndPoint(IGenViewportWnd *wnd, int x, int y, SplinePointObject *p) +{ + if (!wnd || !p) + return -1; + + Point2 pt; + + if (!wnd->worldToClient(p->getPt(), pt)) + return -1; + + float dx = pt.x - x; + float dy = pt.y - y; + + return sqrt(dx * dx + dy * dy); +} + + +void HmapLandObjectEditor::update(real dt) +{ + if (objCreator && objCreator->isFinished()) + { + if (objCreator->isOk() && getEditMode() == CM_CREATE_HOLEBOX_MODE) + { + // create object + HmapLandHoleObject *obj = new HmapLandHoleObject; + + Point3 size = objCreator->matrix.getcol(0) + objCreator->matrix.getcol(1) + objCreator->matrix.getcol(2); + + Point3 center = objCreator->matrix.getcol(3); + + center.y += size.y * 0.5f; + + obj->setPos(center); + + Point3 boxSize; + + boxSize.x = fabsf(size.x); + boxSize.y = fabsf(size.y); + boxSize.z = fabsf(size.z); + + obj->setBoxSize(boxSize); + + String name("HoleBox001"); + setUniqName(obj, name); + + getUndoSystem()->begin(); + addObject(obj); + getUndoSystem()->accept("create land hole box"); + + HmapLandPlugin::self->resetRenderer(); + del_it(objCreator); + } + else if (objCreator->isOk() && getEditMode() == CM_CREATE_LT) + { + SphereLightObject *obj = new SphereLightObject; + String name("Sph_Light_Source_001"); + setUniqName(obj, name); + obj->setWtm(objCreator->matrix); + + getUndoSystem()->begin(); + addObject(obj); + obj->selectObject(); + getUndoSystem()->accept("create sphere light source"); + + del_it(objCreator); + // objCreator = dagGeom->newSphereCreator(); + } + else if (objCreator->isOk() && getEditMode() == CM_CREATE_SNOW_SOURCE) + { + SnowSourceObject *obj = new SnowSourceObject; + String name("Snow_Source_001"); + setUniqName(obj, name); + obj->setWtm(objCreator->matrix); + + getUndoSystem()->begin(); + addObject(obj); + obj->selectObject(); + getUndoSystem()->accept("create snow source"); + + del_it(objCreator); + // objCreator = dagGeom->newSphereCreator(); + } + else + del_it(objCreator); + + if (!objCreator) + setEditMode(CM_OBJED_MODE_SELECT); + } + + __super::update(dt); +} + +void HmapLandObjectEditor::onAvClose() +{ + if (getEditMode() == CM_CREATE_ENTITY) + { + setCreateBySampleMode(NULL); + selectNewObjEntity(NULL); + __super::setEditMode(CM_OBJED_MODE_SELECT); + } +} +void HmapLandObjectEditor::onAvSelectAsset(const char *asset_name) +{ + if (getEditMode() == CM_CREATE_ENTITY) + selectNewObjEntity(asset_name); + else if (getEditMode() == CM_CREATE_SPLINE) + { + curSplineAsset = asset_name; + if (curSpline) + curSpline->changeAsset(curSplineAsset, false); + } + else if (getEditMode() == CM_CREATE_POLYGON) + { + curSplineAsset = asset_name; + if (curSpline) + curSpline->changeAsset(curSplineAsset, false); + } +} + +void HmapLandObjectEditor::onLandRegionChanged(float x0, float z0, float x1, float z1, bool recalc_all /*= false*/) +{ + BBox2 upd(Point2(x0, z0), Point2(x1, z1)); + for (int i = 0; i < splines.size(); ++i) + if (splines[i] && splines[i]->isCreated()) + if (recalc_all || splines[i]->intersects(upd, true)) + { + splines[i]->splineChanged = true; + splinesChanged = true; + } + + for (int i = 0; i < objects.size(); i++) + { + LandscapeEntityObject *o = RTTI_cast(objects[i]); + if (o && o->getProps().placeType) + { + Point3 pp = o->getPos(); + if (recalc_all || (upd & Point2(pp.x, pp.z))) + o->setPos(pp); + } + } +} +void HmapLandObjectEditor::onLandClassAssetChanged(landclass::AssetData *a) +{ + bool changed = false; + for (int i = 0; i < splines.size(); ++i) + changed |= splines[i]->onAssetChanged(a); + + if (changed) + DAGORED2->invalidateViewportCache(); +} +void HmapLandObjectEditor::onSplineClassAssetChanged(splineclass::AssetData *a) +{ + bool changed = false; + for (int i = 0; i < splines.size(); ++i) + changed |= splines[i]->onAssetChanged(a); + + if (changed) + DAGORED2->invalidateViewportCache(); +} + +void HmapLandObjectEditor::clone(bool clone_seed) +{ + PtrTab oldSel(selection); + + unselectAll(); + + for (int i = 0; i < oldSel.size(); ++i) + { + LandscapeEntityObject *l = RTTI_cast(oldSel[i]); + if (l) + { + LandscapeEntityObject *nl = l->clone(); + // cloneName = nl->getName(); + addObject(nl); + cloneObjs.push_back(nl); + nl->setRndSeed(clone_seed ? l->getRndSeed() : grnd()); + nl->selectObject(); + continue; + } + + SplineObject *s = RTTI_cast(oldSel[i]); + if (s) + { + SplineObject *ns = s->clone(); + // cloneName = ns->getName(); + addObject(ns); + cloneObjs.push_back(ns); + ns->prepareSplineClassInPoints(); + ns->getSpline(); + ns->onCreated(); + ns->setRandomSeed(clone_seed ? s->getProps().rndSeed : grnd()); + ns->selectObject(); + continue; + } + + SphereLightObject *o = RTTI_cast(oldSel[i]); + if (o) + { + SphereLightObject *nl = o->clone(); + // cloneName = nl->getName(); + addObject(nl); + cloneObjs.push_back(nl); + nl->selectObject(); + continue; + } + + SnowSourceObject *sn = RTTI_cast(oldSel[i]); + if (sn) + { + SnowSourceObject *nl = sn->clone(); + // cloneName = nl->getName(); + addObject(nl); + cloneObjs.push_back(nl); + nl->selectObject(); + continue; + } + } +} + + +static CrossRoadData *addCross(dag::ConstSpan cr, SplinePointObject *old_pt, SplinePointObject *new_pt) +{ + for (int i = 0; i < cr.size(); i++) + if (cr[i]->find(old_pt) != -1) + { + if (cr[i]->find(old_pt) == -1) + { + cr[i]->points.push_back(new_pt); + new_pt->markChanged(); + } + new_pt->isCross = true; + return cr[i]; + } + return NULL; +} +static void markCrossChanged(dag::ConstSpan cr, SplinePointObject *pt) +{ + for (int i = 0; i < cr.size(); i++) + if (cr[i]->find(pt) != -1) + { + cr[i]->changed = true; + return; + } +} + +void HmapLandObjectEditor::markCrossRoadChanged(SplinePointObject *p) +{ + for (int i = 0; i < crossRoads.size(); i++) + if (crossRoads[i]->find(p) != -1) + { + crossRoads[i]->changed = true; + crossRoadsChanged = true; + return; + } +} + +void HmapLandObjectEditor::updateCrossRoads(SplinePointObject *p) +{ + if (!p) + { + for (int i = 0; i < crossRoads.size(); i++) + for (int j = crossRoads[i]->points.size() - 1; j >= 0; j--) + crossRoads[i]->points[j]->isCross = false; + + clear_all_ptr_items(crossRoads); + for (int i = 0; i < splines.size(); i++) + for (int j = splines[i]->points.size() - 1; j >= 0; j--) + updateCrossRoadsOnPointAdd(splines[i]->points[j]); + } + else + { + for (int i = 0; i < crossRoads.size(); i++) + if (crossRoads[i]->find(p) != -1) + { + Point3 p3 = p->getProps().pt; + for (int j = crossRoads[i]->points.size() - 1; j >= 0; j--) + if (crossRoads[i]->points[j] != p && lengthSq(crossRoads[i]->points[j]->getProps().pt - p3) > 1e-4) + { + updateCrossRoadsOnPointRemove(p); + updateCrossRoadsOnPointAdd(p); + break; + } + return; + } + + updateCrossRoadsOnPointAdd(p); + if (p->arrId > 0 && p->spline->points[p->arrId - 1]->isCross) + { + markCrossChanged(crossRoads, p->spline->points[p->arrId - 1]); + crossRoadsChanged = true; + } + if (p->arrId + 1 < p->spline->points.size() && p->spline->points[p->arrId + 1]->isCross) + { + markCrossChanged(crossRoads, p->spline->points[p->arrId + 1]); + crossRoadsChanged = true; + } + } +} +void HmapLandObjectEditor::updateCrossRoadsOnPointAdd(SplinePointObject *p) +{ + SplineObject *pspl = p->spline; + Point3 p3 = p->getProps().pt; + static Tab cr(tmpmem); + CrossRoadData *dest = NULL; + + for (int i = 0; i < splines.size(); i++) + if (splines[i] && (splines[i] != pspl || pspl->getProps().maySelfCross) && (splines[i]->getSplineBox() & p->getPt())) + { + for (int j = splines[i]->points.size() - 1; j >= 0; j--) + if (splines[i]->points[j] != p && splines[i]->points[j] && lengthSq(splines[i]->points[j]->getProps().pt - p3) < 1e-4) + { + if (!dest) + dest = addCross(crossRoads, splines[i]->points[j], p); + if (!dest) + cr.push_back(splines[i]->points[j].get()); + else + { + for (int i = 0; i < cr.size(); i++) + dest->points.push_back(cr[i]); + cr.clear(); + if (dest->find(p) == -1) + dest->points.push_back(p); + } + break; + } + } + + if (!dest && cr.size()) + { + dest = new CrossRoadData; + dest->points.resize(cr.size() + 1); + dest->points[0] = p; + p->isCross = true; + for (int i = 0; i < cr.size(); i++) + { + dest->points[i + 1] = cr[i]; + cr[i]->isCross = true; + } + crossRoads.push_back(dest); + } + + if (dest) + { + dest->changed = true; + crossRoadsChanged = true; + for (int i = 0; i < dest->points.size(); i++) + dest->points[i]->markChanged(); + } + cr.clear(); +} + +void HmapLandObjectEditor::updateCrossRoadsOnPointRemove(SplinePointObject *p) +{ + for (int i = 0; i < crossRoads.size(); i++) + { + int idx = crossRoads[i]->find(p); + if (idx != -1) + { + if (crossRoads[i]->points.size() == 2) + { + crossRoads[i]->points[0]->isCross = false; + crossRoads[i]->points[1]->isCross = false; + crossRoads[i]->points[0]->markChanged(); + crossRoads[i]->points[1]->markChanged(); + delete crossRoads[i]; + erase_items(crossRoads, i, 1); + crossRoadsChanged = true; + return; + } + else + { + erase_items(crossRoads[i]->points, idx, 1); + p->isCross = false; + p->markChanged(); + crossRoads[i]->changed = true; + crossRoadsChanged = true; + return; + } + } + } +} + + +void HmapLandObjectEditor::calcSnow(StaticGeometryContainer &container) +{ + Tab snow_sources(tmpmem); + snow_sources.reserve(10); + + for (int i = 0; i < objects.size(); ++i) + { + SnowSourceObject *s = RTTI_cast(objects[i]); + if (s) + snow_sources.push_back(s); + } + + SnowSourceObject::calcSnow(snow_sources, HmapLandPlugin::self->getSnowValue(), container); +} + +void HmapLandObjectEditor::updateSnowSources() +{ + if (!HmapLandPlugin::self->hasSnowSpherePreview()) + return; + + if (!DAGORED2->getCurrentViewport()) + return; + + TMatrix ctm; + DAGORED2->getCurrentViewport()->getCameraTransform(ctm); + Point3 cam_pos = ctm.getcol(3); + clear_and_shrink(nearSources); + + for (int i = 0; i < objects.size(); ++i) + if (SnowSourceObject *s = RTTI_cast(objects[i])) + { + float source_dist = (cam_pos - s->getPos()).length(); + + if (nearSources.size() < SnowSourceObject::NEAR_SRC_COUNT) + nearSources.push_back(NearSnowSource(s, source_dist)); + else + { + int worst_index = 0; + + for (int j = 0; j < nearSources.size(); ++j) + { + if (nearSources[j].distance > nearSources[worst_index].distance) + worst_index = j; + } + + if (nearSources[worst_index].distance > source_dist) + { + nearSources[worst_index].distance = source_dist; + nearSources[worst_index].source = s; + } + } + } + + SnowSourceObject::updateSnowSources(nearSources); +} + +GeomObject &HmapLandObjectEditor::getClearedWaterGeom() +{ + if (!waterGeom) + return *(waterGeom = dagGeom->newGeomObject(midmem)); + dagGeom->geomObjectClear(*waterGeom); + return *waterGeom; +} +void HmapLandObjectEditor::removeWaterGeom() { dagGeom->deleteGeomObject(waterGeom); } + + +CrossRoadData::CrossRoadData() : points(midmem), geom(NULL), changed(true) {} +CrossRoadData::~CrossRoadData() { removeRoadGeom(); } +GeomObject &CrossRoadData::getClearedRoadGeom() +{ + if (!geom) + return *(geom = dagGeom->newGeomObject(midmem)); + dagGeom->geomObjectClear(*geom); + return *geom; +} +void CrossRoadData::removeRoadGeom() { dagGeom->deleteGeomObject(geom); } + +bool CrossRoadData::checkCrossRoad() +{ + bool real_cross = false; + int road_cnt = 0; + bool changed = false; + + for (int i = points.size() - 1; i >= 0; i--) + if (!getRoad(points[i])) + continue; + else if (points[i]->arrId > 0 && points[i]->arrId + 1 < points[i]->spline->points.size()) + road_cnt += 2; + else + road_cnt++; + + // DAEDITOR3.conNote("cross %p: %p pts, %p road ends, is_real=%d", + // this, points.size(), road_cnt, (road_cnt>2)); + for (int i = points.size() - 1; i >= 0; i--) + { + int old = points[i]->isRealCross; + points[i]->isRealCross = (road_cnt > 2); + + if (old != points[i]->isRealCross) + { + points[i]->spline->splineChanged = true; + changed = true; + } + } + return changed; +} + +bool HmapLandObjectEditor::traceRay(const Point3 &p, const Point3 &dir, real &maxt, Point3 *norm) +{ + if (maxt <= 0) + return false; + + int st_mask = DAEDITOR3.getEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_COLLISION); + if (!(st_mask & SplineObject::roadsSubtypeMask)) + return false; + + bool hit = false; + bool can_be_cached = fabsf(maxt * dir.x) <= TRACE_CACHE_EXTENSION && fabsf(maxt * dir.z) <= TRACE_CACHE_EXTENSION; + + if (can_be_cached) + { + Tab &splineTab = spline_cache.build(splines, p, dir) ? spline_cache.cached : splines; + + for (int i = 0; i < splineTab.size(); i++) + { + SplineObject *spline = splineTab[i]; + const BBox3 &bbox = spline->getSplineBox(); + if (p.x >= bbox[0].x && p.x <= bbox[1].x && p.z >= bbox[0].z && p.z <= bbox[1].z && spline->isCreated()) + for (int j = spline->points.size() - 1; j >= 0; j--) + { + GeomObject *geom = spline->points[j]->getRoadGeom(); + if (geom && dagGeom->geomObjectTraceRay(*geom, p, dir, maxt, norm)) + hit = true; + } + } + } + else + { + for (int i = 0; i < splines.size(); i++) + if (splines[i]->isCreated()) + for (int j = splines[i]->points.size() - 1; j >= 0; j--) + { + GeomObject *geom = splines[i]->points[j]->getRoadGeom(); + if (geom && dagGeom->geomObjectTraceRay(*geom, p, dir, maxt, norm)) + hit = true; + } + } + +#if CROSSROADS_TRACE_GEOM + for (int i = 0; i < crossRoads.size(); i++) + { + GeomObject *geom = crossRoads[i]->getRoadGeom(); + if (geom && dagGeom->geomObjectTraceRay(*geom, p, dir, maxt, norm)) + hit = true; + } +#endif + + return hit; +} +bool HmapLandObjectEditor::shadowRayHitTest(const Point3 &p, const Point3 &dir, real maxt) +{ + if (maxt <= 0) + return false; + + int st_mask = DAEDITOR3.getEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_COLLISION); + if (!(st_mask & SplineObject::roadsSubtypeMask)) + return false; + + for (int i = 0; i < splines.size(); i++) + for (int j = splines[i]->points.size() - 1; j >= 0; j--) + { + GeomObject *geom = splines[i]->points[j]->getRoadGeom(); + if (geom && dagGeom->geomObjectShadowRayHitTest(*geom, p, dir, maxt)) + return true; + } + + for (int i = 0; i < crossRoads.size(); i++) + { + GeomObject *geom = crossRoads[i]->getRoadGeom(); + if (geom && dagGeom->geomObjectShadowRayHitTest(*geom, p, dir, maxt)) + return true; + } + return false; +} +bool HmapLandObjectEditor::isColliderVisible() const +{ + return HmapLandPlugin::self->getVisible() && + (DAEDITOR3.getEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_RENDER) & SplineObject::roadsSubtypeMask); + + return false; +} + +bool HmapLandObjectEditor::LoftAndGeomCollider::traceRay(const Point3 &p, const Point3 &dir, real &maxt, Point3 *norm) +{ + if (maxt <= 0) + return false; + + bool hit = false; + if (loft) + { + ISplineGenService *splSrv = EDITORCORE->queryEditorInterface(); + if (!splSrv) + return hit; + int end_layer = loftLayerOrder < 0 ? LAYER_ORDER_MAX : min(loftLayerOrder, (int)LAYER_ORDER_MAX); + if (dir.y < -0.999) + { + for (int layer = 0; layer < end_layer; ++layer) + if (bm_loft_mask[layer].isMarked(p.x, p.z)) + if (splSrv->traceRayFoundationGeom(layer, p, dir, maxt, norm)) + hit = true; + return hit; + } + + if (splSrv->traceRayFoundationGeom(-1, p, dir, maxt, norm)) + hit = true; + } + else + { + if (dir.y < -0.999) + if (!bm_poly_mask.isMarked(p.x, p.z)) + return false; + + for (int i = 0; i < objEd.splines.size(); i++) + if (objEd.splines[i]->isCreated()) + { + const objgenerator::LandClassData *lcd = objEd.splines[i]->getLandClass(); + if (!lcd || !lcd->data || !lcd->data->genGeom || !lcd->data->genGeom->foundationGeom) + continue; + + GeomObject *geom = objEd.splines[i]->polyGeom.mainMesh; + if (geom && dagGeom->geomObjectTraceRay(*geom, p, dir, maxt, norm)) + hit = true; + + geom = objEd.splines[i]->polyGeom.borderMesh; + if (geom && dagGeom->geomObjectTraceRay(*geom, p, dir, maxt, norm)) + hit = true; + } + } + return hit; +} +bool HmapLandObjectEditor::LoftAndGeomCollider::shadowRayHitTest(const Point3 &p, const Point3 &dir, real maxt) +{ + if (maxt <= 0) + return false; + + if (loft) + { + ISplineGenService *splSrv = EDITORCORE->queryEditorInterface(); + if (!splSrv) + return false; + int end_layer = loftLayerOrder < 0 ? LAYER_ORDER_MAX : min(loftLayerOrder, (int)LAYER_ORDER_MAX); + if (dir.y < -0.999) + { + for (int layer = 0; layer < end_layer; ++layer) + if (bm_loft_mask[layer].isMarked(p.x, p.z)) + if (splSrv->shadowRayFoundationGeomHitTest(layer, p, dir, maxt)) + return true; + return false; + } + + if (splSrv->shadowRayFoundationGeomHitTest(-1, p, dir, maxt)) + return true; + } + else + { + if (dir.y < -0.999) + if (!bm_poly_mask.isMarked(p.x, p.z)) + return false; + + for (int i = 0; i < objEd.splines.size(); i++) + if (objEd.splines[i]->isCreated()) + { + const objgenerator::LandClassData *lcd = objEd.splines[i]->getLandClass(); + if (!lcd || !lcd->data || !lcd->data->genGeom || !lcd->data->genGeom->foundationGeom) + continue; + + GeomObject *geom = objEd.splines[i]->polyGeom.mainMesh; + if (geom && dagGeom->geomObjectShadowRayHitTest(*geom, p, dir, maxt)) + return true; + + geom = objEd.splines[i]->polyGeom.borderMesh; + if (geom && dagGeom->geomObjectShadowRayHitTest(*geom, p, dir, maxt)) + return true; + } + } + return false; +} +bool HmapLandObjectEditor::LoftAndGeomCollider::isColliderVisible() const { return false; } + +void HmapLandObjectEditor::moveObjects(PtrTab &obj, const Point3 &delta, IEditorCoreEngine::BasisType basis) +{ + Tab spl; + spl.reserve(32); + for (int i = 0; i < obj.size(); ++i) + if (SplineObject *s = RTTI_cast(obj[i])) + spl.push_back(s); + + for (int i = 0; i < obj.size(); ++i) + if (SplinePointObject *p = RTTI_cast(obj[i])) + if (find_value_idx(spl, p->spline) < 0) + { + p->moveObject(delta, basis); + p->spline->markModifChanged(); + } + + for (int i = 0; i < obj.size(); ++i) + { + if (RTTI_cast(obj[i])) + continue; + obj[i]->moveObject(delta, basis); + if (SplineObject *s = RTTI_cast(obj[i])) + s->markModifChanged(); + } +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlObjectsEditor.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlObjectsEditor.h new file mode 100644 index 000000000..7e83649ed --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlObjectsEditor.h @@ -0,0 +1,263 @@ +// Copyright 2023 by Gaijin Games KFT, All rights reserved. +#ifndef _DE2_PLUGIN_ROADS_ROADOBJECTSEDITOR_H_ +#define _DE2_PLUGIN_ROADS_ROADOBJECTSEDITOR_H_ +#pragma once + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class StaticGeometryContainer; +class GeomObject; +class Node; +class LandscapeEntityLibWindowHelper; +class HmapLandHoleObject; +class SplineObject; +class SplinePointObject; +class CrossRoadData; +class LandscapeEntityObject; +class SnowSourceObject; +struct NearSnowSource; + + +class HmapLandObjectEditor : public ObjectEditor, public IAssetBaseViewClient, public IAssetUpdateNotify, public IDagorEdCustomCollider +{ +public: + HmapLandObjectEditor(); + virtual ~HmapLandObjectEditor(); + + // ObjectEditor interface implementation + virtual void fillToolBar(PropertyContainerControlBase *toolbar); + virtual void updateToolbarButtons(); + + // virtual void handleCommand(int cmd); + virtual void handleKeyPress(IGenViewportWnd *wnd, int vk, int modif); + virtual void handleKeyRelease(IGenViewportWnd *wnd, int vk, int modif); + virtual bool handleMouseMove(IGenViewportWnd *wnd, int x, int y, bool inside, int buttons, int key_modif); + virtual bool handleMouseLBPress(IGenViewportWnd *wnd, int x, int y, bool inside, int buttons, int key_modif); + virtual bool handleMouseLBRelease(IGenViewportWnd *wnd, int x, int y, bool inside, int buttons, int key_modif); + virtual bool handleMouseRBPress(IGenViewportWnd *wnd, int x, int y, bool inside, int buttons, int key_modif); + virtual void gizmoStarted(); + virtual void gizmoEnded(bool apply); + + virtual void beforeRender(); + virtual void render(); + virtual void renderTrans(); + + virtual void update(real dt); + + virtual void setEditMode(int cm); + virtual void createObjectBySample(RenderableEditableObject *sample); + + virtual void onClick(int pcb_id, PropPanel2 *panel); + void autoAttachSplines(); + void makeBottomSplines(); + + // IAssetBaseViewClient + virtual void onAvClose(); + virtual void onAvAssetDblClick(const char *asset_name) {} + virtual void onAvSelectAsset(const char *asset_name); + virtual void onAvSelectFolder(const char *asset_folder_name) {} + + + // IAssetUpdateNotify interface + virtual void onLandClassAssetChanged(landclass::AssetData *data); + virtual void onLandClassAssetTexturesChanged(landclass::AssetData *data) override {} + virtual void onSplineClassAssetChanged(splineclass::AssetData *data); + + // IDagorEdCustomCollider + virtual bool traceRay(const Point3 &p, const Point3 &dir, real &maxt, Point3 *norm); + virtual bool shadowRayHitTest(const Point3 &p, const Point3 &dir, real maxt); + virtual const char *getColliderName() const { return "RoadGeom"; } + virtual bool isColliderVisible() const; + virtual void getObjNames(Tab &names, Tab &sel_names, const Tab &types); + virtual void getTypeNames(Tab &names); + virtual void onSelectedNames(const Tab &names); + + void setSelectMode(int cm); + int getSelectMode() { return selectMode; } + + void setSelectionGizmoTranformMode(bool enable); + + void clearToDefaultState(); + void save(DataBlock &blk); + void load(const DataBlock &blk); + + void save(DataBlock &splBlk, DataBlock &polBlk, DataBlock &entBlk, DataBlock <Blk, int layer); + void load(const DataBlock &splBlk, const DataBlock &polBlk, const DataBlock &entBlk, const DataBlock <Blk, int layer); + + void gatherStaticGeometry(StaticGeometryContainer &cont, int flags, bool collision, int stage); + void gatherLoftLandPts(Tab &loft_pt_cloud, Tab &water_border_polys, Tab &hmap_sweep_polys); + + void prepareCatmul(SplinePointObject *p1, SplinePointObject *p2); + void recalcCatmul(); + + float screenDistBetweenPoints(IGenViewportWnd *wnd, SplinePointObject *p1, SplinePointObject *p2); + float screenDistBetweenCursorAndPoint(IGenViewportWnd *wnd, int x, int y, SplinePointObject *p); + + void removeSpline(SplineObject *s); + + void onLandRegionChanged(float x0, float z0, float x1, float z1, bool recalc_all = false); + void clone(bool clone_seed); + + bool isCloneMode() { return cloneMode; } + bool isEditingSpline(SplineObject *spline) { return spline == curSpline; } + + void exportAsComposit(); + void splitComposits(); + void instantiateGenToEntities(); + + void exportToDag(); + void importFromDag(); + void importFromNode(const Node *node, bool &for_all, int &choosed, Tab &imps); + + void renderGeometry(bool opaque); + void renderGrassMask(); + + void onBrushPaintEnd(); + + virtual void moveObjects(PtrTab &obj, const Point3 &delta, IEditorCoreEngine::BasisType basis) override; + + //! marks cross roads where p belongs as changed + void markCrossRoadChanged(SplinePointObject *p); + + //! updates cross roads config when p is changed (if NULL, cross roads are globally rebuilt) + void updateCrossRoads(SplinePointObject *p = NULL); + + //! updates cross roads config when point is added + void updateCrossRoadsOnPointAdd(SplinePointObject *p); + + //! updates cross roads config when point is removed + void updateCrossRoadsOnPointRemove(SplinePointObject *p); + + //! generates road geometry for cross roads that are marked changed + void updateCrossRoadGeom(); + + //! updates all splines/segments marked changed + void updateSplinesGeom(); + + static void unloadRoadBuilderDll(); + + inline int splinesCount() const { return splines.size(); } + inline SplineObject *getSpline(int idx) { return splines[idx]; } + inline const SplineObject *getSpline(int idx) const { return splines[idx]; } + + void calcSnow(StaticGeometryContainer &container); + void updateSnowSources(); + + GeomObject &getClearedWaterGeom(); + void removeWaterGeom(); + + CPanelWindow *getCurrentPanelFor(RenderableEditableObject *obj); + + bool usesRendinstPlacement() const override; + +public: + class LoftAndGeomCollider : public IDagorEdCustomCollider + { + public: + LoftAndGeomCollider(bool _loft, HmapLandObjectEditor &oe) : loft(_loft), objEd(oe), loftLayerOrder(-1) {} + virtual bool traceRay(const Point3 &p, const Point3 &dir, real &maxt, Point3 *norm); + virtual bool shadowRayHitTest(const Point3 &p, const Point3 &dir, real maxt); + virtual const char *getColliderName() const { return loft ? "LoftGeom" : "PolyGeom"; } + virtual bool isColliderVisible() const; + + void setLoftLayer(int layer) { loftLayerOrder = layer; } + + protected: + bool loft; + HmapLandObjectEditor &objEd; + int loftLayerOrder; + }; + LoftAndGeomCollider loftGeomCollider, polyGeomCollider; + + Tab crossRoads; + bool requireTileTex, hasColorTex, hasLightmapTex, useMeshSurface; + String lastExportPath, lastImportPath, lastAsCompositExportPath; + bool crossRoadsChanged; + bool splinesChanged; + bool autoUpdateSpline; + float maxPointVisDist; + int generationCount; + + static int geomBuildCntLoft, geomBuildCntPoly, geomBuildCntRoad; + static int waterSurfSubtypeMask; + + struct LayersDlg : public ControlEventHandler + { + public: + LayersDlg(); + ~LayersDlg(); + + bool isVisible() const; + void show(); + void hide(); + void refillPanel(); + + virtual void onChange(int pid, PropertyContainerControlBase *panel); + virtual void onClick(int pid, PropertyContainerControlBase *panel); + virtual void onDoubleClick(int pid, PropertyContainerControlBase *panel); + virtual void onPostEvent(int pid, PropPanel2 *panel) + { + if (pid == 1) + refillPanel(); + } + + CDialogWindow *dlg; + int wr[4]; + DataBlock panelState; + }; + LayersDlg layersDlg; + +protected: + PlacementRotation buttonIdToPlacementRotation(int id); + virtual void _removeObjects(RenderableEditableObject **obj, int num, bool use_undo); + virtual void _addObjects(RenderableEditableObject **obj, int num, bool use_undo); + virtual bool canSelectObj(RenderableEditableObject *o); + + bool findTargetPos(IGenViewportWnd *wnd, int x, int y, Point3 &out, bool place_on_ri_collision = false); + void selectNewObjEntity(const char *name); + SplineObject *findSplineAndDirection(IGenViewportWnd *wnd, SplinePointObject *p, bool &dirs_equal, SplineObject *excl = NULL); + + Point3 *debugP1, *debugP2; + + SplinePointObject *catmul[4]; + + int selectMode; + int currentMode; + + Tab splines; + GeomObject *waterGeom; + + bool cloneMode; + Point3 cloneDelta; + String cloneName; + PtrTab cloneObjs; + + bool inGizmo; + DynRenderBuffer *ptDynBuf; + Point3 locAx[3]; + + Ptr curPt; + SplineObject *curSpline; + String curSplineAsset; + + Ptr newObj; + + IObjectCreator *objCreator; + bool areLandHoleBoxesVisible; + bool hideSplines; + + Tab nearSources; + + shaders::OverrideStateId zFuncLessStateId; +}; + +#endif diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlPanel.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlPanel.cpp new file mode 100644 index 000000000..ee45a6337 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlPanel.cpp @@ -0,0 +1,73 @@ +#include "hmlPanel.h" +#include +#include "hmlCm.h" + + +//============================================================================== + +HmapLandPlugin::HmapLandPanel::HmapLandPanel(HmapLandPlugin &p) : plugin(p), mPanelWindow(NULL) {} + +bool HmapLandPlugin::HmapLandPanel::showPropPanel(bool show) +{ + if (show != (bool)(mPanelWindow)) + { + if (show) + EDITORCORE->addPropPanel(PROPBAR_EDITOR_WTYPE, hdpi::_pxScaled(PROPBAR_WIDTH)); + else + EDITORCORE->removePropPanel(mPanelWindow->getParentWindowHandle()); + } + + return true; +} + + +//============================================================================== + +void HmapLandPlugin::HmapLandPanel::fillPanel(bool refill, bool schedule_regen, bool hold_pos) +{ + if (mPanelWindow) + mPanelWindow->setPostEvent(refill ? ((schedule_regen ? 2 : 1) | (hold_pos ? 4 : 0)) : 0); +} + + +void HmapLandPlugin::HmapLandPanel::onPostEvent(int pcb_id, PropPanel2 *panel) +{ + if (pcb_id) // refill + { + plugin.mainPanelState.reset(); + panel->saveState(plugin.mainPanelState); + if (pcb_id & 4) + plugin.mainPanelState.setInt("pOffset", mPanelWindow->getScrollPos()); + } + + mPanelWindow->showPanel(false); + plugin.fillPanel(*panel); + if (pcb_id & 3) + panel->loadState(plugin.mainPanelState); + if (pcb_id & 4) + mPanelWindow->setScrollPos(plugin.mainPanelState.getInt("pOffset", 0)); + + mPanelWindow->showPanel(true); + if (pcb_id & 2) // schedule_regen + plugin.onPluginMenuClick(CM_BUILD_COLORMAP); +} + + +void HmapLandPlugin::HmapLandPanel::updateLightGroup() +{ + if (mPanelWindow) + plugin.updateLightGroup(*mPanelWindow); +} + + +//============================================================================== + +void HmapLandPlugin::HmapLandPanel::onChange(int pcb_id, PropPanel2 *panel) { plugin.onChange(pcb_id, panel); } + + +//============================================================================== + +void HmapLandPlugin::HmapLandPanel::onClick(int pcb_id, PropPanel2 *panel) { plugin.onClick(pcb_id, panel); } + + +//============================================================================== diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlPanel.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlPanel.h new file mode 100644 index 000000000..4424cb0a3 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlPanel.h @@ -0,0 +1,36 @@ +#ifndef __GAIJIN_HEIGHTMAPLAND_PANEL__ +#define __GAIJIN_HEIGHTMAPLAND_PANEL__ +#pragma once + + +#include "hmlPlugin.h" + +#include + +class HmapLandPlugin::HmapLandPanel : public ControlEventHandler +{ +public: + HmapLandPanel(HmapLandPlugin &p); + + void fillPanel(bool refill = true, bool schedule_regen = false, bool hold_pos = false); + void updateLightGroup(); + bool showPropPanel(bool show); + + bool isVisible() { return (mPanelWindow) ? true : false; } + + void setPanelWindow(CPanelWindow *panel) { mPanelWindow = panel; } + CPanelWindow *getPanelWindow() const { return mPanelWindow; } + + // ControlEventHandler + + virtual void onClick(int pcb_id, PropPanel2 *panel); + virtual void onChange(int pcb_id, PropPanel2 *panel); + virtual void onPostEvent(int pcb_id, PropPanel2 *panel); + +private: + HmapLandPlugin &plugin; + CPanelWindow *mPanelWindow; +}; + + +#endif //__GAIJIN_GRASS_PANEL__ diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlPlugin.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlPlugin.cpp new file mode 100644 index 000000000..aba7f4244 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlPlugin.cpp @@ -0,0 +1,4121 @@ +#include "hmlPlugin.h" + +#include "hmlCm.h" + +#include "hmlPanel.h" +#include "recastNavMesh.h" + +#include "hmlSelTexDlg.h" +#include "landClassSlotsMgr.h" +#include "roadsSnapshot.h" + +#include "Brushes/hmlBrush.h" + +#include + +#include +#include +#include + +#include + + +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include <3d/dag_texMgr.h> +#include <3d/dag_createTex.h> +#include <3d/dag_tex3d.h> +#include +#include <3d/dag_drv3d.h> +#include + +#include + +#include + +#include +#include +#include +#include +#include // snprintf + +using hdpi::_pxScaled; + +G_STATIC_ASSERT(MAX_NAVMESHES == MAX_UI_NAVMESHES); + +#define MIN_HEIGHT_SCALE 0.01 + +size_t dagormem_max_crt_pool_sz = ~0u; + +IHmapService *HmapLandPlugin::hmlService = NULL; +IBitMaskImageMgr *HmapLandPlugin::bitMaskImgMgr = NULL; +IDagorPhys *HmapLandPlugin::dagPhys = NULL; +int HmapLandPlugin::hmapSubtypeMask = -1; +int HmapLandPlugin::lmeshSubtypeMask = -1; +int HmapLandPlugin::lmeshDetSubtypeMask = -1; +int HmapLandPlugin::grasspSubtypeMask = -1; +int HmapLandPlugin::navmeshSubtypeMask = -1; +extern bool game_res_sys_v2; +bool allow_debug_bitmap_dump = false; + +IGrassService *HmapLandPlugin::grassService = NULL; +IGPUGrassService *HmapLandPlugin::gpuGrassService = nullptr; +IWaterService *HmapLandPlugin::waterService = NULL; +ICableService *HmapLandPlugin::cableService = NULL; +IWaterProjFxService *HmapLandPlugin::waterProjectedFxSrv = NULL; + +inline bool is_pow_2(int num) { return (num && !(num & (num - 1))); } + +// returns the exponent of the greatest power of two equal-to or less than num +// ie GetPower(2) returns 1, GetPower(16) returns 4. +static inline unsigned get_power(int num) +{ + unsigned long power = 0; + _BitScanReverse(&power, num); + return power; +} + +//============================================================================== + + +HmapLandPlugin *HmapLandPlugin::self = NULL; +bool HmapLandPlugin::prepareRequiredServices() +{ + CoolConsole &con = DAGORED2->getConsole(); + + hmlService = DAGORED2->queryEditorInterface(); + if (!hmlService) + { + con.addMessage(ILogWriter::FATAL, "missing IHmapService interface"); + return false; + } + + bitMaskImgMgr = DAGORED2->queryEditorInterface(); + if (!bitMaskImgMgr) + { + con.addMessage(ILogWriter::FATAL, "missing IBitMaskImageMgr interface"); + return false; + } + + dagPhys = DAGORED2->queryEditorInterface(); + if (!dagPhys) + { + con.addMessage(ILogWriter::FATAL, "missing IDagorPhys interface"); + return false; + } + + return true; +} + + +HmapLandPlugin::HmapLandPlugin() : + hasColorTex(false), + propPanel(NULL), + currentBrushId(0), + landClsMap(*hmlService->createUint32MapStorage(512, 512, 0)), + lcmScale(1), + colorMap(*hmlService->createColorMapStorage(512, 512, 0)), + lightMapScaled(*hmlService->createUint32MapStorage(512, 512, 0)), + colorGenParamsData(NULL), + lightmapScaleFactor(1), + detDivisor(0), + detRect(0, 0, 0, 0), + hasWaterSurface(false), + waterSurfaceLevel(0), + minUnderwaterBottomDepth(2), + hasWorldOcean(true), + worldOceanExpand(100), + worldOceanShorelineTolerance(0.3), + waterMaskScale(1), + landMeshRenderer(NULL), + landMeshManager(NULL), + lmDump(NULL), + pendingLandmeshRebuild(false), + gridCellSize(1), + doAutocenter(false), + sunAzimuth(DegToRad(135)), + sunZenith(DegToRad(45)), + numDetailTextures(0), + // detailTexOffset(midmem), + calculating_shadows(false), + detailTexBlkName(midmem), + colorGenParams(midmem_ptr()), + scriptImages(midmem_ptr()), + shadowBias(0.01f), + shadowTraceDist(100), + shadowDensity(0.90f), + heightMapOffset(0, 0), + brushDlg(NULL), + noTraceNow(false), + syncLight(true), + syncDirLight(false), + meshPreviewDistance(20000.f), + meshCells(16), + meshErrorThreshold(1.f), + numMeshVertices(90000), + lod1TrisDensity(30), + importanceMaskScale(10.f), + lightmapTexId(-1), + lmlightmapTexId(BAD_TEXTUREID), + lmlightmapTex(NULL), + bluewhiteTexId(BAD_TEXTUREID), + bluewhiteTex(NULL), + exportType(EXPORT_HMAP), + lcMgr(NULL), + debugLmeshCells(false), + renderAllSplinesAlways(false), + renderSelSplinesAlways(false), + distFieldInvalid(true), + distFieldBuiltAt(0), + snowDynPreview(false), + snowSpherePreview(false), + ambSnowValue(0), + dynSnowValue(0), + snowPrevievSVId(-1), + snowValSVId(-1) +{ + lastMinHeight[0] = lastMinHeight[1] = lastHeightRange[0] = lastHeightRange[1] = MAX_REAL; + detTexIdxMap = detTexWtMap = NULL; + hmapTex[0] = hmapTex[1] = NULL; + hmapTexId[0] = hmapTexId[1] = BAD_TEXTUREID; + + pendingResetRenderer = false; + editedScriptImageIdx = -1; + esiGridW = esiGridH = 1; + esiGridStep = 1; + esiOrigin.set(0, 0); + showBlueWhiteMask = true; + showMonochromeLand = false; + + shownExportedNavMeshIdx = 0; + showExportedNavMesh = false; + showExportedCovers = false; + showExportedNavMeshContours = false; + showExpotedObstacles = false; + disableZtestForDebugNavMesh = false; + + monochromeLandCol = E3DCOLOR(20, 120, 20, 255); + showHtLevelCurves = false; + htLevelCurveStep = 5.0f, htLevelCurveThickness = 0.3f, htLevelCurveOfs = 0.0f, htLevelCurveDarkness = 0.8f; + + G_ASSERT(sizeof(detLayerDescStorage) >= sizeof(HmapBitLayerDesc)); + G_ASSERT(sizeof(impLayerDescStorage) >= sizeof(HmapBitLayerDesc)); + + heightMap.heightScale = 1; + heightMap.heightOffset = 1; + + hmlService->createStorage(heightMap, 512, 512, true); + hmlService->createStorage(heightMapDet, 1, 1, true); + hmlService->createStorage(waterHeightmapDet, 0, 0, false); + hmlService->createStorage(waterHeightmapMain, 0, 0, false); + DAGORED2->getWorkspace().getHmapSettings(requireTileTex, hasColorTex, hasLightmapTex, useMeshSurface, useNormalMap); + + DataBlock app_blk; + if (!app_blk.load(DAGORED2->getWorkspace().getAppPath())) + DAEDITOR3.conError("cannot read <%s>", DAGORED2->getWorkspace().getAppPath()); + + ::game_res_sys_v2 = app_blk.getBlockByNameEx("assets")->getBlockByName("export") != NULL; + allow_debug_bitmap_dump = app_blk.getBlockByNameEx("SDK")->getBool("allow_debug_bitmap_dump", false); + + storeNxzInLtmapTex = app_blk.getBlockByNameEx("heightMap")->getBool("storeNxzInLtmapTex", false); + + landClsLayersHandle = hmlService->createBitLayersList(DAGORED2->getWorkspace().getHmapLandClsLayersDesc()); + landClsLayer = hmlService->getBitLayersList(landClsLayersHandle); + + genHmap = hmlService->registerGenHmap("hmap", &heightMap, &landClsMap, landClsLayer, hasColorTex ? &colorMap : NULL, + hasLightmapTex ? &lightMapScaled : NULL, heightMapOffset, gridCellSize); + G_ASSERT(genHmap && "can't register as "); + + genHmap->sunColor = ldrLight.getSunLightColor(); + genHmap->skyColor = ldrLight.getSkyLightColor(); + + detLayerIdx = hmlService->findBitLayerByAttr(landClsLayersHandle, hmlService->getBitLayerAttrId(landClsLayersHandle, "detTexSlot")); + impLayerIdx = + hmlService->findBitLayerByAttr(landClsLayersHandle, hmlService->getBitLayerAttrId(landClsLayersHandle, "importanceMaskSlot")); + + String ed_cls_fn(0, "%s/assets/editable_landclass_layers.blk", DAGORED2->getWorkspace().getSdkDir()); + if (dd_file_exist(ed_cls_fn)) + { + DAEDITOR3.conNote("loading <%s>", ed_cls_fn); + DataBlock blk(ed_cls_fn); + hmlService->createDetLayerClassList(blk); + } + + if (detLayerIdx < 0) + memset(detLayerDescStorage, 0, sizeof(HmapBitLayerDesc)); + else + memcpy(detLayerDescStorage, &landClsLayer[detLayerIdx], sizeof(HmapBitLayerDesc)); + + if (impLayerIdx < 0) + memset(impLayerDescStorage, 0, sizeof(HmapBitLayerDesc)); + else + memcpy(impLayerDescStorage, &landClsLayer[impLayerIdx], sizeof(HmapBitLayerDesc)); + + debug("using HMAP settings: requireTileTex=%d, hasColorTex=%d, hasLightmapTex=%d " + "detTexLayer=%d impLayerIdx=%d", + requireTileTex, hasColorTex, hasLightmapTex, detLayerIdx, impLayerIdx); + + lcMgr = new LandClassSlotsManager(landClsLayer.size()); + onLandSizeChanged(); + + self = this; + + colorGenParamsData = new (midmem) DataBlock; + collisionArea.ofs = Point2(0, 0); + collisionArea.sz = Point2(100, 100); + collisionArea.show = false; + tileXSize = 32; + tileYSize = 32; + tileTexName = "---"; + tileTexId = BAD_TEXTUREID; + + useVertTex = false; + useVertTexForHMAP = true; + vertTexXZtile = 1; + vertTexYtile = 1; + vertTexYOffset = 0.f; + vertTexAng0 = 30; + vertTexAng1 = 90; + vertTexHorBlend = 1; + vertDetTexXZtile = 1.f; + vertDetTexYtile = 1.f; + vertDetTexYOffset = 0.f; + + + useHorizontalTex = false; + horizontalTex_TileSizeX = 128.f; + horizontalTex_TileSizeY = 128.f; + horizontalTex_OffsetX = 0.f; + horizontalTex_OffsetY = 0.f; + horizontalTex_DetailTexSizeX = 128.f; + horizontalTex_DetailTexSizeY = 128.f; + + useLandModulateColorTex = false; + landModulateColorEdge0 = 0.f; + landModulateColorEdge1 = 1.f; + + useRendinstDetail2Modulation = false; + rendinstDetail2ColorFrom = E3DCOLOR(128, 128, 128, 128); + rendinstDetail2ColorTo = E3DCOLOR(128, 128, 128, 128); + + enableGrass = false; + grassBlk = NULL; + gpuGrassBlk = nullptr; + grass.masks.clear(); + grass.defaultMinDensity = 0.2f; + grass.defaultMaxDensity = 0.75f; + grass.maxRadius = 400.f; + grass.texSize = 256; + + grass.sowPerlinFreq = 0.1; + grass.fadeDelta = 100; + grass.lodFadeDelta = 30; + grass.blendToLandDelta = 100; + + grass.noise_first_rnd = 23.1406926327792690; + grass.noise_first_val_mul = 1; + grass.noise_first_val_add = 0; + + grass.noise_second_rnd = 0.05; + grass.noise_second_val_mul = 1; + grass.noise_second_val_add = 0; + + grass.directWindMul = 1; + grass.noiseWindMul = 1; + grass.windPerlinFreq = 50000; + grass.directWindFreq = 1; + grass.directWindModulationFreq = 1; + grass.windWaveLength = 100; + grass.windToColor = 0.2; + grass.helicopterHorMul = 2; + grass.helicopterVerMul = 1; + grass.helicopterToDirectWindMul = 2; + grass.helicopterFalloff = 0.001; + + renderDebugLines = false; + isVisible = true; + + if (useNormalMap && !hasLightmapTex) + { + useNormalMap = false; + DAEDITOR3.conError("hasNormalMap=true requires hasLightmapTex to be also true!"); + } + if (storeNxzInLtmapTex && !hasLightmapTex) + { + storeNxzInLtmapTex = false; + DAEDITOR3.conError("storeNxzInLtmapTex=true requires hasLightmapTex to be also true!"); + } + if (storeNxzInLtmapTex && useNormalMap) + { + useNormalMap = false; + DAEDITOR3.conError("storeNxzInLtmapTex=true conflicts with useNormalMap=true!"); + } + + objEd.requireTileTex = requireTileTex; + objEd.hasColorTex = hasColorTex; + objEd.hasLightmapTex = hasLightmapTex; + objEd.useMeshSurface = useMeshSurface; + + navMeshBuf = dagRender->newDebugPrimitivesVbuffer("navmesh_lines_vbuf", midmem); + coversBuf = dagRender->newDebugPrimitivesVbuffer("covers_lines_vbuf", midmem); + contoursBuf = dagRender->newDebugPrimitivesVbuffer("contours_lines_vbuf", midmem); + obstaclesBuf = dagRender->newDebugPrimitivesVbuffer("obstacles_lines_vbuf", midmem); + EditLayerProps::resetLayersToDefauls(); + + IAssetService *assetSrv = DAGORED2->queryEditorInterface(); + if (assetSrv) + assetSrv->subscribeUpdateNotify(this, true, false); +} + +void HmapLandPlugin::RenderParams::init() +{ + gridStep = 1; + elemSize = 8; + radiusElems = 4; + ringElems = 3; + numLods = 4; + maxDetailLod = 2; + detailTile = 4.0; + canyonAngle = 60; + canyonFadeAngle = 10; + canyonHorTile = 10.0f; + canyonVertTile = 10.0f; + hm2YbaseForLod = 0; + showFinalHM = true; + hm2displacementQ = 1; +} + + +HmapLandPlugin::~HmapLandPlugin() +{ + detailedLandMask = NULL; + editedScriptImage = NULL; + clear_and_shrink(colorGenParams); + clear_and_shrink(genLayers); + clear_and_shrink(grassLayers); + + del_it(propPanel); + for (int i = 0; i < 2; i++) + if (hmapTex[i]) + dagRender->releaseManagedTexVerified(hmapTexId[i], hmapTex[i]); + + clearTexCache(); + hmlService->unregisterGenHmap("hmap"); + del_it(lcMgr); + del_it(detTexIdxMap); + del_it(detTexWtMap); + delete &landClsMap; + delete &colorMap; + delete &lightMapScaled; + hmlService->destroyStorage(heightMap); + hmlService->destroyStorage(heightMapDet); + hmlService->destroyStorage(waterHeightmapDet); + hmlService->destroyStorage(waterHeightmapMain); + hmlService->destroyBitLayersList(landClsLayersHandle); + landClsLayersHandle = NULL; + del_it(brushDlg); + delete colorGenParamsData; + clear_all_ptr_items(scriptImages); + + self = NULL; + + dagRender->deleteDebugPrimitivesVbuffer(navMeshBuf); + dagRender->deleteDebugPrimitivesVbuffer(coversBuf); + dagRender->deleteDebugPrimitivesVbuffer(contoursBuf); + dagRender->deleteDebugPrimitivesVbuffer(obstaclesBuf); + del_it(grassBlk); + del_it(gpuGrassBlk); + + IAssetService *assetSrv = DAGORED2->queryEditorInterface(); + if (assetSrv) + assetSrv->unsubscribeUpdateNotify(this, true, false); +} + + +//============================================================================== + +void HmapLandPlugin::createPropPanel() +{ + if (!propPanel) + propPanel = new (inimem) HmapLandPanel(*this); + + G_ASSERT(propPanel); + + // propPanel->fillToolBar(); +} + +PropPanel2 *HmapLandPlugin::getPropPanel() const { return propPanel ? propPanel->getPanelWindow() : NULL; } + + +//============================================================================== +void HmapLandPlugin::registerMenuAccelerators() +{ + DAGORED2->getWndManager()->addAccelerator(CM_REIMPORT, wingw::V_F4); + DAGORED2->getWndManager()->addAccelerator(CM_EXPORT_LOFT_MASKS, wingw::V_F9); +} +void HmapLandPlugin::createMenu(unsigned menu_id) +{ + // menu + + IMenu *mainMenu = DAGORED2->getWndManager()->getMainMenu(); + + mainMenu->addItem(menu_id, CM_CREATE_HEIGHTMAP, "Create heightmap"); + mainMenu->addItem(menu_id, CM_IMPORT_HEIGHTMAP, "Import heightmap"); + mainMenu->addItem(menu_id, CM_ERASE_HEIGHTMAP, "Erase heightmap"); + mainMenu->addSeparator(menu_id); + mainMenu->addItem(menu_id, CM_IMPORT_WATER_DET_HMAP, "Import water det heightmap"); + mainMenu->addItem(menu_id, CM_IMPORT_WATER_MAIN_HMAP, "Import water main heightmap"); + mainMenu->addItem(menu_id, CM_ERASE_WATER_HEIGHTMAPS, "Erase water heightmaps"); + mainMenu->addSeparator(menu_id); + mainMenu->addItem(menu_id, CM_REIMPORT, "Re-import changed heightmaps\tF4"); + mainMenu->addSeparator(menu_id); + mainMenu->addItem(menu_id, CM_RESCALE_HMAP, "Rescale heightmap..."); + mainMenu->addSeparator(menu_id); + + mainMenu->addItem(menu_id, CM_RESTORE_HM_BACKUP, "Revert heightmap changes\tCtrl+Alt+H"); + mainMenu->addItem(menu_id, CM_COMMIT_HM_CHANGES, "Save heightmap changes\tCtrl+H"); + mainMenu->addSeparator(menu_id); + mainMenu->addItem(menu_id, CM_MOVE_OBJECTS, "Move objects..."); + mainMenu->addSeparator(menu_id); + mainMenu->addItem(menu_id, CM_BUILD_COLORMAP, "Rebuild colors\tCtrl+G"); + mainMenu->addItem(menu_id, CM_BUILD_LIGHTMAP, "Rebuild ligting"); + mainMenu->addItem(menu_id, CM_REBUILD, "Rebuild colors and lighting\tCtrl+R"); + mainMenu->addSeparator(menu_id); + mainMenu->addItem(menu_id, CM_REBUILD_RIVERS, "Rebuild rivers"); + mainMenu->addSeparator(menu_id); + mainMenu->addItem(menu_id, CM_EXPORT_AS_COMPOSIT, "Export as composit..."); + mainMenu->addSeparator(menu_id); + mainMenu->addItem(menu_id, CM_SPLIT_COMPOSIT, "Split composits into separate objects..."); + mainMenu->addItem(menu_id, CM_INSTANTIATE_GENOBJ_INTO_ENTITIES, "Instantiate gen. objects into separate entities..."); + mainMenu->addSeparator(menu_id); + mainMenu->addItem(menu_id, CM_EXPORT_LAND_TO_GAME, "Export to game..."); + + mainMenu->addItem(menu_id, CM_EXPORT_HEIGHTMAP, "Export heightmap..."); + if (hasColorTex) + mainMenu->addItem(menu_id, CM_EXPORT_COLORMAP, "Export colormap..."); + mainMenu->addItem(menu_id, CM_EXPORT_LAYERS, "Export landClass layers..."); + mainMenu->addItem(menu_id, CM_EXPORT_LOFT_MASKS, "Export loft masks...\tF9"); + mainMenu->addSeparator(menu_id); + mainMenu->addItem(menu_id, CM_SPLINE_IMPORT_FROM_DAG, "Import from DAG..."); + mainMenu->addItem(menu_id, CM_SPLINE_EXPORT_TO_DAG, "Export to DAG..."); + mainMenu->addSeparator(menu_id); + mainMenu->addItem(menu_id, CM_COLLAPSE_MODIFIERS, "Collapse modifier(s)\tCtrl+M"); + mainMenu->addItem(menu_id, CM_UNIFY_OBJ_NAMES, "Unify object names..."); + mainMenu->addSeparator(menu_id); + mainMenu->addItem(menu_id, CM_SET_PT_VIS_DIST, "Set spline points vis. range..."); + mainMenu->addItem(menu_id, CM_HIDE_UNSELECTED_SPLINES, "Hide (inactivate) all unselected splines\tCtrl+E"); + mainMenu->addItem(menu_id, CM_UNHIDE_ALL_SPLINES, "Unhide (activate) all splines\tCtrl+Shift+E"); + mainMenu->addSeparator(menu_id); + mainMenu->addItem(menu_id, CM_AUTO_ATACH, "Auto attach splines..."); + mainMenu->addItem(menu_id, CM_MAKE_SPLINES_CROSSES, "Make crosspoints for splines..."); + mainMenu->addSeparator(menu_id); + mainMenu->addItem(menu_id, CM_MAKE_BOTTOM_SPLINES, "Make bottom splines for polygons..."); +} + + +// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ// + +bool HmapLandPlugin::getTexEntry(const char *s, String *path, String *name) const +{ + if (!s || !*s) + { + if (path) + *path = ""; + return false; + } + + String asset(DagorAsset::fpath2asset(s)), tmp_stor; + if (name) + *name = asset; + + DagorAsset *a = DAEDITOR3.getAssetByName(asset, DAEDITOR3.getAssetTypeId("tex")); + + if (a) + { + if (path && game_res_sys_v2) + path->printf(128, "%s*", a->getName()); + else if (path) + { + TextureMetaData tmd; + tmd.read(a->props, "PC"); + *path = tmd.encode(a->getTargetFilePath(), &tmp_stor); + } + return true; + } + debug("false: %s", s); + return false; +} + + +void HmapLandPlugin::refillPanel(bool schedule_regen) +{ + if (propPanel) + propPanel->fillPanel(true, schedule_regen, true); +} + +void HmapLandPlugin::fillPanel(PropPanel2 &panel) +{ + panel.clear(); + panel.disableFillAutoResize(); + + PropertyContainerControlBase *exportGroup = panel.createGroup(PID_HM_EXPORT_GRP, "Export Parameters"); + + Tab typesExport(tmpmem); + typesExport.push_back() = "Pseudo plane, no export"; // EXPORT_PSEUDO_PLANE + typesExport.push_back() = "Regular height map, 'hmap'"; // EXPORT_HMAP + if (useMeshSurface) + typesExport.push_back() = "Optimized land mesh, 'lmap'"; // EXPORT_LANDMESH + + exportGroup->createCombo(PID_HM_EXPORT_TYPE, "Export type:", typesExport, exportType); + exportGroup->createCheckBox(PID_HM_LOFT_BELOW_ALL, "Geom: render loft below all", geomLoftBelowAll); + panel.setBool(PID_HM_EXPORT_GRP, true); + + + //---Mesh + if (useMeshSurface) + { + PropertyContainerControlBase *meshGroup = panel.createGroup(PID_MESH_GRP, "Mesh"); + + meshGroup->createEditFloat(PID_MESH_PREVIEW_DISTANCE, "Preview distance", meshPreviewDistance); + if (exportType != EXPORT_PSEUDO_PLANE) + meshGroup->createButton(PID_REBUILD_MESH, "Rebuild mesh"); + // meshGroup->createEditFloat(PID_MESH_CELL_SIZE, "Cell size", meshCellSize); + meshGroup->createEditInt(PID_MESH_CELLS, "Cell Grid", meshCells); + meshGroup->createEditFloat(PID_MESH_ERROR_THRESHOLD, "Error threshold", meshErrorThreshold); + meshGroup->createEditInt(PID_NUM_MESH_VERTICES, "Vertices", numMeshVertices); + meshGroup->createTrackInt(PID_LOD1_DENSITY, "LOD1 density (%)", lod1TrisDensity, 1, 100, 1); + meshGroup->createEditFloat(PID_IMPORTANCE_MASK_SCALE, "Importance scale", importanceMaskScale); + meshGroup->createSeparator(0); + meshGroup->createCheckBox(PID_WATER_SURF, "Has water surface", hasWaterSurface); + meshGroup->createButton(PID_WATER_SET_MAT, String(128, "Water mat: <%s>", waterMatAsset.str())); + meshGroup->createEditFloat(PID_WATER_SURF_LEV, "Water surface level (m)", waterSurfaceLevel); + meshGroup->createEditFloat(PID_MIN_UNDERWATER_BOTOM_DEPTH, "Min underwater depth (m)", minUnderwaterBottomDepth); + meshGroup->createCheckBox(PID_WATER_OCEAN, "Add world ocean", hasWorldOcean); + meshGroup->createEditFloat(PID_WATER_OCEAN_EXPAND, "World ocean expand (m)", worldOceanExpand); + meshGroup->createEditFloat(PID_WATER_OCEAN_SL_TOL, "Shoreline tolerance (m)", worldOceanShorelineTolerance); + + meshGroup->createIndent(); + meshGroup->createButton(PID_WATER_SURF_REBUILD, "Rebuild water"); + + if (dagGeom->getShaderVariableId("landmesh_debug_cells_scale") >= 0) + { + meshGroup->createSeparator(0); + meshGroup->createCheckBox(PID_DEBUG_CELLS, "Highlight cells for debug", debugLmeshCells); + } + + panel.setBool(PID_MESH_GRP, true); + } + + //---Brush + PropertyContainerControlBase *maxGrp = panel.createGroup(PID_BRUSH_GRP, "Brush"); + brushes[currentBrushId]->fillParams(*maxGrp); + panel.setBool(PID_BRUSH_GRP, true); + + // Following block is not used in Warthunder version of DaEditor + /* if (exportType!=EXPORT_PSEUDO_PLANE) + { + maxGrp = panel.createGroup(PID_DETAIL_TEX_LIST_GRP, "Canyon settings"); + maxGrp->createEditFloat(PID_CANYON_ANGLE, "Canyon angle", render.canyonAngle); + maxGrp->createEditFloat(PID_CANYON_FADE_ANGLE, "Canyon fade angle", render.canyonFadeAngle); + + panel.setBool(PID_DETAIL_TEX_LIST_GRP, true); + } */ + + // grass options + if (DAGORED2->queryEditorInterface()) + { + const int PID_GRASS_GRP = 0; + grass_panel = panel.createGroup(PID_GRASS_GRP, "Grass"); + + grass_panel->createCheckBox(PID_ENABLE_GRASS, "Enable grass", enableGrass, true); + + grass_panel->createButton(PID_GRASS_LOADFROM_LEVELBLK, "Load from level.blk"); + grass_panel->createButton(PID_GRASS_ADDLAYER, "Add new grass layer"); + + // base options + int i = 0; + for (const auto &mask : grass.masks) + grass_panel->createFileButton(PID_GRASS_MASK_START + i++, mask.first, mask.second); + grass_panel->createEditFloat(PID_GRASS_DEFAULT_MIN_DENSITY, "Min density", grass.defaultMinDensity); + grass_panel->setMinMaxStep(PID_GRASS_DEFAULT_MIN_DENSITY, 0.f, 10.f, 0.01); + + grass_panel->createEditFloat(PID_GRASS_DEFAULT_MAX_DENSITY, "Max density", grass.defaultMaxDensity); + grass_panel->setMinMaxStep(PID_GRASS_DEFAULT_MAX_DENSITY, 0.f, 10.f, 0.01); + + grass_panel->createEditFloat(PID_GRASS_MAX_RADIUS, "Max radius", grass.maxRadius); + grass_panel->setMinMaxStep(PID_GRASS_MAX_RADIUS, 0.f, 10000.f, 0.5); + + grass_panel->createEditInt(PID_GRASS_TEX_SIZE, "Texture size", grass.texSize); + + grass_panel->createEditFloat(PID_GRASS_SOW_PER_LIN_FREQ, "Sow per lin. freq.", grass.sowPerlinFreq); + grass_panel->createEditFloat(PID_GRASS_FADE_DELTA, "Fade delta", grass.fadeDelta); + grass_panel->createEditFloat(PID_GRASS_LOD_FADE_DELTA, "LOD fade delta", grass.lodFadeDelta); + grass_panel->createEditFloat(PID_GRASS_BLEND_TO_LAND_DELTA, "Blend to land delta", grass.blendToLandDelta); + + grass_panel->createEditFloat(PID_GRASS_NOISE_FIRST_RND, "Noise first rnd.", grass.noise_first_rnd, 16); + grass_panel->createEditFloat(PID_GRASS_NOISE_FIRST_VAL_MUL, "Noise first val. mul.", grass.noise_first_val_mul); + grass_panel->createEditFloat(PID_GRASS_NOISE_FIRST_VAL_ADD, "Noise first val. add", grass.noise_first_val_add); + + grass_panel->createEditFloat(PID_GRASS_NOISE_SECOND_RND, "Noise second rnd.", grass.noise_second_rnd); + grass_panel->createEditFloat(PID_GRASS_NOISE_SECOND_VAL_MUL, "Noise second val. mul.", grass.noise_second_val_mul); + grass_panel->createEditFloat(PID_GRASS_NOISE_SECOND_VAL_ADD, "Noise second val. add", grass.noise_second_val_add); + + grass_panel->createEditFloat(PID_GRASS_DIRECT_WIND_MUL, "Direct wind mul.", grass.directWindMul); + grass_panel->createEditFloat(PID_GRASS_NOISE_WIND_MUL, "Noise wind mul.", grass.noiseWindMul); + grass_panel->createEditFloat(PID_GRASS_WIND_PER_LIN_FREQ, "Wind per lin. freq.", grass.windPerlinFreq); + grass_panel->createEditFloat(PID_GRASS_DIRECT_WIND_FREQ, "Direct wind freq.", grass.directWindFreq); + grass_panel->createEditFloat(PID_GRASS_DIRECT_WIND_MODULATION_FREQ, "Wind modulation freq.", grass.directWindModulationFreq); + grass_panel->createEditFloat(PID_GRASS_WIND_WAVE_LENGTH, "Wind wave length", grass.windWaveLength); + grass_panel->createEditFloat(PID_GRASS_WIND_TO_COLOR, "Wind to color", grass.windToColor); + grass_panel->createEditFloat(PID_GRASS_HELICOPTER_HOR_MUL, "Helicopter hor. mul.", grass.helicopterHorMul); + grass_panel->createEditFloat(PID_GRASS_HELICOPTER_VER_MUL, "Helicopter ver. mul.", grass.helicopterVerMul); + grass_panel->createEditFloat(PID_GRASS_HELICOPTER_TO_DIRECT_WIND_MUL, "Helicopter to direct wind mul.", + grass.helicopterToDirectWindMul); + grass_panel->createEditFloat(PID_GRASS_HELICOPTER_FALLOFF, "Helicopter falloff", grass.helicopterFalloff, 3); + + grass_panel->createSeparator(0); + + // grass layers + int grass_pid = PID_GRASS_PARAM_START; + for (int i = 0; i < grassLayers.size(); ++i) + grassLayers[i]->fillParams(grass_panel, grass_pid); + + panel.setBool(PID_GRASS_GRP, true); + } + + if (gpuGrassService && gpuGrassBlk) + gpuGrassPanel.fillPanel(gpuGrassService, gpuGrassBlk, panel); + //---Script Parameters + maxGrp = panel.createGroup(PID_SCRIPT_PARAMS_GRP, "Script Parameters"); + + maxGrp->createButton(PID_SCRIPT_FILE, String("Script: ") + ::get_file_name_wo_ext(colorGenScriptFilename)); + maxGrp->createButton(PID_RESET_SCRIPT, "Reset script"); + maxGrp->createButton(PID_RELOAD_SCRIPT, "Reload script"); + // maxGrp->createButton(PID_IMPORT_SCRIPT_IMAGE, "Import image..."); + // maxGrp->createButton(PID_CREATE_MASK, "Create mask..."); + maxGrp->createButton(PID_GENERATE_COLORMAP, "Generate color map"); + + maxGrp->createIndent(); + + int pid = PID_SCRIPT_PARAM_START; + for (int i = 0; i < colorGenParams.size(); ++i) + colorGenParams[i]->fillParams(*maxGrp, pid); + + maxGrp->createCheckBox(PID_SHOWMASK, "Show blue-white mask", showBlueWhiteMask); + + for (int i = 0; i < genLayers.size(); ++i) + genLayers[i]->fillParams(*maxGrp, pid); + G_ASSERT(pid <= PID_LAST_SCRIPT_PARAM); + maxGrp->createSeparator(0); + maxGrp->createButton(PID_ADDLAYER, "Add new gen layer"); + + panel.setBool(PID_SCRIPT_PARAMS_GRP, true); + +#if defined(USE_HMAP_ACES) +/* maxGrp = panel.createGroup(PID_TILE_OFFSET_GRP, "Tile offset"); + panel.setBool(PID_TILE_OFFSET_GRP, false); + for (unsigned int tileTexNo = 0; + tileTexNo < detailTexBlkName.size() && tileTexNo < detailTexOffset.size(); + tileTexNo++) + { + if (detailTexBlkName[tileTexNo].length() > 0) + maxGrp->createPoint2(PID_DETAIL_TEX_OFFSET_0 + tileTexNo, + ::dd_get_fname(detailTexBlkName[tileTexNo]), detailTexOffset[tileTexNo]); + }*/ +#endif + + + //---Heightmap Parameters + maxGrp = panel.createGroup(PID_HMAP_PARAMS_GRP, "Heightmap Parameters"); + maxGrp->createEditFloat(PID_GRID_CELL_SIZE, "Cell size", gridCellSize); + if (exportType != EXPORT_PSEUDO_PLANE) + { + maxGrp->createEditFloat(PID_HEIGHT_SCALE, "Height scale", heightMap.heightScale); + maxGrp->setMinMaxStep(PID_HEIGHT_SCALE, MIN_HEIGHT_SCALE, 10e6, 0.01); + maxGrp->createEditFloat(PID_HEIGHT_OFFSET, "Height offset", heightMap.heightOffset); + } + maxGrp->createPoint2(PID_HEIGHTMAP_OFFSET, "Origin offset", heightMapOffset, 2, !doAutocenter); + maxGrp->createCheckBox(PID_HEIGHTMAP_AUTOCENTER, "Automatic center", doAutocenter); + + PropertyContainerControlBase *grp; + + if (exportType != EXPORT_PSEUDO_PLANE) + { + PropertyContainerControlBase *rg1 = maxGrp->createRadioGroup(PID_LCMAP_SUBDIV, "Land class map detail"); + rg1->createRadio(PID_LCMAP_1, "1x one-to-one"); + rg1->createRadio(PID_LCMAP_2, "2x"); + rg1->createRadio(PID_LCMAP_4, "4x"); + switch (lcmScale) + { + case 1: maxGrp->setInt(PID_LCMAP_SUBDIV, PID_LCMAP_1); break; + case 2: maxGrp->setInt(PID_LCMAP_SUBDIV, PID_LCMAP_2); break; + case 4: maxGrp->setInt(PID_LCMAP_SUBDIV, PID_LCMAP_4); break; + } + + PropertyContainerControlBase *subGrpH2 = maxGrp->createGroupBox(-1, "Detailed Heightmap area"); + subGrpH2->createEditFloat(PID_GRID_H2_CELL_SIZE, "Cell size:", detDivisor ? gridCellSize / detDivisor : 0); + subGrpH2->createPoint2(PID_GRID_H2_BBOX_OFS, "Area origin:", detRect[0]); + subGrpH2->createPoint2(PID_GRID_H2_BBOX_SZ, "Area Size:", detRect.width()); + subGrpH2->createButton(PID_GRID_H2_APPLY, "Apply!"); + subGrpH2->setEnabledById(PID_GRID_H2_APPLY, false); + + // Following block is not used in Warthunder version of DaEditor + /* grp = maxGrp->createGroupBox(0, "Preload collision area"); + + grp->createPoint2(PID_HM_COLLISION_OFFSET, "Offset (in %):", collisionArea.ofs); + grp->createPoint2(PID_HM_COLLISION_SIZE, "Size (in %):", collisionArea.sz); + grp->createCheckBox(PID_HM_COLLISION_SHOW, "Show area", collisionArea.show);*/ + + + //---Renderer + grp = panel.createGroup(PID_RENDERER_GRP, "Renderer"); + grp->createEditInt(PID_RENDER_GRID_STEP, "Mesh grid step", render.gridStep); + grp->createEditInt(PID_RENDER_RADIUS_ELEMS, "1st LoD radius", render.radiusElems); + grp->createEditInt(PID_RENDER_RING_ELEMS, "LoD ring size", render.ringElems); + grp->createEditInt(PID_RENDER_NUM_LODS, "Number of LoDs", render.numLods); + grp->createEditInt(PID_RENDER_MAX_DETAIL_LOD, "Detail tex. range", render.maxDetailLod); + grp->createEditFloat(PID_RENDER_DETAIL_TILE, "Detail tex. tile", render.detailTile); + grp->createEditFloat(PID_RENDER_CANYON_HOR_TILE, "Canyon hor. tile", render.canyonHorTile); + grp->createEditFloat(PID_RENDER_CANYON_VERT_TILE, "Canyon vert. tile", render.canyonVertTile); + grp->createEditInt(PID_RENDER_ELEM_SIZE, "Mesh element size", render.elemSize); + + + grp->createSeparator(0); + PropertyContainerControlBase *rg = grp->createRadioGroup(PID_RENDER_RADIOGROUP_HM, "Show heightmap"); + + rg->createRadio(PID_RENDER_INITIAL_HM, "initial"); + rg->createRadio(PID_RENDER_FINAL_HM, "final (after modifiers)"); + grp->setInt(PID_RENDER_RADIOGROUP_HM, (render.showFinalHM) ? PID_RENDER_FINAL_HM : PID_RENDER_INITIAL_HM); + + grp->createSeparator(0); + grp->createEditInt(PID_HM2_DISPLACEMENT_Q, "HMAP displacement quality", render.hm2displacementQ); + grp->setMinMaxStep(PID_HM2_DISPLACEMENT_Q, 0, 5, 1); + grp->createSeparator(0); + + grp->createCheckBox(PID_RENDER_DEBUG_LINES, "Render polygon debug lines", renderDebugLines); + grp->createCheckBox(PID_RENDER_ALL_SPLINES_ALWAYS, "Render all splines always", renderAllSplinesAlways); + grp->createCheckBox(PID_RENDER_SEL_SPLINES_ALWAYS, "Render sel splines always", renderSelSplinesAlways); + + grp->createSeparator(0); + grp->createCheckBox(PID_MONOLAND, "Show monochrome land", showMonochromeLand); + grp->createColorBox(PID_MONOLAND_COL, "Monochrome land color", monochromeLandCol); + + grp->createSeparator(0); + grp->createColorBox(PID_GROUND_OBJECTS_COL, "Ground objects color"); + + if (dagGeom->getShaderVariableId("heightmap_show_level_curves") >= 0) + { + grp->createSeparator(0); + grp->createCheckBox(PID_HTLEVELS, "Show height level curves", showHtLevelCurves); + grp->createEditFloat(PID_HTLEVELS_STEP, "Level step, m", htLevelCurveStep); + grp->setMinMaxStep(PID_HTLEVELS_STEP, 0.01f, 100.f, 0.5); + grp->createEditFloat(PID_HTLEVELS_OFS, "Height base, m", htLevelCurveOfs); + grp->setMinMaxStep(PID_HTLEVELS_OFS, -8000, 8000.f, 1); + grp->createEditFloat(PID_HTLEVELS_THICK, "Curve thickness, m", htLevelCurveThickness); + grp->createEditFloat(PID_HTLEVELS_DARK, "Curve darkness, %", htLevelCurveDarkness * 100); + grp->setMinMaxStep(PID_HTLEVELS_DARK, 5, 100, 10); + } + grp->createEditFloat(PID_RENDER_HM2_YBASE_FOR_LOD, "Base height for LOD", render.hm2YbaseForLod); + + panel.setBool(PID_RENDERER_GRP, true); + } + + panel.setBool(PID_HMAP_PARAMS_GRP, true); + + + //---Textures (groups several rarely used panels): + PropertyContainerControlBase *landOptionsGrp = panel.createGroup(PID_LAND_TEXTURES_OPTIONS_GRP, "Textures:"); + + //---Tile detail texture + if (requireTileTex) + { + maxGrp = landOptionsGrp->createGroup(PID_TILE_TEX_GRP, "Tile detail texture"); + + maxGrp->createEditFloat(PID_TILE_SIZE_X, "Tile X size", tileXSize); + maxGrp->setMinMaxStep(PID_TILE_SIZE_X, 10e-3, 10e6, 0.001); + maxGrp->createEditFloat(PID_TILE_SIZE_Y, "Tile Y size", tileYSize); + maxGrp->setMinMaxStep(PID_TILE_SIZE_Y, 10e-3, 10e6, 0.001); + + const char *name = tileTexName; + + if (!name || !*name) + name = "---"; + + maxGrp->createButton(PID_TILE_TEX, String(128, "tex: %s", name)); + + landOptionsGrp->setBool(PID_TILE_TEX_GRP, true); + } + + + //---Land color modulate tex + // if ( requireLandColorModulateTex ) + { + maxGrp = landOptionsGrp->createGroup(PID_LAND_MODULATE_TEX_TEX_GRP, "Land color modulate tex"); + + maxGrp->createCheckBox(PID_USE_LAND_MODULATE_TEX, "Use modulate texture", useLandModulateColorTex); + + maxGrp->createButton(PID_LAND_MODULATE_TEX_NAME, String(128, "tex: %s", landModulateColorTexName.str())); + + maxGrp->createEditFloat(PID_LAND_MODULATE_EDGE0_X, "0 weight at:", landModulateColorEdge0); + maxGrp->setMinMaxStep(PID_LAND_MODULATE_EDGE0_X, 0.f, 1.f, 0.001); + maxGrp->createEditFloat(PID_LAND_MODULATE_EDGE1_X, "1 weight at:", landModulateColorEdge1); + maxGrp->setMinMaxStep(PID_LAND_MODULATE_EDGE1_X, 0.001f, 1.f, 0.001); + + landOptionsGrp->setBool(PID_LAND_MODULATE_TEX_TEX_GRP, true); + } + + + //---Landscape geometry horizontal texture + // if ( requireHorizontalTex) + { + maxGrp = landOptionsGrp->createGroup(PID_HORIZONTAL_TEX_GRP, "Horizontal texture"); + + maxGrp->createCheckBox(PID_USE_HORIZONTAL_TEX, "Use horizontal texture", useHorizontalTex); + + maxGrp->createButton(PID_HORIZONTAL_TEX_NAME, String(128, "tex: %s", horizontalTexName.str())); + maxGrp->createButton(PID_HORIZONTAL_DET_TEX_NAME, String(128, "det.tex: %s", horizontalDetailTexName.str())); + + maxGrp->createEditFloat(PID_HORIZONTAL_TILE_SIZE_X, "Tile X size", horizontalTex_TileSizeX); + maxGrp->setMinMaxStep(PID_HORIZONTAL_TILE_SIZE_X, 10e-3, 10e6, 0.1); + maxGrp->createEditFloat(PID_HORIZONTAL_TILE_SIZE_Y, "Tile Y size", horizontalTex_TileSizeY); + maxGrp->setMinMaxStep(PID_HORIZONTAL_TILE_SIZE_Y, 10e-3, 10e6, 0.1); + + maxGrp->createEditFloat(PID_HORIZONTAL_OFFSET_X, "X offset", horizontalTex_OffsetX); + maxGrp->setMinMaxStep(PID_HORIZONTAL_OFFSET_X, 10e-3, 10e6, 0.01); + maxGrp->createEditFloat(PID_HORIZONTAL_OFFSET_Y, "Y offset", horizontalTex_OffsetY); + maxGrp->setMinMaxStep(PID_HORIZONTAL_OFFSET_Y, 10e-3, 10e6, 0.01); + + maxGrp->createEditFloat(PID_HORIZONTAL_DETAIL_TILE_SIZE_X, "Detail Tile X size", horizontalTex_DetailTexSizeX); + maxGrp->setMinMaxStep(PID_HORIZONTAL_DETAIL_TILE_SIZE_X, 10e-3, 10e6, 0.1); + maxGrp->createEditFloat(PID_HORIZONTAL_DETAIL_TILE_SIZE_Y, "Detail Tile Y size", horizontalTex_DetailTexSizeY); + maxGrp->setMinMaxStep(PID_HORIZONTAL_DETAIL_TILE_SIZE_Y, 10e-3, 10e6, 0.1); + + landOptionsGrp->setBool(PID_HORIZONTAL_TEX_GRP, true); + } + + +//---Vertical texture +#if defined(USE_LMESH_ACES) + maxGrp = landOptionsGrp->createGroup(PID_VERT_TEX_GRP, "Vertical texture"); + + maxGrp->createCheckBox(PID_VERT_TEX_USE, "Use vertical texture", useVertTex); + maxGrp->createCheckBox(PID_VERT_TEX_USE_HMAP, "Use VT for detailed HMAP", useVertTexForHMAP); + maxGrp->createButton(PID_VERT_TEX_NAME, String(128, "tex: %s", vertTexName.str())); + maxGrp->createButton(PID_VERT_NM_TEX_NAME, String(128, "nm tex: %s", vertNmTexName.str())); + maxGrp->createButton(PID_VERT_DET_TEX_NAME, String(128, "det tex: %s", vertDetTexName.str())); + maxGrp->createEditFloat(PID_VERT_TEX_TILE_XZ, "XZ Tile, m", vertTexXZtile); + maxGrp->setMinMaxStep(PID_VERT_TEX_TILE_XZ, 10e-3, 10e6, 0.001); + maxGrp->createEditFloat(PID_VERT_TEX_TILE_Y, "Y Tile, m", vertTexYtile); + maxGrp->setMinMaxStep(PID_VERT_TEX_TILE_Y, 10e-3, 10e6, 0.001); + maxGrp->createEditFloat(PID_VERT_TEX_Y_OFS, "Y Offset, m", vertTexYOffset); + maxGrp->setMinMaxStep(PID_VERT_TEX_Y_OFS, -10e6, 10e6, 0.001); + maxGrp->createEditFloat(PID_VERT_TEX_ANG0, "Start angle, deg", vertTexAng0); + maxGrp->setMinMaxStep(PID_VERT_TEX_ANG0, 0, 90, 0.1); + maxGrp->createEditFloat(PID_VERT_TEX_ANG1, "Full angle, deg", vertTexAng1); + maxGrp->setMinMaxStep(PID_VERT_TEX_ANG1, 0, 90, 0.1); + maxGrp->createEditFloat(PID_VERT_TEX_HBLEND, "Horizontal blend", vertTexHorBlend); + maxGrp->setMinMaxStep(PID_VERT_TEX_HBLEND, 0, 100, 0.1); + maxGrp->createEditFloat(PID_VERT_DET_TEX_TILE_XZ, "Det XZ Tile, m", vertDetTexXZtile); + maxGrp->setMinMaxStep(PID_VERT_DET_TEX_TILE_XZ, 10e-3, 10e6, 0.001); + maxGrp->createEditFloat(PID_VERT_DET_TEX_TILE_Y, "Det Y Tile, m", vertDetTexYtile); + maxGrp->setMinMaxStep(PID_VERT_DET_TEX_TILE_Y, 10e-3, 10e6, 0.001); + maxGrp->createEditFloat(PID_VERT_DET_TEX_Y_OFS, "Det Y Offset, m", vertDetTexYOffset); + maxGrp->setMinMaxStep(PID_VERT_DET_TEX_Y_OFS, -10e6, 10e6, 0.001); + landOptionsGrp->setBool(PID_VERT_TEX_GRP, true); +#endif + + + //---Normalmap + if (exportType != EXPORT_PSEUDO_PLANE) + { + grp = landOptionsGrp->createGroup(PID_LIGHTING_GRP, "Normalmap"); + // Following block is not used in Warthunder version of DaEditor + /* + grp->createCheckBox(PID_GET_SUN_SETTINGS_AUTOMAT, "Automatic sync sun dir and color", + syncLight); + grp->createCheckBox(PID_GET_SUN_DIR_SETTINGS_AUTOMAT, "Automatic sync sun dir", + syncDirLight); + grp->createButton(PID_GET_SUN_SETTINGS, "Get sun settings", !syncLight); + grp->createColorBox(PID_SUN_LIGHT_COLOR, "Sun light color", ldrLight.sunColor, !syncLight); + grp->createEditFloat(PID_SUN_LIGHT_POWER, "Sun light power", ldrLight.sunPower, 2, !syncLight); + grp->createColorBox(PID_SPECULAR_COLOR, "Specular color", ldrLight.specularColor, !syncLight); + grp->createEditFloat(PID_SPECULAR_MUL, "Specular multiplier", ldrLight.specularMul); + grp->createEditFloat(PID_SPECULAR_POWER, "Shininess", ldrLight.specularPower); + grp->createColorBox(PID_SKY_LIGHT_COLOR, "Sky light color", ldrLight.skyColor, !syncLight); + grp->createEditFloat(PID_SKY_LIGHT_POWER, "Sky light power", + ldrLight.skyPower * 4, 2, !syncLight); + + grp->createTrackFloat(PID_SUN_AZIMUTH, "Sun azimuth", + RadToDeg(HALFPI - sunAzimuth), -180, +180, 0.01f, !syncLight && !syncDirLight); + grp->createTrackFloat(PID_SUN_ZENITH, "Sun zenith angle", + RadToDeg(sunZenith), 5, +90, 0.01f, !syncLight && !syncDirLight); + */ + + if (hasLightmapTex) + { + grp->createIndent(); + + // Following block is not used, we have normalmap only + /* if (useNormalMap) + { + grp->createButton(PID_CALC_FAST_LIGHTING, "Calculate normalmap"); + } + else*/ + { + // grp->createButton(PID_CALC_FAST_LIGHTING, "Calculate lighting (no shadows)"); + grp->createButton(PID_CALC_GOOD_LIGHTING, "Calculate normalmap"); + } + + // Following block is not used in Warthunder version of DaEditor + /* PropertyContainerControlBase *rg = grp->createRadioGroup(PID_LIGHTING_SUBDIV, + useNormalMap ? "NormalmapDetail" : "LightmapDetail"); + + rg->createRadio(PID_LIGHTING_1, "1x one-to-one"); + rg->createRadio(PID_LIGHTING_2, "2x"); + rg->createRadio(PID_LIGHTING_4, "4x"); + + int rgid = -1; + switch (lightmapScaleFactor) + { + case 1: + rgid = PID_LIGHTING_1; + break; + + case 2: + rgid = PID_LIGHTING_2; + break; + + case 4: + rgid = PID_LIGHTING_4; + break; + } + + grp->setInt(PID_LIGHTING_SUBDIV, rgid); + + if (!useNormalMap) + { + PropertyContainerControlBase* subGrp = + grp->createGroup(PID_SHADOW_GRP, "Shadows"); + subGrp->createEditFloat(PID_SHADOW_BIAS, "Shadow bias", shadowBias, 3); + subGrp->createEditFloat(PID_SHADOW_TRACE_DIST, "Shadow trace distance", shadowTraceDist); + subGrp->createEditFloat(PID_SHADOW_DENSITY, "Shadow density %", shadowDensity*100); + + panel.setBool(PID_SHADOW_GRP, true); + + subGrp = grp->createGroup(PID_SHADOW_CASTERS_GRP, "Shadow casters"); + + const int colCnt = DAGORED2->getCustomCollidersCount(); + + G_ASSERT(colCnt < PID_SHADOW_CASTER_LAST - PID_SHADOW_CASTER_FIRST); + + for (int i = 0; i < colCnt; ++i) + { + const IDagorEdCustomCollider* collider = DAGORED2->getCustomCollider(i); + + if (collider) + subGrp->createCheckBox(PID_SHADOW_CASTER_FIRST + i, collider->getColliderName(), + DAGORED2->isCustomShadowEnabled(collider)); + } + panel.setBool(PID_SHADOW_CASTERS_GRP, true); + }*/ + } + landOptionsGrp->setBool(PID_LIGHTING_GRP, true); + } + + + //---Rendinst color + { + grp = landOptionsGrp->createGroup(PID_RENDIST_DETAIL2_COLOR_GRP, "Rendinst 2-nd detail color"); + + grp->createCheckBox(PID_USE_RENDIST_DETAIL2_COLOR, "Use detail2 color", useRendinstDetail2Modulation); + + grp->createColorBox(PID_RENDIST_DETAIL2_COLOR_FROM, "From color:", rendinstDetail2ColorFrom); + grp->createColorBox(PID_RENDIST_DETAIL2_COLOR_TO, "From to:", rendinstDetail2ColorTo); // e3dcolor( + + landOptionsGrp->setBool(PID_RENDIST_DETAIL2_COLOR_GRP, true); + } + + panel.setBool(PID_LAND_TEXTURES_OPTIONS_GRP, true); + + //---Navigation meshes + { + grp = panel.createGroup(PID_NAVMESH_COMMON_GRP, "Navigation meshes"); + + for (int pcb_id = PID_NAVMESH_EXPORT_START; pcb_id <= PID_NAVMESH_EXPORT_END; ++pcb_id) + { + const int navMeshIdx = pcb_id - PID_NAVMESH_EXPORT_START; + grp->createCheckBox(pcb_id, String(50, "Export nav mesh #%d", navMeshIdx + 1), + navMeshProps[navMeshIdx].getBool("export", false)); + } + grp->createSeparator(0); + + Tab navMeshes(tmpmem); + for (int navMeshIdx = 0; navMeshIdx < MAX_UI_NAVMESHES; ++navMeshIdx) + navMeshes.push_back() = String(50, "Nav mesh #%d", navMeshIdx + 1); + + grp->createCombo(PID_NAVMESH_SHOWN_NAVMESH, "Displayed nav mesh:", navMeshes, shownExportedNavMeshIdx); + grp->createCheckBox(PID_NAVMESH_EXP_SHOW, "Show exported nav mesh", showExportedNavMesh); + grp->createCheckBox(PID_NAVMESH_COVERS_SHOW, "Show exported covers", showExportedCovers, /*enabled*/ shownExportedNavMeshIdx == 0); + grp->createCheckBox(PID_NAVMESH_CONTOURS_SHOW, "Show exported contours", showExportedNavMeshContours, + /*enabled*/ shownExportedNavMeshIdx == 0); + grp->createCheckBox(PID_NAVMESH_OBSTACLES_SHOW, "Show exported obstacles", showExpotedObstacles); + grp->createCheckBox(PID_NAVMESH_DISABLE_ZTEST, "Disable ztest for debug geometry", disableZtestForDebugNavMesh); + grp->createButton(PID_NAVMESH_BUILD, "Build nav mesh!"); + } + + for (int navMeshIdx = 0; navMeshIdx < MAX_UI_NAVMESHES; ++navMeshIdx) + { + //---Nav mesh jump links and covers + const int baseOfs = PID_NAVMESH_START + NM_PARAMS_COUNT * navMeshIdx; + + if (navMeshIdx == 0) + { + char groupName[100]; + SNPRINTF(groupName, sizeof(groupName), "Nav mesh #%d jump links / covers", navMeshIdx + 1); + grp = panel.createGroup(baseOfs + NM_PARAM_JLK_AND_CVRS_GRP, groupName); + grp->createEditInt(baseOfs + NM_PARAM_JLK_CVRS_EXTRA_CELLS, "extra cells", navMeshProps[navMeshIdx].getInt("jlkExtraCells", 32)); + grp->createCheckBox(baseOfs + NM_PARAM_EMRG_ENABLED, "edge simplification", + navMeshProps[navMeshIdx].getBool("simplificationEdgeEnabled", true)); + grp->createPoint2(baseOfs + NM_PARAM_EMRG_WALK_PRECISION, "walk check precision, m", + navMeshProps[navMeshIdx].getPoint2("walkPrecision", + Point2(navMeshProps[navMeshIdx].getReal("agentRadius", 2.0f), navMeshProps[navMeshIdx].getReal("agentMaxClimb", 1.5f)))); + grp->createEditFloat(baseOfs + NM_PARAM_EMRG_EXTRUDE_LIMIT, "extrude line limit, m", + navMeshProps[navMeshIdx].getReal("extrudeLimit", 0.3f)); + grp->createEditFloat(baseOfs + NM_PARAM_EMRG_EXTRUDE_MISTAKE, "extrude line error, m", + navMeshProps[navMeshIdx].getReal("extrudeError", 0.4f)); + grp->createEditFloat(baseOfs + NM_PARAM_EMRG_SAFE_CUT_LIMIT, "line safe cut limit, m", + navMeshProps[navMeshIdx].getReal("safeCutLimit", 0.5f)); + grp->createEditFloat(baseOfs + NM_PARAM_EMRG_UNSAFE_CUT_LIMIT, "line unsafe cut limit, m", + navMeshProps[navMeshIdx].getReal("unsafeCutLimit", 0.2f)); + grp->createEditFloat(baseOfs + NM_PARAM_EMRG_UNSAFE_MAX_CUT_SPACE, "max unsafe cut space, m2", + navMeshProps[navMeshIdx].getReal("maxUnsafeCutSpace", 1.f)); + + grp->createSeparator(0); + grp->createCheckBox(baseOfs + NM_PARAM_JLK_ENABLED, "Export jump links mesh", + navMeshProps[navMeshIdx].getBool("jumpLinksEnabled", false)); + grp->createEditFloat(baseOfs + NM_PARAM_JLK_JUMP_OVER_HEIGHT, "jump over height, m", + navMeshProps[navMeshIdx].getReal("jumpLinksHeight", 2.0f)); + const float typoDefJumpLength = navMeshProps[navMeshIdx].getReal("jumpLinksLenght", 2.5f); + grp->createEditFloat(baseOfs + NM_PARAM_JLK_JUMP_LENGTH, "jump length, m", + navMeshProps[navMeshIdx].getReal("jumpLinksLength", typoDefJumpLength)); + grp->createEditFloat(baseOfs + NM_PARAM_JLK_MIN_WIDTH, "min width, m", navMeshProps[navMeshIdx].getReal("jumpLinksWidth", 1.0f)); + grp->createEditFloat(baseOfs + NM_PARAM_JLK_DH_THRESHOLD, "delta height threshold, m", + navMeshProps[navMeshIdx].getReal("jumpLinksDeltaHeightTreshold", 0.5f)); + grp->createEditFloat(baseOfs + NM_PARAM_JLK_MERGE_ANGLE, "merge delta angle, deg", + navMeshProps[navMeshIdx].getReal("jumpLinksMergeAngle", 15.0f)); + grp->createEditFloat(baseOfs + NM_PARAM_JLK_MERGE_DIST, "max angle between edges, deg", + navMeshProps[navMeshIdx].getReal("jumpLinksMergeDist", 5.0f)); + grp->createEditFloat(baseOfs + NM_PARAM_JLK_CPLX_THRESHOLD, "complex link threshold", + navMeshProps[navMeshIdx].getReal("complexJumpTheshold", 0.0f)); + grp->createCheckBox(baseOfs + NM_PARAM_JLK_CROSS_OBSTACLES_WITH_JUMPLINKS, "cross obstacles with jlinks", + navMeshProps[navMeshIdx].getBool("crossObstaclesWithJumplinks", false)); + + grp->createSeparator(0); + grp->createCheckBox(baseOfs + NM_PARAM_CVRS_ENABLED, "Export covers", navMeshProps[navMeshIdx].getBool("coversEnabled", false)); + + Tab coversType(tmpmem); + coversType.push_back() = "Standard"; + coversType.push_back() = "Alternative 1"; + int covType = navMeshProps[navMeshIdx].getInt("coversTypeGen", 0); + const bool covEnable1 = (covType == 0); + grp->createCombo(baseOfs + NM_PARAM_CVRS_TYPEGEN, "Covers generation:", coversType, covType); + grp->createEditFloat(baseOfs + NM_PARAM_CVRS_MAX_HEIGHT, "max height, m", + navMeshProps[navMeshIdx].getReal("coversMaxHeight", 2.f), 2, covEnable1); + grp->createEditFloat(baseOfs + NM_PARAM_CVRS_MIN_HEIGHT, "min height, m", + navMeshProps[navMeshIdx].getReal("coversMinHeight", 1.f), 2, covEnable1); + grp->createEditFloat(baseOfs + NM_PARAM_CVRS_MIN_WIDTH, "min width, m", navMeshProps[navMeshIdx].getReal("coversWidth", 1.f), 2, + covEnable1); + grp->createEditFloat(baseOfs + NM_PARAM_CVRS_MIN_DEPTH, "min depth, m", navMeshProps[navMeshIdx].getReal("coversDepth", 1.f), 2, + covEnable1); + grp->createEditFloat(baseOfs + NM_PARAM_CVRS_SHOOT_WINDOW_HEIGHT, "min window for shoot, m", + navMeshProps[navMeshIdx].getReal("coversShootWindow", 0.4f), 2, covEnable1); + grp->createEditFloat(baseOfs + NM_PARAM_CVRS_COLLISION_TARNSP_THRESHOLD, "collision transparent, 0 - 1", + navMeshProps[navMeshIdx].getReal("coversTransparent", 0.8f), 2, covEnable1); + grp->createEditFloat(baseOfs + NM_PARAM_CVRS_MERGE_DIST, "covers merge distance, m", + navMeshProps[navMeshIdx].getReal("coversMergeDist", 0.3f), 2, covEnable1); + grp->createEditFloat(baseOfs + NM_PARAM_CVRS_DH_THRESHOLD, "delta height threshold, m", + navMeshProps[navMeshIdx].getReal("coversDeltaHeightTreshold", 0.2f), 2, covEnable1); + grp->createEditFloat(baseOfs + NM_PARAM_CVRS_SHOOT_DEPTH_CHECK, "checked shoot depth, m", + navMeshProps[navMeshIdx].getReal("coversShootDepth", 3.f), 2, covEnable1); + grp->createEditFloat(baseOfs + NM_PARAM_CVRS_SHOOT_HEIGHT, "shoot height, m", + navMeshProps[navMeshIdx].getReal("coversShootHeight", 1.5f), 2, covEnable1); + grp->createEditFloat(baseOfs + NM_PARAM_CVRS_OPENING_TRESHOLD, "open air treshold, 0-1", + navMeshProps[navMeshIdx].getReal("openingTreshold", 0.9f)); + grp->createEditFloat(baseOfs + NM_PARAM_CVRS_BOX_OFFSET, "visible box offset, m", + navMeshProps[navMeshIdx].getReal("visibleBoxOffset", 1.f)); + + // NOTE: uncomment only for tests + // grp->createEditFloat(baseOfs + NM_PARAM_CVRS_TEST_X, "test X", navMeshProps[navMeshIdx].getReal("coversTestX", 0.0f)); + // grp->createEditFloat(baseOfs + NM_PARAM_CVRS_TEST_Y, "test Y", navMeshProps[navMeshIdx].getReal("coversTestY", 0.0f)); + // grp->createEditFloat(baseOfs + NM_PARAM_CVRS_TEST_Z, "test Z", navMeshProps[navMeshIdx].getReal("coversTestZ", 0.0f)); + + panel.setBool(baseOfs + NM_PARAM_JLK_AND_CVRS_GRP, true); + } + + + //---Nav mesh + { + char groupName[100]; + SNPRINTF(groupName, sizeof(groupName), "Nav mesh #%d setup", navMeshIdx + 1); + grp = panel.createGroup(baseOfs + NM_PARAM_GRP, groupName); + grp->createCheckBox(baseOfs + NM_PARAM_EXP, String(50, "Export nav mesh #%d", navMeshIdx + 1), + navMeshProps[navMeshIdx].getBool("export", false)); + if (navMeshIdx != 0) + grp->createEditBox(baseOfs + NM_PARAM_KIND, "Nav mesh kind", navMeshProps[navMeshIdx].getStr("kind", "")); + + PropertyContainerControlBase *rg = grp->createRadioGroup(baseOfs + NM_PARAM_AREATYPE, "Navigation area"); + rg->createRadio(baseOfs + NM_PARAM_AREATYPE_MAIN, "Full main HMAP area"); + rg->createRadio(baseOfs + NM_PARAM_AREATYPE_DET, "Detailed HMAP area"); + rg->createRadio(baseOfs + NM_PARAM_AREATYPE_RECT, "Explicit rectangle"); + + if (navMeshProps[navMeshIdx].getInt("navArea", 0) <= NM_PARAM_AREATYPE_RECT - NM_PARAM_AREATYPE_MAIN) + grp->setInt(baseOfs + NM_PARAM_AREATYPE, baseOfs + NM_PARAM_AREATYPE_MAIN + navMeshProps[navMeshIdx].getInt("navArea", 0)); + else + grp->setInt(baseOfs + NM_PARAM_AREATYPE, baseOfs + NM_PARAM_AREATYPE_MAIN); + + grp->createPoint2(baseOfs + NM_PARAM_AREATYPE_RECT0, " rectangle min pos", + navMeshProps[navMeshIdx].getPoint2("rect0", Point2(0, 0))); + grp->createPoint2(baseOfs + NM_PARAM_AREATYPE_RECT1, " rectangle max pos", + navMeshProps[navMeshIdx].getPoint2("rect1", Point2(1000, 1000))); + + panel.setEnabledById(baseOfs + NM_PARAM_AREATYPE_RECT0, + panel.getInt(baseOfs + NM_PARAM_AREATYPE) == baseOfs + NM_PARAM_AREATYPE_RECT); + panel.setEnabledById(baseOfs + NM_PARAM_AREATYPE_RECT1, + panel.getInt(baseOfs + NM_PARAM_AREATYPE) == baseOfs + NM_PARAM_AREATYPE_RECT); + + + grp->createSeparator(0); + + PropertyContainerControlBase *rgType = grp->createRadioGroup(baseOfs + NM_PARAM_EXPORT_TYPE, "Navmesh type"); + rgType->createRadio(baseOfs + NM_PARAM_EXPORT_TYPE_WATER, "Water navigation"); + rgType->createRadio(baseOfs + NM_PARAM_EXPORT_TYPE_SPLINES, "Splines navigation"); + rgType->createRadio(baseOfs + NM_PARAM_EXPORT_TYPE_HEIGHT_FROM_ABOVE, "Height from above"); + rgType->createRadio(baseOfs + NM_PARAM_EXPORT_TYPE_GEOMETRY, "Detailed geometry"); + rgType->createRadio(baseOfs + NM_PARAM_EXPORT_TYPE_WATER_AND_GEOMETRY, "Water and geometry"); + + NavmeshExportType navmeshExportType = + navmesh_export_type_name_to_enum(navMeshProps[navMeshIdx].getStr("navmeshExportType", "invalid")); + if (navmeshExportType != NavmeshExportType::INVALID) + grp->setInt(baseOfs + NM_PARAM_EXPORT_TYPE, baseOfs + NM_PARAM_EXPORT_TYPE_WATER + int(navmeshExportType)); + + grp->createSeparator(0); + + grp->createCheckBox(baseOfs + NM_PARAM_WATER, "Use water surface", navMeshProps[navMeshIdx].getBool("hasWater", false)); + panel.setEnabledById(baseOfs + NM_PARAM_WATER, navmeshExportType != NavmeshExportType::WATER); + + grp->createEditFloat(baseOfs + NM_PARAM_WATER_LEV, "Water surface level, m", navMeshProps[navMeshIdx].getReal("waterLev", 0.0f)); + grp->createSeparator(0); + + grp->createEditFloat(baseOfs + NM_PARAM_CELL_DXZ, "Cell size (XZ), m", navMeshProps[navMeshIdx].getReal("cellSize", 2.0f)); + grp->createEditFloat(baseOfs + NM_PARAM_CELL_DY, "Cell size (Y), m", navMeshProps[navMeshIdx].getReal("cellHeight", 0.125f)); + grp->createEditFloat(baseOfs + NM_PARAM_TRACE_STEP, "Trace step (XZ), m", + navMeshProps[navMeshIdx].getReal("traceStep", navMeshProps[navMeshIdx].getReal("cellSize", 2.f))); + grp->createEditFloat(baseOfs + NM_PARAM_CELL_A_HT, "Agent height, m", navMeshProps[navMeshIdx].getReal("agentHeight", 3.0f)); + grp->createEditFloat(baseOfs + NM_PARAM_CELL_A_RAD, "Agent radius, m", navMeshProps[navMeshIdx].getReal("agentRadius", 2.0f)); + grp->createEditFloat(baseOfs + NM_PARAM_CELL_A_SLOPE, "Max agent slope, deg", + navMeshProps[navMeshIdx].getReal("agentMaxSlope", 30.0f)); + grp->createEditFloat(baseOfs + NM_PARAM_CELL_A_CLIMB, "Max agent climb, m", + navMeshProps[navMeshIdx].getReal("agentMaxClimb", 1.5f)); + grp->createEditFloat(baseOfs + NM_PARAM_CELL_EDGE_MAX_LEN, "Edge max len, m", + navMeshProps[navMeshIdx].getReal("edgeMaxLen", 128.0f)); + grp->createEditFloat(baseOfs + NM_PARAM_CELL_EDGE_MAX_ERR, "Edge max error, m", + navMeshProps[navMeshIdx].getReal("edgeMaxError", 2.0f)); + grp->createEditFloat(baseOfs + NM_PARAM_CELL_REG_MIN_SZ, "Region min size, m2", + navMeshProps[navMeshIdx].getReal("regionMinSize", 9.0f)); + grp->createEditFloat(baseOfs + NM_PARAM_CELL_REG_MERGE_SZ, "Region merge size, m2", + navMeshProps[navMeshIdx].getReal("regionMergeSize", 100.0f)); + grp->createEditInt(baseOfs + NM_PARAM_CELL_VERTS_PER_POLY, "Vertices per polygon", + navMeshProps[navMeshIdx].getInt("vertsPerPoly", 3)); + grp->createEditFloat(baseOfs + NM_PARAM_CELL_DET_SAMPLE, "Detail sample dist, m", + navMeshProps[navMeshIdx].getReal("detailSampleDist", 3.0f)); + grp->createEditFloat(baseOfs + NM_PARAM_CELL_DET_MAX_ERR, "Detail sample max error, m", + navMeshProps[navMeshIdx].getReal("detailSampleMaxError", 0.25f)); + grp->createEditFloat(baseOfs + NM_PARAM_CROSSING_WATER_DEPTH, "Crossing water depth, m", + navMeshProps[navMeshIdx].getReal("crossingWaterDepth", 0.f)); + grp->createCheckBox(baseOfs + NM_PARAM_PREFAB_COLLISION, "Use prefab collision", + navMeshProps[navMeshIdx].getBool("usePrefabCollision", true)); + grp->createSeparator(0); + Tab typesNavMesh(tmpmem); + typesNavMesh.push_back() = "Simple"; + typesNavMesh.push_back() = "Tiled"; + typesNavMesh.push_back() = "TileCached"; + int navMeshType = navMeshProps[navMeshIdx].getInt("navMeshType", + navMeshProps[navMeshIdx].getBool("tiled", false) ? pathfinder::NMT_TILED : pathfinder::NMT_SIMPLE); + grp->createCombo(baseOfs + NM_PARAM_TYPE, "Nav mesh type:", typesNavMesh, navMeshType); + grp->createEditInt(baseOfs + NM_PARAM_TILE_SZ, "Tile size (XZ), cells", navMeshProps[navMeshIdx].getInt("tileCells", 128)); + grp->createEditFloat(baseOfs + NM_PARAM_BUCKET_SZ, "Bucket size, m", navMeshProps[navMeshIdx].getReal("bucketSize", 200.0f)); + panel.setEnabledById(baseOfs + NM_PARAM_BUCKET_SZ, navMeshType == pathfinder::NMT_TILECACHED); + grp->createSeparator(0); + grp->createCheckBox(baseOfs + NM_PARAM_DROP_RESULT_ON_COLLISION, "Drop navmesh on collision", + navMeshProps[navMeshIdx].getBool("dropNavmeshOnCollision", false)); + grp->createEditFloat(baseOfs + NM_PARAM_DROP_RESULT_ON_COLLISION_TRACE_OFFSET, "Trace offset, m", 0.3f, 2, + navMeshProps[navMeshIdx].getBool("dropNavmeshOnCollision", false)); + grp->createEditFloat(baseOfs + NM_PARAM_DROP_RESULT_ON_COLLISION_TRACE_LEN, "Trace length, m", 0.3f, 2, + navMeshProps[navMeshIdx].getBool("dropNavmeshOnCollision", false)); + grp->createSeparator(0); + grp->createEditInt(baseOfs + NM_PARAM_COMPRESS_RATIO, "Compress ratio", 19, true); + grp->createIndent(); + panel.setBool(baseOfs + NM_PARAM_GRP, true); + } + } + + //---Snow + if (isSnowAvailable()) + { + grp = panel.createGroup(PID_SNOW_GRP, "Snow"); + grp->createCheckBox(PID_SNOW_PREVIEW, "Dynamic snow preview", snowDynPreview); + grp->createCheckBox(PID_SNOW_SPHERE_PREVIEW, "Snow sources preview", snowSpherePreview); + grp->createTrackFloat(PID_DYN_SNOW, "Dynamic snow coverage", dynSnowValue, 0, 1, 0.001); + grp->createButton(PID_COPY_SNOW, "Copy Dyn to Amb"); + grp->createTrackFloat(PID_AMB_SNOW, "Ambient snow coverage", ambSnowValue, 0, 1, 0.001); + grp->createStatic(0, "Color: Environment/Shader global vars"); + + panel.setEnabledById(PID_SNOW_SPHERE_PREVIEW, snowDynPreview); + panel.setEnabledById(PID_DYN_SNOW, snowDynPreview); + panel.setEnabledById(PID_COPY_SNOW, snowDynPreview); + panel.setBool(PID_SNOW_GRP, true); + } + + panel.restoreFillAutoResize(); + panel.loadState(mainPanelState); +} + + +void HmapLandPlugin::updateLightGroup(PropPanel2 &panel) +{ + panel.setColor(PID_SUN_LIGHT_COLOR, ldrLight.sunColor); + panel.setFloat(PID_SUN_LIGHT_POWER, ldrLight.sunPower); + panel.setColor(PID_SPECULAR_COLOR, ldrLight.specularColor); + panel.setFloat(PID_SPECULAR_MUL, ldrLight.specularMul); + panel.setFloat(PID_SPECULAR_POWER, ldrLight.specularPower); + panel.setColor(PID_SKY_LIGHT_COLOR, ldrLight.skyColor); + panel.setFloat(PID_SKY_LIGHT_POWER, ldrLight.skyPower * 4); + panel.setFloat(PID_SUN_AZIMUTH, (RadToDeg(HALFPI - sunAzimuth))); + panel.setFloat(PID_SUN_ZENITH, (RadToDeg(sunZenith))); +} + + +// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ// + +void HmapLandPlugin::onChange(int pcb_id, PropPanel2 *panel) +{ + + if (pcb_id >= PID_SCRIPT_PARAM_START && pcb_id <= PID_LAST_SCRIPT_PARAM) + { + for (int i = 0; i < colorGenParams.size(); ++i) + colorGenParams[i]->onPPChange(pcb_id, *panel); + for (int i = 0; i < genLayers.size(); ++i) + if (genLayers[i]->onPPChangeEx(pcb_id, *panel)) + break; + } + + if (pcb_id >= PID_GRASS_PARAM_START && pcb_id <= PID_LAST_GRASS_PARAM) + { + for (int i = 0; i < grassLayers.size(); ++i) + if (grassLayers[i]->onPPChangeEx(pcb_id, *panel)) + { + HmapLandPlugin::grassService->resetLayersVB(); + break; + } + } + + // if (!brushDlg->isDialogVisible() && !brushDlg->isDialogClosed()) + // return; + + // PropPanel2 &dlgPanel = brushDlg->getPropPanel(); + // PropPanel2 &plugPanel = *propPanel->getPanel(); + // PropPanel2 &panel = brushDlg->isDialogVisible() ? dlgPanel : plugPanel; + + + switch (pcb_id) + { + case PID_SUN_LIGHT_COLOR: + ldrLight.sunColor = panel->getColor(pcb_id); + updateRendererLighting(); + return; + + case PID_SKY_LIGHT_COLOR: + ldrLight.skyColor = panel->getColor(pcb_id); + updateRendererLighting(); + return; + + case PID_SPECULAR_COLOR: + ldrLight.specularColor = panel->getColor(pcb_id); + updateRendererLighting(); + return; + + case PID_SUN_LIGHT_POWER: + ldrLight.sunPower = panel->getFloat(pcb_id); + updateRendererLighting(); + return; + + case PID_SKY_LIGHT_POWER: + ldrLight.skyPower = panel->getFloat(pcb_id) / 4; + updateRendererLighting(); + return; + + case PID_SPECULAR_MUL: + ldrLight.specularMul = panel->getFloat(pcb_id); + updateRendererLighting(); + return; + + case PID_SPECULAR_POWER: + ldrLight.specularPower = panel->getFloat(pcb_id); + updateRendererLighting(); + return; + + case PID_GET_SUN_SETTINGS_AUTOMAT: + syncLight = panel->getBool(pcb_id); + panel->setEnabledById(PID_GET_SUN_SETTINGS, !syncLight); + + panel->setEnabledById(PID_SUN_LIGHT_COLOR, !syncLight); + panel->setEnabledById(PID_SUN_LIGHT_POWER, !syncLight); + panel->setEnabledById(PID_SKY_LIGHT_COLOR, !syncLight); + panel->setEnabledById(PID_SKY_LIGHT_POWER, !syncLight); + panel->setEnabledById(PID_SPECULAR_COLOR, !syncLight); + + panel->setEnabledById(PID_SUN_AZIMUTH, !syncLight && !syncDirLight); + panel->setEnabledById(PID_SUN_ZENITH, !syncLight && !syncDirLight); + ldrLight.specularMul = panel->getFloat(PID_SPECULAR_MUL); + ldrLight.specularPower = panel->getFloat(PID_SPECULAR_POWER); + + if (!syncLight) + { + ldrLight.sunColor = panel->getColor(PID_SUN_LIGHT_COLOR); + ldrLight.skyColor = panel->getColor(PID_SKY_LIGHT_COLOR); + ldrLight.specularColor = panel->getColor(PID_SPECULAR_COLOR); + ldrLight.sunPower = panel->getFloat(PID_SUN_LIGHT_POWER); + ldrLight.skyPower = panel->getFloat(PID_SKY_LIGHT_POWER) / 4; + if (!syncDirLight) + { + sunAzimuth = HALFPI - DegToRad(panel->getFloat(PID_SUN_AZIMUTH)); + sunZenith = DegToRad(panel->getFloat(PID_SUN_ZENITH)); + } + } + else + { + getAllSunSettings(); + updateLightGroup(*panel); + } + + updateRendererLighting(); + + return; + + case PID_GET_SUN_DIR_SETTINGS_AUTOMAT: + syncDirLight = panel->getBool(pcb_id); + panel->setEnabledById(PID_SUN_AZIMUTH, !syncLight && !syncDirLight); + panel->setEnabledById(PID_SUN_ZENITH, !syncLight && !syncDirLight); + + if (!syncLight && !syncDirLight) + { + sunAzimuth = HALFPI - DegToRad(panel->getFloat(PID_SUN_AZIMUTH)); + sunZenith = DegToRad(panel->getFloat(PID_SUN_ZENITH)); + } + else + { + getDirectionSunSettings(); + panel->setFloat(PID_SUN_AZIMUTH, (RadToDeg(HALFPI - sunAzimuth))); + panel->setFloat(PID_SUN_ZENITH, (RadToDeg(sunZenith))); + } + + updateRendererLighting(); + + return; + + case PID_MESH_PREVIEW_DISTANCE: + meshPreviewDistance = panel->getFloat(pcb_id); + resetRenderer(); + return; + + case PID_MESH_CELLS: + meshCells = panel->getInt(pcb_id); + meshCells = get_closest_pow2(meshCells); + meshCells = clamp(meshCells, 1, 256); + return; + + case PID_MESH_ERROR_THRESHOLD: meshErrorThreshold = panel->getFloat(pcb_id); return; + + case PID_NUM_MESH_VERTICES: numMeshVertices = panel->getInt(pcb_id); return; + + case PID_LOD1_DENSITY: lod1TrisDensity = panel->getInt(pcb_id); return; + + case PID_IMPORTANCE_MASK_SCALE: importanceMaskScale = panel->getFloat(pcb_id); return; + + case PID_WATER_SURF: hasWaterSurface = panel->getBool(pcb_id); return; + case PID_WATER_SURF_LEV: waterSurfaceLevel = panel->getFloat(pcb_id); return; + case PID_MIN_UNDERWATER_BOTOM_DEPTH: minUnderwaterBottomDepth = panel->getFloat(pcb_id); return; + case PID_WATER_OCEAN: hasWorldOcean = panel->getBool(pcb_id); return; + case PID_WATER_OCEAN_EXPAND: worldOceanExpand = panel->getFloat(pcb_id); return; + case PID_WATER_OCEAN_SL_TOL: worldOceanShorelineTolerance = panel->getFloat(pcb_id); return; + + case PID_DEBUG_CELLS: + debugLmeshCells = panel->getBool(pcb_id); + if (landMeshRenderer) + landMeshRenderer->setCellsDebug(debugLmeshCells); + break; + + case PID_HM_EXPORT_TYPE: + exportType = panel->getInt(pcb_id); + genHmap->altCollider = (exportType == EXPORT_LANDMESH) ? this : NULL; + onLandSizeChanged(); + onWholeLandChanged(); + resetRenderer(); + return; + + case PID_HM_LOFT_BELOW_ALL: + geomLoftBelowAll = panel->getBool(pcb_id); + if (hmlService) + hmlService->invalidateClipmap(false); + DAGORED2->invalidateViewportCache(); + break; + + case PID_SNOW_PREVIEW: + case PID_DYN_SNOW: + case PID_SNOW_SPHERE_PREVIEW: + snowDynPreview = panel->getBool(PID_SNOW_PREVIEW); + snowSpherePreview = panel->getBool(PID_SNOW_SPHERE_PREVIEW); + dynSnowValue = panel->getFloat(PID_DYN_SNOW); + + if (isSnowAvailable()) + { + int p_val = (snowDynPreview && snowSpherePreview) ? 2 : (snowDynPreview ? 1 : 0); + + dagGeom->shaderGlobalSetInt(snowPrevievSVId, p_val); + dagGeom->shaderGlobalSetReal(snowValSVId, dynSnowValue); + if (snowSpherePreview) + updateSnowSources(); + } + + panel->setEnabledById(PID_SNOW_SPHERE_PREVIEW, snowDynPreview); + panel->setEnabledById(PID_DYN_SNOW, snowDynPreview); + panel->setEnabledById(PID_COPY_SNOW, snowDynPreview); + break; + + case PID_AMB_SNOW: ambSnowValue = panel->getFloat(PID_AMB_SNOW); break; + + case PID_GRID_H2_CELL_SIZE: + if (detDivisor != panel->getFloat(pcb_id)) + panel->setEnabledById(PID_GRID_H2_APPLY, true); + break; + case PID_GRID_H2_BBOX_OFS: + if (detRect[0] != panel->getPoint2(pcb_id)) + panel->setEnabledById(PID_GRID_H2_APPLY, true); + break; + case PID_GRID_H2_BBOX_SZ: + if (detRect[1] - detRect[0] != panel->getPoint2(pcb_id)) + panel->setEnabledById(PID_GRID_H2_APPLY, true); + break; + + case PID_HM2_DISPLACEMENT_Q: + render.hm2displacementQ = panel->getInt(pcb_id); + updateHmap2Tesselation(); + break; + + case PID_NAVMESH_SHOWN_NAVMESH: + shownExportedNavMeshIdx = panel->getInt(pcb_id); + panel->setEnabledById(PID_NAVMESH_COVERS_SHOW, shownExportedNavMeshIdx == 0); + panel->setEnabledById(PID_NAVMESH_CONTOURS_SHOW, shownExportedNavMeshIdx == 0); + clearNavMesh(); + break; + + case PID_NAVMESH_EXP_SHOW: showExportedNavMesh = panel->getBool(pcb_id); break; + case PID_NAVMESH_COVERS_SHOW: showExportedCovers = panel->getBool(pcb_id); break; + case PID_NAVMESH_CONTOURS_SHOW: showExportedNavMeshContours = panel->getBool(pcb_id); break; + case PID_NAVMESH_OBSTACLES_SHOW: showExpotedObstacles = panel->getBool(pcb_id); break; + case PID_NAVMESH_DISABLE_ZTEST: disableZtestForDebugNavMesh = panel->getBool(pcb_id); break; + } + + if (pcb_id >= PID_NAVMESH_EXPORT_START && pcb_id <= PID_NAVMESH_EXPORT_END) + { + const int navMeshIdx = pcb_id - PID_NAVMESH_EXPORT_START; + navMeshProps[navMeshIdx].setBool("export", panel->getBool(pcb_id)); + panel->setBool(PID_NAVMESH_START + navMeshIdx * NM_PARAMS_COUNT + NM_PARAM_EXP, panel->getBool(pcb_id)); + } + + if ((pcb_id == PID_NAVMESH_EXP_SHOW || pcb_id == PID_NAVMESH_COVERS_SHOW || pcb_id == PID_NAVMESH_CONTOURS_SHOW || + pcb_id == PID_NAVMESH_OBSTACLES_SHOW) && + (panel->getBool(pcb_id) || !(showExportedNavMesh || showExportedCovers || showExportedNavMeshContours || showExpotedObstacles))) + if (IGenEditorPlugin *p = DAGORED2->getPluginByName("_navmesh")) + p->setVisible(panel->getBool(pcb_id)); + + if (pcb_id >= PID_NAVMESH_START && pcb_id <= PID_NAVMESH_END) + { + const int navMeshIdx = (pcb_id - PID_NAVMESH_START) / NM_PARAMS_COUNT; + const int navMeshParam = (pcb_id - PID_NAVMESH_START) % NM_PARAMS_COUNT; + const int baseOfs = PID_NAVMESH_START + NM_PARAMS_COUNT * navMeshIdx; + switch (navMeshParam) + { + case NM_PARAM_EXP: + navMeshProps[navMeshIdx].setBool("export", panel->getBool(pcb_id)); + panel->setBool(PID_NAVMESH_EXPORT_START + navMeshIdx, panel->getBool(pcb_id)); + break; + case NM_PARAM_KIND: navMeshProps[navMeshIdx].setStr("kind", panel->getText(pcb_id)); break; + case NM_PARAM_CELL_DXZ: navMeshProps[navMeshIdx].setReal("cellSize", panel->getFloat(pcb_id)); break; + case NM_PARAM_TRACE_STEP: navMeshProps[navMeshIdx].setReal("traceStep", panel->getFloat(pcb_id)); break; + case NM_PARAM_CELL_DY: navMeshProps[navMeshIdx].setReal("cellHeight", panel->getFloat(pcb_id)); break; + case NM_PARAM_CELL_A_HT: navMeshProps[navMeshIdx].setReal("agentHeight", panel->getFloat(pcb_id)); break; + case NM_PARAM_CELL_A_RAD: navMeshProps[navMeshIdx].setReal("agentRadius", panel->getFloat(pcb_id)); break; + case NM_PARAM_CELL_A_SLOPE: navMeshProps[navMeshIdx].setReal("agentMaxSlope", panel->getFloat(pcb_id)); break; + case NM_PARAM_CELL_A_CLIMB: navMeshProps[navMeshIdx].setReal("agentMaxClimb", panel->getFloat(pcb_id)); break; + case NM_PARAM_CELL_EDGE_MAX_LEN: navMeshProps[navMeshIdx].setReal("edgeMaxLen", panel->getFloat(pcb_id)); break; + case NM_PARAM_CELL_EDGE_MAX_ERR: navMeshProps[navMeshIdx].setReal("edgeMaxError", panel->getFloat(pcb_id)); break; + case NM_PARAM_CELL_REG_MIN_SZ: navMeshProps[navMeshIdx].setReal("regionMinSize", panel->getFloat(pcb_id)); break; + case NM_PARAM_CELL_REG_MERGE_SZ: navMeshProps[navMeshIdx].setReal("regionMergeSize", panel->getFloat(pcb_id)); break; + case NM_PARAM_CELL_VERTS_PER_POLY: navMeshProps[navMeshIdx].setInt("vertsPerPoly", panel->getInt(pcb_id)); break; + case NM_PARAM_CELL_DET_SAMPLE: navMeshProps[navMeshIdx].setReal("detailSampleDist", panel->getFloat(pcb_id)); break; + case NM_PARAM_CELL_DET_MAX_ERR: navMeshProps[navMeshIdx].setReal("detailSampleMaxError", panel->getFloat(pcb_id)); break; + case NM_PARAM_AREATYPE: + panel->setEnabledById(baseOfs + NM_PARAM_AREATYPE_RECT0, panel->getInt(pcb_id) == baseOfs + NM_PARAM_AREATYPE_RECT); + panel->setEnabledById(baseOfs + NM_PARAM_AREATYPE_RECT1, panel->getInt(pcb_id) == baseOfs + NM_PARAM_AREATYPE_RECT); + break; + case NM_PARAM_AREATYPE_RECT0: navMeshProps[navMeshIdx].setPoint2("rect0", panel->getPoint2(pcb_id)); break; + case NM_PARAM_AREATYPE_RECT1: navMeshProps[navMeshIdx].setPoint2("rect1", panel->getPoint2(pcb_id)); break; + case NM_PARAM_WATER: navMeshProps[navMeshIdx].setBool("hasWater", panel->getBool(pcb_id)); break; + case NM_PARAM_WATER_LEV: navMeshProps[navMeshIdx].setReal("waterLev", panel->getFloat(pcb_id)); break; + case NM_PARAM_TYPE: + navMeshProps[navMeshIdx].setInt("navMeshType", panel->getInt(pcb_id)); + panel->setEnabledById(baseOfs + NM_PARAM_BUCKET_SZ, panel->getInt(pcb_id) == pathfinder::NMT_TILECACHED); + break; + case NM_PARAM_PREFAB_COLLISION: navMeshProps[navMeshIdx].setBool("usePrefabCollision", panel->getBool(pcb_id)); break; + case NM_PARAM_TILE_SZ: navMeshProps[navMeshIdx].setInt("tileCells", panel->getInt(pcb_id)); break; + case NM_PARAM_BUCKET_SZ: navMeshProps[navMeshIdx].setReal("bucketSize", panel->getFloat(pcb_id)); break; + case NM_PARAM_CROSSING_WATER_DEPTH: navMeshProps[navMeshIdx].setReal("crossingWaterDepth", panel->getFloat(pcb_id)); break; + + case NM_PARAM_JLK_CVRS_EXTRA_CELLS: navMeshProps[navMeshIdx].setInt("jlkExtraCells", panel->getInt(pcb_id)); break; + case NM_PARAM_EMRG_ENABLED: navMeshProps[navMeshIdx].setBool("simplificationEdgeEnabled", panel->getBool(pcb_id)); break; + case NM_PARAM_EMRG_WALK_PRECISION: navMeshProps[navMeshIdx].setPoint2("walkPrecision", panel->getPoint2(pcb_id)); break; + case NM_PARAM_EMRG_EXTRUDE_MISTAKE: navMeshProps[navMeshIdx].setReal("extrudeError", panel->getFloat(pcb_id)); break; + case NM_PARAM_EMRG_EXTRUDE_LIMIT: navMeshProps[navMeshIdx].setReal("extrudeLimit", panel->getFloat(pcb_id)); break; + case NM_PARAM_EMRG_SAFE_CUT_LIMIT: navMeshProps[navMeshIdx].setReal("safeCutLimit", panel->getFloat(pcb_id)); break; + case NM_PARAM_EMRG_UNSAFE_CUT_LIMIT: navMeshProps[navMeshIdx].setReal("unsafeCutLimit", panel->getFloat(pcb_id)); break; + case NM_PARAM_EMRG_UNSAFE_MAX_CUT_SPACE: navMeshProps[navMeshIdx].setReal("maxUnsafeCutSpace", panel->getFloat(pcb_id)); break; + + case NM_PARAM_JLK_ENABLED: navMeshProps[navMeshIdx].setBool("jumpLinksEnabled", panel->getBool(pcb_id)); break; + case NM_PARAM_JLK_JUMP_OVER_HEIGHT: navMeshProps[navMeshIdx].setReal("jumpLinksHeight", panel->getFloat(pcb_id)); break; + case NM_PARAM_JLK_JUMP_LENGTH: navMeshProps[navMeshIdx].setReal("jumpLinksLength", panel->getFloat(pcb_id)); break; + case NM_PARAM_JLK_MIN_WIDTH: navMeshProps[navMeshIdx].setReal("jumpLinksWidth", panel->getFloat(pcb_id)); break; + case NM_PARAM_JLK_DH_THRESHOLD: navMeshProps[navMeshIdx].setReal("jumpLinksDeltaHeightTreshold", panel->getFloat(pcb_id)); break; + case NM_PARAM_JLK_MERGE_ANGLE: navMeshProps[navMeshIdx].setReal("jumpLinksMergeAngle", panel->getFloat(pcb_id)); break; + case NM_PARAM_JLK_MERGE_DIST: navMeshProps[navMeshIdx].setReal("jumpLinksMergeDist", panel->getFloat(pcb_id)); break; + case NM_PARAM_JLK_CPLX_THRESHOLD: navMeshProps[navMeshIdx].setReal("complexJumpTheshold", panel->getFloat(pcb_id)); break; + case NM_PARAM_JLK_CROSS_OBSTACLES_WITH_JUMPLINKS: + navMeshProps[navMeshIdx].setBool("crossObstaclesWithJumplinks", panel->getBool(pcb_id)); + break; + + case NM_PARAM_CVRS_ENABLED: navMeshProps[navMeshIdx].setBool("coversEnabled", panel->getBool(pcb_id)); break; + case NM_PARAM_CVRS_TYPEGEN: + navMeshProps[navMeshIdx].setInt("coversTypeGen", panel->getInt(pcb_id)); + { + const bool covEnable1 = (panel->getInt(pcb_id) == 0); + panel->setEnabledById(baseOfs + NM_PARAM_CVRS_MAX_HEIGHT, covEnable1); + panel->setEnabledById(baseOfs + NM_PARAM_CVRS_MIN_HEIGHT, covEnable1); + panel->setEnabledById(baseOfs + NM_PARAM_CVRS_MIN_WIDTH, covEnable1); + panel->setEnabledById(baseOfs + NM_PARAM_CVRS_MIN_DEPTH, covEnable1); + panel->setEnabledById(baseOfs + NM_PARAM_CVRS_SHOOT_WINDOW_HEIGHT, covEnable1); + panel->setEnabledById(baseOfs + NM_PARAM_CVRS_COLLISION_TARNSP_THRESHOLD, covEnable1); + panel->setEnabledById(baseOfs + NM_PARAM_CVRS_MERGE_DIST, covEnable1); + panel->setEnabledById(baseOfs + NM_PARAM_CVRS_DH_THRESHOLD, covEnable1); + panel->setEnabledById(baseOfs + NM_PARAM_CVRS_SHOOT_DEPTH_CHECK, covEnable1); + panel->setEnabledById(baseOfs + NM_PARAM_CVRS_SHOOT_HEIGHT, covEnable1); + panel->setEnabledById(baseOfs + NM_PARAM_CVRS_MAX_HEIGHT, covEnable1); + } + break; + case NM_PARAM_CVRS_MAX_HEIGHT: navMeshProps[navMeshIdx].setReal("coversMaxHeight", panel->getFloat(pcb_id)); break; + case NM_PARAM_CVRS_MIN_HEIGHT: navMeshProps[navMeshIdx].setReal("coversMinHeight", panel->getFloat(pcb_id)); break; + case NM_PARAM_CVRS_MIN_WIDTH: navMeshProps[navMeshIdx].setReal("coversWidth", panel->getFloat(pcb_id)); break; + case NM_PARAM_CVRS_MIN_DEPTH: navMeshProps[navMeshIdx].setReal("coversDepth", panel->getFloat(pcb_id)); break; + case NM_PARAM_CVRS_SHOOT_WINDOW_HEIGHT: navMeshProps[navMeshIdx].setReal("coversShootWindow", panel->getFloat(pcb_id)); break; + case NM_PARAM_CVRS_COLLISION_TARNSP_THRESHOLD: + navMeshProps[navMeshIdx].setReal("coversTransparent", panel->getFloat(pcb_id)); + break; + case NM_PARAM_CVRS_MERGE_DIST: navMeshProps[navMeshIdx].setReal("coversMergeDist", panel->getFloat(pcb_id)); break; + case NM_PARAM_CVRS_DH_THRESHOLD: navMeshProps[navMeshIdx].setReal("coversDeltaHeightTreshold", panel->getFloat(pcb_id)); break; + case NM_PARAM_CVRS_SHOOT_DEPTH_CHECK: navMeshProps[navMeshIdx].setReal("coversShootDepth", panel->getFloat(pcb_id)); break; + case NM_PARAM_CVRS_SHOOT_HEIGHT: navMeshProps[navMeshIdx].setReal("coversShootHeight", panel->getFloat(pcb_id)); break; + case NM_PARAM_CVRS_OPENING_TRESHOLD: navMeshProps[navMeshIdx].setReal("openingTreshold", panel->getFloat(pcb_id)); break; + case NM_PARAM_CVRS_BOX_OFFSET: navMeshProps[navMeshIdx].setReal("visibleBoxOffset", panel->getFloat(pcb_id)); break; + + case NM_PARAM_CVRS_TEST_X: + if (panel->getFloat(pcb_id) != 0.0f || navMeshProps[navMeshIdx].findParam("coversTestX") >= 0) + navMeshProps[navMeshIdx].setReal("coversTestX", panel->getFloat(pcb_id)); + break; + case NM_PARAM_CVRS_TEST_Y: + if (panel->getFloat(pcb_id) != 0.0f || navMeshProps[navMeshIdx].findParam("coversTestY") >= 0) + navMeshProps[navMeshIdx].setReal("coversTestY", panel->getFloat(pcb_id)); + break; + case NM_PARAM_CVRS_TEST_Z: + if (panel->getFloat(pcb_id) != 0.0f || navMeshProps[navMeshIdx].findParam("coversTestZ") >= 0) + navMeshProps[navMeshIdx].setReal("coversTestZ", panel->getFloat(pcb_id)); + break; + + case NM_PARAM_DROP_RESULT_ON_COLLISION: + navMeshProps[navMeshIdx].setBool("dropNavmeshOnCollision", panel->getBool(pcb_id)); + panel->setEnabledById(baseOfs + NM_PARAM_DROP_RESULT_ON_COLLISION_TRACE_OFFSET, panel->getBool(pcb_id)); + panel->setEnabledById(baseOfs + NM_PARAM_DROP_RESULT_ON_COLLISION_TRACE_LEN, panel->getBool(pcb_id)); + break; + case NM_PARAM_DROP_RESULT_ON_COLLISION_TRACE_OFFSET: + navMeshProps[navMeshIdx].setReal("dropNavmeshOffset", panel->getFloat(pcb_id)); + break; + case NM_PARAM_DROP_RESULT_ON_COLLISION_TRACE_LEN: + navMeshProps[navMeshIdx].setReal("dropNavmeshTraceLen", panel->getFloat(pcb_id)); + break; + case NM_PARAM_COMPRESS_RATIO: navMeshProps[navMeshIdx].setInt("navmeshCompressRatio", panel->getInt(pcb_id)); break; + } + + if ( + panel->getInt(baseOfs + NM_PARAM_AREATYPE) - (baseOfs + NM_PARAM_AREATYPE_MAIN) != navMeshProps[navMeshIdx].getInt("navArea", 0)) + navMeshProps[navMeshIdx].setInt("navArea", panel->getInt(baseOfs + NM_PARAM_AREATYPE) - (baseOfs + NM_PARAM_AREATYPE_MAIN)); + + int navmeshExportType = panel->getInt(baseOfs + NM_PARAM_EXPORT_TYPE); + if (navmeshExportType >= baseOfs + NM_PARAM_EXPORT_TYPE_WATER && + navmeshExportType <= baseOfs + NM_PARAM_EXPORT_TYPE_WATER_AND_GEOMETRY) + { + navMeshProps[navMeshIdx].setStr("navmeshExportType", + navmesh_export_type_to_string( + NavmeshExportType(int(NavmeshExportType::WATER) + (navmeshExportType - (baseOfs + NM_PARAM_EXPORT_TYPE_WATER))))); + panel->setEnabledById(baseOfs + NM_PARAM_WATER, navmeshExportType != baseOfs + NM_PARAM_EXPORT_TYPE_WATER && + navmeshExportType != baseOfs + NM_PARAM_EXPORT_TYPE_WATER_AND_GEOMETRY); + } + } + + + bool newShowHm = panel->getInt(PID_RENDER_RADIOGROUP_HM) == PID_RENDER_FINAL_HM; + if (newShowHm != render.showFinalHM) + { + render.showFinalHM = newShowHm; + if (render.showFinalHM) + applyHmModifiers(false); + // generateLandColors(NULL); not my comment + // calcFastLandLighting(); not my comment + updateHeightMapTex(false); + updateHeightMapTex(true); + } + + int newLightingDetails = 0; + switch (panel->getInt(PID_LIGHTING_SUBDIV)) + { + case PID_LIGHTING_1: newLightingDetails = 1; break; + + case PID_LIGHTING_2: newLightingDetails = 2; break; + + case PID_LIGHTING_4: newLightingDetails = 4; break; + } + + if (newLightingDetails && newLightingDetails != lightmapScaleFactor) + { + lightmapScaleFactor = newLightingDetails; + lightMapScaled.reset(heightMap.getMapSizeX() * lightmapScaleFactor, heightMap.getMapSizeY() * lightmapScaleFactor, 0xFFFF); + createLightmapFile(DAGORED2->getConsole()); + resetRenderer(); + } + + + int newLcmDetails = 0; + switch (panel->getInt(PID_LCMAP_SUBDIV)) + { + case PID_LCMAP_1: newLcmDetails = 1; break; + case PID_LCMAP_2: newLcmDetails = 2; break; + case PID_LCMAP_4: newLcmDetails = 4; break; + } + if (newLcmDetails && newLcmDetails != lcmScale) + { + lcmScale = newLcmDetails; + resizeLandClassMapFile(DAGORED2->getConsole()); + lcMgr->reinitRIGen(); + onLandSizeChanged(); + generateLandColors(); + } + + + // if (!edit_finished) + // return; + + if (pcb_id < PID_BRUSHES_PIDS) + { + brushes[currentBrushId]->updateFromPanelRef(*panel, pcb_id); + if (brushDlg->isVisible()) + { + if (propPanel->getPanelWindow()) + brushes[currentBrushId]->updateToPanel(*propPanel->getPanelWindow()); + + return; + } + DAGORED2->repaint(); + } + + /*if (pcb_id>=PID_DETAIL_TEX_OFFSET_0 && pcb_id<=PID_DETAIL_TEX_OFFSET_LAST) + { + int index = pcb_id-PID_DETAIL_TEX_OFFSET_0; + if (index >= detailTexOffset.size()) + detailTexOffset.resize(index + 1); + + detailTexOffset[index] = panel->getPoint2(pcb_id); + #if defined(USE_HMAP_ACES) + //panel->setCaption(pcb_id, ::dd_get_fname(detailTexBlkName[index])); + #endif + resetRenderer(); + return; + }*/ + + switch (pcb_id) + { + case PID_GRID_CELL_SIZE: + gridCellSize = panel->getFloat(pcb_id); + if (gridCellSize <= 0) + gridCellSize = 1; + autocenterHeightmap(panel); + resetRenderer(); + onLandSizeChanged(); + onWholeLandChanged(); + break; + + case PID_HEIGHT_SCALE: + case PID_HEIGHT_OFFSET: + case PID_HEIGHTMAP_OFFSET: onChangeFinished(pcb_id, panel); break; + + case PID_HEIGHTMAP_AUTOCENTER: + doAutocenter = panel->getBool(pcb_id); + autocenterHeightmap(panel); + onLandSizeChanged(); + onWholeLandChanged(); + break; + + case PID_HM_COLLISION_OFFSET: + collisionArea.ofs = panel->getPoint2(pcb_id); + DAGORED2->invalidateViewportCache(); + break; + + case PID_HM_COLLISION_SIZE: + collisionArea.sz = panel->getPoint2(pcb_id); + DAGORED2->invalidateViewportCache(); + break; + + case PID_HM_COLLISION_SHOW: + collisionArea.show = panel->getBool(pcb_id); + DAGORED2->invalidateViewportCache(); + break; + + case PID_RENDER_GRID_STEP: + render.gridStep = panel->getInt(pcb_id); + resetRenderer(); + break; + + case PID_RENDER_RADIUS_ELEMS: + render.radiusElems = panel->getInt(pcb_id); + resetRenderer(); + break; + + case PID_RENDER_RING_ELEMS: + render.ringElems = panel->getInt(pcb_id); + resetRenderer(); + break; + + case PID_RENDER_NUM_LODS: + render.numLods = panel->getInt(pcb_id); + resetRenderer(); + break; + + case PID_RENDER_MAX_DETAIL_LOD: + render.maxDetailLod = panel->getInt(pcb_id); + resetRenderer(); + break; + + case PID_RENDER_DETAIL_TILE: + render.detailTile = panel->getFloat(pcb_id); + resetRenderer(); + break; + + case PID_RENDER_CANYON_HOR_TILE: + render.canyonHorTile = panel->getFloat(pcb_id); + resetRenderer(); + break; + + case PID_RENDER_CANYON_VERT_TILE: + render.canyonVertTile = panel->getFloat(pcb_id); + resetRenderer(); + break; + + case PID_RENDER_HM2_YBASE_FOR_LOD: + render.hm2YbaseForLod = panel->getFloat(pcb_id); + DAGORED2->repaint(); + break; + + case PID_RENDER_ELEM_SIZE: + render.elemSize = panel->getInt(pcb_id); + if (render.elemSize < 1) + render.elemSize = 1; + if (render.elemSize > 16) + render.elemSize = 16; + resetRenderer(); + break; + + case PID_RENDER_DEBUG_LINES: + renderDebugLines = panel->getBool(pcb_id); + DAGORED2->repaint(); + break; + case PID_RENDER_ALL_SPLINES_ALWAYS: renderAllSplinesAlways = panel->getBool(pcb_id); break; + case PID_RENDER_SEL_SPLINES_ALWAYS: renderSelSplinesAlways = panel->getBool(pcb_id); break; + + case PID_CANYON_ANGLE: + render.canyonAngle = panel->getFloat(pcb_id); + resetRenderer(); + break; + + case PID_CANYON_FADE_ANGLE: + render.canyonFadeAngle = panel->getFloat(pcb_id); + resetRenderer(); + break; + + case PID_SUN_AZIMUTH: + sunAzimuth = HALFPI - DegToRad(panel->getFloat(pcb_id)); + updateRendererLighting(); + break; + + case PID_SUN_ZENITH: + sunZenith = DegToRad(panel->getFloat(pcb_id)); + updateRendererLighting(); + break; + + case PID_SHADOW_BIAS: shadowBias = panel->getFloat(pcb_id); break; + + case PID_SHADOW_TRACE_DIST: shadowTraceDist = panel->getFloat(pcb_id); break; + + case PID_SHADOW_DENSITY: shadowDensity = panel->getFloat(pcb_id) / 100; break; + + case PID_SHOWMASK: + showBlueWhiteMask = panel->getBool(pcb_id); + setShowBlueWhiteMask(); + if (editedScriptImage) + { + if (showBlueWhiteMask) + updateBlueWhiteMask(NULL); + DAGORED2->invalidateViewportCache(); + } + break; + + case PID_MONOLAND: + showMonochromeLand = panel->getBool(pcb_id); + if (hmlService) + hmlService->invalidateClipmap(showMonochromeLand); + DAGORED2->invalidateViewportCache(); + break; + + case PID_MONOLAND_COL: + monochromeLandCol = panel->getColor(pcb_id); + if (showMonochromeLand) + if (hmlService) + hmlService->invalidateClipmap(true); + DAGORED2->invalidateViewportCache(); + break; + + case PID_GROUND_OBJECTS_COL: + dagGeom->shaderGlobalSetColor4(dagGeom->getShaderVariableId("prefabs_color"), Color4(panel->getColor(pcb_id))); + DAGORED2->invalidateViewportCache(); + break; + + case PID_HTLEVELS: + showHtLevelCurves = panel->getBool(pcb_id); + updateHtLevelCurves(); + break; + case PID_HTLEVELS_STEP: + htLevelCurveStep = panel->getFloat(pcb_id); + updateHtLevelCurves(); + break; + case PID_HTLEVELS_OFS: + htLevelCurveOfs = panel->getFloat(pcb_id); + updateHtLevelCurves(); + break; + case PID_HTLEVELS_THICK: + htLevelCurveThickness = panel->getFloat(pcb_id); + updateHtLevelCurves(); + break; + case PID_HTLEVELS_DARK: + htLevelCurveDarkness = panel->getFloat(pcb_id) / 100; + updateHtLevelCurves(); + break; + + case PID_TILE_SIZE_X: + tileXSize = panel->getFloat(pcb_id); + resetRenderer(); + break; + + case PID_TILE_SIZE_Y: + tileYSize = panel->getFloat(pcb_id); + resetRenderer(); + break; + + + case PID_HORIZONTAL_TILE_SIZE_X: + horizontalTex_TileSizeX = panel->getFloat(pcb_id); + updateHorizontalTex(); + break; + + case PID_HORIZONTAL_TILE_SIZE_Y: + horizontalTex_TileSizeY = panel->getFloat(pcb_id); + updateHorizontalTex(); + break; + + case PID_HORIZONTAL_OFFSET_X: + horizontalTex_OffsetX = panel->getFloat(pcb_id); + updateHorizontalTex(); + break; + + case PID_HORIZONTAL_OFFSET_Y: + horizontalTex_OffsetY = panel->getFloat(pcb_id); + updateHorizontalTex(); + break; + + case PID_HORIZONTAL_DETAIL_TILE_SIZE_X: + horizontalTex_DetailTexSizeX = panel->getFloat(pcb_id); + updateHorizontalTex(); + break; + + case PID_HORIZONTAL_DETAIL_TILE_SIZE_Y: + horizontalTex_DetailTexSizeY = panel->getFloat(pcb_id); + updateHorizontalTex(); + break; + + case PID_USE_HORIZONTAL_TEX: + useHorizontalTex = panel->getBool(pcb_id); + updateHorizontalTex(); + break; + + + case PID_LAND_MODULATE_EDGE0_X: + landModulateColorEdge0 = min(panel->getFloat(pcb_id), landModulateColorEdge1 - 0.001f); + panel->setFloat(PID_LAND_MODULATE_EDGE0_X, landModulateColorEdge0); + updateLandModulateColorTex(); + break; + + case PID_LAND_MODULATE_EDGE1_X: + landModulateColorEdge1 = panel->getFloat(pcb_id); + landModulateColorEdge0 = min(landModulateColorEdge0, landModulateColorEdge1 - 0.001f); + panel->setFloat(PID_LAND_MODULATE_EDGE0_X, landModulateColorEdge0); + updateLandModulateColorTex(); + break; + + case PID_USE_LAND_MODULATE_TEX: + useLandModulateColorTex = panel->getBool(pcb_id); + updateLandModulateColorTex(); + if (hmlService) + hmlService->invalidateClipmap(true); + break; + + case PID_USE_RENDIST_DETAIL2_COLOR: + useRendinstDetail2Modulation = panel->getBool(pcb_id); + setRendinstlayeredDetailColor(); + break; + case PID_RENDIST_DETAIL2_COLOR_FROM: + rendinstDetail2ColorFrom = panel->getColor(pcb_id); + setRendinstlayeredDetailColor(); + break; + case PID_RENDIST_DETAIL2_COLOR_TO: + rendinstDetail2ColorTo = panel->getColor(pcb_id); + setRendinstlayeredDetailColor(); + break; + + + case PID_ENABLE_GRASS: + enableGrass = panel->getBool(pcb_id); + if (grassService) + grassService->enableGrass(enableGrass); + if (gpuGrassService) + gpuGrassService->enableGrass(enableGrass); + break; + + + case PID_VERT_TEX_USE: + useVertTex = panel->getBool(pcb_id); + updateVertTex(); + break; + case PID_VERT_TEX_USE_HMAP: + useVertTexForHMAP = panel->getBool(pcb_id); + updateVertTex(); + break; + + case PID_VERT_TEX_TILE_XZ: + vertTexXZtile = panel->getFloat(pcb_id); + updateVertTex(); + break; + case PID_VERT_TEX_TILE_Y: + vertTexYtile = panel->getFloat(pcb_id); + updateVertTex(); + break; + case PID_VERT_TEX_Y_OFS: + vertTexYOffset = panel->getFloat(pcb_id); + updateVertTex(); + break; + case PID_VERT_TEX_ANG0: + vertTexAng0 = panel->getFloat(pcb_id); + updateVertTex(); + break; + case PID_VERT_TEX_ANG1: + vertTexAng1 = panel->getFloat(pcb_id); + updateVertTex(); + break; + case PID_VERT_TEX_HBLEND: + vertTexHorBlend = panel->getFloat(pcb_id); + updateVertTex(); + break; + case PID_VERT_DET_TEX_TILE_XZ: + vertDetTexXZtile = panel->getFloat(pcb_id); + updateVertTex(); + break; + case PID_VERT_DET_TEX_TILE_Y: + vertDetTexYtile = panel->getFloat(pcb_id); + updateVertTex(); + break; + case PID_VERT_DET_TEX_Y_OFS: + vertDetTexYOffset = panel->getFloat(pcb_id); + updateVertTex(); + break; + } + + if (pcb_id >= PID_SHADOW_CASTER_FIRST && pcb_id < PID_SHADOW_CASTER_LAST) + { + const int shadowIdx = pcb_id - PID_SHADOW_CASTER_FIRST; + const IDagorEdCustomCollider *collider = DAGORED2->getCustomCollider(shadowIdx); + + if (collider) + { + if (panel->getBool(pcb_id)) + DAGORED2->enableCustomShadow(collider->getColliderName()); + else + DAGORED2->disableCustomShadow(collider->getColliderName()); + } + } + + if (pcb_id >= PID_GRASS_MASK_START && pcb_id <= PID_GRASS_MASK_END) + { + SimpleString fname = panel->getText(pcb_id); + int index = pcb_id - PID_GRASS_MASK_START; + String maskName = ::get_file_name_wo_ext(fname); + panel->setText(pcb_id, maskName); + grassBlk->setStr(grass.masks[index].first, maskName.c_str()); + grassService->resetGrassMask(*landMeshRenderer, index, *grassBlk, grass.masks[index].first, maskName); + // This texture is released in landMeshRenderer + Tab &landClasses = landMeshManager->getLandClasses(); + landClasses[index].grassMaskTexId = BAD_TEXTUREID; + HmapLandPlugin::grassService->forceUpdate(); + } + else if (pcb_id >= PID_GRASS_DEFAULT_MIN_DENSITY && pcb_id <= PID_GRASS_HELICOPTER_FALLOFF) + { + switch (pcb_id) + { + case PID_GRASS_DEFAULT_MIN_DENSITY: + grass.defaultMinDensity = panel->getFloat(pcb_id); + grassBlk->setReal("minLodDensity", grass.defaultMinDensity); + break; + case PID_GRASS_DEFAULT_MAX_DENSITY: + grass.defaultMaxDensity = panel->getFloat(pcb_id); + grassBlk->setReal("density", grass.defaultMaxDensity); + break; + case PID_GRASS_MAX_RADIUS: + grass.maxRadius = panel->getFloat(pcb_id); + grassBlk->setReal("maxRadius", grass.maxRadius); + break; + case PID_GRASS_TEX_SIZE: + grass.texSize = panel->getInt(pcb_id); + grassBlk->setReal("texSize", grass.texSize); + break; + case PID_GRASS_SOW_PER_LIN_FREQ: + grass.sowPerlinFreq = panel->getFloat(pcb_id); + grassBlk->setReal("sowPerlinFreq", grass.sowPerlinFreq); + break; + case PID_GRASS_FADE_DELTA: + grass.fadeDelta = panel->getFloat(pcb_id); + grassBlk->setReal("fadeDelta", grass.fadeDelta); + break; + case PID_GRASS_LOD_FADE_DELTA: + grass.lodFadeDelta = panel->getFloat(pcb_id); + grassBlk->setReal("lodFadeDelta", grass.lodFadeDelta); + break; + case PID_GRASS_BLEND_TO_LAND_DELTA: + grass.blendToLandDelta = panel->getFloat(pcb_id); + grassBlk->setReal("blendToLandDelta", grass.blendToLandDelta); + break; + case PID_GRASS_NOISE_FIRST_RND: + grass.noise_first_rnd = panel->getFloat(pcb_id); + grassBlk->setReal("noise_first_rnd", grass.noise_first_rnd); + break; + case PID_GRASS_NOISE_FIRST_VAL_MUL: + grass.noise_first_val_mul = panel->getFloat(pcb_id); + grassBlk->setReal("noise_first_val_mul", grass.noise_first_val_mul); + break; + case PID_GRASS_NOISE_FIRST_VAL_ADD: + grass.noise_first_val_add = panel->getFloat(pcb_id); + grassBlk->setReal("noise_first_val_add", grass.noise_first_val_add); + break; + case PID_GRASS_NOISE_SECOND_RND: + grass.noise_second_rnd = panel->getFloat(pcb_id); + grassBlk->setReal("noise_second_rnd", grass.noise_second_rnd); + break; + case PID_GRASS_NOISE_SECOND_VAL_MUL: + grass.noise_second_val_mul = panel->getFloat(pcb_id); + grassBlk->setReal("noise_second_val_mul", grass.noise_second_val_mul); + break; + case PID_GRASS_NOISE_SECOND_VAL_ADD: + grass.noise_second_val_add = panel->getFloat(pcb_id); + grassBlk->setReal("noise_second_val_add", grass.noise_second_val_add); + break; + case PID_GRASS_DIRECT_WIND_MUL: + grass.directWindMul = panel->getFloat(pcb_id); + grassBlk->setReal("directWindMul", grass.directWindMul); + break; + case PID_GRASS_NOISE_WIND_MUL: + grass.noiseWindMul = panel->getFloat(pcb_id); + grassBlk->setReal("noiseWindMul", grass.noiseWindMul); + break; + case PID_GRASS_WIND_PER_LIN_FREQ: + grass.windPerlinFreq = panel->getFloat(pcb_id); + grassBlk->setReal("windPerlinFreq", grass.windPerlinFreq); + break; + case PID_GRASS_DIRECT_WIND_FREQ: + grass.directWindFreq = panel->getFloat(pcb_id); + grassBlk->setReal("directWindFreq", grass.directWindFreq); + break; + case PID_GRASS_DIRECT_WIND_MODULATION_FREQ: + grass.directWindModulationFreq = panel->getFloat(pcb_id); + grassBlk->setReal("directWindModulationFreq", grass.directWindModulationFreq); + break; + case PID_GRASS_WIND_WAVE_LENGTH: + grass.windWaveLength = panel->getFloat(pcb_id); + grassBlk->setReal("windWaveLength", grass.windWaveLength); + break; + case PID_GRASS_WIND_TO_COLOR: + grass.windToColor = panel->getFloat(pcb_id); + grassBlk->setReal("windToColor", grass.windToColor); + break; + case PID_GRASS_HELICOPTER_HOR_MUL: + grass.helicopterHorMul = panel->getFloat(pcb_id); + grassBlk->setReal("helicopterHorMul", grass.helicopterHorMul); + break; + case PID_GRASS_HELICOPTER_VER_MUL: + grass.helicopterVerMul = panel->getFloat(pcb_id); + grassBlk->setReal("helicopterVerMul", grass.helicopterVerMul); + break; + case PID_GRASS_HELICOPTER_TO_DIRECT_WIND_MUL: + grass.helicopterToDirectWindMul = panel->getFloat(pcb_id); + grassBlk->setReal("helicopterToDirectWindMul", grass.helicopterToDirectWindMul); + break; + case PID_GRASS_HELICOPTER_FALLOFF: + grass.helicopterFalloff = panel->getFloat(pcb_id); + grassBlk->setReal("helicopterFalloff", grass.helicopterFalloff); + break; + } + HmapLandPlugin::grassService->reloadAll(*grassBlk, levelBlk); + bool savedEnableGrass = enableGrass; + loadGrassLayers(*grassBlk, false); + enableGrass = savedEnableGrass; //-V1048 + hmlService->setGrassBlk(grassBlk); + } + gpuGrassPanel.onChange(pcb_id, panel); +} +void HmapLandPlugin::onChangeFinished(int pcb_id, PropPanel2 *panel) +{ + switch (pcb_id) + { + case PID_HEIGHT_SCALE: + heightMap.heightScale = panel->getFloat(pcb_id); + resetRenderer(); + heightMap.resetFinal(); + applyHmModifiers(true, true, false); + updateHeightMapTex(false); + // onLandSizeChanged(); + // onWholeLandChanged(); + break; + + case PID_HEIGHT_OFFSET: + heightMap.heightOffset = panel->getFloat(pcb_id); + resetRenderer(); + heightMap.resetFinal(); + applyHmModifiers(true, true, false); + updateHeightMapTex(false); + // onLandSizeChanged(); + // onWholeLandChanged(); + break; + + case PID_HEIGHTMAP_OFFSET: + heightMapOffset = panel->getPoint2(pcb_id); + resetRenderer(); + heightMap.resetFinal(); + applyHmModifiers(true, true, false); + // onLandSizeChanged(); + // onWholeLandChanged(); + break; + } +} + + +// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ// + +bool HmapLandPlugin::importScriptImage(String *name) +{ + String fname = + wingw::file_open_dlg(NULL, "Import image for generator script", "TGA files (*.tga)|*.tga", "tga", DAGORED2->getSdkDir()); + + if (!fname.length()) + return false; + + String texName = ::get_file_name_wo_ext(fname); + String destFile(DAGORED2->getPluginFilePath(this, texName + ".tga")); + + if (::dd_file_exist(destFile)) + { + if (wingw::message_box(wingw::MBS_YESNO | wingw::MBS_QUEST, "Confirmation", "Overwrite old image?") != wingw::MB_ID_YES) + return false; + } + + if (!dagTools->copyFile(fname, destFile)) + { + wingw::message_box(wingw::MBS_EXCL, "Import error", "Unable to copy image\n\"%s\"\nto\n\"%s\"", (const char *)fname, + (const char *)destFile); + + return false; + } + + if (name) + *name = texName; + + return true; +} + + +bool HmapLandPlugin::importTileTex() +{ + const char *tex = DAEDITOR3.selectAssetX(tileTexName, "Select tile texture", "tex"); + + if (tex) + { + tileTexName = tex; + if (propPanel) + propPanel->fillPanel(); + resetRenderer(); + } + return true; +} + + +bool HmapLandPlugin::createMask(int bpp, String *name) +{ + static const int INPUT_STRING_EDIT_ID = 222; + CDialogWindow *dialog = DAGORED2->createDialog(_pxScaled(250), _pxScaled(120), "Create mask"); + PropPanel2 *panel = dialog->getPanel(); + panel->createEditBox(INPUT_STRING_EDIT_ID, "Enter mask name:"); + panel->setFocusById(INPUT_STRING_EDIT_ID); + + String result; + + for (bool nameValid = false; !nameValid;) + { + nameValid = true; + int ret = dialog->showDialog(); + if (ret == DIALOG_ID_OK) + { + result = panel->getText(INPUT_STRING_EDIT_ID); + } + + if (result.length()) + { + for (const char *c = result; *c; ++c) + { + if (!isalnum(*c) && *c != '_') + { + wingw::message_box(wingw::MBS_EXCL, "Name error", "Mask name can contain only latin letters, digits and '_' symbol."); + + nameValid = false; + break; + } + } + } + } + + DAGORED2->deleteDialog(dialog); + + if (result.length()) + { + IBitMaskImageMgr::BitmapMask img; + if (bpp == 32) + bitMaskImgMgr->createImage32(img, getHeightmapSizeX(), getHeightmapSizeY()); + else + bitMaskImgMgr->createBitMask(img, getHeightmapSizeX(), getHeightmapSizeY(), bpp); + + if (bitMaskImgMgr->saveImage(img, HmapLandPlugin::self->getInternalName(), result)) + if (*name) + *name = result; + bitMaskImgMgr->destroyImage(img); + return true; + } + + return false; +} + + +void HmapLandPlugin::onClick(int pcb_id, PropPanel2 *panel) +{ + if (pcb_id >= PID_GRASS_PARAM_START && pcb_id <= PID_LAST_GRASS_PARAM) + { + bool layer_removed = false; + for (int i = 0; i < grassLayers.size(); i++) + { + grassLayers[i]->onClick(pcb_id, *panel); + if (grassLayers[i]->remove_this_layer) + { + HmapLandPlugin::grassService->removeLayer(grassLayers[i]->grass_layer_i); + safe_erase_items(grassLayers, i, 1); + layer_removed = true; + break; + } + } + + if (layer_removed) + { + // reset layer ids + for (int i = 0; i < grassLayers.size(); i++) + grassLayers[i]->grass_layer_i = i; + if (propPanel) + propPanel->fillPanel(); + } + } + + if (pcb_id == PID_IMPORT_SCRIPT_IMAGE) + { + importScriptImage(); + } + else if (pcb_id == PID_TILE_TEX) + { + importTileTex(); + } + + + else if (pcb_id == PID_HORIZONTAL_TEX_NAME) + { + const char *tex = DAEDITOR3.selectAssetX(horizontalTexName, "Select rendinst vertical texture", "tex"); + + if (tex) + { + releaseHorizontalTexRef(); + horizontalTexName = tex; + if (propPanel) + propPanel->fillPanel(); + acquireHorizontalTexRef(); + updateHorizontalTex(); + } + } + else if (pcb_id == PID_HORIZONTAL_DET_TEX_NAME) + { + const char *tex = DAEDITOR3.selectAssetX(horizontalDetailTexName, "Select rendinst vertical detail texture", "tex"); + + if (tex) + { + releaseHorizontalTexRef(); + horizontalDetailTexName = tex; + if (propPanel) + propPanel->fillPanel(); + acquireHorizontalTexRef(); + updateHorizontalTex(); + } + } + + else if (pcb_id == PID_LAND_MODULATE_TEX_NAME) + { + const char *tex = DAEDITOR3.selectAssetX(landModulateColorTexName, "Select land modulate texture", "tex"); + + if (tex) + { + releaseLandModulateColorTexRef(); + landModulateColorTexName = tex; + if (propPanel) + propPanel->fillPanel(); + acquireLandModulateColorTexRef(); + updateLandModulateColorTex(); + } + } + + else if (pcb_id == PID_VERT_TEX_NAME) + { + const char *tex = DAEDITOR3.selectAssetX(vertTexName, "Select vertical texture", "tex"); + + if (tex) + { + releaseVertTexRef(); + vertTexName = tex; + if (propPanel) + propPanel->fillPanel(); + acquireVertTexRef(); + updateVertTex(); + } + } + else if (pcb_id == PID_VERT_NM_TEX_NAME) + { + const char *tex = DAEDITOR3.selectAssetX(vertNmTexName, "Select vertical NM texture", "tex"); + + if (tex) + { + releaseVertTexRef(); + vertNmTexName = tex; + if (propPanel) + propPanel->fillPanel(); + acquireVertTexRef(); + updateVertTex(); + } + } + else if (pcb_id == PID_VERT_DET_TEX_NAME) + { + const char *tex = DAEDITOR3.selectAssetX(vertDetTexName, "Select vertical detail texture", "tex"); + + if (tex) + { + releaseVertTexRef(); + vertDetTexName = tex; + if (propPanel) + propPanel->fillPanel(); + acquireVertTexRef(); + updateVertTex(); + } + } + else if (pcb_id == PID_CREATE_MASK) + { + createMask(1); + } + else if (pcb_id == PID_RESET_SCRIPT) + { + if (colorGenScriptFilename.empty()) + return; + if (wingw::message_box(wingw::MBS_YESNO | wingw::MBS_QUEST, "Confirmation", + "Do you really want to reset generation script?\n\n" + "(generation layers, if any, can do processing without script)") != wingw::MB_ID_YES) + return; + + colorGenScriptFilename = ""; + getColorGenVarsFromScript(); + onWholeLandChanged(); + if (propPanel) + propPanel->fillPanel(); + } + else if (pcb_id == PID_RELOAD_SCRIPT) + { + getColorGenVarsFromScript(); + onWholeLandChanged(); + if (propPanel) + propPanel->fillPanel(); + } + else if (pcb_id == PID_GENERATE_COLORMAP) + { + generateLandColors(); + resetRenderer(); + } + else if (pcb_id == PID_CALC_FAST_LIGHTING) + { + calcFastLandLighting(); + resetRenderer(); + } + else if (pcb_id == PID_GET_SUN_SETTINGS) + { + getAllSunSettings(); + updateLightGroup(*panel); + } + else if (pcb_id == PID_CALC_GOOD_LIGHTING) + { + calcGoodLandLighting(); + resetRenderer(); + } + else if (pcb_id == PID_SAVE_LIGHTING_PC || pcb_id == PID_SAVE_LIGHTING_X360 || pcb_id == PID_SAVE_LIGHTING_PS3 || + pcb_id == PID_SAVE_LIGHTING_PS4 || pcb_id == PID_SAVE_LIGHTING_iOS || pcb_id == PID_SAVE_LIGHTING_AND) + { + String fileName = wingw::file_open_dlg(NULL, "Save lightmap", "Lightmap (*.ddsx)|*.ddsx", ".dds", "lightmap.ddsx"); + + if (fileName.length()) + { + if (pcb_id == PID_SAVE_LIGHTING_PC) + exportLightmapToFile(fileName, _MAKE4C('PC'), true); + else if (pcb_id == PID_SAVE_LIGHTING_X360) + exportLightmapToFile(fileName, _MAKE4C('PS4'), true); + else if (pcb_id == PID_SAVE_LIGHTING_iOS) + exportLightmapToFile(fileName, _MAKE4C('iOS'), true); + else if (pcb_id == PID_SAVE_LIGHTING_AND) + exportLightmapToFile(fileName, _MAKE4C('and'), true); + } + } + else if (pcb_id == PID_SAVE_LIGHTING_DDS) + { + String fileName = wingw::file_open_dlg(NULL, "Save lightmap", "Lightmap (*.dds)|*.dds", ".dds", "lightmap.dds"); + + exportLightmapToFile(fileName, _MAKE4C('DDS'), true); + } + else if (pcb_id >= PID_SCRIPT_PARAM_START && pcb_id <= PID_LAST_SCRIPT_PARAM) + { + for (int i = 0; i < colorGenParams.size(); ++i) + colorGenParams[i]->onPPBtnPressed(pcb_id, *panel); + for (int i = 0; i < genLayers.size(); ++i) + if (genLayers[i]->onPPBtnPressedEx(pcb_id, *panel)) + break; + } + else if (pcb_id == PID_SCRIPT_FILE) + { + String fname = wingw::file_open_dlg(NULL, "Select color map generator script", "Squirrel files (*.nut)|*.nut|All files (*.*)|*.*", + "nut", colorGenScriptFilename); + + if (!fname.length()) + return; + + colorGenScriptFilename = fname; + getColorGenVarsFromScript(); + onWholeLandChanged(); + if (propPanel) + propPanel->fillPanel(); + } + else if (pcb_id == PID_ADDLAYER) + { + CDialogWindow *dialog = DAGORED2->createDialog(_pxScaled(250), _pxScaled(120), "Create generation layer"); + PropPanel2 *panel = dialog->getPanel(); + panel->createEditBox(0, "Enter generation layer name:"); + panel->setFocusById(0); + + int ret = dialog->showDialog(); + if (ret == DIALOG_ID_OK) + { + addGenLayer(panel->getText(0)); + if (propPanel) + propPanel->fillPanel(); + } + DAGORED2->deleteDialog(dialog); + } + else if (pcb_id == PID_GRASS_LOADFROM_LEVELBLK) + { + loadGrassFromLevelBlk(); + if (propPanel) + propPanel->fillPanel(); + } + else if (pcb_id == PID_GRASS_ADDLAYER) + { + CDialogWindow *dialog = DAGORED2->createDialog(_pxScaled(250), _pxScaled(120), "Create grass layer"); + PropPanel2 *panel = dialog->getPanel(); + panel->createEditBox(0, "Enter grass layer name:"); + panel->setFocusById(0); + + int ret = dialog->showDialog(); + if (ret == DIALOG_ID_OK) + { + addGrassLayer(panel->getText(0)); + if (propPanel) + propPanel->fillPanel(); + } + DAGORED2->deleteDialog(dialog); + } + else if (pcb_id == PID_REBUILD_MESH) + { + dd_erase(DAGORED2->getPluginFilePath(HmapLandPlugin::self, "delaunayGen.cache.bin")); + generateLandMeshMap(landMeshMap, DAGORED2->getConsole(), false, NULL); + onWholeLandChanged(); // Place objects on current hmap. + resetLandmesh(); + } + else if (pcb_id == PID_WATER_SURF_REBUILD) + { + rebuildWaterSurface(); + } + else if (pcb_id == PID_WATER_SET_MAT) + { + const char *mat = DAEDITOR3.selectAssetX(waterMatAsset, "Select water material", "mat"); + if (mat) + { + waterMatAsset = mat; + panel->setCaption(pcb_id, String(128, "Water mat: <%s>", waterMatAsset.str())); + } + } + else if (pcb_id == PID_COPY_SNOW) + { + ambSnowValue = panel->getFloat(PID_DYN_SNOW); + panel->setFloat(PID_AMB_SNOW, ambSnowValue); + } + else if (pcb_id == PID_GRID_H2_APPLY) + { + float csz = panel->getFloat(PID_GRID_H2_CELL_SIZE); + Point2 b0 = panel->getPoint2(PID_GRID_H2_BBOX_OFS); + Point2 b1 = panel->getPoint2(PID_GRID_H2_BBOX_SZ) + b0; + int old_detDivisor = detDivisor; + BBox2 old_detRect = detRect; + IBBox2 old_detRectC = detRectC; + float *heights = NULL; + + if (!csz) + detDivisor = 0; + else + { + float land_cell_sz = getLandCellSize(); + b0.x = floor((b0.x - heightMapOffset.x) / land_cell_sz) * land_cell_sz + heightMapOffset.x; + b0.y = floor((b0.y - heightMapOffset.y) / land_cell_sz) * land_cell_sz + heightMapOffset.y; + b1.x = floor((b1.x - heightMapOffset.x) / land_cell_sz) * land_cell_sz + heightMapOffset.x; + b1.y = floor((b1.y - heightMapOffset.y) / land_cell_sz) * land_cell_sz + heightMapOffset.y; + if (b0.x == b1.x) + b1.x += land_cell_sz; + if (b0.y == b1.y) + b1.y += land_cell_sz; + detDivisor = gridCellSize / csz; + detRect[0] = b0; + detRect[1] = b1; + detRectC[0].set_xy((detRect[0] - heightMapOffset) / gridCellSize); + detRectC[0] *= detDivisor; + detRectC[1].set_xy((detRect[1] - heightMapOffset) / gridCellSize); + detRectC[1] *= detDivisor; + + heights = (float *)midmem->tryAlloc(sizeof(float) * (detRectC[1].x - detRectC[0].x) * (detRectC[1].y - detRectC[0].y)); + if (heights) + { + memset(heights, 0, sizeof(float) * (detRectC[1].x - detRectC[0].x) * (detRectC[1].y - detRectC[0].y)); + + int new_detDivisor = detDivisor; + BBox2 new_detRect = detRect; + IBBox2 new_detRectC = detRectC; + + detDivisor = old_detDivisor; + detRect = old_detRect; + detRectC = old_detRectC; + + float *hp = heights; + DEBUG_DUMP_VAR(old_detRectC); + DEBUG_DUMP_VAR(detRectC); + DEBUG_DUMP_VAR(new_detRectC); + for (int y = new_detRectC[0].y; y < new_detRectC[1].y; y++) + for (int x = new_detRectC[0].x; x < new_detRectC[1].x; x++, hp++) + { + Point3 p(heightMapOffset.x + x * gridCellSize / new_detDivisor, 100, + heightMapOffset.y + y * gridCellSize / new_detDivisor); + if (getHeightmapOnlyPointHt(p, NULL)) + *hp = p.y; + else + debug("failed %d,%d: %@", x, y, p); + } + + detDivisor = new_detDivisor; + detRect = new_detRect; + detRectC = new_detRectC; + } + } + panel->setFloat(PID_GRID_H2_CELL_SIZE, detDivisor ? gridCellSize / detDivisor : 0); + panel->setPoint2(PID_GRID_H2_BBOX_OFS, detRect[0]); + panel->setPoint2(PID_GRID_H2_BBOX_SZ, detRect.width()); + + if (detDivisor) + { + int dw = heightMap.getMapSizeX() * detDivisor, dh = heightMap.getMapSizeY() * detDivisor; + bool created_anew = !heightMapDet.isFileOpened(); + + if (created_anew || heightMapDet.getMapSizeX() != dw || heightMapDet.getMapSizeY() != dh) + { + resizeHeightMapDet(DAGORED2->getConsole()); + + if (heights) + { + float *hp = heights; + for (int y = detRectC[0].y; y < detRectC[1].y; y++) + for (int x = detRectC[0].x; x < detRectC[1].x; x++, hp++) + { + heightMapDet.setInitialData(x, y, *hp); + heightMapDet.setFinalData(x, y, *hp); + } + } + onLandRegionChanged(detRectC[0].x / detDivisor, detRectC[0].y / detDivisor, detRectC[1].x / detDivisor, + detRectC[1].y / detDivisor); + applyHmModifiers(); + heightMapDet.flushData(); + } + } + else + heightMapDet.closeFile(); + + if (heights) + midmem->free(heights); + + updateHeightMapTex(true); + updateHeightMapConstants(); + panel->setEnabledById(PID_GRID_H2_APPLY, false); + } + else if (pcb_id == PID_NAVMESH_BUILD) + { + BinDumpSaveCB cwr(1 << 10, 0, false); + buildAndWriteSingleNavMesh(cwr, shownExportedNavMeshIdx); + } + gpuGrassPanel.onClick( + pcb_id, panel, [this]() { loadGPUGrassFromLevelBlk(); }, + [this]() { + if (propPanel) + propPanel->fillPanel(); + }); +} + + +void HmapLandPlugin::processTexName(SimpleString &out, const char *in) +{ + if (!in || !in[0]) + { + out = NULL; + return; + } + + String asset(DagorAsset::fpath2asset(in)); + DagorAsset *a = DAEDITOR3.getAssetByName(asset, DAEDITOR3.getAssetTypeId("tex")); + + if (a) + out = a->getTargetFilePath(); + else + { + DAEDITOR3.conError("cant find det texture asset: %s", asset); + out = in; + } +} + +bool HmapLandPlugin::setDetailTexSlot(int slot, const char *blk_name) +{ + // debug("setDetailTexSlot %d. %s. %s. %s. %s %.3f", slot, det, det_n, side, side_n, tile); + if (slot < 0 || getDetLayerDesc().checkOverflow(slot)) + return false; + + if (numDetailTextures < slot + 1) + numDetailTextures = slot + 1; + + while (detailTexBlkName.size() < slot + 1) + detailTexBlkName.push_back() = ""; + + detailTexBlkName[slot] = blk_name ? blk_name : ""; + resetRenderer(); + + // debug("setDetailTexSlot[%d]: <%s>", slot, (char*)det); + return true; +} +// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ// + + +HmapLandPlugin::ScriptImage::ScriptImage(const char *n) : isModified(false), isSaved(false), name(n), fileNotifyId(-1) +{ + memset(bitsTile, 0, sizeof(bitsTile)); + w = h = 1; + bpp = bmStride = 0; + tileSz = 1; + wTiles = 1; + + IFileChangeTracker *ftracker = DAGORED2->queryEditorInterface(); + if (ftracker) // register file notify + { + char fullPath[260]; + String projPath; + DAGORED2->getProjectFolderPath(projPath); + if (n[0] != '*') + SNPRINTF(fullPath, sizeof(fullPath), "%s/%s/%s.tif", projPath.str(), HmapLandPlugin::self->getInternalName(), n); + else + SNPRINTF(fullPath, sizeof(fullPath), "%s/%s.tif", projPath.str(), n + 1); + G_ASSERT(fileNotifyId < 0); + fileNotifyId = ftracker->addFileChangeTracking(fullPath); + if (fileNotifyId >= 0) + ftracker->subscribeUpdateNotify(fileNotifyId, this); + else + debug("can't find file '%s' to track changes from", fullPath); + } +} + + +HmapLandPlugin::ScriptImage::~ScriptImage() +{ + if (fileNotifyId >= 0) + { + IFileChangeTracker *ftracker = DAGORED2->queryEditorInterface(); + if (ftracker) + ftracker->unsubscribeUpdateNotify(fileNotifyId, this); + } + bitMaskImgMgr->destroyImage(*this); +} + + +bool HmapLandPlugin::ScriptImage::loadImage() +{ + if (!name.length()) + return false; + + if (getBitsPerPixel() && isModified) + return false; + + bitMaskImgMgr->destroyImage(*this); + if (name[0] == '*') + return bitMaskImgMgr->loadImage(*this, NULL, &name[1]); + return bitMaskImgMgr->loadImage(*this, HmapLandPlugin::self->getInternalName(), name); +} + + +bool HmapLandPlugin::ScriptImage::saveImage() +{ + if (!name.length()) + return true; + + if (!getBitsPerPixel() || !isModified) + return true; + + if (!bitMaskImgMgr->saveImage(*this, HmapLandPlugin::self->getInternalName(), name)) + return false; + + isModified = false; + isSaved = true; + return true; +} + +void HmapLandPlugin::ScriptImage::onFileChanged(int) +{ + if (isSaved) + isSaved = false; // image was saved by editor, ignore it + else + { + debug("file '%s' changed, reloading...", getName()); + if (isImageModified()) + DAEDITOR3.conWarning("overwrite modified image '%s' from disk", getName()); + isModified = false; + loadImage(); + } +} + +E3DCOLOR HmapLandPlugin::ScriptImage::sampleImageUV(real fx, real fy, bool clamp_x, bool clamp_y) +{ + if (!getBitsPerPixel() || !isImage32()) + return E3DCOLOR(255, 255, 255, 0); + + fy = 1 - fy; + + fx *= getWidth(); + fy *= getHeight(); + + int ix = int(floorf(fx)); + int iy = int(floorf(fy)); + + fx -= ix; + fy -= iy; + + if (clamp_x) + { + if (ix < 0) + { + ix = 0; + fx = 0; + } + else if (ix >= getWidth() - 1) + { + ix = getWidth() - 1; + fx = 0; + } + } + else + { + ix %= getWidth(); + if (ix < 0) + ix += getWidth(); + } + + if (clamp_y) + { + if (iy < 0) + { + iy = 0; + fy = 0; + } + else if (iy >= getHeight() - 1) + { + iy = getHeight() - 1; + fy = 0; + } + } + else + { + iy %= getHeight(); + if (iy < 0) + iy += getHeight(); + } + + int nx = ix + 1; + if (nx >= getWidth()) + nx = 0; + int ny = iy + 1; + if (ny >= getHeight()) + ny = 0; + + E3DCOLOR c00 = getImagePixel(ix, iy); + E3DCOLOR c01 = getImagePixel(nx, iy); + E3DCOLOR c10 = getImagePixel(ix, ny); + E3DCOLOR c11 = getImagePixel(nx, ny); + + int r = real2int((c00.r * (1 - fx) + c01.r * fx) * (1 - fy) + (c10.r * (1 - fx) + c11.r * fx) * fy); + int g = real2int((c00.g * (1 - fx) + c01.g * fx) * (1 - fy) + (c10.g * (1 - fx) + c11.g * fx) * fy); + int b = real2int((c00.b * (1 - fx) + c01.b * fx) * (1 - fy) + (c10.b * (1 - fx) + c11.b * fx) * fy); + + if (r < 0) + r = 0; + else if (r > 255) + r = 255; + + if (g < 0) + g = 0; + else if (g > 255) + g = 255; + + if (b < 0) + b = 0; + else if (b > 255) + b = 255; + + return E3DCOLOR(r, g, b, 0); +} + + +E3DCOLOR HmapLandPlugin::ScriptImage::sampleImagePixelUV(real fx, real fy, bool clamp_x, bool clamp_y) +{ + if (!getBitsPerPixel() || !isImage32()) + return E3DCOLOR(255, 255, 255, 0); + + fy = 1 - fy; + + fx *= getWidth(); + fy *= getHeight(); + + int ix = real2int(fx); + int iy = real2int(fy); + + fx -= ix; + fy -= iy; + + if (clamp_x) + { + if (ix < 0) + { + ix = 0; + fx = 0; + } + else if (ix >= getWidth() - 1) + { + ix = getWidth() - 1; + fx = 0; + } + } + else + { + ix %= getWidth(); + if (ix < 0) + ix += getWidth(); + } + + if (clamp_y) + { + if (iy < 0) + { + iy = 0; + fy = 0; + } + else if (iy >= getHeight() - 1) + { + iy = getHeight() - 1; + fy = 0; + } + } + else + { + iy %= getHeight(); + if (iy < 0) + iy += getHeight(); + } + + return getImagePixel(ix, iy); +} + +inline void HmapLandPlugin::ScriptImage::calcClampMapping(float &fx, float &fy, int &ix, int &iy, int &nx, int &ny) +{ + fy = 1 - fy; + + fx *= getWidth(); + fy *= getHeight(); + + ix = int(floorf(fx)); + iy = int(floorf(fy)); + + fx -= ix; + fy -= iy; + + if (ix < 0) + { + ix = 0; + fx = 0; + } + else if (ix >= getWidth() - 1) + { + ix = getWidth() - 1; + fx = 0; + } + + if (iy < 0) + { + iy = 0; + fy = 0; + } + else if (iy >= getHeight() - 1) + { + iy = getHeight() - 1; + fy = 0; + } + + nx = ix + 1; + if (nx >= getWidth()) + nx = 0; + ny = iy + 1; + if (ny >= getHeight()) + ny = 0; +} +inline void HmapLandPlugin::ScriptImage::calcMapping(float &fx, float &fy, int &ix, int &iy, int &nx, int &ny, bool clamp_u, + bool clamp_v) +{ + fy = 1 - fy; + + fx *= getWidth(); + fy *= getHeight(); + + ix = int(floorf(fx)); + iy = int(floorf(fy)); + + fx -= ix; + fy -= iy; + + if (clamp_u) + { + if (ix < 0) + { + ix = 0; + fx = 0; + } + else if (ix >= getWidth() - 1) + { + ix = getWidth() - 1; + fx = 0; + } + } + else + { + ix %= getWidth(); + if (ix < 0) + ix += getWidth(); + } + + if (clamp_v) + { + if (iy < 0) + { + iy = 0; + fy = 0; + } + else if (iy >= getHeight() - 1) + { + iy = getHeight() - 1; + fy = 0; + } + } + else + { + iy %= getHeight(); + if (iy < 0) + iy += getHeight(); + } + + nx = ix + 1; + if (nx >= getWidth()) + nx = 0; + ny = iy + 1; + if (ny >= getHeight()) + ny = 0; +} +inline void HmapLandPlugin::ScriptImage::calcClampMapping(float fx0, float fy0, int &ix0, int &iy0) +{ + fy0 = 1 - fy0; + + fx0 *= getWidth(); + fy0 *= getHeight(); + + ix0 = real2int(fx0); + iy0 = real2int(fy0); + + if (ix0 < 0) + ix0 = 0; + else if (ix0 >= getWidth() - 1) + ix0 = getWidth() - 1; + + if (iy0 < 0) + iy0 = 0; + else if (iy0 >= getHeight() - 1) + iy0 = getHeight() - 1; +} + + +float HmapLandPlugin::ScriptImage::sampleMask1UV(real fx, real fy) +{ + if (getBitsPerPixel() != 1) + return 1.0; + + int ix, iy, nx, ny; + calcClampMapping(fx, fy, ix, iy, nx, ny); + + float c00 = getMaskPixel1(ix, iy) ? 1.0 : 0.0; + float c01 = getMaskPixel1(nx, iy) ? 1.0 : 0.0; + float c10 = getMaskPixel1(ix, ny) ? 1.0 : 0.0; + float c11 = getMaskPixel1(nx, ny) ? 1.0 : 0.0; + + return (c00 * (1 - fx) + c01 * fx) * (1 - fy) + (c10 * (1 - fx) + c11 * fx) * fy; +} + +float HmapLandPlugin::ScriptImage::sampleMask1UV(real fx, real fy, bool clamp_u, bool clamp_v) +{ + if (getBitsPerPixel() != 1) + return 1.0; + + int ix, iy, nx, ny; + calcMapping(fx, fy, ix, iy, nx, ny, clamp_u, clamp_v); + + float c00 = getMaskPixel1(ix, iy) ? 1.0 : 0.0; + float c01 = getMaskPixel1(nx, iy) ? 1.0 : 0.0; + float c10 = getMaskPixel1(ix, ny) ? 1.0 : 0.0; + float c11 = getMaskPixel1(nx, ny) ? 1.0 : 0.0; + + return (c00 * (1 - fx) + c01 * fx) * (1 - fy) + (c10 * (1 - fx) + c11 * fx) * fy; +} + +float HmapLandPlugin::ScriptImage::sampleMask8UV(real fx, real fy) +{ + if (getBitsPerPixel() != 8) + return 1.0; + + int ix, iy, nx, ny; + calcClampMapping(fx, fy, ix, iy, nx, ny); + + float c00 = getMaskPixel8(ix, iy) / 255.0; + float c01 = getMaskPixel8(nx, iy) / 255.0; + float c10 = getMaskPixel8(ix, ny) / 255.0; + float c11 = getMaskPixel8(nx, ny) / 255.0; + + return (c00 * (1 - fx) + c01 * fx) * (1 - fy) + (c10 * (1 - fx) + c11 * fx) * fy; +} + +float HmapLandPlugin::ScriptImage::sampleMask8UV(real fx, real fy, bool clamp_u, bool clamp_v) +{ + if (getBitsPerPixel() != 8) + return 1.0; + + int ix, iy, nx, ny; + calcMapping(fx, fy, ix, iy, nx, ny, clamp_u, clamp_v); + + float c00 = getMaskPixel8(ix, iy) / 255.0; + float c01 = getMaskPixel8(nx, iy) / 255.0; + float c10 = getMaskPixel8(ix, ny) / 255.0; + float c11 = getMaskPixel8(nx, ny) / 255.0; + + return (c00 * (1 - fx) + c01 * fx) * (1 - fy) + (c10 * (1 - fx) + c11 * fx) * fy; +} + +float HmapLandPlugin::ScriptImage::sampleMask1PixelUV(real fx, real fy) +{ + if (getBitsPerPixel() != 1) + return 1.0; + + int ix, iy; + calcClampMapping(fx, fy, ix, iy); + return getMaskPixel1(ix, iy) ? 1.0 : 0.0; +} + +float HmapLandPlugin::ScriptImage::sampleMask8PixelUV(real fx, real fy) +{ + if (getBitsPerPixel() != 8) + return 1.0; + + int ix, iy; + calcClampMapping(fx, fy, ix, iy); + return getMaskPixel8(ix, iy) / 255.0; +} + +void HmapLandPlugin::ScriptImage::paintImageUV(real fx0, real fy0, real fx1, real fy1, bool clamp_x, bool clamp_y, E3DCOLOR color) +{ + G_UNUSED(fx1); + G_UNUSED(fy1); + + if (!getBitsPerPixel() || !isImage32()) + return; + + fy0 = 1 - fy0; + + fx0 *= getWidth(); + fy0 *= getHeight(); + + int ix0 = real2int(fx0); + int iy0 = real2int(fy0); + + if (clamp_x) + { + if (ix0 < 0) + { + ix0 = 0; + } + else if (ix0 >= getWidth() - 1) + ix0 = getWidth() - 1; + } + else + { + ix0 %= getWidth(); + if (ix0 < 0) + ix0 += getWidth(); + } + + if (clamp_y) + { + if (iy0 < 0) + { + iy0 = 0; + } + else if (iy0 >= getHeight() - 1) + iy0 = getHeight() - 1; + } + else + { + iy0 %= getHeight(); + if (iy0 < 0) + iy0 += getHeight(); + } + + setImagePixel(ix0, iy0, color); + + isModified = true; +} + +void HmapLandPlugin::ScriptImage::paintMask1UV(real fx0, real fy0, bool val) +{ + if (getBitsPerPixel() != 1) + return; + + int ix0, iy0; + calcClampMapping(fx0, fy0, ix0, iy0); + setMaskPixel1(ix0, iy0, val ? 0x80 : 0); + + isModified = true; +} +void HmapLandPlugin::ScriptImage::paintMask8UV(real fx0, real fy0, char val) +{ + if (getBitsPerPixel() != 8) + return; + + int ix0, iy0; + calcClampMapping(fx0, fy0, ix0, iy0); + setMaskPixel8(ix0, iy0, val); + + isModified = true; +} + +// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ// + + +void HmapLandPlugin::updateScriptImageList() +{ + alefind_t ff; + String fname; + + for (bool ok = ::dd_find_first(DAGORED2->getPluginFilePath(this, "*.tif"), 0, &ff); ok; ok = ::dd_find_next(&ff)) + { + fname = ::get_file_name_wo_ext(ff.name); + if (stricmp(fname, "importanceMask_lc") == 0) // skip temporary files + continue; + + int i; + for (i = 0; i < scriptImages.size(); ++i) + if (stricmp(scriptImages[i]->getName(), fname) == 0) + break; + + if (i >= scriptImages.size()) + scriptImages.push_back(new ScriptImage(fname)); + } + ::dd_find_close(&ff); + + for (bool ok = ::dd_find_first(DAGORED2->getPluginFilePath(this, "*.tga"), 0, &ff); ok; ok = ::dd_find_next(&ff)) + { + fname = ::get_file_name_wo_ext(ff.name); + + int i; + for (i = 0; i < scriptImages.size(); ++i) + if (stricmp(scriptImages[i]->getName(), fname) == 0) + break; + + if (i >= scriptImages.size()) + scriptImages.push_back(new ScriptImage(fname)); + } + ::dd_find_close(&ff); +} + + +const char *HmapLandPlugin::pickScriptImage(const char *current_name, int bpp) +{ + static String stor; + HmlSelTexDlg dlg(*this, current_name, bpp); + if (dlg.execute()) + return stor = dlg.getSetTex(); + return NULL; +} + + +E3DCOLOR HmapLandPlugin::sampleScriptImageUV(int id, real x, real y, bool clamp_x, bool clamp_y) +{ + if (id < 0 || id >= scriptImages.size()) + return E3DCOLOR(255, 255, 255, 0); + return scriptImages[id]->sampleImageUV(x, y, clamp_x, clamp_y); +} + + +E3DCOLOR HmapLandPlugin::sampleScriptImagePixelUV(int id, real x, real y, bool clamp_x, bool clamp_y) +{ + if (id < 0 || id >= scriptImages.size()) + return E3DCOLOR(255, 255, 255, 0); + return scriptImages[id]->sampleImagePixelUV(x, y, clamp_x, clamp_y); +} + + +void HmapLandPlugin::paintScriptImageUV(int id, real x0, real y0, real x1, real y1, bool clamp_x, bool clamp_y, E3DCOLOR color) +{ + if (id < 0 || id >= scriptImages.size()) + return; + return scriptImages[id]->paintImageUV(x0, y0, x1, y1, clamp_x, clamp_y, color); +} + +float HmapLandPlugin::sampleMask1UV(int id, real x, real y) +{ + if (id < 0 || id >= scriptImages.size()) + return 1.0; + return scriptImages[id]->sampleMask1UV(x, y); +} +float HmapLandPlugin::sampleMask1UV(int id, real x, real y, bool clamp_u, bool clamp_v) +{ + if (id < 0 || id >= scriptImages.size()) + return 1.0; + return scriptImages[id]->sampleMask1UV(x, y, clamp_u, clamp_v); +} +float HmapLandPlugin::sampleMask8UV(int id, real x, real y) +{ + if (id < 0 || id >= scriptImages.size()) + return 1.0; + return scriptImages[id]->sampleMask8UV(x, y); +} +float HmapLandPlugin::sampleMask8UV(int id, real x, real y, bool clamp_u, bool clamp_v) +{ + if (id < 0 || id >= scriptImages.size()) + return 1.0; + return scriptImages[id]->sampleMask8UV(x, y, clamp_u, clamp_v); +} +float HmapLandPlugin::sampleMask1PixelUV(int id, real x, real y) +{ + if (id < 0 || id >= scriptImages.size()) + return 1.0; + return scriptImages[id]->sampleMask1PixelUV(x, y); +} +float HmapLandPlugin::sampleMask8PixelUV(int id, real x, real y) +{ + if (id < 0 || id >= scriptImages.size()) + return 1.0; + return scriptImages[id]->sampleMask8PixelUV(x, y); +} +void HmapLandPlugin::paintMask1UV(int id, real x0, real y0, bool color) +{ + if (id < 0 || id >= scriptImages.size()) + return; + scriptImages[id]->paintMask1UV(x0, y0, color); +} +void HmapLandPlugin::paintMask8UV(int id, real x0, real y0, char color) +{ + if (id < 0 || id >= scriptImages.size()) + return; + scriptImages[id]->paintMask8UV(x0, y0, color); +} + +bool HmapLandPlugin::saveImage(int id) +{ + if (id < 0 || id >= scriptImages.size()) + return false; + return scriptImages[id]->saveImage(); +} + +int HmapLandPlugin::getScriptImageWidth(int id) +{ + if (id < 0 || id >= scriptImages.size()) + return 1; + return scriptImages[id]->getWidth(); +} + + +int HmapLandPlugin::getScriptImageHeight(int id) +{ + if (id < 0 || id >= scriptImages.size()) + return 1; + return scriptImages[id]->getHeight(); +} + +int HmapLandPlugin::getScriptImageBpp(int id) +{ + if (id < 0 || id >= scriptImages.size()) + return 1; + if (int bpp = scriptImages[id]->getBitsPerPixel()) + return bpp; + + int w, h, bpp; + if (bitMaskImgMgr->getBitMaskProps(HmapLandPlugin::self->getInternalName(), scriptImages[id]->getName(), w, h, bpp)) + return bpp; + return 0; +} + +void HmapLandPlugin::prepareScriptImage(const char *name, int img_size_mul, int img_bpp) +{ + if (!name || !*name) + return; + + for (int i = 0; i < scriptImages.size(); ++i) + if (stricmp(name, scriptImages[i]->getName()) == 0) + return; + + if (img_size_mul && img_bpp) + { + const char *dirname = NULL; + const char *fname = name; + + if (fname[0] == '*') + fname++; + else + dirname = HmapLandPlugin::self->getInternalName(); + + if (!bitMaskImgMgr->checkBitMask(dirname, fname, getHeightmapSizeX() * img_size_mul, getHeightmapSizeY() * img_size_mul, img_bpp)) + getScriptImage(name, img_size_mul, img_bpp); + } +} +int HmapLandPlugin::getScriptImage(const char *name, int img_size_mul, int img_bpp) +{ + if (!name || !*name) + return -1; + + int id = -1; + for (int i = 0; i < scriptImages.size(); ++i) + { + if (stricmp(name, scriptImages[i]->getName()) != 0) + continue; + + scriptImages[i]->loadImage(); + id = i; + } + + if (img_size_mul && img_bpp) + { + int dest_w = getHeightmapSizeX(); + int dest_h = getHeightmapSizeY(); + if (trail_stricmp(name, "_lc")) + dest_w *= lcmScale, dest_h *= lcmScale; + else if (trail_stricmp(name, "_dr") && detDivisor) + dest_w = detRectC[1].x - detRectC[0].x, dest_h = detRectC[1].y - detRectC[0].y; + + if (id == -1) + { + id = scriptImages.size(); + scriptImages.push_back(new ScriptImage(name)); + } + + ScriptImage &img = *scriptImages[id]; + + if (!img.loadImage() && img_bpp < 32 && img_bpp > 0) + { + bitMaskImgMgr->createBitMask(img, dest_w * img_size_mul, dest_h * img_size_mul, img_bpp); + bitMaskImgMgr->saveImage(img, HmapLandPlugin::self->getInternalName(), name); + } + else if (img_bpp < 32) + { + int sizeX = dest_w * img_size_mul; + int sizeY = dest_h * img_size_mul; + if (img_bpp < 0) + img_bpp = scriptImages[id]->getBitsPerPixel(); + + if (scriptImages[id]->getWidth() != sizeX || scriptImages[id]->getHeight() != sizeY || + scriptImages[id]->getBitsPerPixel() != img_bpp) + { + bool needToResample = true; + + if (sizeX < scriptImages[id]->getWidth() || sizeY < scriptImages[id]->getHeight() || + img_bpp < scriptImages[id]->getBitsPerPixel()) + { + String msg(512, + "Mask <%s>, %dx%d %d bpp requires downsapling.\n" + "Continue resampling to %dx%d %d bpp?", + name, scriptImages[id]->getWidth(), scriptImages[id]->getHeight(), scriptImages[id]->getBitsPerPixel(), sizeX, sizeY, + img_bpp); + + if (wingw::message_box(wingw::MBS_YESNO | wingw::MBS_EXCL, "Are you sure?", msg) != wingw::MB_ID_YES) + needToResample = false; + } + + if (needToResample) + { + if (bitMaskImgMgr->resampleBitMask(img, sizeX, sizeY, img_bpp)) + bitMaskImgMgr->saveImage(img, HmapLandPlugin::self->getInternalName(), name); + } + } + } + } + + return id; +} + + +// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ// + + +void HmapLandPlugin::onBrushPaint(Brush *brush, const Point3 ¢er, const Point3 &prev_center, const Point3 &normal, int buttons, + int key_modif) +{ + Point3 c = center - Point3::x0y(editedScriptImage ? esiOrigin : heightMapOffset); + float cell_sz = editedScriptImage ? esiGridStep : (detDivisor ? gridCellSize / detDivisor : gridCellSize); + ((HmapLandBrush *)brush)->setHeightmapOffset(editedScriptImage ? esiOrigin : heightMapOffset); + noTraceNow = true; + ((HmapLandBrush *)brush)->onBrushPaint(c, prev_center, normal, buttons, key_modif, cell_sz); + noTraceNow = false; + if (propPanel && propPanel->getPanelWindow()) + ((HmapLandBrush *)brush)->dynamicItemChange(*propPanel->getPanelWindow()); + updateLandOnPaint(brush, false); +} + + +void HmapLandPlugin::onRBBrushPaint(Brush *brush, const Point3 ¢er, const Point3 &prev_center, const Point3 &normal, int buttons, + int key_modif) +{ + Point3 c = center - Point3::x0y(editedScriptImage ? esiOrigin : heightMapOffset); + float cell_sz = editedScriptImage ? esiGridStep : (detDivisor ? gridCellSize / detDivisor : gridCellSize); + ((HmapLandBrush *)brush)->setHeightmapOffset(editedScriptImage ? esiOrigin : heightMapOffset); + noTraceNow = true; + ((HmapLandBrush *)brush)->onRBBrushPaint(c, prev_center, normal, buttons, key_modif, cell_sz); + noTraceNow = false; + if (propPanel && propPanel->getPanelWindow()) + ((HmapLandBrush *)brush)->dynamicItemChange(*propPanel->getPanelWindow()); + updateLandOnPaint(brush, false); +} + + +IRoadsProvider::Roads *HmapLandPlugin::getRoadsSnapshot() +{ + if (!roadsSnapshot.get() || roadsSnapshot->getGenTimeStamp() != objEd.generationCount) + { + roadsSnapshot = NULL; + roadsSnapshot = new RoadsSnapshot(objEd); + } + + roadsSnapshot.addRef(); + return roadsSnapshot.get(); +} + + +void HmapLandPlugin::updateLandOnPaint(Brush *brush, bool finished) +{ + IBBox2 rect; + + if (finished) + rect = brushFullDirtyBox; + else + { + rect = ((HmapLandBrush *)brush)->getDirtyBox(); + if (detDivisor && !editedScriptImage) + rect[0] /= detDivisor, rect[1].x = (rect[1].x + detDivisor - 1) / detDivisor, + rect[1].y = (rect[1].y + detDivisor - 1) / detDivisor; + else if (editedScriptImage) + { + rect[0].x = (rect[0].x * esiGridStep + esiOrigin.x - heightMapOffset.x) / gridCellSize; + rect[0].y = (rect[0].y * esiGridStep + esiOrigin.y - heightMapOffset.y) / gridCellSize; + rect[1].x = (rect[1].x * esiGridStep + esiOrigin.x - heightMapOffset.x - 1) / gridCellSize + 1; + rect[1].y = (rect[1].y * esiGridStep + esiOrigin.y - heightMapOffset.y - 1) / gridCellSize + 1; + } + } + + if (rect.isEmpty()) + return; + + rect[0] -= IPoint2(1, 1); + rect[1] += IPoint2(1, 1); + + if (editedScriptImage && editedScriptImageIdx >= 0) + { + if (!finished) + updateBlueWhiteMask(&rect); + return; + } + + if (finished) + { + if (!editedScriptImage && ((HmapLandBrush *)brush) != brushes[SCRIPT_BRUSH]) + recalcLightingInRect(rect); + generateLandColors(&rect, true); + + updateHeightMapTex(false, &rect); + if (detDivisor) + { + rect[0] *= detDivisor; + rect[1] *= detDivisor; + } + updateHeightMapTex(true, &rect); + resetTexCacheRect(rect); + } + else + { + if (editedScriptImage) + updateBlueWhiteMask(&rect); + + brushFullDirtyBox += rect; + ((HmapLandBrush *)brush)->resetDirtyBox(); + + applyHmModifiers(false, true, false); + if (!editedScriptImage) + { + updateHeightMapTex(false, &rect); + rect[0] *= detDivisor; + rect[1] *= detDivisor; + updateHeightMapTex(true, &rect); + } + } +} + + +void HmapLandPlugin::onBrushPaintEnd(Brush *brush, int buttons, int key_modif) +{ + ((HmapLandBrush *)brush)->onBrushPaintEnd(buttons, key_modif); + updateLandOnPaint(brush, true); + objEd.onBrushPaintEnd(); +} + + +void HmapLandPlugin::onRBBrushPaintEnd(Brush *brush, int buttons, int key_modif) +{ + ((HmapLandBrush *)brush)->onRBBrushPaintEnd(buttons, key_modif); + updateLandOnPaint(brush, true); +} + + +void HmapLandPlugin::onBrushPaintStart(Brush *brush, int buttons, int key_modif) +{ + brushFullDirtyBox.setEmpty(); + ((HmapLandBrush *)brush)->onBrushPaintStart(buttons, key_modif); +} + + +void HmapLandPlugin::onRBBrushPaintStart(Brush *brush, int buttons, int key_modif) +{ + brushFullDirtyBox.setEmpty(); + ((HmapLandBrush *)brush)->onRBBrushPaintEnd(buttons, key_modif); +} + + +void HmapLandPlugin::onLightingSettingsChanged() +{ + if (syncLight) + { + getAllSunSettings(); + updateRendererLighting(); + } + else if (syncDirLight) + { + getDirectionSunSettings(); + updateRendererLighting(); + } + DataBlock level_blk; + if (loadLevelSettingsBlk(level_blk)) + updateWaterSettings(level_blk); +} + + +void HmapLandPlugin::onLandRegionChanged(int x0, int y0, int x1, int y1, bool recalc_all, bool finished) +{ + if (x0 < 0) + x0 = 0; + if (y0 < 0) + y0 = 0; + if (x1 > landClsMap.getMapSizeX()) + x1 = landClsMap.getMapSizeX(); + if (y1 > landClsMap.getMapSizeY()) + y1 = landClsMap.getMapSizeY(); + + if (x0 > x1 || y0 > y1) + return; + + float fx0, fz0, fx1, fz1; + fx0 = heightMapOffset.x + gridCellSize * x0 * heightMap.getMapSizeX() / landClsMap.getMapSizeX(); + fz0 = heightMapOffset.y + gridCellSize * y0 * heightMap.getMapSizeY() / landClsMap.getMapSizeY(); + fx1 = heightMapOffset.x + gridCellSize * x1 * heightMap.getMapSizeX() / landClsMap.getMapSizeX(); + fz1 = heightMapOffset.y + gridCellSize * y1 * heightMap.getMapSizeY() / landClsMap.getMapSizeY(); + objEd.onLandRegionChanged(fx0, fz0, fx1, fz1, recalc_all); + lcMgr->onLandRegionChanged(x0, y0, x1, y1, landClsMap, finished); + if (hmlService) + hmlService->invalidateClipmap(false); + invalidateDistanceField(); +} +void HmapLandPlugin::onWholeLandChanged() { onLandRegionChanged(0, 0, landClsMap.getMapSizeX(), landClsMap.getMapSizeY()); } +void HmapLandPlugin::onLandSizeChanged() +{ + genHmap->offset = heightMapOffset; + genHmap->cellSize = gridCellSize; + if (brushes.size()) + brushes.back()->setMaxRadius(1000 * gridCellSize); + lcMgr->onLandSizeChanged(gridCellSize * heightMap.getMapSizeX() / landClsMap.getMapSizeX(), heightMapOffset.x, heightMapOffset.y, + landClsLayer); + invalidateDistanceField(); +} + +/*void HmapLandPlugin::prepareDetailTexTileAndOffset(Tab &out_tile, Tab &out_offset) +{ + out_tile = detailTexTile; + out_offset = detailTexOffset; + + for ( int i = 0; i < out_tile.size(); i ++ ) + { + if ( out_tile[i] < 0) + out_tile[i] = -render.detailTile/out_tile[i]; + //else + // out_tile[i] = -render.detailTile; + } +}*/ + +#if defined(USE_HMAP_ACES) +void HmapLandPlugin::getEnvironmentSettings(DataBlock &blk) +{ + blk.clearData(); + ldrLight.save("", blk); + blk.setReal("sunAzimuth", sunAzimuth); + blk.setReal("sunZenith", sunZenith); +} + +void HmapLandPlugin::setEnvironmentSettings(DataBlock &blk) +{ + ldrLight.load("", blk); + sunAzimuth = blk.getReal("sunAzimuth", sunAzimuth); + sunZenith = blk.getReal("sunZenith", sunZenith); + resetRenderer(); + if (DAGORED2->curPlugin() == this && propPanel) + propPanel->updateLightGroup(); +} +#endif + + +void HmapLandPlugin::setSelectMode() { objEd.setEditMode(CM_OBJED_MODE_SELECT); } +// IPostProcessGeometry +void HmapLandPlugin::processGeometry(StaticGeometryContainer &container) +{ + DataBlock app_blk(DAGORED2->getWorkspace().getAppPath()); + const char *mgr_type = app_blk.getBlockByNameEx("projectDefaults")->getBlockByNameEx("hmap")->getStr("type", NULL); + bool snow = (!mgr_type || strcmp(mgr_type, "aces") != 0); + if (snow) + objEd.calcSnow(container); + else + removeInvisibleFaces(container); +} + + +//------------------------------------------------------------------------------------ +//---------------------------------------------------------GRASS +//------------------------------------------------------------------------------------ + +// Layers manipulations + +void HmapLandPlugin::addGrassLayer(const char *name) +{ + int layerId = HmapLandPlugin::grassService->addDefaultLayer(); + if (layerId != -1) + { + GrassLayerPanel *grass_layer = new GrassLayerPanel(name, layerId); + grassLayers.push_back(grass_layer); + } +} + +GrassLayerPanel::GrassLayerPanel(const char *name, int layer_i) : + grass_layer_i(layer_i), layerName(name), newLayerGrp(NULL), pidBase(0), remove_this_layer(false) +{} + + +// Grass interface + +void GrassLayerPanel::fillParams(PropertyContainerControlBase *parent_panel, int &pid) +{ + GrassLayerInfo *layerProps = HmapLandPlugin::grassService->getLayerInfo(grass_layer_i); + if (!layerProps) + return; + + pidBase = pid; + newLayerGrp = parent_panel->createGroup(PID_GRASS_LAYER_GRP + grass_layer_i, layerName.str()); + + newLayerGrp->createButton(GL_PID_ASSET_NAME + pid, String(128, "AssetName: %s", layerProps->resName.str())); + + newLayerGrp->createStatic(0, "Mask:"); + newLayerGrp->createCheckBox(GL_PID_MASK_R + pid, "r", (layerProps->bitMask & 1) ? true : false, true, false); + newLayerGrp->createCheckBox(GL_PID_MASK_G + pid, "g", (layerProps->bitMask & 2) ? true : false, true, false); + newLayerGrp->createCheckBox(GL_PID_MASK_B + pid, "b", (layerProps->bitMask & 4) ? true : false, true, false); + + newLayerGrp->createEditFloat(GL_PID_DENSITY + pid, "Density", layerProps->density); + newLayerGrp->setMinMaxStep(GL_PID_DENSITY + pid, 0.f, 5.f, 0.01); + + newLayerGrp->createStatic(0, "Horizontal scale:"); + newLayerGrp->createEditFloat(GL_PID_HORIZONTAL_SCALE_MIN + pid, "min", layerProps->minScale.x); + newLayerGrp->setMinMaxStep(GL_PID_HORIZONTAL_SCALE_MIN + pid, 0.f, 10.f, 0.01); + newLayerGrp->createEditFloat(GL_PID_HORIZONTAL_SCALE_MAX + pid, "max", layerProps->maxScale.x, 2, true, false); + newLayerGrp->setMinMaxStep(GL_PID_HORIZONTAL_SCALE_MAX + pid, 0.f, 10.f, 0.01); + + newLayerGrp->createStatic(0, "Vertical scale:"); + newLayerGrp->createEditFloat(GL_PID_VERTICAL_SCALE_MIN + pid, "min", layerProps->minScale.y); + newLayerGrp->setMinMaxStep(GL_PID_VERTICAL_SCALE_MIN + pid, 0.f, 10.f, 0.01); + newLayerGrp->createEditFloat(GL_PID_VERTICAL_SCALE_MAX + pid, "max", layerProps->maxScale.y, 2, true, false); + newLayerGrp->setMinMaxStep(GL_PID_VERTICAL_SCALE_MAX + pid, 0.f, 10.f, 0.01); + newLayerGrp->createEditFloat(GL_PID_WIND_MUL + pid, "Wind mul.", layerProps->windMul); + newLayerGrp->createEditFloat(GL_PID_RADIUS_MUL + pid, "Radius mul.", layerProps->radiusMul); + + + newLayerGrp->createStatic(0, ""); + + newLayerGrp->createColorBox(GL_PID_GRASS_RED_COLOR_FROM + pid, "Red color (from):", e3dcolor(layerProps->colors[0].start)); + newLayerGrp->createColorBox(GL_PID_GRASS_RED_COLOR_TO + pid, "Red color (to):", e3dcolor(layerProps->colors[0].end)); + + newLayerGrp->createColorBox(GL_PID_GRASS_GREEN_COLOR_FROM + pid, "Green color (from):", e3dcolor(layerProps->colors[1].start)); + newLayerGrp->createColorBox(GL_PID_GRASS_GREEN_COLOR_TO + pid, "Green color (to):", e3dcolor(layerProps->colors[1].end)); + + newLayerGrp->createColorBox(GL_PID_GRASS_BLUE_COLOR_FROM + pid, "Blue color (from):", e3dcolor(layerProps->colors[2].start)); + newLayerGrp->createColorBox(GL_PID_GRASS_BLUE_COLOR_TO + pid, "Blue color (to):", e3dcolor(layerProps->colors[2].end)); + + newLayerGrp->createButton(GL_PID_REMOVE_LAYER + pid, "Remove layer"); + + pid += GL_PID_ELEM_COUNT; + + parent_panel->setBool(PID_GRASS_LAYER_GRP + grass_layer_i, true); +} + +void GrassLayerPanel::onClick(int pid, PropPanel2 &p) +{ + int detailTypePid = pid - pidBase; + + if (detailTypePid == GL_PID_ASSET_NAME) + { + String fname = + wingw::file_open_dlg(NULL, "Select grass layer resource", "Grass blades (*.dag)|*.dag|All files (*.*)|*.*", "dag", ""); + + if (!fname.length()) + return; + + String resName = ::get_file_name_wo_ext(fname); + String corrected_resName; + corrected_resName.setStr(resName.str(), resName.length() - 6); // cut off file extention + + p.setCaption(pid, *corrected_resName.str() ? corrected_resName.str() : "AssetName:"); + + HmapLandPlugin::grassService->changeLayerResource(grass_layer_i, corrected_resName.str()); + } + else if (detailTypePid == GL_PID_REMOVE_LAYER) + { + remove_this_layer = true; + } +} + +bool GrassLayerPanel::onPPChangeEx(int pid, PropPanel2 &p) +{ + if (pid < pidBase || pid >= pidBase + GL_PID_ELEM_COUNT) + return false; + onPPChange(pid, p); + return true; +} + +void GrassLayerPanel::onPPChange(int pid, PropPanel2 &panel) +{ + GrassLayerInfo *layerProps = HmapLandPlugin::grassService->getLayerInfo(grass_layer_i); + if (!layerProps) + return; + + int detailTypePid = pid - pidBase; + + switch (detailTypePid) + { + case GL_PID_MASK_R: + layerProps->bitMask = panel.getBool(pid) ? (layerProps->bitMask | 1ULL) : (layerProps->bitMask & (~1ULL)); + break; + case GL_PID_MASK_G: + layerProps->bitMask = panel.getBool(pid) ? (layerProps->bitMask | 2ULL) : (layerProps->bitMask & (~2ULL)); + break; + case GL_PID_MASK_B: + layerProps->bitMask = panel.getBool(pid) ? (layerProps->bitMask | 4ULL) : (layerProps->bitMask & (~4ULL)); + break; + + case GL_PID_DENSITY: + layerProps->density = panel.getFloat(pid); + layerProps->resetLayerVB = true; + HmapLandPlugin::grassService->setLayerDensity(grass_layer_i, layerProps->density); + break; + + case GL_PID_HORIZONTAL_SCALE_MIN: + layerProps->minScale.x = panel.getFloat(pid); + layerProps->resetLayerVB = true; + HmapLandPlugin::grassService->updateLayerVbo(grass_layer_i); + break; + case GL_PID_HORIZONTAL_SCALE_MAX: + layerProps->maxScale.x = panel.getFloat(pid); + layerProps->resetLayerVB = true; + HmapLandPlugin::grassService->updateLayerVbo(grass_layer_i); + break; + + + case GL_PID_VERTICAL_SCALE_MIN: + layerProps->minScale.y = panel.getFloat(pid); + layerProps->resetLayerVB = true; + HmapLandPlugin::grassService->updateLayerVbo(grass_layer_i); + break; + case GL_PID_VERTICAL_SCALE_MAX: + layerProps->maxScale.y = panel.getFloat(pid); + layerProps->resetLayerVB = true; + HmapLandPlugin::grassService->updateLayerVbo(grass_layer_i); + break; + + + case GL_PID_GRASS_RED_COLOR_FROM: layerProps->colors[0].start = color4(panel.getColor(pid)); break; + case GL_PID_GRASS_RED_COLOR_TO: layerProps->colors[0].end = color4(panel.getColor(pid)); break; + + case GL_PID_GRASS_GREEN_COLOR_FROM: layerProps->colors[1].start = color4(panel.getColor(pid)); break; + case GL_PID_GRASS_GREEN_COLOR_TO: layerProps->colors[1].end = color4(panel.getColor(pid)); break; + + case GL_PID_GRASS_BLUE_COLOR_FROM: layerProps->colors[2].start = color4(panel.getColor(pid)); break; + case GL_PID_GRASS_BLUE_COLOR_TO: layerProps->colors[2].end = color4(panel.getColor(pid)); break; + + case GL_PID_WIND_MUL: layerProps->windMul = panel.getFloat(pid); break; + case GL_PID_RADIUS_MUL: layerProps->radiusMul = panel.getFloat(pid); break; + }; +} + + +// Save & load grass + +bool HmapLandPlugin::loadGrassLayers(const DataBlock &blk, bool update_grass_blk) +{ + enableGrass = blk.getBool("enableGrass", enableGrass); + const Tab &landClasses = landMeshRenderer->getLandClasses(); + grass.masks.clear(); + for (int i = 0; i < landClasses.size(); ++i) + { + String detailName(grassService->getResName(landClasses[i].colormapId)); + if (detailName.length() > 0 && detailName[detailName.length() - 1] == '*') + detailName[detailName.length() - 1] = 0; + grass.masks.emplace_back(detailName, String{blk.getStr(detailName, "grass_mask_black")}); + } + grass.defaultMinDensity = blk.getReal("minLodDensity", 0.2f); + grass.defaultMaxDensity = blk.getReal("density", 0.75f); + grass.maxRadius = blk.getReal("maxRadius", 400.f); + + grass.texSize = blk.getInt("texSize", 256); + grass.sowPerlinFreq = blk.getReal("sowPerlinFreq", 0.1); + grass.fadeDelta = blk.getReal("fadeDelta", 100); + grass.lodFadeDelta = blk.getReal("lodFadeDelta", 30); + grass.blendToLandDelta = blk.getReal("blendToLandDelta", 100); + + grass.noise_first_rnd = blk.getReal("noise_first_rnd", 23.1406926327792690); + grass.noise_first_val_mul = blk.getReal("noise_first_val_mul", 1); + grass.noise_first_val_add = blk.getReal("noise_first_val_add", 0); + + grass.noise_second_rnd = blk.getReal("noise_second_rnd", 0.05); + grass.noise_second_val_mul = blk.getReal("noise_second_val_mul", 1); + grass.noise_second_val_add = blk.getReal("noise_second_val_add", 0); + + grass.directWindMul = blk.getReal("directWindMul", 1); + grass.noiseWindMul = blk.getReal("noiseWindMul", 1); + grass.windPerlinFreq = blk.getReal("windPerlinFreq", 50000); + grass.directWindFreq = blk.getReal("directWindFreq", 1); + grass.directWindModulationFreq = blk.getReal("directWindModulationFreq", 1); + grass.windWaveLength = blk.getReal("windWaveLength", 100); + grass.windToColor = blk.getReal("windToColor", 0.2); + grass.helicopterHorMul = blk.getReal("helicopterHorMul", 2); + grass.helicopterVerMul = blk.getReal("helicopterVerMul", 1); + grass.helicopterToDirectWindMul = blk.getReal("helicopterToDirectWindMul", 2); + grass.helicopterFalloff = blk.getReal("helicopterFalloff", 0.001); + + int nid = blk.getNameId("layer"); + grassLayers.clear(); + + for (int i = 0, idx = 0; i < blk.blockCount(); i++) + if (blk.getBlock(i)->getBlockNameId() == nid) + { + String defLayerName(16, "layer_%i", i); + const char *layerName = blk.getBlock(i)->getStr("layerName", defLayerName.str()); + GrassLayerPanel *l = new GrassLayerPanel(layerName, i); + grassLayers.push_back(l); + } + + // set grass mask + resetGrassMask(blk); + + // create copy from blk + if (update_grass_blk) + { + delete grassBlk; + grassBlk = new DataBlock(blk); + } + hmlService->setGrassBlk(grassBlk); + return true; +} + +bool HmapLandPlugin::loadGrassFromBlk(const DataBlock &level_blk) +{ + const DataBlock *blk = level_blk.getBlockByName("randomGrass"); + if (!blk) + return false; + enableGrass = true; + delete grassBlk; + grassBlk = new DataBlock(*blk); + return true; +} + +void HmapLandPlugin::loadGrassFromLevelBlk() +{ + if (wingw::message_box(wingw::MBS_YESNO | wingw::MBS_QUEST, "Confirmation", "Overwrite grass settings?") != wingw::MB_ID_YES) + return; + + DataBlock level_blk; + if (loadLevelSettingsBlk(level_blk)) + if (loadGrassFromBlk(level_blk)) + { + HmapLandPlugin::grassService->reloadAll(*grassBlk, level_blk); + bool savedEnableGrass = enableGrass; // assume that this flag always false in level.blk - save it + loadGrassLayers(*grassBlk, false); + enableGrass = savedEnableGrass; + } +} + +bool HmapLandPlugin::loadGPUGrassFromBlk(const DataBlock &level_blk) +{ + const DataBlock *gpuGrassBlock = level_blk.getBlockByNameEx("grass", nullptr); + if (!gpuGrassBlock) + return false; + enableGrass = true; + delete gpuGrassBlk; + gpuGrassBlk = new DataBlock(*gpuGrassBlock); + return true; +} + +void HmapLandPlugin::loadGPUGrassFromLevelBlk() +{ + DataBlock level_blk; + bool savedEnableGrass = gpuGrassService->isGrassEnabled(); + if (loadLevelSettingsBlk(level_blk)) + { + loadGPUGrassFromBlk(level_blk); + gpuGrassService->enableGrass(savedEnableGrass); + if (propPanel) + propPanel->fillPanel(); + } +} + +void HmapLandPlugin::onLandClassAssetTexturesChanged(landclass::AssetData *data) { resetLandmesh(); } diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlPlugin.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlPlugin.h new file mode 100644 index 000000000..a3ced3f0f --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlPlugin.h @@ -0,0 +1,1115 @@ +#ifndef __GAIJIN_HEIGHTMAPLAND_PLUGIN__ +#define __GAIJIN_HEIGHTMAPLAND_PLUGIN__ +#pragma once + + +#include "Brushes/hmlBrush.h" +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include <3d/dag_texMgr.h> + +#include +#include +#include "landMeshMap.h" + +#include "hmlObjectsEditor.h" +#include "hmlLayers.h" +#include +#include +#include +#include +#include +#include "gpuGrassPanel.h" + +#define DECAL_BITMAP_SZ 32 +#define KERNEL_RAD 2 +#define EXTENDED_DECAL_BITMAP_SZ (DECAL_BITMAP_SZ + 2 * 2 * KERNEL_RAD) +#define MAX_NAVMESHES 2 + +class CoolConsole; +class IObjectCreator; +class HmapLandBrush; + +struct HmapBitLayerDesc; +struct MemoryChainedData; + +class LandClassSlotsManager; +class GenHmapData; +class RoadsSnapshot; +class PostFxRenderer; + +class IHmapService; +class IBitMaskImageMgr; +class IDagorPhys; +class Bitarray; + +class DebugPrimitivesVbuffer; + + +namespace mkbindump +{ +class BinDumpSaveCB; +} + + +enum GrassLayerPanelElements +{ + // GL = Grass Layer + GL_PID_ASSET_NAME, + + GL_PID_MASK_R, + GL_PID_MASK_G, + GL_PID_MASK_B, + GL_PID_MASK_A, + + GL_PID_DENSITY, + GL_PID_HORIZONTAL_SCALE_MIN, + GL_PID_HORIZONTAL_SCALE_MAX, + GL_PID_VERTICAL_SCALE_MIN, + GL_PID_VERTICAL_SCALE_MAX, + GL_PID_WIND_MUL, + GL_PID_RADIUS_MUL, + + GL_PID_GRASS_RED_COLOR_FROM, + GL_PID_GRASS_RED_COLOR_TO, + GL_PID_GRASS_GREEN_COLOR_FROM, + GL_PID_GRASS_GREEN_COLOR_TO, + GL_PID_GRASS_BLUE_COLOR_FROM, + GL_PID_GRASS_BLUE_COLOR_TO, + + GL_PID_REMOVE_LAYER, + + GL_PID_ELEM_COUNT +}; + +class GrassLayerPanel : public DObject +{ +public: + String layerName; + int grass_layer_i; + + PropertyContainerControlBase *newLayerGrp; + int pidBase; + bool remove_this_layer; + + GrassLayerPanel(const char *name, int layer_i); + + void fillParams(PropertyContainerControlBase *parent_panel, int &pid); + void onClick(int pid, PropPanel2 &p); + bool onPPChangeEx(int pid, PropPanel2 &p); + void onPPChange(int pid, PropPanel2 &panel); + + void saveLayer(DataBlock &blk); +}; + + +class HmapLandPlugin : public IGenEditorPlugin, + public IGenEventHandlerWrapper, + public IBrushClient, + public IBinaryDataBuilder, + public IWriteAddLtinputData, + public IDagorEdCustomCollider, + public IHmapBrushImage, + public IHeightmap, + public IRoadsProvider, + public ILightingChangeClient, + public IGatherStaticGeometry, + public IRenderingService, + public IOnExportNotify, + public IPluginAutoSave, + public ControlEventHandler, + public IWndManagerWindowHandler, + public IPostProcessGeometry, +#if defined(USE_HMAP_ACES) + public IEnvironmentSettings, +#endif + public IConsoleCmd, + public IExportToDag, + public IAssetUpdateNotify +{ +public: + enum + { + HMAX_DET_TEX_NUM = LandMeshManager::DET_TEX_NUM, + LMAX_DET_TEX_NUM = LandMeshManager::DET_TEX_NUM + }; + enum HeightmapTypes + { + HEIGHTMAP_MAIN, + HEIGHTMAP_DET, + HEIGHTMAP_WATER_DET, + HEIGHTMAP_WATER_MAIN + }; + static HmapLandPlugin *self; + static bool defMipOrdRev; + static bool preferZstdPacking; + static bool allowOodlePacking; + + static IHmapService *hmlService; + static IBitMaskImageMgr *bitMaskImgMgr; + static IDagorPhys *dagPhys; + + Tab lcRemap; + + static bool prepareRequiredServices(); + static void processTexName(SimpleString &out_name, const char *in_name); + + + static IGrassService *grassService; + static IGPUGrassService *gpuGrassService; + static IWaterService *waterService; + static ICableService *cableService; + bool enableGrass; + DataBlock *grassBlk = nullptr, *gpuGrassBlk = nullptr; + GPUGrassPanel gpuGrassPanel; + + static IWaterProjFxService *waterProjectedFxSrv; + void updateWaterProjectedFx(); + + HmapLandPlugin(); + ~HmapLandPlugin(); + + // IGenEditorPlugin + virtual const char *getInternalName() const { return "heightmapLand"; } + virtual const char *getMenuCommandName() const { return "Landscape"; } + virtual const char *getHelpUrl() const { return "/html/Plugins/HeightmapLand/index.htm"; } + + virtual int getRenderOrder() const { return 100; } + virtual int getBuildOrder() const { return 0; } + + virtual bool showSelectAll() const { return true; } + virtual bool showInTabs() const { return true; } + + virtual void registered(); + virtual void unregistered(); + virtual void beforeMainLoop(); + + void registerMenuAccelerators() override; + virtual bool begin(int toolbar_id, unsigned menu_id); + virtual bool end(); + virtual IGenEventHandler *getEventHandler(); + + virtual void setVisible(bool vis); + virtual bool getVisible() const { return isVisible; } + virtual bool getSelectionBox(BBox3 &box) const; + virtual bool getStatusBarPos(Point3 &pos) const { return false; } + + virtual void clearObjects(); + virtual void onNewProject(); + virtual void autoSaveObjects(DataBlock &local_data); + virtual void saveObjects(DataBlock &blk, DataBlock &local_data, const char *base_path); + virtual void loadObjects(const DataBlock &blk, const DataBlock &local_data, const char *base_path); + virtual bool acceptSaveLoad() const { return true; } + + virtual void selectAll() { objEd.selectAll(); } + virtual void deselectAll() { objEd.unselectAll(); } + void invalidateObjectProps() { objEd.invalidateObjectProps(); } + + virtual void actObjects(float dt); + virtual void beforeRenderObjects(IGenViewportWnd *vp); + virtual void renderObjects(); + virtual void renderTransObjects(); + virtual void renderGrass(Stage stage); + virtual void renderGPUGrass(Stage stage); + virtual void renderWater(Stage stage); + virtual void renderCables(); + + virtual void replaceGrassMask(int landclass_id, const char *newGrassMaskName); + virtual void resetGrassMask(const DataBlock &grassBlk); + virtual int getLandclassIndex(const char *landclass_name); + virtual bool catchEvent(unsigned ev_huid, void *userData); + + virtual void *queryInterfacePtr(unsigned huid); + + virtual bool onPluginMenuClick(unsigned id); + + // ControlEventHandler + virtual void onClick(int pcb_id, PropPanel2 *panel); + virtual void onChange(int pcb_id, PropPanel2 *panel); + virtual void onChangeFinished(int pcb_id, PropPanel2 *panel); + + // IWndManagerWindowHandler + virtual IWndEmbeddedWindow *onWmCreateWindow(void *handle, int type); + virtual bool onWmDestroyWindow(void *handle); + + // IRenderingService + virtual void renderGeometry(Stage stage); + virtual void prepare(const Point3 ¢er_pos, const BBox3 &box) override; + virtual int setSubDiv(int lod) override; + + // IGenEventHandler + virtual IGenEventHandler *getWrappedHandler() { return &objEd; } + + virtual void handleKeyPress(IGenViewportWnd *wnd, int vk, int modif); + virtual void handleKeyRelease(IGenViewportWnd *wnd, int vk, int modif); + + // IBrushClient + virtual void onBrushPaintStart(Brush *brush, int buttons, int key_modif); + virtual void onBrushPaintEnd(Brush *brush, int buttons, int key_modif); + virtual void onBrushPaint(Brush *brush, const Point3 ¢er, const Point3 &prev_center, const Point3 &normal, int buttons, + int key_modif); + virtual void onRBBrushPaintStart(Brush *brush, int buttons, int key_modif); + virtual void onRBBrushPaintEnd(Brush *brush, int buttons, int key_modif); + virtual void onRBBrushPaint(Brush *brush, const Point3 ¢er, const Point3 &prev_center, const Point3 &normal, int buttons, + int key_modif); + + // IBinaryDataBuilder + virtual bool validateBuild(int target, ILogWriter &rep, PropPanel2 *params); + virtual bool addUsedTextures(ITextureNumerator &tn); + virtual bool buildAndWrite(BinDumpSaveCB &cwr, const ITextureNumerator &tn, PropPanel2 *pp); + virtual bool checkMetrics(const DataBlock &metrics_blk) { return true; } + + // IWriteAddLtinputData + virtual void writeAddLtinputData(IGenSave &cwr); + + // IConsoleCmd + virtual bool onConsoleCommand(const char *cmd, dag::ConstSpan params); + virtual const char *onConsoleCommandHelp(const char *cmd); + + // IHeightmapProvider + virtual void requestHeightmapData(int x0, int y0, int step, int x_size, int y_size); + + virtual void getHeightmapData(int x0, int y0, int step, int x_size, int y_size, real *data, int stride_bytes); + + virtual bool isLandPreloadRequestComplete(); + + void updateLandDetailTexture(unsigned i); + + float getLandCellSize() const; + int getNumCellsX() const; + int getNumCellsY() const; + IPoint2 getCellOrigin() const; + const IBBox2 *getExclCellBBox(); + + float getGridCellSize() const { return gridCellSize; } + float getMeshCellSize() + { + meshCells = clamp(meshCells, 1, 256); + int mapSize = getHeightmapSizeX(); + return max((mapSize / meshCells) * getGridCellSize(), 1.0f); + } + virtual Point3 getOffset() const; + + virtual TEXTUREID getLightMap(); + // Loads Land Datail Texture for LandMesh + void loadLandDetailTexture(int x0, int y0, Texture *tex1, Texture *tex2, carray &detail_tex_ids, + bool *done_mark, int tex_size, int elem_size); + + int loadLandDetailTexture(unsigned targetCode, int x0, int y0, char *imgPtr, int stride, char *imgPtr2, int stride2, + carray &detail_tex_ids, bool *done_mark, int size, int elem_size, bool tex1_rgba, bool tex2_rgba); + + int getMostUsedDetTex(int x0, int y0, int texDataSize, uint8_t *det_tex_ids, uint8_t *idx_remap, int max_dtn); + + template + int updateLandclassWeight(int x0, int y0, int x1, int y1, UpdateLC &update_cb); + + // from IGatherStaticGeometry + virtual void gatherStaticVisualGeometry(StaticGeometryContainer &cont) + { + gatherStaticGeometry(cont, StaticGeometryNode::FLG_RENDERABLE, false); + } + + virtual void gatherStaticCollisionGeomGame(StaticGeometryContainer &cont); + + virtual void gatherStaticCollisionGeomEditor(StaticGeometryContainer &cont) { gatherStaticGeometry(cont, 0, true); } + + virtual void gatherStaticEnviGeometry(StaticGeometryContainer &container) {} + void gatherStaticGeometry(StaticGeometryContainer &cont, int flags, bool collision, int stage = 0) + { + objEd.gatherStaticGeometry(cont, flags, collision, stage); + } + + // IDagorEdCustomCollider + virtual bool traceRay(const Point3 &p, const Point3 &dir, real &maxt, Point3 *norm); + virtual bool shadowRayHitTest(const Point3 &p, const Point3 &dir, real maxt); + virtual const char *getColliderName() const { return "HeightMap"; } + virtual bool isColliderVisible() const; + + // IHmapBrushImage + virtual real getBrushImageData(int x, int y, IHmapBrushImage::Channel channel); + virtual void setBrushImageData(int x, int y, real v, IHmapBrushImage::Channel channel); + +#if defined(USE_HMAP_ACES) + // IEnvironmentSettings. + virtual void getEnvironmentSettings(DataBlock &blk); + virtual void setEnvironmentSettings(DataBlock &blk); +#endif + + // IExportToDag. + void gatherExportToDagGeometry(StaticGeometryContainer &container) + { + if (!useMeshSurface || exportType == EXPORT_PSEUDO_PLANE) + return; + + if (landMeshMap.isEmpty()) + generateLandMeshMap(landMeshMap, DAGORED2->getConsole(), false, NULL); + + landMeshMap.gatherExportToDagGeometry(container); + } + + + bool traceRayPrivate(const Point3 &p, const Point3 &dir, real &maxt, Point3 *norm); + + void createHeightmapFile(CoolConsole &con); + void resizeHeightMapDet(CoolConsole &con); + void createColormapFile(CoolConsole &con); + void createLightmapFile(CoolConsole &con); + void resizeLandClassMapFile(CoolConsole &con); + + void resetLandmesh() { pendingLandmeshRebuild = true; } + void resetRenderer(bool immediate = false); + void invalidateRenderer(); + void updateHeightMapTex(bool det_hmap, const IBBox2 *dirty_box = NULL); + void updateHeightMapConstants(); + void updateHmap2Tesselation(); + + int getNumDetailTextures() const { return numDetailTextures; } + + + void updateScriptImageList(); + bool importScriptImage(String *name = NULL); + bool createMask(int bpp, String *name = NULL); + + const char *pickScriptImage(const char *current_name, int bpp); + void prepareScriptImage(const char *name, int img_size_mul, int img_bpp); + int getScriptImage(const char *name, int img_size_mul = 0, int img_bpp = 0); + int getScriptImageWidth(int id); + int getScriptImageHeight(int id); + int getScriptImageBpp(int id); + E3DCOLOR sampleScriptImageUV(int id, real x, real y, bool clamp_x, bool clamp_y); + E3DCOLOR sampleScriptImagePixelUV(int id, real x, real y, bool clamp_x, bool clamp_y); + bool saveImage(int idx); + + void paintScriptImageUV(int id, real x0, real y0, real x1, real y1, bool clamp_x, bool clamp_y, E3DCOLOR color); + + float sampleMask1UV(int id, real x, real y); + float sampleMask1UV(int id, real x, real y, bool clamp_x, bool clamp_y); + float sampleMask8UV(int id, real x, real y); + float sampleMask8UV(int id, real x, real y, bool clamp_x, bool clamp_y); + float sampleMask1PixelUV(int id, real x, real y); + float sampleMask8PixelUV(int id, real x, real y); + void paintMask1UV(int id, real x0, real y0, bool c); + void paintMask8UV(int id, real x0, real y0, char c); + + using PackedDecalBitmap = carray; + using ExtendedDecalBitmap = carray; + class ScriptParam : public DObject + { + public: + SimpleString paramName; + + ScriptParam(const char *name) : paramName(name) {} + + virtual void fillParams(PropPanel2 &panel, int &pid) = 0; + virtual void onPPChange(int pid, PropPanel2 &panel) = 0; + virtual void onPPBtnPressed(int pid, PropPanel2 &panel) {} + + virtual void save(DataBlock &blk) = 0; + virtual void load(const DataBlock &blk) = 0; + + virtual void setToScript(HSQUIRRELVM vm) = 0; + + virtual bool onPPChangeEx(int pid, PropPanel2 &panel) + { + onPPChange(pid, panel); + return false; + } + virtual bool onPPBtnPressedEx(int pid, PropPanel2 &panel) + { + onPPBtnPressed(pid, panel); + return false; + } + }; + + + ScriptParam *getEditedScriptImage(); + void editScriptImage(ScriptParam *image, int idx = -1); + + IHmapBrushImage::Channel getEditedChannel() const; + bool showEditedMask() const; + + bool importTileTex(); + + // IHeightmap + virtual bool isLoaded() const { return heightMap.isFileOpened(); } + virtual real getHeightmapCellSize() const { return gridCellSize; } + virtual int getHeightmapSizeX() const { return heightMap.getMapSizeX(); } + virtual int getHeightmapSizeY() const { return heightMap.getMapSizeY(); } + + virtual bool getHeightmapPointHt(Point3 &inout_p, Point3 *out_norm) const; + virtual bool getHeightmapCell5Pt(const IPoint2 &cell, real &h0, real &hx, real &hy, real &hxy, real &hmid) const; + + virtual Point3 getHeightmapOffset() const { return Point3(heightMapOffset[0], 0, heightMapOffset[1]); } + + bool getHeightmapHeight(const IPoint2 &cell, real &ht) const; + bool getHeightmapOnlyPointHt(Point3 &inout_p, Point3 *out_norm) const; + + // IRoadsProvider + virtual IRoadsProvider::Roads *getRoadsSnapshot(); + + bool applyHmModifiers1(HeightMapStorage &hm, float gc_sz, bool gen_colors, bool reset_final, IBBox2 *out_dirty_clip, + IBBox2 *out_sum_dirty, bool *out_colors_changed); + void applyHmModifiers(bool gen_colors = true, bool reset_final = true, bool finished = true); + void collapseModifiers(dag::ConstSpan collapse_splines); + void copyFinalHmapToInitial(); + void restoreBackup(); + + void heightmapChanged(bool ch = true) { heightMap.changed = ch; } + void invalidateFinalBox(const BBox3 &box); + + bool hmBackupCanBeRestored() + { + if (heightMap.getInitialMap().canBeReverted()) + return true; + if (detDivisor && heightMapDet.getInitialMap().canBeReverted()) + return true; + return false; + } + bool hmCommitChanges(); + + bool getTexEntry(const char *s, String *path, String *name) const; + + void calcGoodLandLightingInBox(const IBBox2 &calc_box); + + // ILightingChangeClient + virtual void onLightingChanged() {} + virtual void onLightingSettingsChanged(); + + // IOnExportNotify interface + virtual void onBeforeExport(unsigned target_code); + virtual void onAfterExport(unsigned target_code); + + // IPostProcessGeometry + virtual void processGeometry(StaticGeometryContainer &container); + + //! returns number of invisible faces, and marked faces to stay + int markUndergroundFaces(MeshData &mesh, Bitarray &facesAbove, TMatrix *wtm); + //! removes faces below ground + void removeInvisibleFaces(StaticGeometryContainer &container); + + + const HmapBitLayerDesc &getDetLayerDesc() const { return (HmapBitLayerDesc &)detLayerDescStorage; } + const HmapBitLayerDesc &getImpLayerDesc() const { return (HmapBitLayerDesc &)impLayerDescStorage; } + void *getLayersHandle() const { return landClsLayersHandle; } + int getDetLayerIdx() const { return detLayerIdx; } + MapStorage &getlandClassMap() { return landClsMap; } + + MapStorage *getDetTexIdxMap() const { return detTexIdxMap; } + MapStorage *getDetTexWtMap() const { return detTexWtMap; } + void prepareDetTexMaps(); + + LandClassSlotsManager &getLandClassMgr() { return *lcMgr; } + bool setDetailTexSlot(int s, const char *blk_name); + + bool exportLightmapToFile(const char *file_name, int target_code, bool high_quality); + + bool rebuildSplinesPolyBitmask(BBox2 &out_dirty_box); + bool rebuildSplinesLoftBitmask(int layer, BBox2 &out_dirty_box); + void rebuildSplinesBitmask(bool auto_regen = true); + + void rebuildRivers(); + + bool buildAndWriteSingleNavMesh(BinDumpSaveCB &cwr, int nav_mesh_idx); + bool buildAndWriteNavMesh(BinDumpSaveCB &cwr); + void clearNavMesh(); + void renderNavMeshDebug(); + + bool rebuildHtConstraintBitmask(); + bool applyHtConstraintBitmask(Mesh &mesh); // returns true if changed + + bool isSnowAvailable() { return (snowValSVId != -1 && snowPrevievSVId != -1); } + float getSnowValue() { return ambSnowValue; } + bool hasSnowSpherePreview() { return (snowSpherePreview && snowDynPreview); } + void updateSnowSources() { objEd.updateSnowSources(); } + + void setSelectMode(); + + bool renderDebugLines; + bool renderAllSplinesAlways, renderSelSplinesAlways; + + bool hasWaterSurf() const { return hasWaterSurface; } + float getWaterSurfLevel() const { return waterSurfaceLevel; } + bool isPointUnderWaterSurf(float x, float z); + bool isPseudoPlane() const { return exportType == EXPORT_PSEUDO_PLANE; } + + bool getHeight(const Point2 &p, real &ht, Point3 *normal) const; + void setShowBlueWhiteMask(); + + void refillPanel(bool schedule_regen = false); + + void prepareEditableLandClasses(); + void addGenLayer(const char *name, int insert_before = -1); + bool moveGenLayer(ScriptParam *gl, bool up); + bool delGenLayer(ScriptParam *gl); + + struct HMDetGH + { + static Point3 getHeightmapOffset() { return HmapLandPlugin::self->getHeightmapOffset(); } + static real getHeightmapCellSize() { return HmapLandPlugin::self->getHeightmapCellSize() / HmapLandPlugin::self->detDivisor; } + static bool getHeightmapCell5Pt(const IPoint2 &cell, real &h0, real &hx, real &hy, real &hxy, real &hmid) + { + h0 = HmapLandPlugin::self->heightMapDet.getFinalData(cell.x, cell.y); + hx = HmapLandPlugin::self->heightMapDet.getFinalData(cell.x + 1, cell.y); + hy = HmapLandPlugin::self->heightMapDet.getFinalData(cell.x, cell.y + 1); + hxy = HmapLandPlugin::self->heightMapDet.getFinalData(cell.x + 1, cell.y + 1); + + hmid = (h0 + hx + hy + hxy) * 0.25f; + return true; + } + }; + struct HMDetTR : public HMDetGH + { + static int getHeightmapSizeX() { return HmapLandPlugin::self->getHeightmapSizeX() * HmapLandPlugin::self->detDivisor; } + static int getHeightmapSizeY() { return HmapLandPlugin::self->getHeightmapSizeY() * HmapLandPlugin::self->detDivisor; } + static bool getHeightmapCell5Pt(const IPoint2 &cell, real &h0, real &hx, real &hy, real &hxy, real &hmid) + { + if (HmapLandPlugin::self->insideDetRectC(cell) && HmapLandPlugin::self->insideDetRectC(cell.x + 1, cell.y + 1)) + return HMDetGH::getHeightmapCell5Pt(cell, h0, hx, hy, hxy, hmid); + return false; + } + }; + + bool hasDetaledRect() const { return detDivisor; } + bool mapGlobalTCtoDetRectTC(float &inout_fx, float &inout_fy) const + { + inout_fx *= detDivisor * getHeightmapSizeX(); + inout_fy *= detDivisor * getHeightmapSizeY(); + if (!detDivisor || !insideDetRectC(inout_fx, inout_fy)) + return false; + inout_fx = (inout_fx - detRectC[0].x) / (detRectC[1].x - detRectC[0].x); + inout_fy = (inout_fy - detRectC[0].y) / (detRectC[1].y - detRectC[0].y); + return true; + } + + bool usesGenScript() const { return !colorGenScriptFilename.empty(); } + PropPanel2 *getPropPanel() const; + + bool insideDetRectC(int x, int y) const + { + return x >= detRectC[0].x && x < detRectC[1].x && y >= detRectC[0].y && y < detRectC[1].y; + } + bool insideDetRectC(const IPoint2 &p) const { return insideDetRectC(p.x, p.y); } + + bool loadLevelSettingsBlk(DataBlock &level_blk); + void updateWaterSettings(const DataBlock &level_blk); + void invalidateDistanceField() { distFieldInvalid = true; } + + void onLayersDlgClosed(); + void selectLayerObjects(int lidx, bool sel = true); + void moveObjectsToLayer(int lidx); + +private: + // Caches datailed textures for LandMesh + int toolbarId; + + // IAssetUpdateNotify + virtual void onLandClassAssetChanged(landclass::AssetData *data) override {} + virtual void onLandClassAssetTexturesChanged(landclass::AssetData *data) override; + virtual void onSplineClassAssetChanged(splineclass::AssetData *data) override {} + + void clearTexCache(); + void refillTexCache(); + void resetTexCacheRect(const IBBox2 &box); + + class HmapLandPanel; + BBox3 landBox; + class HmlSelTexDlg; + + enum + { + HILLUP_BRUSH, + HILLDOWN_BRUSH, + SMOOTH_BRUSH, + ALIGN_BRUSH, + SHADOWS_BRUSH, + SCRIPT_BRUSH, + + BRUSHES_COUNT + }; + + SmallTab brushes; + int currentBrushId; + IBBox2 brushFullDirtyBox; + bool noTraceNow; // for align to collision + + HmapLandPanel *propPanel; + HmapLandObjectEditor objEd; + + const char *hmapImportCaption = "TIFF 8/16 bit (*.tif)|*.tif;*.tiff|" + "Raw 32f (*.r32)|*.r32|" + "Raw 16 (*.r16)|*.r16|" + "Photoshop Raw 16 (*.raw)|*.raw|" + "Raw 32f with header (*.height)|*.height|" + "|All files(*.*)|*.*"; + + DataBlock mainPanelState; + + real gridCellSize; + Point2 heightMapOffset; + + String levelBlkFName; + DataBlock levelBlk; + + struct + { + Point2 ofs, sz; + bool show; + } collisionArea; + + struct RenderParams + { + int gridStep, elemSize, radiusElems, ringElems, numLods, maxDetailLod; + real detailTile, canyonHorTile, canyonVertTile; + int holesLod; + real canyonAngle, canyonFadeAngle; + real hm2YbaseForLod; + + int landTexSize, landTexElemSize; + int detMapSize, detMapElemSize; + + int hm2displacementQ; + bool showFinalHM; + + RenderParams() { init(); } + + void init(); + }; + + RenderParams render; + + real sunAzimuth, sunZenith; + + struct SunSkyLight + { + E3DCOLOR sunColor, skyColor, specularColor; + real sunPower, skyPower, specularMul, specularPower; + + SunSkyLight() { init(); } + + void init() + { + sunColor = E3DCOLOR(255, 240, 140); + sunPower = 1.2f; + skyColor = E3DCOLOR(60, 120, 255); + skyPower = 0.5f; + specularColor = E3DCOLOR(255, 240, 140); + specularMul = 1.0f; + specularPower = 16; + } + + Color3 getSunLightColor() const { return color3(sunColor) * sunPower; } + Color3 getSkyLightColor() const { return color3(skyColor) * skyPower; } + Color3 getSpecularColor() const { return color3(specularColor) * specularMul; } + void save(const char *prefix, DataBlock &) const; + void load(const char *prefix, const DataBlock &); + }; + + SunSkyLight ldrLight; + + real shadowBias, shadowTraceDist, shadowDensity; + + SimpleString origBasePath; + HeightMapStorage heightMap; + + MapStorage &landClsMap; + int lcmScale; + void *landClsLayersHandle; + dag::Span landClsLayer; + LandClassSlotsManager *lcMgr; + + MapStorage &colorMap; + MapStorage &lightMapScaled; + int lightmapScaleFactor; + + bool geomLoftBelowAll; + bool hasWaterSurface, hasWorldOcean; + SimpleString waterMatAsset; + float waterSurfaceLevel, minUnderwaterBottomDepth, worldOceanExpand; + float worldOceanShorelineTolerance; + objgenerator::HugeBitmask waterMask; + int waterMaskScale; + + TEXTUREID lmlightmapTexId; + BaseTexture *lmlightmapTex; + TEXTUREID bluewhiteTexId; + Texture *bluewhiteTex; + + LandMeshMap landMeshMap; + + MapStorage *detTexIdxMap, *detTexWtMap; + + int detDivisor; + HeightMapStorage heightMapDet; + BBox2 detRect; + IBBox2 detRectC; + Texture *hmapTex[2]; + TEXTUREID hmapTexId[2]; + + int numDetailTextures; + Tab detailTexBlkName; + + String lastHmapImportPath, lastLandExportPath, lastHmapExportPath, lastColormapExportPath, colorGenScriptFilename, lastTexImportPath, + lastGATExportPath, lastWaterHeightmapImportPath, lastHmapImportPathDet, lastHmapImportPathMain, lastWaterHeightmapImportPathDet, + lastWaterHeightmapImportPathMain; + struct FileChangeStat + { + int64_t size = 0, mtime = 0; + } lastChangeDet, lastChangeMain, lastChangeWaterDet, lastChangeWaterMain; + + bool isVisible; + bool doAutocenter; + + real lastMinHeight[2]; + real lastHeightRange[2]; + + HeightMapStorage waterHeightmapDet; + HeightMapStorage waterHeightmapMain; + Point2 waterHeightMinRangeDet; + Point2 waterHeightMinRangeMain; + + String lastExpLoftFolder; + bool lastExpLoftMain = true, lastExpLoftDet = true; + int lastExpLoftMainSz = 4096, lastExpLoftDetSz = 4096; + bool lastExpLoftCreateAreaSubfolders = true; + bool lastExpLoftUseRect[2] = {false, false}; + BBox2 lastExpLoftRect[2]; + + LandMeshManager *landMeshManager; + LandMeshRenderer *landMeshRenderer; + MemoryChainedData *lmDump; + bool pendingLandmeshRebuild; + TEXTUREID lightmapTexId; + + PtrTab colorGenParams; + Ptr detailedLandMask; + DataBlock *colorGenParamsData; + + Ptr editedScriptImage; + int editedScriptImageIdx; + int esiGridW, esiGridH; + float esiGridStep; + Point2 esiOrigin; + + DataBlock navMeshProps[MAX_NAVMESHES]; + int shownExportedNavMeshIdx; + bool showExportedNavMesh; + bool showExportedCovers; + bool showExportedNavMeshContours; + bool showExpotedObstacles = false; + bool disableZtestForDebugNavMesh = false; + + PtrTab genLayers; + bool showBlueWhiteMask; + void updateBlueWhiteMask(const IBBox2 *); + void updateGenerationMask(const IBBox2 *rect); + + bool showMonochromeLand; + E3DCOLOR monochromeLandCol; + + bool showHtLevelCurves; + float htLevelCurveStep, htLevelCurveThickness, htLevelCurveOfs, htLevelCurveDarkness; + + void addGrassLayer(const char *name); + void exportGrass(BinDumpSaveCB &cwr); + bool saveGrassLayers(DataBlock &blk); + bool loadGrassLayers(const DataBlock &blk, bool update_grass_blk = true); + void loadGrassFromLevelBlk(); + bool loadGrassFromBlk(const DataBlock &level_blk); + void loadGPUGrassFromLevelBlk(); + bool loadGPUGrassFromBlk(const DataBlock &level_blk); + + PropertyContainerControlBase *grass_panel; + PtrTab grassLayers; + struct + { + float defaultMinDensity; + float defaultMaxDensity; + float maxRadius; + int texSize; + eastl::vector> masks; + + float sowPerlinFreq; + float fadeDelta; + float lodFadeDelta; + float blendToLandDelta; + + float noise_first_rnd; + float noise_first_val_mul; + float noise_first_val_add; + + float noise_second_rnd; + float noise_second_val_mul; + float noise_second_val_add; + + float directWindMul; + float noiseWindMul; + float windPerlinFreq; + float directWindFreq; + float directWindModulationFreq; + float windWaveLength; + float windToColor; + float helicopterHorMul; + float helicopterVerMul; + float helicopterToDirectWindMul; + float helicopterFalloff; + } grass; + + + CDialogWindow *brushDlg; + + + Point3 calcSunLightDir() const; + inline void getNormalAndSky(int x, int y, Point3 &normal, real &sky, float *ht = NULL); + unsigned calcFastLandLightingAt(float x, float y, const Point3 &sun_light_dir); + inline void getNormal(int x, int y, Point3 &normal); + unsigned calcNormalAt(float ox, float oy); + real calcSunShadow(float x, float y, const Point3 &sun_light_dir, float *other_ht = NULL); + + void createPropPanel(); + void createMenu(unsigned menu_id); + void refillBrush(); + void fillPanel(PropPanel2 &panel); + void updateLightGroup(PropPanel2 &panel); + + void createHeightmap(); + void importHeightmap(); + void reimportHeightmap(); + bool checkAndReimport(String &path, FileChangeStat &lastChangeOld, HeightmapTypes is_det); + bool importHeightmap(String &filename, HeightmapTypes type); + void eraseHeightmap(); + void importWaterHeightmap(bool det); + void eraseWaterHeightmap(); + void autocenterHeightmap(PropPanel2 *panel, bool reset_render = true); + + void exportHeightmap(); + bool exportHeightmap(String &filename, real min_height, real height_range, bool exp_det_hmap); + + void exportColormap(); + bool exportColormap(String &filename); + + void exportLand(); + bool exportLand(String &filename); + bool exportLand(mkbindump::BinDumpSaveCB &cwr); // throws exception on error + + void exportSplines(mkbindump::BinDumpSaveCB &cwr); + void exportLoftMasks(const char *out_folder, int main_hmap_sz, int det_hmap_sz, float hmin, float hmax, int prefab_dest_idx); + + bool exportLandMesh(mkbindump::BinDumpSaveCB &cwr, IWriterToLandmesh *land_modifier, LandRayTracer *raytracer, + bool tools_internal = false); + + void generateLandColors(const IBBox2 *in_rect = NULL, bool finished = true); + + void onLandRegionChanged(int x0, int y0, int x1, int y1, bool recalc_all = false, bool finished = true); + void onWholeLandChanged(); + void onLandSizeChanged(); + + bool getAllSunSettings(); + bool getDirectionSunSettings(); + template + bool calcLandLighting(const IBBox2 *calc_box = NULL); + void calcFastLandLighting(); + void calcGoodLandLighting(); + void blurLightmap(int kernel_size, float sigma, const IBBox2 *calc_box = NULL); + void recalcLightingInRect(const IBBox2 &rect); + void updateRendererLighting(); + + void updateLandOnPaint(Brush *brush, bool finished); + void delayedResetRenderer(); + void rebuildLandmeshDump(); + void rebuildLandmeshManager(); + + template + void loadMapFile(MapStorage &map, const char *filename, CoolConsole &con); + + template + void createMapFile(MapStorage &map, const char *filename, CoolConsole &con); + + void createWaterHmapFile(CoolConsole &con, bool det); + + bool generateLandMeshMap(LandMeshMap &map, CoolConsole &con, bool import_sgeom, LandRayTracer **out_tracer, + bool strip_det_hmap_from_tracer = true); + + void rebuildWaterSurface(Tab *loft_pt_cloud = NULL, Tab *water_border_polys = NULL, + Tab *hmap_sweep_polys = NULL); + + bool compileAndRunColorGenScript(bool &was_inited, SQPRINTFUNCTION &old_print_func, SQPRINTFUNCTION &old_err_func); + void closeColorGenScript(bool &was_inited, SQPRINTFUNCTION &old_print_func, SQPRINTFUNCTION &old_err_func); + bool createDefaultScript(const char *path) const; + + bool getColorGenVarsFromScript(); + + bool loadGenLayers(const DataBlock &blk); + bool saveGenLayers(DataBlock &blk); + void regenLayerTex(); + void storeLayerTex(); + + // void prepareDetailTexTileAndOffset(Tab &out_tile, Tab &out_offset); + + void renderHeight(); + void renderGrassMask(); +#if defined(USE_HMAP_ACES) + bool getRenderNoTex() { return !(showBlueWhiteMask && editedScriptImage); } +#else + bool getRenderNoTex() { return false; } +#endif + + void updateVertTex(); + void acquireVertTexRef(); + void releaseVertTexRef(); + + void updateHorizontalTex(); + void acquireHorizontalTexRef(); + void releaseHorizontalTexRef(); + void saveHorizontalTex(DataBlock &blk); + void loadHorizontalTex(const DataBlock &blk); + + void updateLandModulateColorTex(); + void acquireLandModulateColorTexRef(); + void releaseLandModulateColorTexRef(); + void saveLandModulateColorTex(DataBlock &blk); + void loadLandModulateColorTex(const DataBlock &blk); + + void setRendinstlayeredDetailColor(); + void saveRendinstDetail2Color(DataBlock &blk); + void loadRendinstDetail2Color(const DataBlock &blk); + + void updateHtLevelCurves(); + void applyClosingPostProcess(ExtendedDecalBitmap &accum_bitmap); + PackedDecalBitmap to_1bit_bitmap(const ExtendedDecalBitmap &accum_bitmap); + + class ScriptImage : public IBitMaskImageMgr::BitmapMask, private IFileChangedNotify + { + public: + ScriptImage(const char *name); + ~ScriptImage(); + + bool loadImage(); + bool saveImage(); + + const char *getName() const { return name; } + + E3DCOLOR sampleImageUV(real x, real y, bool clamp_x, bool clamp_y); + E3DCOLOR sampleImagePixelUV(real x, real y, bool clamp_x, bool clamp_y); + float sampleMask1UV(real x, real y); + float sampleMask1PixelUV(real x, real y); + float sampleMask8UV(real x, real y); + float sampleMask8PixelUV(real x, real y); + + float sampleMask1UV(real x, real y, bool clamp_x, bool clamp_y); + float sampleMask8UV(real x, real y, bool clamp_x, bool clamp_y); + + void paintImageUV(real x0, real y0, real x1, real y1, bool clamp_x, bool clamp_y, E3DCOLOR color); + void paintMask1UV(real x, real y, bool val); + void paintMask8UV(real x, real y, char val); + + bool isImageModified() const { return isModified; } + + protected: + SimpleString name; + bool isModified; + bool isSaved; + int fileNotifyId; + + inline void calcClampMapping(float &fx, float &fy, int &ix, int &iy, int &nx, int &ny); + inline void calcClampMapping(float fx, float fy, int &ix, int &iy); + inline void calcMapping(float &fx, float &fy, int &ix, int &iy, int &nx, int &ny, bool clamp_u, bool clamp_v); + void registerFnotify(); + virtual void onFileChanged(int /*file_name_id*/); // IFileChangedNotify + }; + + Tab scriptImages; + + + SimpleString horizontalTexName; + SimpleString horizontalDetailTexName; + real horizontalTex_TileSizeX, horizontalTex_TileSizeY; + real horizontalTex_OffsetX, horizontalTex_OffsetY; + real horizontalTex_DetailTexSizeX, horizontalTex_DetailTexSizeY; + bool useHorizontalTex; + + SimpleString landModulateColorTexName; + real landModulateColorEdge0, landModulateColorEdge1; + bool useLandModulateColorTex; + + bool useRendinstDetail2Modulation; + E3DCOLOR rendinstDetail2ColorFrom, rendinstDetail2ColorTo; + + real tileXSize, tileYSize; + SimpleString tileTexName; + TEXTUREID tileTexId; + + bool useVertTex; + bool useVertTexForHMAP; + SimpleString vertTexName; + SimpleString vertNmTexName; + SimpleString vertDetTexName; + float vertTexXZtile, vertTexYtile, vertTexYOffset, vertTexAng0, vertTexAng1, vertTexHorBlend; + float vertDetTexXZtile, vertDetTexYtile, vertDetTexYOffset; + + char detLayerDescStorage[8]; + char impLayerDescStorage[8]; + int detLayerIdx; + int impLayerIdx; + + bool syncLight, syncDirLight, pendingResetRenderer; + bool requireTileTex, hasColorTex, hasLightmapTex, useMeshSurface; + bool useNormalMap; + bool storeNxzInLtmapTex; + GenHmapData *genHmap; + + Ptr roadsSnapshot; + static int hmapSubtypeMask; + static int lmeshSubtypeMask; + static int lmeshDetSubtypeMask; + static int grasspSubtypeMask; + static int navmeshSubtypeMask; + + float meshPreviewDistance; + // float meshCellSize; + int meshCells; + float meshErrorThreshold; + int numMeshVertices; + int lod1TrisDensity; + float importanceMaskScale; + + bool distFieldInvalid; + int distFieldBuiltAt; + + enum + { + EXPORT_PSEUDO_PLANE, + EXPORT_HMAP, + EXPORT_LANDMESH, + }; + + int exportType; + bool debugLmeshCells; + + bool snowDynPreview, snowSpherePreview; + float ambSnowValue, dynSnowValue; + int snowValSVId, snowPrevievSVId; + bool calculating_shadows; // calculating shadows - now + + DebugPrimitivesVbuffer *navMeshBuf; + DebugPrimitivesVbuffer *coversBuf; + DebugPrimitivesVbuffer *contoursBuf; + DebugPrimitivesVbuffer *obstaclesBuf; +}; + + +#endif //__GAIJIN_HEIGHTMAPLAND_PLUGIN__ diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlRivers.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlRivers.cpp new file mode 100644 index 000000000..630899a0e --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlRivers.cpp @@ -0,0 +1,18 @@ +#include "hmlPlugin.h" +#include +#include + +void HmapLandPlugin::rebuildRivers() +{ + GeomObject *obj = dagGeom->newGeomObject(midmem); + + gatherStaticGeometry(*obj->getGeometryContainer(), StaticGeometryNode::FLG_RENDERABLE, false, 1); + obj->notChangeVertexColors(true); + dagGeom->geomObjectRecompile(*obj); + obj->notChangeVertexColors(false); + + //== do something with geom object (render, etc.) + + + dagGeom->deleteGeomObject(obj); +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSelTexDlg.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSelTexDlg.cpp new file mode 100644 index 000000000..e8d74f8a1 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSelTexDlg.cpp @@ -0,0 +1,123 @@ +#include "hmlSelTexDlg.h" +#include +#include +#include + +using hdpi::_pxScaled; + +enum +{ + PID_BPP_GROUP, + PID_TEX_LIST, + PID_IMPORT_TEX, + PID_CREATE_MASK, +}; + +static inline int str_compare(const String *s1, const String *s2) { return stricmp(s1->str(), s2->str()); } + +//================================================================================================== +HmapLandPlugin::HmlSelTexDlg::HmlSelTexDlg(HmapLandPlugin &plug, const char *selected, int bpp) : + plugin(plug), selTex(selected), reqBpp(bpp), texNamesCur(NULL) +{ + rebuildTexList(selected); +} + +void HmapLandPlugin::HmlSelTexDlg::rebuildTexList(const char *sel) +{ + plugin.updateScriptImageList(); + texNames1.clear(); + texNames8.clear(); + texNames1.push_back() = "<-- reset tex -->"; + texNames8.push_back() = "<-- reset tex -->"; + for (int i = 0; i < plugin.scriptImages.size(); i++) + { + switch (HmapLandPlugin::self->getScriptImageBpp(i)) + { + case 1: texNames1.push_back() = plugin.scriptImages[i]->getName(); break; + case 8: texNames8.push_back() = plugin.scriptImages[i]->getName(); break; + } + if (stricmp(plugin.scriptImages[i]->getName(), sel) == 0) + reqBpp = HmapLandPlugin::self->getScriptImageBpp(i); + } + sort(texNames1, &str_compare); + sort(texNames8, &str_compare); + switch (reqBpp) + { + case 1: texNamesCur = &texNames1; break; + case 8: texNamesCur = &texNames8; break; + default: + reqBpp = 1; + texNamesCur = &texNames1; + break; + } +} + +bool HmapLandPlugin::HmlSelTexDlg::execute() +{ + CDialogWindow *dlg = EDITORCORE->createDialog(_pxScaled(250), _pxScaled(510), "Select mask"); + PropertyContainerControlBase *_panel = dlg->getPanel(); + G_ASSERT(_panel && "HmlSelTexDlg: NO PANEL FOUND!!!"); + _panel->setEventHandler(this); + + PropertyContainerControlBase &bpp_panel = *_panel->createRadioGroup(PID_BPP_GROUP, "Mask depth, bits per pixel"); + bpp_panel.createRadio(1, "1 bit"); + bpp_panel.createRadio(8, "8 bits"); + _panel->createSeparator(); + + _panel->createList(PID_TEX_LIST, "Masks", *texNamesCur, selTex); + //_panel->createButton(PID_IMPORT_TEX, "Import...", true, true); + _panel->createButton(PID_CREATE_MASK, "Create mask..."); + _panel->setFocusById(PID_TEX_LIST); + _panel->getById(PID_TEX_LIST)->setHeight(_pxScaled(300)); + _panel->createSeparator(); + + _panel->setInt(PID_BPP_GROUP, reqBpp); + int ret = dlg->showDialog(); + EDITORCORE->deleteDialog(dlg); + return ret == DIALOG_ID_OK; +} + +void HmapLandPlugin::HmlSelTexDlg::onChange(int pcb_id, PropertyContainerControlBase *panel) +{ + switch (pcb_id) + { + case PID_BPP_GROUP: + reqBpp = panel->getInt(pcb_id); + switch (panel->getInt(pcb_id)) + { + case 1: texNamesCur = &texNames1; break; + case 8: texNamesCur = &texNames8; break; + default: texNamesCur = NULL; + } + panel->setStrings(PID_TEX_LIST, *texNamesCur); + panel->setInt(PID_TEX_LIST, selTex.empty() ? 0 : find_value_idx(*texNamesCur, selTex)); + break; + case PID_TEX_LIST: selTex = panel->getInt(pcb_id) <= 0 ? "" : texNamesCur->at(panel->getInt(pcb_id)); break; + } +} +void HmapLandPlugin::HmlSelTexDlg::onClick(int pcb_id, PropertyContainerControlBase *panel) +{ + switch (pcb_id) + { + case PID_IMPORT_TEX: + if (plugin.importScriptImage(&selTex)) + { + rebuildTexList(selTex); + panel->setInt(PID_BPP_GROUP, reqBpp); + panel->setStrings(PID_TEX_LIST, *texNamesCur); + panel->setInt(PID_TEX_LIST, selTex.empty() ? 0 : find_value_idx(*texNamesCur, selTex)); + } + break; + + case PID_CREATE_MASK: + if (plugin.createMask(reqBpp, &selTex)) + { + rebuildTexList(selTex); + panel->setInt(PID_BPP_GROUP, reqBpp); + panel->setStrings(PID_TEX_LIST, *texNamesCur); + panel->setInt(PID_TEX_LIST, selTex.empty() ? 0 : find_value_idx(*texNamesCur, selTex)); + } + break; + } +} +void HmapLandPlugin::HmlSelTexDlg::onDoubleClick(int pcb_id, PropertyContainerControlBase *panel) {} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSelTexDlg.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSelTexDlg.h new file mode 100644 index 000000000..034d1b1d4 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSelTexDlg.h @@ -0,0 +1,34 @@ +#ifndef __GAIJIN_HML_PLUGIN_SEL_TEX_DLG__ +#define __GAIJIN_HML_PLUGIN_SEL_TEX_DLG__ +#pragma once + + +#include "hmlPlugin.h" +#include + + +class HmapLandPlugin::HmlSelTexDlg : public ControlEventHandler +{ +public: + HmlSelTexDlg(HmapLandPlugin &plug, const char *selected, int bpp); + + bool execute(); + + const char *getSetTex() const { return selTex; } + + virtual void onChange(int pcb_id, PropertyContainerControlBase *panel); + virtual void onClick(int pcb_id, PropertyContainerControlBase *panel); + virtual void onDoubleClick(int pcb_id, PropertyContainerControlBase *panel); + +private: + HmapLandPlugin &plugin; + Tab texNames1, texNames8; + Tab *texNamesCur; + String selTex; + int reqBpp; + + void rebuildTexList(const char *sel); +}; + + +#endif //__GAIJIN_HML_PLUGIN_SEL_TEX_DLG__ diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSnow.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSnow.cpp new file mode 100644 index 000000000..9621cce52 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSnow.cpp @@ -0,0 +1,438 @@ +#include "hmlSnow.h" +#include "hmlPlugin.h" +#include +#include +#include +#include +#include +#include +#include +#include + + +enum +{ + PID_DIRECTIONAL = 1, + PID_GEOM_POS, + PID_GEOM_RADIUS, + PID_SNOW_VALUE, + PID_SNOW_BORDER, +}; + +void SnowSourceObject::Props::defaults() +{ + value = 0.25; + border = 1.0; +} + + +int SnowSourceObject::showSubtypeId = -1; + + +SnowSourceObject::SnowSourceObject() +{ + props.defaults(); + if (showSubtypeId == -1) + showSubtypeId = 1 << IDaEditor3Engine::get().registerEntitySubTypeId("snow_obj"); +} + + +SnowSourceObject::~SnowSourceObject() {} + + +bool SnowSourceObject::isSelectedByRectangle(IGenViewportWnd *vp, const EcRect &rect) const +{ + Point2 cp[8]; + BBox3 box(Point3(-0.5, -0.5, -0.5), Point3(0.5, 0.5, 0.5)); + BBox2 box2; + real z; + bool in_frustum = false; + +#define TEST_POINT(i, P) \ + in_frustum |= vp->worldToClient(matrix * P, cp[i], &z) && z > 0; \ + if (z > 0 && rect.l <= cp[i].x && rect.t <= cp[i].y && cp[i].x <= rect.r && cp[i].y <= rect.b) \ + return true; \ + else \ + box2 += cp[i]; + +#define TEST_SEGMENT(i, j) \ + if (::isect_line_segment_box(cp[i], cp[j], rbox)) \ + return true + + for (int i = 0; i < 8; i++) + { + TEST_POINT(i, box.point(i)); + } + + if (!in_frustum) + return false; + BBox2 rbox(Point2(rect.l, rect.t), Point2(rect.r, rect.b)); + if (!(box2 & rbox)) + return false; + + TEST_SEGMENT(0, 4); + TEST_SEGMENT(4, 5); + TEST_SEGMENT(5, 1); + TEST_SEGMENT(1, 0); + TEST_SEGMENT(2, 6); + TEST_SEGMENT(6, 7); + TEST_SEGMENT(7, 3); + TEST_SEGMENT(3, 2); + TEST_SEGMENT(0, 2); + TEST_SEGMENT(1, 3); + TEST_SEGMENT(4, 6); + TEST_SEGMENT(5, 7); + +#undef TEST_POINT +#undef TEST_SEGMENT + + return isSelectedByPointClick(vp, rect.l, rect.t); + return false; +} + + +bool SnowSourceObject::isSelectedByPointClick(IGenViewportWnd *vp, int x, int y) const +{ + Point3 dir, p0; + float out_t; + + vp->clientToWorld(Point2(x, y), p0, dir); + float wtm_det = getWtm().det(); + if (fabsf(wtm_det) < 1e-12) + return false; + TMatrix iwtm = inverse(getWtm(), wtm_det); + return rayIntersectSphere(iwtm * p0, normalize(iwtm % dir), Point3(0, 0, 0), 0.5 * 0.5); +} + + +bool SnowSourceObject::getWorldBox(BBox3 &box) const +{ + box = matrix * BSphere3(Point3(0, 0, 0), 0.5); + return true; +} + + +void SnowSourceObject::render() {} + + +void SnowSourceObject::renderTrans() {} + + +void SnowSourceObject::renderObject() +{ + TMatrix tm = getWtm(); + bool sel = isSelected(); + E3DCOLOR dc = sel ? E3DCOLOR(8, 242, 242, 255) : E3DCOLOR(0, 0, 255, 255); + + dagRender->setLinesTm(tm); + dagRender->renderSphere(Point3(0, 0, 0), 0.5, dc); +} + +void SnowSourceObject::fillProps(PropPanel2 &op, DClassID for_class_id, dag::ConstSpan objects) +{ + bool one_type = true; + + for (int i = 0; i < objects.size(); ++i) + { + SnowSourceObject *o = RTTI_cast(objects[i]); + if (!o) + { + one_type = false; + continue; + } + } + + if (one_type) + { + op.createIndent(-1); + + op.createPoint3(PID_GEOM_POS, "Position", getPos()); + op.createTrackFloat(PID_GEOM_RADIUS, "Radius", getRadius(), 0.1, 1000, 0.1); + + op.createTrackFloat(PID_SNOW_VALUE, "Snow value", props.value, -4, 4, 0.001); + op.createTrackFloat(PID_SNOW_BORDER, "Border", props.border, 0, 1, 0.01); + } +} + +void SnowSourceObject::onPPChange(int pid, bool edit_finished, PropPanel2 &panel, dag::ConstSpan objects) +{ +#define CHANGE_VAL(type, pname, getfunc) \ + { \ + type val = panel.getfunc(pid); \ + for (int i = 0; i < objects.size(); ++i) \ + { \ + SnowSourceObject *o = RTTI_cast(objects[i]); \ + if (!o || o->pname == val) \ + continue; \ + getObjEditor()->getUndoSystem()->put(new UndoPropsChange(o)); \ + o->pname = val; \ + o->propsChanged(); \ + } \ + } + + switch (pid) + { + case PID_GEOM_POS: setPos(panel.getPoint3(pid)); break; + + case PID_GEOM_RADIUS: + { + float d = panel.getFloat(pid) * 2.0; + setSize(Point3(d, d, d)); + propsChanged(); + } + break; + + case PID_SNOW_VALUE: CHANGE_VAL(float, props.value, getFloat) break; + + case PID_SNOW_BORDER: CHANGE_VAL(float, props.border, getFloat) break; + } + + DAGORED2->repaint(); + +#undef CHANGE_VAL +} + + +void SnowSourceObject::scaleObject(const Point3 &delta, const Point3 &origin, IEditorCoreEngine::BasisType basis) +{ + __super::scaleObject(delta, origin, basis); + + Point3 size = getSize(); + if (size.x != size.y || size.x != size.z) + size.y = size.z = size.x; + setSize(size); + + propsChanged(); +} + + +void SnowSourceObject::save(DataBlock &blk) +{ + blk.setStr("name", getName()); + blk.setTm("tm", matrix); + blk.setReal("value", props.value); + blk.setReal("border", props.border); +} + + +void SnowSourceObject::load(const DataBlock &blk) +{ + getObjEditor()->setUniqName(this, blk.getStr("name", "")); + setWtm(blk.getTm("tm", TMatrix::IDENT)); + props.value = blk.getReal("value", 0.25); + props.border = blk.getReal("border", 1.0); + + propsChanged(); +} + + +void SnowSourceObject::setWtm(const TMatrix &wtm) { __super::setWtm(wtm); } + +void SnowSourceObject::onRemove(ObjectEditor *) { propsChanged(); } + +void SnowSourceObject::onAdd(ObjectEditor *objEditor) {} + +bool SnowSourceObject::setPos(const Point3 &p) +{ + if (!__super::setPos(p)) + return false; + + propsChanged(); + return true; +} + + +void SnowSourceObject::propsChanged() { HmapLandPlugin::self->updateSnowSources(); } + + +SnowSourceObject *SnowSourceObject::clone() +{ + SnowSourceObject *obj = new SnowSourceObject; + + getObjEditor()->setUniqName(obj, getName()); + + obj->setProps(getProps()); + + TMatrix tm = getWtm(); + obj->setWtm(tm); + + return obj; +} + + +void SnowSourceObject::putMoveUndo() +{ + HmapLandObjectEditor *ed = (HmapLandObjectEditor *)getObjEditor(); + if (!ed->isCloneMode()) + __super::putMoveUndo(); +} + +//----------------------------------------- + +static PtrTab originalSharedMats(tmpmem); +static PtrTab snowSharedMats(tmpmem); +static Tab differentMatIdx(tmpmem); + +void SnowSourceObject::clearMats() +{ + clear_and_shrink(originalSharedMats); + clear_and_shrink(snowSharedMats); + clear_and_shrink(differentMatIdx); +} + +StaticGeometryMaterial *SnowSourceObject::makeSnowMat(StaticGeometryMaterial *source_mat) +{ + if (!source_mat) + return NULL; + + for (int i = 0; i < originalSharedMats.size(); ++i) + if (originalSharedMats[i].get() == source_mat) + return snowSharedMats[i]; + + for (int i = 0; i < differentMatIdx.size(); ++i) + if (originalSharedMats[differentMatIdx[i]]->equal(*source_mat)) + { + StaticGeometryMaterial *gm = snowSharedMats[differentMatIdx[i]]; + originalSharedMats.push_back(source_mat); + snowSharedMats.push_back(gm); + return gm; + } + + StaticGeometryMaterial *gm = new StaticGeometryMaterial(*source_mat); + gm->name = String(256, "%s_snow", gm->name.str()); + gm->scriptText = String(128, "%s\r\nhas_snow=1\r\n", gm->scriptText.str()); + + differentMatIdx.push_back(originalSharedMats.size()); + originalSharedMats.push_back(source_mat); + snowSharedMats.push_back(gm); + return gm; +} + + +void SnowSourceObject::calcSnow(dag::ConstSpan src, float avg_snow, StaticGeometryContainer &cont) +{ + static const int SNOW_CH = 7; + Tab matRemap(tmpmem); + int node_cnt = 0, vert_cnt = 0; + + clearMats(); + for (int i = 0; i < cont.nodes.size(); ++i) + { + StaticGeometryNode &node = *cont.nodes[i]; + if (!node.mesh->mats.size()) + continue; + + Mesh *mesh = &node.mesh->mesh; + bool has_snow = false; + + for (int j = 0; j < mesh->vert.size(); ++j) + { + Point3 v = node.wtm * mesh->vert[j]; + float snow_value = avg_snow; + + for (int k = 0; k < src.size(); ++k) + { + float distance = (src[k]->getPos() - v).length(); + if (distance < src[k]->getRadius()) + { + float add_value = src[k]->getProps().value; + + float to_center_pos = distance / src[k]->getRadius(); + float brush_bs = src[k]->getProps().border; + if (to_center_pos > brush_bs && brush_bs < 1.0) + add_value = lerp(add_value, 0.0f, (to_center_pos - brush_bs) / (1.0 - brush_bs)); + + snow_value += add_value; + } + } + if (snow_value <= 0) + continue; + + if (!has_snow) + { + has_snow = true; + if (mesh->tface[SNOW_CH].size()) + DAEDITOR3.conWarning("tface[%d].count=%d (is not empty) in node \"%s\"", SNOW_CH, mesh->tface[SNOW_CH].size(), + node.name.str()); + + if (node.mesh->getRefCount() > 1) + { + // clone mesh when it is used by more than one node + StaticGeometryMesh *m = new StaticGeometryMesh; + m->mats = node.mesh->mats; + m->mesh = *mesh; + node.mesh = m; + mesh = &m->mesh; + } + + mesh->tvert[SNOW_CH].resize(mesh->vert.size()); + mem_set_0(mesh->tvert[SNOW_CH]); + mesh->tface[SNOW_CH].resize(mesh->face.size()); + for (int k = 0; k < mesh->face.size(); k++) + { + mesh->tface[SNOW_CH][k].t[0] = mesh->face[k].v[0]; + mesh->tface[SNOW_CH][k].t[1] = mesh->face[k].v[1]; + mesh->tface[SNOW_CH][k].t[2] = mesh->face[k].v[2]; + } + } + + mesh->tvert[SNOW_CH][j].x = min(snow_value, 1.0f); + vert_cnt++; + } + + if (has_snow) + { + Point2 *tv = mesh->tvert[SNOW_CH].data(); + matRemap.resize(node.mesh->mats.size()); + mem_set_ff(matRemap); + node_cnt++; + + int last_mat_index = node.mesh->mats.size(); + for (Face *f = mesh->face.data(), *fe = f + mesh->face.size(); f < fe; f++) + { + if (tv[f->v[0]].x + tv[f->v[1]].x + tv[f->v[2]].x <= 0) + continue; + int mat = f->mat % matRemap.size(); + if (matRemap[mat] == -1) + { + matRemap[mat] = node.mesh->mats.size(); + node.mesh->mats.push_back(makeSnowMat(node.mesh->mats[mat])); + } + f->mat = matRemap[mat]; + } + } + } + if (vert_cnt) + DAEDITOR3.conNote("separated snow meshed: %d nodes, %d vertices, %d mats", node_cnt, vert_cnt, differentMatIdx.size()); + clearMats(); +} + +void SnowSourceObject::updateSnowSources(dag::ConstSpan nearSources) +{ + for (int i = 0; i < NEAR_SRC_COUNT; ++i) + { + Color4 snow_pos(0, 0, 0, 0); + Color4 snow_params(0, 0, 0, 0); + + if (i < nearSources.size()) + { + float r = nearSources[i].source->getRadius(); + float b = nearSources[i].source->getProps().border; + + Point3 _pos = nearSources[i].source->getPos(); + snow_pos.r = _pos.x; + snow_pos.g = _pos.y; + snow_pos.b = _pos.z; + snow_params.r = b * r; + snow_params.g = nearSources[i].source->getProps().value; + snow_params.b = r * (1.0 - b); + snow_params.b = (snow_params.b < 1e-3) ? 1e+3 : 1.0 / snow_params.b; + } + + int snowPos_id = dagGeom->getShaderVariableId(String(64, "snow_pos%d", i)); + dagGeom->shaderGlobalSetColor4(snowPos_id, snow_pos); + + int snowParam_id = dagGeom->getShaderVariableId(String(64, "snow_param%d", i)); + dagGeom->shaderGlobalSetColor4(snowParam_id, snow_params); + } +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSnow.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSnow.h new file mode 100644 index 000000000..80db1be2a --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSnow.h @@ -0,0 +1,122 @@ +#pragma once + +#include +#include + +class StaticGeometryContainer; +class StaticGeometryMaterial; +struct NearSnowSource; + +static constexpr unsigned CID_SnowSourceObject = 0xD04E90DAu; + +// +// Entity object placed on landscape +// +class SnowSourceObject : public RenderableEditableObject +{ +public: + SnowSourceObject(); + + virtual void update(float) {} + virtual void beforeRender() {} + virtual void render(); + virtual void renderTrans(); + + virtual bool isSelectedByRectangle(IGenViewportWnd *vp, const EcRect &rect) const; + virtual bool isSelectedByPointClick(IGenViewportWnd *vp, int x, int y) const; + virtual bool getWorldBox(BBox3 &box) const; + + virtual void fillProps(PropPanel2 &op, DClassID for_class_id, dag::ConstSpan objects); + + virtual void onPPChange(int pid, bool edit_finished, PropPanel2 &panel, dag::ConstSpan objects); + + virtual void save(DataBlock &blk); + virtual void load(const DataBlock &blk); + + virtual bool mayRename() { return true; } + virtual bool mayDelete() { return true; } + virtual void setWtm(const TMatrix &wtm); + + virtual void onRemove(ObjectEditor *); + virtual void onAdd(ObjectEditor *objEditor); + + virtual bool setPos(const Point3 &p); + + virtual void putMoveUndo(); + + virtual void onObjectNameChange(RenderableEditableObject *obj, const char *old_name, const char *new_name) {} + + EO_IMPLEMENT_RTTI(CID_SnowSourceObject) + + UndoRedoObject *makePropsUndoObj() { return new UndoPropsChange(this); } + SnowSourceObject *clone(); + + struct Props + { + real value; + real border; + + void defaults(); + }; + + const Props &getProps() const { return props; } + void setProps(const Props &p) + { + props = p; + propsChanged(); + } + + void propsChanged(); + void renderObject(); + + virtual void scaleObject(const Point3 &delta, const Point3 &origin, IEditorCoreEngine::BasisType basis); + + float getRadius() { return getSize().x / 2.0; } + + static int showSubtypeId; + +public: + static const int NEAR_SRC_COUNT = 16; + + static void updateSnowSources(dag::ConstSpan nearSources); + + static void calcSnow(dag::ConstSpan src, float avg, StaticGeometryContainer &cont); + static void clearMats(); + static StaticGeometryMaterial *makeSnowMat(StaticGeometryMaterial *source_mat); + +protected: + Props props; + + ~SnowSourceObject(); + + class UndoPropsChange : public UndoRedoObject + { + Ptr obj; + SnowSourceObject::Props oldProps, redoProps; + + public: + UndoPropsChange(SnowSourceObject *o) : obj(o) { oldProps = redoProps = obj->props; } + + virtual void restore(bool save_redo) + { + if (save_redo) + redoProps = obj->props; + obj->setProps(oldProps); + } + + virtual void redo() { obj->setProps(redoProps); } + + virtual size_t size() { return sizeof(*this); } + virtual void accepted() {} + virtual void get_description(String &s) { s = "UndoSnowPropsChange"; } + }; +}; + +struct NearSnowSource +{ + SnowSourceObject *source; + float distance; + + NearSnowSource() : source(NULL), distance(0) {} + NearSnowSource(SnowSourceObject *s, float d) : source(s), distance(d) {} +}; diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSplineMask.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSplineMask.cpp new file mode 100644 index 000000000..aedff3120 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSplineMask.cpp @@ -0,0 +1,440 @@ +#include "hmlPlugin.h" +#include "landClassSlotsMgr.h" +#include +#include +#include +#include +#include "hmlSplineObject.h" +#include "hmlSplinePoint.h" +#include +#include +#include +#include +#include + +objgenerator::WorldHugeBitmask bm_loft_mask[LAYER_ORDER_MAX], bm_poly_mask; +//! allocated for this DLL plugin (but should be avoided in future) +objgenerator::WorldHugeBitmask objgenerator::lcmapExcl, objgenerator::splgenExcl; + + +static void build_loft_sizes(Tab &lso, splineclass::LoftGeomGenData *g) +{ + if (!g || !g->loft.size() || !g->foundationGeom) + { + lso.resize(0); + return; + } + + lso.resize(g->loft.size()); + for (int i = 0; i < lso.size(); i++) + { + lso[i] = Point4(g->loft[i].offset.x, g->loft[i].offset.y, 0, 0); + for (int j = 0; j < g->loft[i].shapePts.size(); j++) + { + inplace_min(lso[i].z, g->loft[i].shapePts[j].x); + inplace_max(lso[i].w, g->loft[i].shapePts[j].x); + } + } +} + +static float calc_loft_rad(splineclass::LoftGeomGenData *g) +{ + if (!g || !g->loft.size() || !g->foundationGeom) + return -1; + + float rad = 0; + for (int i = 0; i < g->loft.size(); i++) + for (int j = 0; j < g->loft[i].shapePts.size(); j++) + inplace_max(rad, fabs(g->loft[i].shapePts[j].x) + max(fabs(g->loft[i].offset.x), fabs(g->loft[i].offset.y))); + return rad; +} + +static void saveBmTiff(objgenerator::WorldHugeBitmask &bm, const char *name) +{ + if (!bm.w || !bm.h) + return; + IBitMaskImageMgr::BitmapMask img; + HmapLandPlugin::bitMaskImgMgr->createBitMask(img, (bm.w + 7) & ~7, bm.h, 1); + + for (int y = 0; y < bm.h; y++) + for (int x = 0; x < bm.w; x++) + img.setMaskPixel1(x, y, bm.bm->get(x, y) ? 128 : 0); + + HmapLandPlugin::bitMaskImgMgr->saveImage(img, ".", name); + HmapLandPlugin::bitMaskImgMgr->destroyImage(img); +} + +bool HmapLandPlugin::rebuildSplinesPolyBitmask(BBox2 &out_dirty_box) +{ + int t0 = get_time_msec(); + objgenerator::WorldHugeBitmask bmPoly; + int poly_count = 0; + + BBox2 bb_poly; + for (int i = 0; i < objEd.splinesCount(); i++) + { + SplineObject *sobj = objEd.getSpline(i); + if (!sobj->isPoly()) + continue; + const objgenerator::LandClassData *lcd = sobj->getLandClass(); + if (!lcd || !lcd->data || !lcd->data->genGeom || !lcd->data->genGeom->foundationGeom) + continue; + for (int i = 0; i < sobj->points.size(); i++) + { + Point3 p = sobj->points[i]->getPt(); + bb_poly += Point2(p.x - 2, p.z - 2); + bb_poly += Point2(p.x + 2, p.z + 2); + } + } + if (bb_poly.isempty()) + goto update_map; + + bmPoly.initEven(bb_poly[0].x, bb_poly[0].y, bb_poly[1].x, bb_poly[1].y, 8192, 1.0); + // DAEDITOR3.conRemark("poly: %dx%d, scale=%.3f", bmPoly.w, bmPoly.h, bmPoly.scale); + + for (int i = 0; i < objEd.splinesCount(); i++) + { + SplineObject *sobj = objEd.getSpline(i); + if (!sobj->isPoly()) + continue; + const objgenerator::LandClassData *lcd = sobj->getLandClass(); + if (lcd && lcd->data && lcd->data->genGeom && lcd->data->genGeom->foundationGeom) + { + rasterize_poly_2(*bmPoly.bm, sobj->points, bmPoly.ox, bmPoly.oz, bmPoly.scale); + poly_count++; + } + } + if (!poly_count) + bmPoly.clear(); + + // saveBmTiff(bmPoly, "spl_poly_mask.tif"); + +update_map: + IBBox2 b; + if (bm_poly_mask.updateFrom(bmPoly, b)) + { + out_dirty_box[0].set(b[0].x / bmPoly.scale + bmPoly.ox, b[0].y / bmPoly.scale + bmPoly.oz); + out_dirty_box[1].set(b[1].x / bmPoly.scale + bmPoly.ox, b[1].y / bmPoly.scale + bmPoly.oz); + DAEDITOR3.conRemark("new poly map differs (%.1f,%.1f)-(%.1f,%.1f), %d polys for %dms", out_dirty_box[0].x, out_dirty_box[0].y, + out_dirty_box[1].x, out_dirty_box[1].y, poly_count, get_time_msec() - t0); + return true; + } + else + DAEDITOR3.conRemark("new poly map is the same, build and compared for %dms", get_time_msec() - t0); + return false; +} + +bool HmapLandPlugin::rebuildSplinesLoftBitmask(int layer, BBox2 &out_dirty_box) +{ + int t0 = get_time_msec(); + objgenerator::WorldHugeBitmask bmLoft; + Bitrender renderer; + BezierSpline2d s2d_src; + Tab verts(tmpmem); + int loft_count = 0; + + BBox2 bb_loft; + for (int i = 0; i < objEd.splinesCount(); i++) + { + SplineObject *sobj = objEd.getSpline(i); + if (sobj->isPoly() || sobj->getLayer() != layer) + continue; + + sobj->getSplineXZ(s2d_src); + BezierSplinePrec2d &s2d = toPrecSpline(s2d_src); + + float splineLen = s2d.getLength(), st; + + const splineclass::AssetData *a = sobj->points[0]->getSplineClass(); + int seg = 0; + float rad = calc_loft_rad(a ? a->genGeom : NULL); + + for (float s = 0.0; s < splineLen; s += 1) + { + int n_seg = s2d.findSegment(s, st); + if (seg != n_seg) + { + seg = n_seg; + rad = calc_loft_rad(a ? a->genGeom : NULL); + } + if (rad > 0) + { + Point2 p = s2d.segs[n_seg].point(st); + bb_loft += p + Point2(rad + 2, rad + 2); + bb_loft += p - Point2(rad + 2, rad + 2); + } + } + } + if (bb_loft.isempty()) + goto update_map; + + bmLoft.initEven(bb_loft[0].x, bb_loft[0].y, bb_loft[1].x, bb_loft[1].y, 8192, 1.0); + // DAEDITOR3.conRemark("loft[%d]: %dx%d, scale=%.3f", layer, bmLoft.w, bmLoft.h, bmLoft.scale); + + renderer.init(bmLoft.w, bmLoft.h, &bmLoft); + + for (int i = 0; i < objEd.splinesCount(); i++) + { + SplineObject *sobj = objEd.getSpline(i); + if (sobj->isPoly() || sobj->getLayer() != layer) + continue; + + if (sobj->splineChanged) + { + objEd.loftGeomCollider.setLoftLayer(layer); + sobj->updateSpline(sobj->STAGE_GEN_LOFT); + objEd.loftGeomCollider.setLoftLayer(-1); + } + + bool has_loft = false; + for (int j = 0, je = sobj->points.size(); j < je; j++) + { + ISplineGenObj *gen = sobj->points[j]->getSplineGen(); + if (!gen || !gen->loftGeom) + continue; + GeomObject *geom = gen->loftGeom; + const splineclass::AssetData *a = sobj->points[j]->getSplineClass(); + if (!a || !a->genGeom || !a->genGeom->foundationGeom) + continue; + + StaticSceneRayTracer *rt = dagGeom->geomObjectGetRayTracer(*geom); + if (!rt) + continue; + + verts.resize(rt->getVertsCount()); + for (int vi = 0; vi < verts.size(); vi++) + verts[vi].set((rt->verts(vi).x - bmLoft.ox) * bmLoft.scale - 0.5, (rt->verts(vi).z - bmLoft.oz) * bmLoft.scale - 0.5); + + for (int fi = 0, fie = rt->getFacesCount(); fi < fie; fi++) + { + StaticSceneRayTracer::RTface &f = rt->faces(fi); + renderer.draw_indexed_triangle(verts.data(), f.v[0], f.v[1], f.v[2]); + } + has_loft = true; + } + if (has_loft) + loft_count++; + } + if (!loft_count) + bmLoft.clear(); + + // saveBmTiff(bmLoft, String(32, "spl_loft%d_mask.tif", layer)); + +update_map: + IBBox2 b; + if (bm_loft_mask[layer].updateFrom(bmLoft, b)) + { + out_dirty_box[0].set(b[0].x / bmLoft.scale + bmLoft.ox, b[0].y / bmLoft.scale + bmLoft.oz); + out_dirty_box[1].set(b[1].x / bmLoft.scale + bmLoft.ox, b[1].y / bmLoft.scale + bmLoft.oz); + DAEDITOR3.conRemark("new loft[%d] map differs (%.1f,%.1f)-(%.1f,%.1f), %d polys, for %dms", layer, out_dirty_box[0].x, + out_dirty_box[0].y, out_dirty_box[1].x, out_dirty_box[1].y, loft_count, get_time_msec() - t0); + return true; + } + else + DAEDITOR3.conRemark("new loft[%d] map is the same, built and compared for %dms", layer, get_time_msec() - t0); + return false; +} + +void HmapLandPlugin::rebuildSplinesBitmask(bool auto_regen) +{ + int t0 = get_time_msec(); + BBox2 bb_changed[1 + LAYER_ORDER_MAX], bb_full; + bool poly_changed = rebuildSplinesPolyBitmask(bb_changed[0]); + bool loft_changed = false; + + bb_full = bb_changed[0]; + for (int layer = 0; layer < LAYER_ORDER_MAX; ++layer) + { + if (loft_changed || poly_changed) + { + objEd.loftGeomCollider.setLoftLayer(layer); + for (int i = 0; i < objEd.splinesCount(); ++i) + { + SplineObject *s = objEd.getSpline(i); + if (!s || !s->isCreated() || s->isPoly() || s->getLayer() != layer) + continue; + + for (int j = 0; j <= layer; j++) + if (!bb_changed[j].isempty() && s->intersects(bb_changed[j], true)) + { + s->splineChanged = true; + s->pointChanged(-1); + s->updateSpline(s->STAGE_GEN_LOFT); + break; + } + } + objEd.loftGeomCollider.setLoftLayer(-1); + } + if (rebuildSplinesLoftBitmask(layer, bb_changed[layer + 1])) + { + loft_changed = true; + bb_full += bb_changed[layer + 1]; + } + } + + int t1 = get_time_msec(); + objgenerator::WorldHugeBitmask bmExcl; + objgenerator::WorldHugeBitmask bm2Excl; + BezierSpline2d s2d_src; + int spl_count = 0; + int spl2_count = 0; + + const float sx = 0.5; + bmExcl.initExplicit(heightMapOffset.x, heightMapOffset.y, sx, sx * gridCellSize * heightMap.getMapSizeX(), + sx * gridCellSize * heightMap.getMapSizeY()); + bm2Excl.initExplicit(heightMapOffset.x, heightMapOffset.y, sx, sx * gridCellSize * heightMap.getMapSizeX(), + sx * gridCellSize * heightMap.getMapSizeY()); + + for (int i = 0; i < objEd.splinesCount(); i++) + { + SplineObject *sobj = objEd.getSpline(i); + if (sobj->isPoly()) + continue; + + sobj->getSplineXZ(s2d_src); + BezierSplinePrec2d &s2d = toPrecSpline(s2d_src); + float splineLen = s2d.getLength(), st; + + const splineclass::AssetData *a = sobj->points[0]->getSplineClass(); + int seg = 0, hw0 = (a && a->sweepWidth > 0) ? int(a->sweepWidth / 2 * sx) : -1; + int hw1 = (a && a->sweepWidth + a->addFuzzySweepHalfWidth > 0) ? int((a->sweepWidth / 2 + a->addFuzzySweepHalfWidth) * sx) : -1; + bool has_width = false; + + for (float s = 0.0; s < splineLen; s += 0.5 / sx) + { + int n_seg = s2d.findSegment(s, st); + if (seg != n_seg) + { + a = sobj->points[n_seg]->getSplineClass(); + hw0 = (a && a->sweepWidth > 0) ? int(a->sweepWidth / 2 * sx) : -1; + hw1 = (a && a->sweepWidth + a->addFuzzySweepHalfWidth > 0) ? int((a->sweepWidth / 2 + a->addFuzzySweepHalfWidth) * sx) : -1; + seg = n_seg; + } + + if (hw1 < 0) + continue; + + Point2 p = s2d.segs[n_seg].point(st); + Point2 t = normalize(s2d.segs[n_seg].tang(st)); + Point2 n(t.y / sx, -t.x / sx); + for (int i = -hw0 + 1; i <= hw0 - 1; i++) + bmExcl.mark3x3(p.x + n.x * i, p.y + n.y * i); + + for (int i = hw0 + 1; i <= hw1; i++) + { + int thres = 0x2000 * (i - hw0) / (hw1 - hw0) + 0x5F00; + int px = p.x + n.x * i, py = p.y + n.y * i; + int seed = py * bmExcl.w + px; + + if (_rnd(seed) > thres) + bmExcl.mark(px, py); + + px = p.x - n.x * i, py = p.y - n.y * i; + seed = py * bmExcl.w + px; + if (_rnd(seed) > thres) + bmExcl.mark(px, py); + } + has_width = true; + } + if (has_width) + spl_count++; + + a = sobj->points[0]->getSplineClass(); + seg = 0, hw0 = (a && a->sweep2Width > 0) ? int(a->sweep2Width / 2 * sx) : -1; + hw1 = (a && a->sweep2Width + a->addFuzzySweep2HalfWidth > 0) ? int((a->sweep2Width / 2 + a->addFuzzySweep2HalfWidth) * sx) : -1; + has_width = false; + + for (float s = 0.0; s < splineLen; s += 0.5 / sx) + { + int n_seg = s2d.findSegment(s, st); + if (seg != n_seg) + { + a = sobj->points[n_seg]->getSplineClass(); + hw0 = (a && a->sweep2Width > 0) ? int(a->sweep2Width / 2 * sx) : -1; + hw1 = + (a && a->sweep2Width + a->addFuzzySweep2HalfWidth > 0) ? int((a->sweep2Width / 2 + a->addFuzzySweep2HalfWidth) * sx) : -1; + seg = n_seg; + } + + if (hw1 < 0) + continue; + + Point2 p = s2d.segs[n_seg].point(st); + Point2 t = normalize(s2d.segs[n_seg].tang(st)); + Point2 n(t.y / sx, -t.x / sx); + for (int i = -hw0 + 1; i <= hw0 - 1; i++) + bm2Excl.mark3x3(p.x + n.x * i, p.y + n.y * i); + + for (int i = hw0 + 1; i <= hw1; i++) + { + int thres = 0x2000 * (i - hw0) / (hw1 - hw0) + 0x5F00; + int px = p.x + n.x * i, py = p.y + n.y * i; + int seed = py * bm2Excl.w + px; + + if (_rnd(seed) > thres) + bm2Excl.mark(px, py); + + px = p.x - n.x * i, py = p.y - n.y * i; + seed = py * bm2Excl.w + px; + if (_rnd(seed) > thres) + bm2Excl.mark(px, py); + } + has_width = true; + } + if (has_width) + spl2_count++; + } + DAEDITOR3.conRemark("rebuilt excl map %dx%d of %d(%d)/%d splines for %dms (%dms total for all maps)", bmExcl.w, bmExcl.h, spl_count, + spl2_count, objEd.splinesCount(), get_time_msec() - t1, get_time_msec() - t0); + + if (!spl_count) + bmExcl.clear(); + if (!spl2_count) + bm2Excl.clear(); + // saveBmTiff(bmExcl, "spl_sweep_mask.tif"); + // saveBmTiff(bm2Excl, "spl_sweep2_mask.tif"); + + if (IRendInstGenService *rigenSrv = DAGORED2->queryEditorInterface()) + rigenSrv->setSweepMask(nullptr, 0, 0, 1); + + t0 = get_time_msec(); + IBBox2 b; + bool excl_changed = objgenerator::lcmapExcl.updateFrom(bmExcl, b); + if (excl_changed) + { + bb_full += Point2(b[0].x / bmExcl.scale + bmExcl.ox, b[0].y / bmExcl.scale + bmExcl.oz); + bb_full += Point2(b[1].x / bmExcl.scale + bmExcl.ox, b[1].y / bmExcl.scale + bmExcl.oz); + } + if (objgenerator::splgenExcl.updateFrom(bm2Excl, b)) + { + bb_full += Point2(b[0].x / bm2Excl.scale + bmExcl.ox, b[0].y / bm2Excl.scale + bm2Excl.oz); + bb_full += Point2(b[1].x / bm2Excl.scale + bmExcl.ox, b[1].y / bm2Excl.scale + bm2Excl.oz); + excl_changed = true; + } + if (IRendInstGenService *rigenSrv = DAGORED2->queryEditorInterface()) + rigenSrv->setSweepMask(objgenerator::lcmapExcl.bm, objgenerator::lcmapExcl.ox, objgenerator::lcmapExcl.oz, + objgenerator::lcmapExcl.scale); + if (ISplineGenService *splSrv = EDITORCORE->queryEditorInterface()) + splSrv->setSweepMask(objgenerator::splgenExcl.bm, objgenerator::splgenExcl.ox, objgenerator::splgenExcl.oz, + objgenerator::splgenExcl.scale); + + if (excl_changed || poly_changed || loft_changed) + { + DAEDITOR3.conRemark("compared for %dms", get_time_msec() - t0); + if (!auto_regen) + return; + + t0 = get_time_msec(); + + float s = landClsMap.getMapSizeX() / gridCellSize / heightMap.getMapSizeX(); + b[0].x = (bb_full[0].x - heightMapOffset.x) * s; + b[0].y = (bb_full[0].y - heightMapOffset.y) * s; + b[1].x = (bb_full[1].x - heightMapOffset.x) * s; + b[1].y = (bb_full[1].y - heightMapOffset.y) * s; + + onLandRegionChanged(0, 0, landClsMap.getMapSizeX(), landClsMap.getMapSizeY(), true); + DAEDITOR3.conRemark("regenerated objects in (%d,%d)-(%d,%d) for %dms", b[0].x, b[0].y, b[1].x, b[1].y, get_time_msec() - t0); + } + else + DAEDITOR3.conRemark("new excl map is the same, compared for %dms", get_time_msec() - t0); +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSplineModifier.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSplineModifier.cpp new file mode 100644 index 000000000..fe3c3b73e --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSplineModifier.cpp @@ -0,0 +1,303 @@ +#include "hmlSplineObject.h" +#include "hmlSplinePoint.h" + +#include +#include "hmlPlugin.h" + +static inline real distance_point_to_line_segment(const Point2 &pt, const Point2 &p1, const Point2 &p2, float &out_t) +{ + Point2 dp = pt - p1; + Point2 dir = p2 - p1; + real len2 = lengthSq(dir); + + if (len2 == 0) + { + out_t = 0; + return length(dp); + } + + real t = (dp * dir) / len2; + + if (t <= 0) + { + out_t = 0; + return length(dp); + } + if (t >= 1) + { + out_t = 1; + return length(pt - p2); + } + + out_t = t; + return rabs(dp * Point2(dir.y, -dir.x)) / sqrtf(len2); +} + +void SplineObject::applyHmapModifier(HeightMapStorage &hm, Point2 hm_ofs, float hm_cell_size, IBBox2 &dirty, const IBBox2 &dirty_clip, + HmapBitmap *bmp) +{ + if (!points.size() || (props.modifParams.width <= 0 && props.modifParams.smooth <= 0)) + return; + + float maxLen = bezierSpline.getLength(); + + real minY = points[0]->getPt().y; + if (poly) + for (int i = 1; i < points.size(); i++) + if (points[i]->getPt().y < minY) + minY = points[i]->getPt().y; + + float dY = 0; + if (props.modifParams.additive) + for (int i = 0; i < points.size(); i++) + { + int xs = (int)floorf((points[i]->getPt().x - hm_ofs.x) / hm_cell_size); + int ys = (int)floorf((points[i]->getPt().z - hm_ofs.y) / hm_cell_size); + float dh = points[i]->getPt().y - hm.getFinalData(clamp(xs, 0, hm.getMapSizeX()), clamp(ys, 0, hm.getMapSizeY())); + if (i == 0 || dY > dh) + dY = dh; + } + minY -= 0.5; + + Tab> heightmapDistance(tmpmem); + int elemSize = 32; + int xSize = hm.getMapSizeX() / elemSize + 1; + int ySize = hm.getMapSizeY() / elemSize + 1; + heightmapDistance.resize(xSize * ySize); + + float splineWidth = props.modifParams.width / hm_cell_size; + float splineSmooth = props.modifParams.smooth / hm_cell_size; + float maxSizeFloat = splineWidth + splineSmooth; + Point3 updir = Point3(0, 1, 0); + float step = maxSizeFloat / 2; + if (step < hm_cell_size / 4) + step = hm_cell_size / 4; + if (step > maxLen) + step = maxLen; + int maxSize = ceilf(maxSizeFloat + step / 2); + + // debug("maxLen=%.3f maxSizeFloat=%.3f poly=%d hm_cell_size=%.3f step=%.3f", maxLen, maxSizeFloat, poly, hm_cell_size, step); + Point3 pt = bezierSpline.segs[0].point(0) - Point3::x0y(hm_ofs); + Point3 tang = normalize(bezierSpline.segs[0].tang(0)); + int segId = 0; + pt.x /= hm_cell_size; + pt.z /= hm_cell_size; + for (float len = step; len <= maxLen; len += step) + { + float locT; + int next_segId = bezierSpline.findSegment(len, locT); + Point3 pt_next = bezierSpline.segs[next_segId].point(locT) - Point3::x0y(hm_ofs); + pt_next.x /= hm_cell_size; + pt_next.z /= hm_cell_size; + + for (int ys = int(floorf((pt.z + pt_next.z) / 2)) - maxSize, ye = int(ceil((pt.z + pt_next.z) / 2)) + maxSize; ys <= ye; ys++) + { + if (ys < 0) + continue; + int yElems = ys / elemSize; + if (yElems >= ySize) + continue; + for (int xs = int(floorf((pt.x + pt_next.x) / 2)) - maxSize, xe = int(ceil((pt.x + pt_next.x) / 2)) + maxSize; xs <= xe; xs++) + { + if (xs < 0) + continue; + int xElems = xs / elemSize; + if (xElems >= xSize) + continue; + + real line_t; + real distance = distance_point_to_line_segment(Point2(xs, ys), Point2(pt.x, pt.z), Point2(pt_next.x, pt_next.z), line_t); + if (distance > maxSizeFloat) + continue; + + int elemId = xElems + yElems * xSize; + if (!heightmapDistance[elemId].size()) + { + clear_and_resize(heightmapDistance[elemId], elemSize * elemSize); + for (int j = 0; j < heightmapDistance[elemId].size(); ++j) + heightmapDistance[elemId][j].x = 1e6; + } + int subIndex = xs - xElems * elemSize + (ys - yElems * elemSize) * elemSize; + if (heightmapDistance[elemId][subIndex].x <= distance) + continue; + heightmapDistance[elemId][subIndex].x = distance; + + Point3 side = updir % tang; + side.normalize(); + real k = Point2(xs - pt.x * (1 - line_t) - pt_next.x * line_t, ys - pt.z * (1 - line_t) - pt_next.z * line_t) * + Point2(side.x, side.z); + side *= k; + + heightmapDistance[elemId][subIndex].y = (poly ? minY : pt.y * (1 - line_t) + pt_next.y * line_t) + side.y * 2; + heightmapDistance[elemId][subIndex].z = segId; + } + } + tang = normalize(bezierSpline.segs[next_segId].tang(locT)); + pt = pt_next; + segId = next_segId; + } + + if (poly) + { + Point3 diff = points[0]->getPt() - points.back()->getPt(); + real diffLength = diff.length(); + + pt = points[0]->getPt() - Point3::x0y(hm_ofs); + pt.x /= hm_cell_size; + pt.z /= hm_cell_size; + for (float len = 0; len < diffLength; len += step) + { + Point3 pt_next = + points[0]->getPt() * (1 - (len / diffLength)) + points.back()->getPt() * (len / diffLength) - Point3::x0y(hm_ofs); + pt_next.x /= hm_cell_size; + pt_next.z /= hm_cell_size; + + for (int ys = int(floorf((pt.z + pt_next.z) / 2)) - maxSize, ye = int(ceil((pt.z + pt_next.z) / 2)) + maxSize; ys <= ye; ys++) + { + if (ys < 0) + continue; + int yElems = ys / elemSize; + if (yElems >= ySize) + continue; + for (int xs = int(floorf((pt.x + pt_next.x) / 2)) - maxSize, xe = int(ceil((pt.x + pt_next.x) / 2)) + maxSize; xs <= xe; xs++) + { + if (xs < 0) + continue; + int xElems = xs / elemSize; + if (xElems >= xSize) + continue; + int elemId = xElems + yElems * xSize; + real line_t; + real distance = distance_point_to_line_segment(Point2(xs, ys), Point2(pt.x, pt.z), Point2(pt_next.x, pt_next.z), line_t); + + if (distance >= maxSizeFloat) + continue; + if (!heightmapDistance[elemId].size()) + { + clear_and_resize(heightmapDistance[elemId], elemSize * elemSize); + for (int j = 0; j < heightmapDistance[elemId].size(); ++j) + heightmapDistance[elemId][j].x = 1e6; + } + int subIndex = xs - xElems * elemSize + (ys - yElems * elemSize) * elemSize; + if (heightmapDistance[elemId][subIndex].x <= distance) + continue; + heightmapDistance[elemId][subIndex].x = distance; + heightmapDistance[elemId][subIndex].y = minY; + heightmapDistance[elemId][subIndex].z = -1; + } + } + pt = pt_next; + } + } + + dirty.setEmpty(); + IBBox2 eBox; + eBox[0].x = dirty_clip[0].x / elemSize; + eBox[0].y = dirty_clip[0].y / elemSize; + eBox[1].x = (dirty_clip[1].x + elemSize - 1) / elemSize; + eBox[1].y = (dirty_clip[1].y + elemSize - 1) / elemSize; + if (eBox[1].x >= xSize) + eBox[1].x = xSize - 1; + if (eBox[1].y >= ySize) + eBox[1].y = ySize - 1; + + for (int elemId = eBox[0].y * xSize + eBox[0].x, ye = eBox[0].y, eStep = xSize - eBox.width().x - 1; ye <= eBox[1].y; + ++ye, elemId += eStep) + for (int xe = eBox[0].x; xe <= eBox[1].x; ++xe, ++elemId) + { + if (!heightmapDistance[elemId].size()) + continue; + for (int subId = 0, ys = ye * elemSize; ys < ye * elemSize + elemSize; ++ys) + for (int xs = xe * elemSize; xs < xe * elemSize + elemSize; ++xs, ++subId) + { + if (!(dirty_clip & IPoint2(xs, ys))) + continue; + + float dist = heightmapDistance[elemId][subId].x; + + if (dist >= 1e6) + continue; + + float ht = heightmapDistance[elemId][subId].y; + dirty += IPoint2(xs, ys); + + if (bmp) + bmp->set(xs, ys); + + if (dist > splineWidth) + { + ht += props.modifParams.offset[1]; + float strength = (dist - splineWidth) / splineSmooth; + float tx = xs * hm_cell_size + hm_ofs.x; + float ty = ys * hm_cell_size + hm_ofs.y; + if (poly && pointInsidePoly(Point2(tx, ty))) + strength = 0; + if (strength < 1.0f) + { + hm.setFinalData(xs, ys, + props.modifParams.additive ? hm.getFinalData(xs, ys) + dY * (1.0f - strength) + : hm.getFinalData(xs, ys) * strength + ht * (1.0f - strength)); + } + } + else + { + if (props.modifParams.additive) + ht = hm.getFinalData(xs, ys) + dY; + float interp = powf(dist / splineWidth, props.modifParams.offsetPow); + ht += props.modifParams.offset[0] * (1.0f - interp) + props.modifParams.offset[1] * interp; + hm.setFinalData(xs, ys, ht); + } + } + } + + IBBox2 polyBox(IPoint2(floor((splBox[0].x - hm_ofs.x) / hm_cell_size), floor((splBox[0].z - hm_ofs.y) / hm_cell_size)), + IPoint2(ceil((splBox[1].x - hm_ofs.x) / hm_cell_size), ceil((splBox[1].z - hm_ofs.y) / hm_cell_size))); + + dirty_clip.clipBox(polyBox); + + if (poly && !polyBox.isEmpty()) + for (int ys = polyBox[0].y; ys <= polyBox[1].y; ++ys) + for (int xs = polyBox[0].x; xs <= polyBox[1].x; ++xs) + { + float tx = xs * hm_cell_size + hm_ofs.x; + float ty = ys * hm_cell_size + hm_ofs.y; + + if (pointInsidePoly(Point2(tx, ty))) + { + if (props.modifParams.additive) + { + int xe = xs / elemSize, ye = ys / elemSize; + if (xe < 0 || ye < 0 || xe >= xSize || ye >= ySize) + continue; + + int hmd_idx = xe + ye * xSize; + if (hmd_idx >= 0 && hmd_idx < heightmapDistance.size()) + { + dag::ConstSpan hmd = heightmapDistance[hmd_idx]; + if (hmd.size() && hmd[(ys % elemSize) * elemSize + (xs % elemSize)].x < 5e5) + continue; + } + hm.setFinalData(xs, ys, hm.getFinalData(xs, ys) + dY); + } + else + hm.setFinalData(xs, ys, minY); + } + + dirty += IPoint2(xs, ys); + if (bmp) + bmp->set(xs, ys); + } + + IBBox2 sum = dirty; + if (HmapLandPlugin::self->getHeightmapSizeX() == hm.getMapSizeX() && HmapLandPlugin::self->getHeightmapSizeY() == hm.getMapSizeY()) + { + sum += lastModifArea; + lastModifArea = dirty; + } + else + { + sum += lastModifAreaDet; + lastModifAreaDet = dirty; + } + dirty = sum; +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSplineObject.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSplineObject.cpp new file mode 100644 index 000000000..23b713a11 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSplineObject.cpp @@ -0,0 +1,3072 @@ +#include "hmlSplineObject.h" +#include "hmlSplinePoint.h" +#include "roadUtil.h" +#include + +#include <3d/dag_drv3d.h> +#include <3d/dag_render.h> +#include +#include +#include +#include +#include +#include "common.h" + +#include "hmlPlugin.h" +#include "hmlCm.h" +#include +#include +#include +#include +#include +#include +#include +// #include +#include +#include +#include +#include + +#include "hmlSplineUndoRedo.h" + +#include + +#include +#include + +#define RENDER_SPLINE_POINTS 1000 +#define RENDER_SPLINE_POINTS_MIN 10 +#define RENDER_SPLINE_POINTS_LENGTH_COEFF 5 + +class RenderableInstanceLodsResource; +class RenderableInstanceResource; + +enum +{ + PID_GENBLKNAME = 1, + PID_GENBLKNAME2, + + PID_NOTES, + PID_SPLINE_LEN, + PID_TC_ALONG_MUL, + PID_LAYER_ORDER, + PID_MAY_SELF_CROSS, + + PID_EXPORTABLE, + PID_ALT_GEOM, + PID_BBOX_ALIGN_STEP, + + PID_CORNER_TYPE, + + PID_MODIF_GRP, + PID_MODIFTYPE_S, + PID_MODIFTYPE_P, + PID_MODIF_WIDTH, + PID_MODIF_SMOOTH, + PID_MODIF_CT_OFFSET, + PID_MODIF_SD_OFFSET, + PID_MODIF_OFFSET_POW, + PID_MODIF_ADDITIVE, + + PID_POLY_OFFSET, + PID_POLY_ROTATE, + PID_POLY_SMOOTH, + PID_POLY_CURV, + PID_POLY_MINSTEP, + PID_POLY_MAXSTEP, + + PID_MONOTONOUS_Y_UP, + PID_MONOTONOUS_Y_DOWN, + PID_LINEARIZE_Y, + PID_CATMUL_XYZ, + PID_CATMUL_XZ, + PID_CATMUL_Y, + + PID_FLATTEN_Y, + PID_FLATTEN_AVERAGE, + PID_FLATTEN_SPLINE_GROUP, + PID_FLATTEN_SPLINE, + PID_FLATTEN_SPLINE_APPLY, + + PID_OPACGEN_BASE, + PID_OPACGEN_VAR, + PID_OPACGEN_APPLY, + + PID_USE_FOR_NAVMESH, + PID_NAVMESH_STRIPE_WIDTH, + + PID_PERINST_SEED, +}; +#define DEF_USE_FOR_NAVMESH false +#define DEF_NAVMESH_STRIPE_WIDTH 20.0f + +int SplineObject::polygonSubtypeMask = -1; +int SplineObject::splineSubtypeMask = -1; +int SplineObject::tiledByPolygonSubTypeId = -1; +int SplineObject::roadsSubtypeMask = -1; +int SplineObject::splineSubTypeId = -1; +bool SplineObject::isSplineCacheValid = false; + +static float opac_gen_base = 1, opac_gen_var = 0; + +static int spline_unique_buf_idx = 0; + +//================================================================================================== +SplineObject::SplineObject(bool make_poly) : points(tmpmem), poly(make_poly), landClass(NULL), segSph(midmem) +{ + isSplineCacheValid = false; + csgGen = NULL; + splineChanged = true; + modifChanged = false; + roadBox.setempty(); + loftBox.setempty(); + + clear_and_shrink(points); + clear_and_shrink(segSph); + + created = false; + + props.rndSeed = grnd(); + props.perInstSeed = 0; + props.maySelfCross = false; + props.modifType = MODIF_NONE; + lastModifArea.setEmpty(); + lastModifAreaDet.setEmpty(); + + props.modifParams.offset = Point2(-0.05, 0); + props.modifParams.width = 60; + props.modifParams.smooth = 10; + props.modifParams.offsetPow = 2; + props.modifParams.additive = false; + + props.poly.hmapAlign = false; + props.poly.objRot = 0; + props.poly.objOffs = Point2(0, 0); + props.poly.smooth = false; + props.poly.curvStrength = 1; + props.poly.minStep = 10; + props.poly.maxStep = 100; + + props.cornerType = 0; + props.exportable = false; + props.layerOrder = 0; + props.scaleTcAlong = 1; + props.useForNavMesh = DEF_USE_FOR_NAVMESH; + props.navMeshStripeWidth = DEF_NAVMESH_STRIPE_WIDTH; + + firstApply = true; + flattenBySpline = NULL; + + if (polygonSubtypeMask == -1) + polygonSubtypeMask = 1 << IDaEditor3Engine::get().registerEntitySubTypeId("poly_tile"); + if (splineSubtypeMask == -1) + splineSubtypeMask = 1 << IDaEditor3Engine::get().registerEntitySubTypeId("spline_cls"); + // debug ( "polygonSubtypeMask=%p splineSubtypeMask=%p", polygonSubtypeMask, splineSubtypeMask); + if (tiledByPolygonSubTypeId == -1) + tiledByPolygonSubTypeId = IDaEditor3Engine::get().registerEntitySubTypeId("poly_tile"); + + if (splineSubTypeId == -1) + splineSubTypeId = IDaEditor3Engine::get().registerEntitySubTypeId("spline_cls"); + + if (roadsSubtypeMask == -1) + roadsSubtypeMask = 1 << IDaEditor3Engine::get().registerEntitySubTypeId("road_obj"); + + shaders::OverrideState zFuncLessState; + zFuncLessState.set(shaders::OverrideState::Z_FUNC); + zFuncLessState.zFunc = CMPF_LESS; + zFuncLessStateId = dagGeom->create(zFuncLessState); + + bezierBuf = dagRender->newDebugPrimitivesVbuffer(String(0, "bezier_splines_%d_vbuf", spline_unique_buf_idx++), midmem); +} + +SplineObject::~SplineObject() +{ + dagGeom->destroy(zFuncLessStateId); + destroy_it(csgGen); + del_it(landClass); + clear_and_shrink(points); + polyGeom.clear(); + + segSph.clear(); + isSplineCacheValid = false; + + dagRender->deleteDebugPrimitivesVbuffer(bezierBuf); +} + +void SplineObject::prepareSplineClassInPoints() +{ + if (poly) + { + if (props.blkGenName.empty()) + { + destroy_it(csgGen); + del_it(landClass); + polyGeom.clear(); + } + else if (!landClass) + landClass = new objgenerator::LandClassData(props.blkGenName); + } + + if (points.size() < 1) + return; + + const char *splineClassAssetName = !poly ? props.blkGenName.str() : NULL; + + if (poly && landClass && landClass->data && landClass->data->splineClassAssetName.length()) + splineClassAssetName = landClass->data->splineClassAssetName; + + splineclass::AssetData *a = points[0]->prepareSplineClass(splineClassAssetName, NULL); + int pnum = isClosed() ? points.size() - 1 : points.size(); + for (int pi = 1; pi < pnum; ++pi) + a = points[pi]->prepareSplineClass(NULL, a); + + // erase old objects in last segment (only when spline is not circular!) + if (!isClosed()) + (points.back())->clearSegment(); +} + +void SplineObject::resetSplineClass() { del_it(landClass); } + +//================================================================================================== +void SplineObject::getSpline() +{ + PropPanel2 *pw = ((HmapLandObjectEditor *)getObjEditor())->getCurrentPanelFor(this); + if (!points.size()) + { + const char *str = "Length: 0.0 m"; + if (pw && strcmp(pw->getText(PID_SPLINE_LEN), str) != 0) + pw->setText(PID_SPLINE_LEN, str); + return; + } + + isSplineCacheValid = false; + + int pts_num = points.size() + (poly ? 1 : 0); + if (poly && props.poly.smooth) + applyCatmull(true, false); + + SmallTab pts; + clear_and_resize(pts, pts_num * 3); + + for (int pi = 0; pi < pts_num; ++pi) + { + int wpi = pi % points.size(); + pts[pi * 3 + 1] = points[wpi]->getPt(); + if ((poly && !props.poly.smooth) || (points[wpi]->isCross && points[wpi]->isRealCross)) + pts[pi * 3 + 2] = pts[pi * 3] = pts[pi * 3 + 1]; + else + { + pts[pi * 3] = points[wpi]->getBezierIn(); + pts[pi * 3 + 2] = points[wpi]->getBezierOut(); + } + } + + bezierSpline.calculate(pts.data(), pts.size(), false); + + float sln = bezierSpline.getLength(); + splStep = sln ? 0.1 / sln : 1.0; + if (splStep < 0.004) + splStep = 0.004; + + segSph.resize(bezierSpline.segs.size()); + + for (int i = 0; i < pts_num - 1; i++) + { + real startT = 0, endT = 0; + + for (int j = 0; j < i; j++) + startT += bezierSpline.segs[j].len; + + for (int j = 0; j < i + 1; j++) + endT += bezierSpline.segs[j].len; + + BBox3 bb; + for (real t = startT; t < endT; t += sln / RENDER_SPLINE_POINTS) + bb += bezierSpline.get_pt(t); + + segSph[i] = bb; + } + + splBox.setempty(); + for (int i = 0; i < points.size(); i++) + splBox += points[i]->getPt(); + for (int i = 0; i < segSph.size(); i++) + splBox += segSph[i]; + splBox[0] -= Point3(1, 1, 1); + splBox[1] += Point3(1, 1, 1); + + splSph = splBox; + if (pw) + { + String str(128, "Length: %.1f m", bezierSpline.getLength()); + if (strcmp(pw->getText(PID_SPLINE_LEN), str) != 0) + pw->setText(PID_SPLINE_LEN, str); + } +} + +void SplineObject::getSplineXZ(BezierSpline2d &spline2d) +{ + if (!points.size()) + return; + int pts_num = points.size() + (poly ? 1 : 0); + if (poly && props.poly.smooth) + applyCatmull(true, false); + + SmallTab pts; + clear_and_resize(pts, pts_num * 3); + + for (int pi = 0; pi < pts_num; ++pi) + { + int wpi = pi % points.size(); + Point3 p = points[wpi]->getPt(); + pts[pi * 3 + 1] = Point2(p.x, p.z); + if ((poly && !props.poly.smooth) || (points[wpi]->isCross && points[wpi]->isRealCross)) + pts[pi * 3 + 2] = pts[pi * 3] = pts[pi * 3 + 1]; + else + { + Point3 pin = points[wpi]->getBezierIn(); + Point3 pout = points[wpi]->getBezierOut(); + pts[pi * 3] = Point2(pin.x, pin.z); + pts[pi * 3 + 2] = Point2(pout.x, pout.z); + } + } + + spline2d.calculate(pts.data(), pts.size(), false); +} + +void SplineObject::getSpline(DagSpline &spline) +{ + spline.closed = 0; + spline.knot.resize(points.size()); + + for (int i = 0; i < points.size(); ++i) + if (points[i]) + { + spline.knot[i].i = points[i]->getBezierIn(); + spline.knot[i].p = points[i]->getPt(); + spline.knot[i].o = points[i]->getBezierOut(); + } +} + + +static void gatherGeomTags(GeomObject *g, OAHashNameMap &tags) +{ + int nnum = g->getGeometryContainer()->nodes.size(); + for (int ni = 0; ni < nnum; ++ni) + if (StaticGeometryNode *node = g->getGeometryContainer()->nodes[ni]) + if (const char *t = node->script.getStr("layerTag", NULL)) + tags.addNameId(t); +} +void SplineObject::gatherPolyGeomLoftTags(OAHashNameMap &loft_tags) +{ + if (splineInactive) + return; + if (polyGeom.mainMesh) + gatherGeomTags(polyGeom.mainMesh, loft_tags); + if (polyGeom.borderMesh) + gatherGeomTags(polyGeom.borderMesh, loft_tags); +} + +//================================================================================================== +void SplineObject::updateLoftBox() +{ + loftBox.setempty(); + for (int i = 0; i < points.size(); ++i) + loftBox += points[i]->getGeomBox(true, false); +} +void SplineObject::updateRoadBox() +{ + roadBox.setempty(); + for (int i = 0; i < points.size(); ++i) + roadBox += points[i]->getGeomBox(false, true); +} + +BBox3 SplineObject::getGeomBox() +{ + BBox3 worldBox; + if (created) + worldBox = splBox; + else + worldBox.setempty(); + worldBox += loftBox; + worldBox += roadBox; + if (geomBoxPrev != worldBox) + geomBoxPrev = worldBox; + return worldBox; +} + +BBox3 SplineObject::getGeomBoxChanges() +{ + BBox3 prev = geomBoxPrev; + BBox3 worldBox = getGeomBox(); + geomBoxPrev = worldBox; + worldBox += prev; + return worldBox; +} + +static inline int hide_non_stage0_nodes(GeomObject &gobj) +{ + StaticGeometryContainer *cont = gobj.getGeometryContainer(); + if (!cont) + return 0; + int nnum = cont->nodes.size(); + bool changed = false; + + for (int ni = 0; ni < nnum; ++ni) + if (StaticGeometryNode *node = cont->nodes[ni]) + if (node->script.getInt("stage", 0) != 0) + { + changed = true; + node->flags |= StaticGeometryNode::FLG_OPERATIVE_HIDE; + } + return changed ? nnum : 0; +} +static inline void reset_hide_non_stage0_nodes(GeomObject &gobj, int nnum) +{ + if (!nnum) + return; + StaticGeometryContainer *cont = gobj.getGeometryContainer(); + for (int ni = 0; ni < nnum; ++ni) + if (StaticGeometryNode *node = cont->nodes[ni]) + node->flags &= ~StaticGeometryNode::FLG_OPERATIVE_HIDE; +} + +void SplineObject::renderGeom(bool opaque, int layer, const Frustum &frustum) +{ + if (EditLayerProps::layerProps[getEditLayerIdx()].hide) + return; + + int st_mask = IDaEditor3Engine::get().getEntitySubTypeMask(IObjEntityFilter::STMASK_TYPE_RENDER); + + if (poly && landClass && landClass->data && landClass->data->genGeom && (st_mask & polygonSubtypeMask)) + { + if (polyGeom.mainMesh) + { + int nnum = hide_non_stage0_nodes(*polyGeom.mainMesh); + if (opaque) + dagGeom->geomObjectRender(*polyGeom.mainMesh); + else + dagGeom->geomObjectRenderTrans(*polyGeom.mainMesh); + reset_hide_non_stage0_nodes(*polyGeom.mainMesh, nnum); + } + + if (polyGeom.borderMesh) + { + int nnum = hide_non_stage0_nodes(*polyGeom.borderMesh); + if (opaque) + dagGeom->geomObjectRender(*polyGeom.borderMesh); + else + dagGeom->geomObjectRenderTrans(*polyGeom.borderMesh); + reset_hide_non_stage0_nodes(*polyGeom.borderMesh, nnum); + } + } + + if (!created) + return; + + if (!(st_mask & (splineSubtypeMask | roadsSubtypeMask))) + return; + + for (int i = 0; i < points.size(); ++i) + { + if (!frustum.testBoxB(points[i]->getGeomBox(false, st_mask & roadsSubtypeMask))) + continue; + if (st_mask & roadsSubtypeMask) + points[i]->renderRoadGeom(opaque); + } +} + + +void SplineObject::renderLines(bool opaque_pass, const Frustum &frustum) +{ + if (!((HmapLandObjectEditor *)getObjEditor())->isEditingSpline(this) && !frustum.testBoxB(getGeomBox())) + return; + if (splineInactive) + return; + if (!points.size()) + return; + if (EditLayerProps::layerProps[getEditLayerIdx()].hide) + return; + bool lock = (EditLayerProps::layerProps[getEditLayerIdx()].lock); + + if (HmapLandPlugin::self->renderDebugLines && opaque_pass && !lock) + if (created && landClass && landClass->data && landClass->data->genGeom) + polyGeom.renderLines(); + + E3DCOLOR col; + if (isSelected()) + col = E3DCOLOR(255, 255, 255, 255); + else if (lock) + col = E3DCOLOR(128, 128, 128, 255); + else + { + col = poly ? E3DCOLOR(0, 200, 0, 255) : E3DCOLOR(170, 170, 170, 255); + for (int i = 0; i < points.size(); i++) + if (points[i]->isSelected()) + { + col = E3DCOLOR(170, 200, 200, 255); + break; + } + } + + if (opaque_pass && points.size() > 1 && (isSelected() || (poly && !props.poly.smooth) || props.cornerType == -1)) + { + E3DCOLOR col2 = E3DCOLOR(200, 0, 0, 255); + if ((poly && !props.poly.smooth) || props.cornerType == -1) + col2 = col; + else if (poly && props.poly.smooth) + col2 = E3DCOLOR(0, 100, 0, 255); + + for (int i = 0; i < (int)points.size() - 1; i++) + dagRender->renderLine(points[i]->getPt(), points[i + 1]->getPt(), col2); + + if (poly && !props.poly.smooth && created) + dagRender->renderLine(points.back()->getPt(), points[0]->getPt(), col); + } + + if (!poly && opaque_pass && props.cornerType == 1 && !lock) + for (int i = 0; i < points.size(); i++) + if (points[i]->isSelected()) + dagRender->renderLine(points[i]->getBezierIn(), points[i]->getBezierOut(), E3DCOLOR(0, 200, 100, 255)); + + if ((!poly || props.poly.smooth) && props.cornerType != -1) + { + if (dagRender->isLinesVbufferValid(*bezierBuf)) + { + if (!opaque_pass) + col = E3DCOLOR(col.r * 3 / 5, col.g * 3 / 5, col.b * 3 / 5, 64); + dagRender->renderLinesFromVbuffer(*bezierBuf, col); + } + } +} + +void SplineObject::regenerateVBuf() +{ + dagRender->invalidateDebugPrimitivesVbuffer(*bezierBuf); + real splineLen = bezierSpline.getLength(); + + int renderSplinePoints = int(splineLen * RENDER_SPLINE_POINTS_LENGTH_COEFF); + if (renderSplinePoints > RENDER_SPLINE_POINTS) + renderSplinePoints = RENDER_SPLINE_POINTS; + else if (renderSplinePoints < RENDER_SPLINE_POINTS_MIN) + renderSplinePoints = RENDER_SPLINE_POINTS_MIN; + + Tab splinePoly(tmpmem); + splinePoly.reserve(renderSplinePoints + 1); + + for (real t = 0.0; t < splineLen; t += splineLen / renderSplinePoints) + splinePoly.push_back(bezierSpline.get_pt(t)); + + E3DCOLOR col(255, 255, 255, 255); + dagRender->beginDebugLinesCacheToVbuffer(*bezierBuf); + for (int i = 0; i < (int)splinePoly.size() - 1; ++i) + dagRender->addLineToVbuffer(*bezierBuf, splinePoly[i], splinePoly[i + 1], col); + dagRender->endDebugLinesCacheToVbuffer(*bezierBuf); +} + +void SplineObject::render(DynRenderBuffer *db, const TMatrix4 >m, const Point2 &s, const Frustum &frustum, int &cnt) +{ + if (splineInactive) + return; + if (!points.size()) + return; + if (EditLayerProps::layerProps[getEditLayerIdx()].hide) + return; + if (EditLayerProps::layerProps[getEditLayerIdx()].lock) + return; + + if (!((HmapLandObjectEditor *)getObjEditor())->isEditingSpline(this) && !frustum.testBoxB(getGeomBox())) + return; + + bool ortho = DAGORED2->getRenderViewport()->isOrthogonal(); + Point3 cpos = dagRender->curView().pos; + float dist2 = getObjEd().maxPointVisDist; + dist2 *= dist2; + + cnt++; + if (ortho || lengthSq(points[0]->getPt() - cpos) < dist2) + points[0]->renderPts(*db, gtm, s, !poly); + + for (int i = 1; i < points.size(); i++) + { + if (!ortho && lengthSq(points[i]->getPt() - cpos) > dist2) + continue; + + points[i]->renderPts(*db, gtm, s); + + cnt++; + if (cnt >= 4096) + { + dagGeom->set(zFuncLessStateId); + dagGeom->shaderGlobalSetInt(SplinePointObject::ptRenderPassId, 0); + dagRender->dynRenderBufferFlushToBuffer(*db, SplinePointObject::texPt); + dagGeom->reset_override(); + + dagGeom->shaderGlobalSetInt(SplinePointObject::ptRenderPassId, 1); + dagRender->dynRenderBufferFlushToBuffer(*db, SplinePointObject::texPt); + dagRender->dynRenderBufferClearBuf(*db); + cnt = 0; + } + } +} + + +void SplineObject::fillProps(PropertyContainerControlBase &op, DClassID for_class_id, + dag::ConstSpan objects) +{ + bool one_type = true; + int one_layer = -1; + + for (int i = 0; i < objects.size(); ++i) + if (SplineObject *s = RTTI_cast(objects[i])) + { + if (one_layer == -1) + one_layer = s->getEditLayerIdx(); + else if (one_layer != s->getEditLayerIdx()) + one_layer = -2; + } + else + { + one_layer = -2; + one_type = false; + break; + } + + if (one_layer < 0) + op.createStatic(-1, "Edit layer: --multiple selected--"); + else + op.createStatic(-1, String(0, "Edit layer: %s", EditLayerProps::layerProps[one_layer].name())); + + if (one_type) + { + op.createStatic(PID_SPLINE_LEN, String(128, "Length: %.1f m", bezierSpline.getLength())); + op.createEditBox(PID_NOTES, "Notes", props.notes); + op.createEditFloat(PID_TC_ALONG_MUL, "Scale TC along spline", props.scaleTcAlong); + + Tab lorders(tmpmem); + for (int i = 0; i < LAYER_ORDER_MAX; ++i) + lorders.push_back(String(8, "%d", i)); + op.createCombo(PID_LAYER_ORDER, "Place layer order", lorders, props.layerOrder); + + String title(poly ? "Land class asset" : "Spline class asset"); + + op.createIndent(); + op.createStatic(-1, title); + op.createButton(PID_GENBLKNAME, ::dd_get_fname(props.blkGenName)); + if (poly) + { + op.createStatic(-1, "Border spline class asset"); + op.createButton(PID_GENBLKNAME2, ::dd_get_fname(points[0]->getProps().blkGenName)); + } + + if (!poly) + { + op.createIndent(); + op.createCheckBox(PID_MAY_SELF_CROSS, "Self cross allowed", props.maySelfCross); + } + + if (poly) + { + op.createCheckBox(PID_ALT_GEOM, "Alternative geom export", polyGeom.altGeom); + op.createEditFloat(PID_BBOX_ALIGN_STEP, "geom bbox align step", polyGeom.bboxAlignStep); + op.setEnabledById(PID_BBOX_ALIGN_STEP, polyGeom.altGeom); + op.createSeparator(0); + } + op.createCheckBox(PID_EXPORTABLE, "Export to game", props.exportable); + + op.createCheckBox(PID_USE_FOR_NAVMESH, "Use for NavMesh", props.useForNavMesh); + op.createEditFloat(PID_NAVMESH_STRIPE_WIDTH, "Width", props.navMeshStripeWidth); + + if (objects.size() == 1) + op.createTrackInt(PID_PERINST_SEED, "Per-instance seed", props.perInstSeed, 0, 32767, 1); + + PropertyContainerControlBase &cornerGrp = *op.createRadioGroup(PID_CORNER_TYPE, "Spline knots corner type"); + cornerGrp.createRadio(-1, "Corner"); + cornerGrp.createRadio(0, "Smooth tangent"); + cornerGrp.createRadio(1, "Smooth curvature"); + op.setInt(PID_CORNER_TYPE, props.cornerType); + + PropertyContainerControlBase *modGroup = op.createGroup(PID_MODIF_GRP, "Modify"); + + if (!poly) + { + Tab names(tmpmem); + names.resize(3); + + names[0] = "No modify"; + names[1] = "Modify self"; + names[2] = "Modify heightmap"; + + modGroup->createCombo(PID_MODIFTYPE_S, "Modify type", names, props.modifType); + } + else + { + Tab names(tmpmem); + names.resize(2); + + names[0] = "No modify"; + names[1] = "Modify heightmap"; + + modGroup->createCombo(PID_MODIFTYPE_P, "Modify type", names, props.poly.hmapAlign ? 1 : 0); + } + + modGroup->createEditFloat(PID_MODIF_WIDTH, "Width", props.modifParams.width); + modGroup->createEditFloat(PID_MODIF_SMOOTH, "Smooth", props.modifParams.smooth); + modGroup->createEditFloat(PID_MODIF_CT_OFFSET, "Ht center ofs", props.modifParams.offset[0]); + modGroup->createEditFloat(PID_MODIF_SD_OFFSET, "Ht side ofs", props.modifParams.offset[1]); + modGroup->createEditFloat(PID_MODIF_OFFSET_POW, "Ht ofs function", props.modifParams.offsetPow); + modGroup->createCheckBox(PID_MODIF_ADDITIVE, "Preserve land details", props.modifParams.additive); + + if (poly) + { + op.createPoint2(PID_POLY_OFFSET, "Gen. objects offset", props.poly.objOffs); + op.createEditFloat(PID_POLY_ROTATE, "Gen. objects rotation", props.poly.objRot); + op.createCheckBox(PID_POLY_SMOOTH, "Smooth contour", props.poly.smooth); + op.createEditFloat(PID_POLY_CURV, "Curv. strength", props.poly.curvStrength); + op.createEditFloat(PID_POLY_MINSTEP, "Min step", props.poly.minStep); + op.createEditFloat(PID_POLY_MAXSTEP, "Max step", props.poly.maxStep); + } + + op.createButton(PID_MONOTONOUS_Y_UP, "Monotonous points height (up)"); + op.createButton(PID_MONOTONOUS_Y_DOWN, "Monotonous points height (down)"); + op.createButton(PID_LINEARIZE_Y, "Linearize points height"); + op.createButton(PID_CATMUL_XYZ, "Catmull-Rom smooth (XYZ)"); + op.createButton(PID_CATMUL_XZ, "Catmull-Rom smooth (XZ)"); + op.createButton(PID_CATMUL_Y, "Catmull-Rom smooth (Y)"); + + op.createButton(PID_FLATTEN_Y, "Flatten Y"); + op.createButton(PID_FLATTEN_AVERAGE, "Flatten average"); + + if (poly) + { + PropertyContainerControlBase *flGroup = op.createGroup(PID_FLATTEN_SPLINE_GROUP, "Flatten by spline"); + Tab spls(tmpmem); + + for (int i = 0; i < ((HmapLandObjectEditor *)getObjEditor())->splinesCount(); i++) + { + SplineObject *ss = ((HmapLandObjectEditor *)getObjEditor())->getSpline(i); + if (!ss->poly && ss->created) + spls.push_back(ss); + } + + if (spls.size()) + { + Tab flatSplines(tmpmem); + flatSplines.resize(spls.size() + 1); + + flatSplines[0] = "none"; + String curs(flatSplines[0]); + int idx = 0; + + for (int i = 0; i < spls.size(); i++) + { + flatSplines[i + 1] = spls[i]->getName(); + if (spls[i] == flattenBySpline) + curs = flatSplines[i + 1]; + idx = i + 1; + } + + flGroup->createCombo(PID_FLATTEN_SPLINE, "Spline", flatSplines, idx); + flGroup->createButton(PID_FLATTEN_SPLINE_APPLY, "Apply"); + } + } + + op.createSeparator(0); + op.createStatic(-1, "Opacity generation formula:"); + op.createStatic(-1, " base + variation * Rnd(-1..+1)"); + op.createEditFloat(PID_OPACGEN_BASE, "Base opacity", opac_gen_base); + op.createEditFloat(PID_OPACGEN_VAR, "Max opacity variation", opac_gen_var); + op.createButton(PID_OPACGEN_APPLY, "Generate opacity in points!"); + } + + for (int i = 0; i < objects.size(); ++i) + { + SplineObject *o = RTTI_cast(objects[i]); + if (!o) + continue; + + if (o->props.notes != props.notes) + op.setText(PID_NOTES, ""); + if (stricmp(o->props.blkGenName, props.blkGenName) != 0) + op.setCaption(PID_GENBLKNAME, ""); + if (o->poly != poly || stricmp(o->points[0]->getProps().blkGenName, points[0]->getProps().blkGenName) != 0) + op.setCaption(PID_GENBLKNAME2, ""); + if (o->getEffModifType() != getEffModifType()) + op.resetById(poly ? PID_MODIFTYPE_P : PID_MODIFTYPE_S); + if (o->props.cornerType != props.cornerType) + op.resetById(PID_CORNER_TYPE); + } +} + +void SplineObject::setEditLayerIdx(int idx) +{ + editLayerIdx = idx; + for (SplinePointObject *p : points) + p->setEditLayerIdx(editLayerIdx); +} + +void SplineObject::onLayerOrderChanged() +{ + for (SplinePointObject *p : points) + if (auto *gen = p->getSplineGen()) + gen->splineLayer = props.layerOrder; +} + +void SplineObject::onPPChange(int pid, bool edit_finished, PropPanel2 &panel, dag::ConstSpan objects) +{ + if (!edit_finished) + return; + +#define CHANGE_VAL(type, pname, getfunc) \ + { \ + type val(panel.getfunc(pid)); \ + for (int i = 0; i < objects.size(); ++i) \ + { \ + SplineObject *o = RTTI_cast(objects[i]); \ + if (!o || o->pname == val) \ + continue; \ + o->pname = val; \ + } \ + } +#define CHANGE_VAL_FUNC(type, pname, getfunc, func) \ + { \ + type val(panel.getfunc(pid)); \ + for (int i = 0; i < objects.size(); ++i) \ + { \ + SplineObject *o = RTTI_cast(objects[i]); \ + if (!o || o->pname == val) \ + continue; \ + o->pname = val; \ + o->func; \ + } \ + } + + if (pid == PID_NOTES) + { + CHANGE_VAL(String, props.notes, getText) + DAGORED2->invalidateViewportCache(); + } + + if (pid == PID_TC_ALONG_MUL) + { + CHANGE_VAL_FUNC(float, props.scaleTcAlong, getFloat, invalidateSplineCurve()); + DAGORED2->invalidateViewportCache(); + HmapLandPlugin::hmlService->invalidateClipmap(true); + } + + if (pid == PID_LAYER_ORDER) + { + CHANGE_VAL_FUNC(int, props.layerOrder, getInt, onLayerOrderChanged()) + // rebuild splines here + DAGORED2->invalidateViewportCache(); + HmapLandPlugin::hmlService->invalidateClipmap(true); + } + + if (pid == PID_PERINST_SEED) + { + CHANGE_VAL_FUNC(int, props.perInstSeed, getInt, regenerateObjects()) + DAGORED2->repaint(); + } + + if (pid == PID_MODIFTYPE_S || pid == PID_MODIFTYPE_P) + { + for (int i = 0; i < objects.size(); ++i) + { + SplineObject *o = RTTI_cast(objects[i]); + if (!o) + continue; + + int modif = panel.getInt(pid); + if (pid == PID_MODIFTYPE_P && modif == 1) + modif = MODIF_HMAP; + + if (modif == o->getEffModifType()) + continue; + + if (!o->poly) + { + if (props.modifType == MODIF_SPLINE || modif == MODIF_SPLINE) + { + o->splineChanged = true; + for (int i = 0; i < o->points.size(); i++) + o->points[i]->markChanged(); + } + o->props.modifType = modif; + } + else + o->props.poly.hmapAlign = modif == MODIF_HMAP; + + o->reApplyModifiers(false, true); + o->markModifChanged(); + } + } + else if (pid == PID_MAY_SELF_CROSS) + { + CHANGE_VAL_FUNC(bool, props.maySelfCross, getBool, pointChanged(-1)) + if (getObjEditor()) + getObjEd().updateCrossRoads(NULL); + DAGORED2->repaint(); + } + else if (pid == PID_POLY_OFFSET) + { + CHANGE_VAL_FUNC(Point2, props.poly.objOffs, getPoint2, regenerateObjects()) + DAGORED2->repaint(); + } + else if (pid == PID_POLY_ROTATE) + { + CHANGE_VAL_FUNC(real, props.poly.objRot, getFloat, regenerateObjects()) + DAGORED2->repaint(); + } + else if (pid == PID_POLY_SMOOTH) + { + CHANGE_VAL_FUNC(bool, props.poly.smooth, getBool, invalidateSplineCurve()) + DAGORED2->repaint(); + } + else if (pid == PID_POLY_CURV) + { + CHANGE_VAL_FUNC(real, props.poly.curvStrength, getFloat, invalidateSplineCurve()) + DAGORED2->repaint(); + } + else if (pid == PID_POLY_MINSTEP) + { + CHANGE_VAL_FUNC(real, props.poly.minStep, getFloat, invalidateSplineCurve()) + DAGORED2->repaint(); + } + else if (pid == PID_POLY_MAXSTEP) + { + CHANGE_VAL_FUNC(real, props.poly.maxStep, getFloat, invalidateSplineCurve()) + DAGORED2->repaint(); + } + else if (pid == PID_ALT_GEOM) + { + CHANGE_VAL(bool, polyGeom.altGeom, getBool) + panel.setEnabledById(PID_BBOX_ALIGN_STEP, polyGeom.altGeom); + } + else if (pid == PID_BBOX_ALIGN_STEP) + { + CHANGE_VAL(float, polyGeom.bboxAlignStep, getFloat) + } + else if (pid == PID_EXPORTABLE) + { + CHANGE_VAL(bool, props.exportable, getBool) + } + else if (pid == PID_USE_FOR_NAVMESH) + { + CHANGE_VAL(bool, props.useForNavMesh, getBool) + } + else if (pid == PID_NAVMESH_STRIPE_WIDTH) + { + CHANGE_VAL(float, props.navMeshStripeWidth, getFloat) + } + else if (pid == PID_CORNER_TYPE) + { + CHANGE_VAL_FUNC(int, props.cornerType, getInt, invalidateSplineCurve()) + } + else if (pid == PID_MODIF_WIDTH) + { + CHANGE_VAL_FUNC(real, props.modifParams.width, getFloat, markModifChangedWhenUsed()) + DAGORED2->repaint(); + } + else if (pid == PID_MODIF_SMOOTH) + { + for (int i = 0; i < objects.size(); ++i) + { + SplineObject *o = RTTI_cast(objects[i]); + if (!o) + continue; + + o->props.modifParams.smooth = panel.getFloat(pid); + if (o->props.modifParams.smooth < 0) + o->props.modifParams.smooth = 0; + + o->markModifChangedWhenUsed(); + } + DAGORED2->repaint(); + } + else if (pid == PID_MODIF_ADDITIVE) + CHANGE_VAL_FUNC(bool, props.modifParams.additive, getBool, markModifChangedWhenUsed()) + else if (pid == PID_MODIF_CT_OFFSET) + { + CHANGE_VAL_FUNC(real, props.modifParams.offset[0], getFloat, markModifChangedWhenUsed()) + DAGORED2->repaint(); + } + else if (pid == PID_MODIF_SD_OFFSET) + { + CHANGE_VAL_FUNC(real, props.modifParams.offset[1], getFloat, markModifChangedWhenUsed()) + DAGORED2->repaint(); + } + else if (pid == PID_MODIF_OFFSET_POW) + { + for (int i = 0; i < objects.size(); ++i) + { + SplineObject *o = RTTI_cast(objects[i]); + if (!o) + continue; + + o->props.modifParams.offsetPow = panel.getFloat(pid); + if (o->props.modifParams.offsetPow < 0) + o->props.modifParams.offsetPow = 0; + o->markModifChangedWhenUsed(); + } + DAGORED2->repaint(); + } + else if (pid == PID_OPACGEN_BASE) + opac_gen_base = panel.getFloat(pid); + else if (pid == PID_OPACGEN_VAR) + opac_gen_var = panel.getFloat(pid); +#undef CHANGE_VAL +} + +void SplineObject::changeAsset(const char *asset_name, bool _undo) +{ + if (_undo) + getObjEditor()->getUndoSystem()->put(new UndoChangeAsset(this, -1)); + props.blkGenName = asset_name ? asset_name : ""; + + if (!poly) + points[0]->resetSplineClass(); + else + del_it(landClass); + + markAssetChanged(0); +} + +void SplineObject::onPPBtnPressed(int pid, PropPanel2 &panel, dag::ConstSpan objects) +{ + if (!points.size()) + return; + + if (pid == PID_GENBLKNAME) + { + const char *asset_name = + DAEDITOR3.selectAssetX(props.blkGenName, poly ? "Select landclass" : "Select splineclass", poly ? "land" : "spline"); + + for (int i = 0; i < objects.size(); i++) + { + SplineObject *o = RTTI_cast(objects[i]); + if (!o) + continue; + o->changeAsset(asset_name, true); + } + + panel.setText(pid, asset_name); + IEditorCoreEngine::get()->invalidateViewportCache(); + } + else if (pid == PID_GENBLKNAME2) + { + const char *asset_name = DAEDITOR3.selectAssetX(points[0]->getProps().blkGenName, "Select border splineclass", "spline"); + + for (int i = 0; i < objects.size(); i++) + { + SplineObject *o = RTTI_cast(objects[i]); + if (!o) + continue; + o->points[0]->setBlkGenName(asset_name); + o->points[0]->setEffectiveAsset(asset_name, true, 0); + } + + panel.setText(pid, asset_name); + IEditorCoreEngine::get()->invalidateViewportCache(); + } + else if (pid == PID_MONOTONOUS_Y_UP || pid == PID_MONOTONOUS_Y_DOWN) + { + getObjEditor()->getUndoSystem()->begin(); + for (int si = 0; si < objects.size(); si++) + { + SplineObject *o = RTTI_cast(objects[si]); + if (!o) + continue; + + o->putObjTransformUndo(); + for (int i = 0; i < o->points.size(); i++) + o->points[i]->putMoveUndo(); + + if (pid == PID_MONOTONOUS_Y_UP) + o->makeMonoUp(); + else + o->makeMonoDown(); + if (o->props.cornerType > 0) + o->applyCatmull(false, true); + } + getObjEditor()->getUndoSystem()->accept("Monotonous spline(s) height"); + } + else if (pid == PID_LINEARIZE_Y) + { + getObjEditor()->getUndoSystem()->begin(); + for (int si = 0; si < objects.size(); si++) + { + SplineObject *o = RTTI_cast(objects[si]); + if (!o || o->isPoly()) + continue; + + o->putObjTransformUndo(); + for (int i = 0; i < o->points.size(); i++) + o->points[i]->putMoveUndo(); + + o->makeLinearHt(); + if (o->props.cornerType >= 0) + o->applyCatmull(false, true); + } + getObjEditor()->getUndoSystem()->accept("Linearize spline(s) height"); + } + else if (pid == PID_CATMUL_XYZ || pid == PID_CATMUL_XZ || pid == PID_CATMUL_Y) + { + getObjEditor()->getUndoSystem()->begin(); + for (int si = 0; si < objects.size(); si++) + { + SplineObject *o = RTTI_cast(objects[si]); + if (!o) + continue; + + o->putObjTransformUndo(); + for (int i = 0; i < o->points.size(); i++) + o->points[i]->putMoveUndo(); + + o->applyCatmull(pid == PID_CATMUL_XYZ || pid == PID_CATMUL_XZ, pid == PID_CATMUL_XYZ || pid == PID_CATMUL_Y); + o->getSpline(); + } + getObjEditor()->getUndoSystem()->accept("Smooth Catmull-Rom"); + } + else if (pid == PID_FLATTEN_Y) + { + getObjEditor()->getUndoSystem()->begin(); + putObjTransformUndo(); + for (int i = 0; i < points.size(); i++) + points[i]->putMoveUndo(); + + flattenBySpline = NULL; + + real midY = 0; + for (int i = 0; i < points.size(); i++) + midY += points[i]->getPt().y; + + midY /= points.size(); + + for (int i = 0; i < points.size(); i++) + { + Point3 npos = points[i]->getPt(); + npos.y = midY; + points[i]->setPos(npos); + points[i]->FlattenY(); + } + + getObjEditor()->getUndoSystem()->accept("Flatten spline(s)"); + + markModifChangedWhenUsed(); + } + else if (pid == PID_FLATTEN_AVERAGE) + { + getObjEditor()->getUndoSystem()->begin(); + putObjTransformUndo(); + for (int i = 0; i < points.size(); i++) + points[i]->putMoveUndo(); + + flattenBySpline = NULL; + + Point3 cpos = Point3(0, 0, 0); + for (int i = 0; i < points.size(); i++) + cpos += points[i]->getPt(); + + cpos /= points.size(); + + Point3 cnorm = Point3(0, 0, 0); + + for (int i = 0; i < points.size(); i++) + { + Point3 p1 = points[i]->getPt(); + Point3 p2 = (i == points.size() - 1 ? points[0]->getPt() : points[i + 1]->getPt()); + + Point3 v1 = p1 - cpos; + Point3 v2 = p2 - cpos; + + Point3 tnorm = v1 % v2; + tnorm.normalize(); + + cnorm += tnorm; + } + + cnorm.normalize(); + + real tD = -cnorm.x * cpos.x - cnorm.y * cpos.y - cnorm.z * cpos.z; + + BBox3 oldBox, newBox; + getWorldBox(oldBox); + for (int i = 0; i < points.size(); i++) + { + real NY = -tD - cnorm.x * points[i]->getPt().x - cnorm.z * points[i]->getPt().z; + NY /= cnorm.y; + + Point3 npos = points[i]->getPt(); + npos.y = NY; + points[i]->setPos(npos); + } + getWorldBox(newBox); + float mul = newBox.width().y / oldBox.width().y; + for (int i = 0; i < points.size(); i++) + points[i]->FlattenAverage(mul); + + getObjEditor()->getUndoSystem()->accept("Flatten spline(s)"); + + markModifChangedWhenUsed(); + } + else if (pid == PID_FLATTEN_SPLINE_APPLY) + { + getObjEditor()->getUndoSystem()->begin(); + putObjTransformUndo(); + for (int i = 0; i < points.size(); i++) + points[i]->putMoveUndo(); + + flattenBySpline = NULL; + + RenderableEditableObject *o = getObjEditor()->getObjectByName(panel.getText(PID_FLATTEN_SPLINE).str()); + if (!o) + { + destroy_it(csgGen); + polyGeom.clear(); + return; + } + + SplineObject *s = RTTI_cast(o); + if (!s || !s->points.size()) + { + destroy_it(csgGen); + polyGeom.clear(); + return; + } + + flattenBySpline = s; + + getObjEditor()->getUndoSystem()->accept("Flatten spline(s)"); + + markModifChangedWhenUsed(); + + triangulatePoly(); + } + else if (pid == PID_OPACGEN_APPLY) + { + getObjEditor()->getUndoSystem()->begin(); + + for (int si = 0; si < objects.size(); si++) + if (SplineObject *o = RTTI_cast(objects[si])) + { + for (int i = 0; i < o->points.size(); i++) + { + float new_opac = clamp(opac_gen_base + gsrnd() * opac_gen_var, 0.0f, 1.0f); + SplinePointObject::Props p = o->points[i]->getProps(); + if (new_opac != p.attr.opacity) + { + getObjEditor()->getUndoSystem()->put(o->points[i]->makePropsUndoObj()); + + p.attr.opacity = opac_gen_base + gsrnd() * opac_gen_var; + o->points[i]->setProps(p); + o->points[i]->markChanged(); + } + } + o->getSpline(); + } + getObjEditor()->getUndoSystem()->accept("Generate opacity in points"); + } +} + + +//================================================================================================== +bool SplineObject::getWorldBox(BBox3 &box) const +{ + if (points.size()) + { + for (int i = 0; i < points.size(); ++i) + box += points[i]->getPt(); + + return true; + } + + return false; +} + +void SplineObject::onPointRemove(int id) +{ + if (!points.size()) + return; + + G_ASSERT(id >= 0 && id < points.size()); + + bool closed = isClosed(); + erase_items(points, id, 1); + + if (!points.size()) + return; + + if (closed && id == 0) + points.resize(points.size() - 1); + else if (closed && id == points.size()) + erase_items(points, 0, 1); + + for (int i = points.size() - 1; i >= 0; i--) + points[i]->arrId = i; + + if (points.size() > 1) + getSpline(); + + if (id > 0 && getObjEditor()) + getObjEd().updateCrossRoads(points[id - 1]); + if (id < points.size() && getObjEditor()) + getObjEd().updateCrossRoads(points[id]); + + prepareSplineClassInPoints(); + pointChanged(id); + if (id > 0) + pointChanged(id - 1); +} + +void SplineObject::addPoint(SplinePointObject *pt) +{ + G_ASSERTF(pt->arrId >= 0 && pt->arrId <= points.size(), "pt->arrId=%d points.size()=%d", pt->arrId, points.size()); + + insert_items(points, pt->arrId, 1, &pt); + + for (int i = points.size() - 1; i >= 0; i--) + points[i]->arrId = i; + + if (points.size() > 1) + getSpline(); + + if (getObjEditor()) + { + if (pt->arrId > 0) + getObjEd().updateCrossRoads(points[pt->arrId - 1]); + getObjEd().updateCrossRoads(points[pt->arrId]); + } + + prepareSplineClassInPoints(); + pointChanged(pt->arrId); + if (pt->arrId > 0) + pointChanged(pt->arrId - 1); +} + +void SplineObject::refine(int seg_id, real loc_t, Point3 &p_pos) +{ + getObjEditor()->getUndoSystem()->begin(); + + SplinePointObject *pt = new SplinePointObject; + + SplinePointObject *p1 = points[seg_id]; + SplinePointObject *p2 = points[(seg_id + 1) % points.size()]; + + SplinePointObject::Props startProp1 = p1->getProps(); + SplinePointObject::Props startProp2 = p2->getProps(); + + Point3 targetPos; + + if (poly) + targetPos = p_pos; + else + { + Point3 sp[4], cp[2]; + + sp[0] = p1->getPt(); + sp[1] = p1->getBezierOut(); + sp[2] = p2->getBezierIn(); + sp[3] = p2->getPt(); + sp[0] = sp[0] * (1 - loc_t) + sp[1] * loc_t; + sp[1] = sp[1] * (1 - loc_t) + sp[2] * loc_t; + sp[2] = sp[2] * (1 - loc_t) + sp[3] * loc_t; + sp[0] = sp[0] * (1 - loc_t) + sp[1] * loc_t; + sp[1] = sp[1] * (1 - loc_t) + sp[2] * loc_t; + targetPos = sp[0] * (1 - loc_t) + sp[1] * loc_t; + + p1->setRelBezierOut((p1->getBezierOut() - p1->getPt()) * loc_t); + p2->setRelBezierIn((p2->getBezierIn() - p2->getPt()) * (1 - loc_t)); + + pt->setRelBezierIn(sp[0] - targetPos); + pt->setRelBezierOut(sp[1] - targetPos); + } + + SplinePointObject::Props endProp1 = p1->getProps(); + SplinePointObject::Props endProp2 = p2->getProps(); + + pt->setPos(targetPos); + pt->spline = this; + pt->arrId = seg_id + 1; + getObjEditor()->addObject(pt); + + UndoRefineSpline *undoRefine = new UndoRefineSpline(this, pt, seg_id, startProp1, startProp2, endProp1, endProp2); + + pointChanged(-1); + prepareSplineClassInPoints(); + getSpline(); + + getObjEditor()->getUndoSystem()->put(undoRefine); + putObjTransformUndo(); + getObjEditor()->getUndoSystem()->accept("Refine spline"); +} + + +void SplineObject::split(int pt_id) +{ + G_ASSERT(pt_id >= 0 && pt_id < points.size()); + G_ASSERT(!isClosed()); + + if (pt_id == 0) + { + DAEDITOR3.conWarning("cannot split spline at start point"); + return; + } + else if (pt_id == points.size() - 1) + { + DAEDITOR3.conWarning("cannot split spline at end point"); + return; + } + + SplineObject *newSpline = new SplineObject(false); + newSpline->setEditLayerIdx(EditLayerProps::activeLayerIdx[newSpline->lpIndex()]); + newSpline->setCornerType(props.cornerType); + + getObjEditor()->getUndoSystem()->begin(); + UndoSplitSpline *undoSplit = new UndoSplitSpline(this, newSpline, pt_id, (HmapLandObjectEditor *)getObjEditor()); + + newSpline->onCreated(); + + getObjEditor()->getUndoSystem()->put(undoSplit); + putObjTransformUndo(); + getObjEditor()->getUndoSystem()->accept("Split spline"); +} + + +void SplineObject::splitOnTwoPolys(int pt1, int pt2) +{ + if (pt1 < 0 || pt1 + 1 > points.size() || pt2 < 0 || pt2 + 1 > points.size() || pt1 == pt2) + return; + + int segid1, segid2; + if (pt1 < pt2) + { + segid1 = pt1; + segid2 = pt2; + } + else + { + segid1 = pt2; + segid2 = pt1; + } + + SplineObject *newPoly = new SplineObject(true); + newPoly->setEditLayerIdx(EditLayerProps::activeLayerIdx[newPoly->lpIndex()]); + newPoly->setBlkGenName(props.blkGenName); + + getObjEditor()->getUndoSystem()->begin(); + + UndoSplitPoly *undoSplit = new UndoSplitPoly(this, newPoly, segid1, segid2, (HmapLandObjectEditor *)getObjEditor()); + + newPoly->onCreated(); + + getObjEditor()->getUndoSystem()->put(undoSplit); + getObjEditor()->getUndoSystem()->accept("Split polygons"); +} + + +void SplineObject::save(DataBlock &blk) +{ + if (!points.size()) + return; + + DataBlock *sblk = blk.addNewBlock(poly ? "polygon" : "spline"); + sblk->setStr("name", name); + sblk->setStr("notes", props.notes); + sblk->setInt("layerOrder", props.layerOrder); + if (props.scaleTcAlong != 1.0f) + sblk->setReal("scaleTcAlong", props.scaleTcAlong); + + sblk->setStr("blkGenName", props.blkGenName); + sblk->setInt("modifType", props.modifType); + + if (poly) + { + sblk->setBool("polyHmapAlign", props.poly.hmapAlign); + sblk->setPoint2("polyObjOffs", props.poly.objOffs); + sblk->setReal("polyObjRot", props.poly.objRot); + sblk->setBool("polySmooth", props.poly.smooth); + sblk->setReal("polyCurv", props.poly.curvStrength); + sblk->setReal("polyMinStep", props.poly.minStep); + sblk->setReal("polyMaxStep", props.poly.maxStep); + } + else + sblk->setBool("maySelfCross", props.maySelfCross); + + sblk->setBool("exportable", props.exportable); + if (props.useForNavMesh != DEF_USE_FOR_NAVMESH) + sblk->setBool("useForNavMesh", props.useForNavMesh); + if (props.navMeshStripeWidth != DEF_NAVMESH_STRIPE_WIDTH) + sblk->setReal("navMeshStripeWidth", props.navMeshStripeWidth); + if (polyGeom.altGeom) + { + sblk->setBool("altGeom", polyGeom.altGeom); + if (polyGeom.bboxAlignStep != 1.0f) + sblk->setReal("bboxAlignStep", polyGeom.bboxAlignStep); + } + + if (props.cornerType != 0) + sblk->setInt("cornerType", props.cornerType); + + sblk->setInt("rseed", props.rndSeed); + if (props.perInstSeed) + sblk->setInt("perInstSeed", props.perInstSeed); + + DataBlock *mblk = sblk->addNewBlock("modifParams"); + mblk->setReal("width", props.modifParams.width); + mblk->setReal("smooth", props.modifParams.smooth); + mblk->setReal("offsetPow", props.modifParams.offsetPow); + mblk->setPoint2("offset", props.modifParams.offset); + mblk->setBool("additive", props.modifParams.additive); + + int pt_num = points.size(); + if (isClosed()) + { + sblk->setBool("closed", true); + pt_num--; + } + + for (int i = 0; i < pt_num; i++) + { + DataBlock *cb = sblk->addNewBlock("point"); + points[i]->save(*cb); + } +} + + +void SplineObject::load(const DataBlock &blk, bool use_undo) +{ + const char *n = blk.getStr("name", NULL); + if (n) + getObjEditor()->setUniqName(this, n); + + props.notes = blk.getStr("notes", ""); + props.layerOrder = blk.getInt("layerOrder", 0); + props.blkGenName = blk.getStr("blkGenName", ""); + props.scaleTcAlong = blk.getReal("scaleTcAlong", 1.0f); + + const DataBlock *mblk = blk.getBlockByName("modifParams"); + if (mblk) + loadModifParams(*mblk); + + props.maySelfCross = blk.getBool("maySelfCross", false); + + props.modifType = blk.getInt("modifType", MODIF_NONE); + props.poly.hmapAlign = blk.getBool("polyHmapAlign", false); + + props.poly.objOffs = blk.getPoint2("polyObjOffs", Point2(0, 0)); + props.poly.objRot = blk.getReal("polyObjRot", 0); + props.poly.smooth = blk.getBool("polySmooth", false); + props.poly.curvStrength = blk.getReal("polyCurv", 1); + props.poly.minStep = blk.getReal("polyMinStep", 30); + props.poly.maxStep = blk.getReal("polyMaxStep", 1000); + + props.exportable = blk.getBool("exportable", false); + props.cornerType = blk.getInt("cornerType", 0); + props.useForNavMesh = blk.getBool("useForNavMesh", DEF_USE_FOR_NAVMESH); + props.navMeshStripeWidth = blk.getReal("navMeshStripeWidth", DEF_NAVMESH_STRIPE_WIDTH); + + polyGeom.altGeom = blk.getBool("altGeom", false); + polyGeom.bboxAlignStep = blk.getReal("bboxAlignStep", blk.getReal("minGridStep", 1.0f)); + + int nid = blk.getNameId("point"); + + for (int i = 0; i < blk.blockCount(); i++) + if (blk.getBlock(i)->getBlockNameId() == nid) + { + const DataBlock &cb = *blk.getBlock(i); + + SplinePointObject *s = new SplinePointObject; + s->load(cb); + + s->arrId = points.size(); + s->spline = this; + + getObjEditor()->addObject(s, use_undo); + } + if (blk.getBool("closed", false)) + { + points.push_back(points[0]); + getSpline(); + } + + props.rndSeed = blk.getInt("rseed", points[1]->getPt().lengthSq() * 1000); + props.perInstSeed = blk.getInt("perInstSeed", 0); + + prepareSplineClassInPoints(); + markModifChangedWhenUsed(); +} + +void SplineObject::loadModifParams(const DataBlock &blk) +{ + props.modifParams.width = blk.getReal("width", 60); + props.modifParams.smooth = blk.getReal("smooth", 10); + props.modifParams.offsetPow = blk.getReal("offsetPow", 2); + props.modifParams.offset = blk.getPoint2("offset", Point2(-0.05, 0)); + props.modifParams.additive = blk.getBool("additive", false); +} + +bool SplineObject::isSelectedByRectangle(IGenViewportWnd *vp, const EcRect &rect) const +{ + if (EditLayerProps::layerProps[getEditLayerIdx()].hide) + return false; + if (points.size() < 2) + return false; + + Matrix44 gtm; + d3d::getglobtm(gtm); + Frustum f(gtm); + if (!f.testSphereB(splSph.c, splSph.r)) + return false; + + Point2 last, cur; + BBox2 box(Point2(rect.l, rect.t), Point2(rect.r, rect.b)); + + if (poly && !props.poly.smooth) + { + if (vp->worldToClient(points[0]->getPt(), last) && (box & last)) + return true; + + for (int i = 1; i < points.size(); i++) + { + if (vp->worldToClient(points[i]->getPt(), cur) && (box & cur)) + return true; + + if (::isect_line_segment_box(last, cur, box)) + return true; + + last = cur; + } + + if (vp->worldToClient(points[0]->getPt(), cur) && (box & cur)) + return true; + if (::isect_line_segment_box(last, cur, box)) + return true; + } + else + { + for (int i = 0; i < segSph.size(); i++) + if (::is_sphere_hit_by_rect(segSph[i].c, segSph[i].r, vp, rect)) + { + if (vp->worldToClient(bezierSpline.segs[i].point(0.0), last) && (box & last)) + return true; + + for (float t = splStep; t < 1.0; t += splStep) + { + if (vp->worldToClient(bezierSpline.segs[i].point(t), cur) && (box & cur)) + return true; + if (::isect_line_segment_box(last, cur, box)) + return true; + last = cur; + } + if (vp->worldToClient(bezierSpline.segs[i].point(1.0), cur) && (box & cur)) + return true; + if (::isect_line_segment_box(last, cur, box)) + return true; + } + } + + return false; +} + +bool SplineObject::isSelectedByPointClick(IGenViewportWnd *vp, int x, int y) const +{ + if (EditLayerProps::layerProps[getEditLayerIdx()].hide) + return false; + for (int i = 0; i < points.size(); i++) + if (points[i]->isSelectedByPointClick(vp, x, y)) + return ((HmapLandObjectEditor *)objEditor)->getSelectMode() == CM_SELECT_SPLINES; + return getPosOnSpline(vp, x, y, 4); +} + +bool SplineObject::getPosOnSpline(IGenViewportWnd *vp, int x, int y, float max_dist, int *out_segid, float *out_local_t, + Point3 *out_p) const +{ + if (out_segid) + *out_segid = -1; + + if (points.size() < 2) + return false; + + Matrix44 gtm; + d3d::getglobtm(gtm); + Frustum f(gtm); + if (!f.testSphereB(splSph.c, splSph.r)) + return false; + + Point3 last_p3, cur_p3; + Point2 last_p2, cur_p2; + float last_t, cur_t; + Point2 p(x, y); + int segId = -1; + + for (int i = 0; i < segSph.size(); i++) + if (::is_sphere_hit_by_point(segSph[i].c, segSph[i].r, vp, x, y)) + { + segId = i; + + last_t = 0.0; + last_p3 = bezierSpline.segs[i].point(last_t); + vp->worldToClient(last_p3, last_p2); + + for (float t = splStep; t < 1.0; t += splStep) + { + cur_t = t; + cur_p3 = bezierSpline.segs[i].point(t); + vp->worldToClient(cur_p3, cur_p2); + if (::distance_point_to_line_segment(p, last_p2, cur_p2) < max_dist) + goto success; + last_t = cur_t; + last_p2 = cur_p2; + last_p3 = cur_p3; + } + + cur_t = 1.0; + cur_p3 = bezierSpline.segs[i].point(cur_t); + vp->worldToClient(cur_p3, cur_p2); + if (::distance_point_to_line_segment(p, last_p2, cur_p2) < max_dist) + goto success; + } + + if (poly && !props.poly.smooth) + { + segId = points.size() - 1; + last_p3 = points.back()->getPt(); + vp->worldToClient(last_p3, last_p2); + + for (float tt = splStep; tt < 1.0; tt += splStep) + { + cur_p3 = points.back()->getPt() * (1 - tt) + points[0]->getPt() * tt; + + vp->worldToClient(cur_p3, cur_p2); + + if (::distance_point_to_line_segment(p, last_p2, cur_p2) < max_dist) + goto success; + + last_p2 = cur_p2; + last_p3 = cur_p3; + } + } + + if (out_segid) + *out_segid = -1; + + return false; + +success: + + if (out_segid) + *out_segid = segId; + + if (out_local_t || out_p) + { + Point2 dp = p - last_p2; + Point2 dir = cur_p2 - last_p2; + real len2 = lengthSq(dir); + + float t = (dp * dir) / len2; + + if (t <= 0) + { + if (out_local_t) + *out_local_t = last_t; + if (out_p) + *out_p = last_p3; + } + else if (t >= 1) + { + if (out_local_t) + *out_local_t = cur_t; + if (out_p) + *out_p = cur_p3; + } + else + { + if (out_local_t) + *out_local_t = last_t * (1 - t) + cur_t * t; + if (out_p) + *out_p = last_p3 * (1 - t) + cur_p3 * t; + } + } + return true; +} + + +static void build_corner_spline(BezierSplinePrec3d &loftSpl, BezierSplinePrec3d &baseSpl, dag::ConstSpan seg, + int ss, int es) +{ + clear_and_shrink(loftSpl.segs); + if (!seg.size()) + { + loftSpl.calculateLength(); + return; + } + + Tab pts(tmpmem); + pts.reserve(seg.size() * 3); + + // debug("loftSegs=%d (%d..%d)", seg.size(), ss, es); + for (int i = 0; i < seg.size(); ++i) + { + if (seg[i].segN + ss < ss) + continue; + else if (seg[i].segN + ss > es) + break; + int base = append_items(pts, 3); + pts[base + 0] = pts[base + 1] = pts[base + 2] = Point3::xVz(baseSpl.segs[seg[i].segN + ss].point(seg[i].offset), seg[i].y); + // debug(" %d: seg=%d ofs=%.4f y=%.4f %~p3", i, seg[i].segN+ss, seg[i].offset, seg[i].y, pts[base+0]); + } + loftSpl.calculate(pts.data(), pts.size(), false); +} +static void build_ground_spline(BezierSpline3d &gndSpl, const PtrTab &points, bool poly, bool poly_smooth, + bool is_closed) +{ + Tab pt_gnd; + pt_gnd.resize(points.size() * 3); + + // drop points to collision and recompute Y for helpers using CatmullRom + { + for (int pi = 0; pi < points.size(); pi++) + { + pt_gnd[pi * 3 + 0] = points[pi]->getPt(); + HmapLandPlugin::self->getHeightmapPointHt(pt_gnd[pi * 3 + 0], NULL); + + pt_gnd[pi * 3 + 1] = points[pi]->getPtEffRelBezierIn(); + pt_gnd[pi * 3 + 2] = points[pi]->getPtEffRelBezierOut(); + } + + Point3 *catmul[4]; + BezierSplineInt sp; + Point3 v[4]; + int pn = points.size(); + + for (int i = -1; i < pn - 2; i++) + { + for (int j = 0; j < 4; j++) + catmul[j] = pt_gnd.data() + ((poly || is_closed) ? (i + j + pn) % pn : clamp(i + j, 0, pn - 1)) * 3; + + for (int j = 0; j < 4; j++) + v[j] = *catmul[j]; + sp.calculateCatmullRom(v); + sp.calculateBack(v); + + float pi0_y = v[0].y - v[1].y, pi1_y = v[2].y - v[3].y; + catmul[1][1].y = pi0_y; + catmul[1][2].y = -pi0_y; + catmul[2][1].y = pi1_y; + catmul[2][2].y = -pi1_y; + } + } + + // build spline from ground points + SmallTab pts; + int pts_num = points.size() + (poly ? 1 : 0); + clear_and_resize(pts, pts_num * 3); + + for (int pi = 0; pi < pts_num; ++pi) + { + int wpi = pi % points.size(); + pts[pi * 3 + 1] = pt_gnd[wpi * 3 + 0]; + if ((poly && !poly_smooth) || (points[wpi]->isCross && points[wpi]->isRealCross)) + pts[pi * 3 + 0] = pts[pi * 3 + 2] = pts[pi * 3 + 1]; + else + { + pts[pi * 3 + 0] = pt_gnd[wpi * 3 + 0] + pt_gnd[wpi * 3 + 1]; + pts[pi * 3 + 2] = pt_gnd[wpi * 3 + 0] + pt_gnd[wpi * 3 + 2]; + } + } + + gndSpl.calculate(pts.data(), pts.size(), false); +} + +void SplineObject::regenerateObjects() +{ + if (splineInactive) + return; + if (!points.size()) + return; + + if (poly) + placeObjectsInsidePolygon(); + + if (points.size() > 1) + { + BezierSpline3d onGndSpline; + BezierSpline3d &effSpline = (props.modifType == MODIF_SPLINE) ? onGndSpline : bezierSpline; + + if (props.modifType == MODIF_SPLINE) + { + for (SplinePointObject *p : points) + if (ISplineGenObj *gen = p->getSplineGen()) + for (auto &p : gen->entPools) + p.resetUsedEntities(); + build_ground_spline(onGndSpline, points, poly, props.poly.smooth, isClosed()); + } + + int start_seg = 0; + SplinePointObject *p0 = points[start_seg]; + + for (int i = 0; i < cablesPool.size(); ++i) + HmapLandPlugin::cableService->removeCable(cablesPool[i]); + cablesPool.clear(); + + for (int i = 1; i < (int)points.size() - 1; i++) + { + if (!points[i]->getSplineGen()) + continue; + + if (ISplineGenObj *gen = p0->getSplineGen()) + gen->generateObjects(effSpline, start_seg, i, splineSubTypeId, editLayerIdx, props.rndSeed, props.perInstSeed, &cablesPool); + + start_seg = i; + p0 = points[start_seg]; + } + + if (ISplineGenObj *gen = p0->getSplineGen()) + gen->generateObjects(effSpline, start_seg, effSpline.segs.size(), splineSubTypeId, editLayerIdx, props.rndSeed, + props.perInstSeed, &cablesPool); + } + DAGORED2->restoreEditorColliders(); +} + + +bool SplineObject::onAssetChanged(landclass::AssetData *data) +{ + if (landClass && landClass->data == data) + { + pointChanged(-1); + return !splineInactive; + } + return false; +} + +bool SplineObject::onAssetChanged(splineclass::AssetData *data) +{ + if (poly) + return false; + + bool ret = false; + for (int i = 0; i < points.size(); i++) + if (points[i]->getSplineClass() == data) + { + points[i]->resetSplineClass(); + markAssetChanged(i); + ret = true; + } + return !splineInactive; +} + +void SplineObject::putObjTransformUndo() +{ + class ObjTransformUndo : public UndoRedoObject + { + Ptr obj; + + public: + ObjTransformUndo(SplineObject *o) : obj(o) {} + + virtual void restore(bool save_redo) + { + obj->pointChanged(-1); + if (obj->isAffectingHmap()) + obj->markModifChanged(); + } + virtual void redo() + { + obj->pointChanged(-1); + if (obj->isAffectingHmap()) + obj->markModifChanged(); + } + + virtual size_t size() { return sizeof(*this); } + virtual void accepted() {} + virtual void get_description(String &s) { s = "ObjTransformUndo"; } + }; + + getObjEditor()->getUndoSystem()->put(new ObjTransformUndo(this)); +} + +void SplineObject::placeObjectsInsidePolygon() +{ + // lines.clear(); + if (!landClass) + return; + + Point3 hmofs = HmapLandPlugin::self->getHeightmapOffset(); + landClass->beginGenerate(); + if (landClass->data && landClass->data->tiled) + objgenerator::generateTiledEntitiesInsidePoly(*landClass->data->tiled, tiledByPolygonSubTypeId, editLayerIdx, HmapLandPlugin::self, + make_span(landClass->poolTiled), make_span_const((SplinePointObject **)points.data(), points.size()), + DEG_TO_RAD * props.poly.objRot, props.poly.objOffs + Point2(hmofs.x, hmofs.z)); + if (landClass->data && landClass->data->planted) + { + typedef HierBitMap2d> HierBitmap32; + HierBitmap32 bmp; + float ofs_x, ofs_z, cell; + + cell = rasterize_poly(bmp, ofs_x, ofs_z, make_span_const((SplinePointObject **)points.data(), points.size())); + float mid_y = 0; + for (int i = 0; i < points.size(); i++) + mid_y += points[i]->getPt().y / points.size(); + + + objgenerator::generatePlantedEntitiesInMaskedRect(*landClass->data->planted, tiledByPolygonSubTypeId, editLayerIdx, NULL, + make_span(landClass->poolPlanted), bmp, 1.0 / cell, 0, 0, bmp.getW() * cell, bmp.getH() * cell, ofs_x, ofs_z, mid_y); + } + landClass->endGenerate(); + + DAGORED2->restoreEditorColliders(); +} + +void SplineObject::gatherStaticGeometry(StaticGeometryContainer &cont, int flags, bool collision, int layer, int stage) +{ + if (splineInactive) + return; + if (!created) + return; + + if (collision) + flags |= StaticGeometryNode::FLG_COLLIDABLE; + + int st_mask = + DAEDITOR3.getEntitySubTypeMask(collision ? IObjEntityFilter::STMASK_TYPE_COLLISION : IObjEntityFilter::STMASK_TYPE_EXPORT); + + const char *num_suffix = strrchr(name, '_'); + int id = num_suffix ? atoi(num_suffix + 1) : 0; + + if (st_mask & roadsSubtypeMask) + for (int i = 0; i < (int)points.size() - 1; i++) + { + GeomObject *road = points[i]->getRoadGeom(); + if (!road) + continue; + + const StaticGeometryContainer *geom = road->getGeometryContainer(); + if (geom) + gatherStaticGeom(cont, *geom, flags, id, i, stage); + } + + if (poly && (st_mask & polygonSubtypeMask) && !polyGeom.altGeom) + { + if (polyGeom.mainMesh) + gatherStaticGeom(cont, *polyGeom.mainMesh->getGeometryContainer(), flags, id, 0, stage); + if (polyGeom.borderMesh) + gatherStaticGeom(cont, *polyGeom.borderMesh->getGeometryContainer(), flags, id, 1, stage); + } +} + +void SplineObject::gatherStaticGeom(StaticGeometryContainer &cont, const StaticGeometryContainer &geom, int flags, int id, + int name_idx1, int stage) +{ + for (int ni = 0; ni < geom.nodes.size(); ++ni) + { + StaticGeometryNode *node = geom.nodes[ni]; + if (node && node->script.getInt("stage", 0) != stage) + continue; + + if (node && (!flags || (node->flags & flags))) + { + StaticGeometryNode *n = dagGeom->newStaticGeometryNode(*node, tmpmem); + n->name = (const char *)String(1024, "%d_%s#%d", id, (const char *)n->name, name_idx1); + cont.addNode(n); + } + } +} + +void SplineObject::gatherStaticGeomLayered(StaticGeometryContainer &cont, const StaticGeometryContainer &geom, int flags, int id, + int name_idx1, int layer, int stage) +{ + for (int ni = 0; ni < geom.nodes.size(); ++ni) + { + StaticGeometryNode *node = geom.nodes[ni]; + if (node && node->script.getInt("stage", 0) != stage) + continue; + + if (node && node->script.getInt("layer", 0) == layer && (!flags || (node->flags & flags))) + { + StaticGeometryNode *n = dagGeom->newStaticGeometryNode(*node, tmpmem); + n->name = (const char *)String(1024, "%d_%s#%d", id, (const char *)n->name, name_idx1); + cont.addNode(n); + } + } +} + +void SplineObject::moveObject(const Point3 &delta, IEditorCoreEngine::BasisType basis) +{ + if (!points.size()) + return; + + __super::putMoveUndo(); + putObjTransformUndo(); + __super::moveObject(delta, basis); + + int pnum = isClosed() ? points.size() - 1 : points.size(); + for (int i = 0; i < pnum; i++) + { + points[i]->putMoveUndo(); + points[i]->setPos(points[i]->getPos() + delta); + } + + objectWasMoved = true; +} + +void SplineObject::rotateObject(const Point3 &delta, const Point3 &origin, IEditorCoreEngine::BasisType basis) +{ + if (!points.size()) + return; + + if (basis == IEditorCoreEngine::BASIS_Local) + return; + + __super::putRotateUndo(); + putObjTransformUndo(); + __super::rotateObject(delta, origin, basis); + + + Matrix3 dtm = rotxM3(delta.x) * rotyM3(delta.y) * rotzM3(delta.z); + TMatrix tdtm = rotxTM(delta.x) * rotyTM(delta.y) * rotzTM(delta.z); + + int pnum = isClosed() ? points.size() - 1 : points.size(); + for (int i = 0; i < pnum; i++) + { + points[i]->putRotateUndo(); + + Point3 pIn = points[i]->getProps().relIn, pOut = points[i]->getProps().relOut; + + pIn = tdtm * pIn; + pOut = tdtm * pOut; + + float wtm_det = points[i]->getWtm().det(); + if (fabsf(wtm_det) < 1e-12) + continue; + Point3 lorg = inverse(points[i]->getWtm(), wtm_det) * origin; + points[i]->setMatrix(dtm * points[i]->getMatrix()); + points[i]->setPos(points[i]->getPos() + origin - points[i]->getWtm() * lorg); + + points[i]->setRelBezierIn(pIn); + points[i]->setRelBezierOut(pOut); + } + + objectWasRotated = true; +} + +void SplineObject::scaleObject(const Point3 &delta, const Point3 &origin, IEditorCoreEngine::BasisType basis) +{ + if (!points.size()) + return; + + __super::putScaleUndo(); + putObjTransformUndo(); + __super::scaleObject(delta, origin, basis); + + Matrix3 dtm; + dtm.zero(); + dtm[0][0] = delta.x; + dtm[1][1] = delta.y; + dtm[2][2] = delta.z; + + TMatrix tdtm; + tdtm.zero(); + tdtm[0][0] = delta.x; + tdtm[1][1] = delta.y; + tdtm[2][2] = delta.z; + + int pnum = isClosed() ? points.size() - 1 : points.size(); + for (int i = 0; i < pnum; i++) + { + points[i]->putScaleUndo(); + + Point3 pIn = points[i]->getProps().relIn, pOut = points[i]->getProps().relOut; + + pIn = tdtm * pIn; + pOut = tdtm * pOut; + + const Point3 pos = points[i]->getPos(); + const Point3 dir = pos - origin; + points[i]->setPos(pos - dir + dtm * dir); + + points[i]->setRelBezierIn(pIn); + points[i]->setRelBezierOut(pOut); + } + + objectWasScaled = true; +} + +struct TmpPointRec +{ + Ptr p; + String blk; + int aIdx; +}; +void SplineObject::reverse() +{ + G_ASSERT(points.size()); + + Tab old(tmpmem); + bool closed = isClosed(); + + old.resize(points.size()); + int a_idx = 0; + for (int i = 0; i < points.size(); i++) + { + old[i].p = points[i]; + if (poly) + old[i].blk = points[i]->getProps().blkGenName.str(); + else + old[i].blk = i == 0 ? props.blkGenName.str() : points[i]->getProps().blkGenName.str(); + if (points[i]->hasSplineClass()) + a_idx = i; + old[i].aIdx = a_idx; + + points[i]->resetSplineClass(); + } + + points[0]->setBlkGenName(NULL); + for (int i = 0; i < (int)points.size() - 1; i++) + { + points[i] = old[points.size() - 1 - i].p; + points[i]->arrId = i; + points[i]->swapHelpers(); + } + + if (closed) + points.back() = points[0]; + else + { + points.back() = old[0].p; + points.back()->arrId = points.size() - 1; + points.back()->swapHelpers(); + points.back()->setBlkGenName(NULL); + } + + a_idx = old.back().aIdx; + if (poly) + points[0]->setBlkGenName(old[a_idx].blk); + else + props.blkGenName = old[a_idx].blk; + + for (int i = 1; i < (int)points.size() - 1; i++) + { + int inv_id = (points.size() - 1) - i - 1; + + if (a_idx == old[inv_id].aIdx) + points[i]->setBlkGenName(NULL); + else + { + a_idx = old[inv_id].aIdx; + points[i]->setBlkGenName(old[a_idx].blk); + } + } + + for (int i = 0; i < points.size(); i++) + markAssetChanged(i); +} + +void SplineObject::onCreated(bool gen) +{ + created = true; + pointChanged(-1); +} + +bool SplineObject::isSelfCross() +{ + // TODO: self crossing + return false; +} + + +void SplineObject::updateFullLoft() { generateLoftSegments(0, points.size() - (poly ? 0 : 1)); } + + +bool SplineObject::pointInsidePoly(const Point2 &p) +{ + if (!poly) + return false; + + int pj, pk = 0; + double wrkx, yu, yl; + + for (pj = 0; pj < points.size(); pj++) + { + Point3 ppj = points[pj]->getPt(); + Point3 ppj1 = points[(pj + 1) % points.size()]->getPt(); + + yu = ppj.z > ppj1.z ? ppj.z : ppj1.z; + yl = ppj.z < ppj1.z ? ppj.z : ppj1.z; + + if (ppj1.z - ppj.z) + wrkx = ppj.x + (ppj1.x - ppj.x) * (p.y - ppj.z) / (ppj1.z - ppj.z); + else + wrkx = ppj.x; + + if (yu >= p.y) + if (yl < p.y) + { + if (p.x > wrkx) + pk++; + if (fabs(p.x - wrkx) < 0.001) + return true; + } + + if ((fabs(p.y - yl) < 0.001) && (fabs(yu - yl) < 0.001) && + (fabs(fabs(wrkx - ppj.x) + fabs(wrkx - ppj1.x) - fabs(ppj.x - ppj1.x)) < 0.001)) + return true; + } + + if (pk % 2) + return true; + else + return false; + + return false; +} + +void SplineObject::updateSpline(int stage) +{ + switch (stage) + { + case STAGE_START: + getSpline(); + updateChangedSegmentsRoadGeom(); + return; + + case STAGE_GEN_POLY: + if (poly) + triangulatePoly(); + return; + + case STAGE_GEN_LOFT: updateChangedSegmentsLoftGeom(); return; + + case STAGE_FINISH: + regenerateObjects(); + regenerateVBuf(); + for (int i = 0; i < points.size(); i++) + points[i]->segChanged = false; + splineChanged = false; + return; + + default: fatal("bad stage: %d"); + } +} + +void SplineObject::onAdd(ObjectEditor *objEditor) +{ + if (name.empty()) + { + String objname((poly ? "Polygon_001" : "Spline_001")); + objEditor->setUniqName(this, objname); + } + + prepareSplineClassInPoints(); + pointChanged(-1); + markModifChangedWhenUsed(); +} + +void SplineObject::onRemove(ObjectEditor *objEditor) +{ + for (int i = 0; i < cablesPool.size(); ++i) + HmapLandPlugin::cableService->removeCable(cablesPool[i]); + + for (int i = 0; i < points.size(); i++) + points[i]->resetSplineClass(); + + del_it(landClass); + pointChanged(-1); + markModifChangedWhenUsed(); + HmapLandPlugin::hmlService->invalidateClipmap(false); +} + +Point3 SplineObject::splineCenter() const +{ + if (!points.size()) + return Point3(0, 0, 0); + + BBox3 box; + for (int i = 0; i < points.size(); i++) + box += points[i]->getPt(); + + BSphere3 sph; + sph = box; + + return sph.c; +} + +Point3 SplineObject::getProjPoint(const Point3 &p, real *proj_t) +{ + real splineLen = bezierSpline.getLength(); + + Tab splinePoly(tmpmem); + for (real t = 0.0; t < splineLen; t += splineLen / RENDER_SPLINE_POINTS) + splinePoly.push_back(bezierSpline.get_pt(t)); + + if (!splinePoly.size()) + return Point3(0, 0, 0); + + Point3 diff = splinePoly[0] - p; + + Point3 ddest = splinePoly[0]; + real ddist = diff.length(); + real dt = 0; + + for (int j = 1; j < splinePoly.size(); j++) + { + Point3 tdiff = splinePoly[j] - p; + if (tdiff.length() < ddist) + { + ddist = tdiff.length(); + ddest = splinePoly[j]; + dt = splineLen / RENDER_SPLINE_POINTS * j; + } + } + + if (proj_t) + *proj_t = dt; + + return ddest; +} + +Point3 SplineObject::getPolyClosingProjPoint(Point3 &p, real *proj_t) +{ + Point3 p1 = points.back()->getPt(); + Point3 p2 = points[0]->getPt(); + + Point3 dest; + real out_t = 0, dist = MAX_REAL; + + real splineLen = bezierSpline.getLength(); + + Point3 ptsDiff = p2 - p1; + real ptsL = ptsDiff.length(); + + for (real t = 0.0; t < ptsL; t += splineLen / RENDER_SPLINE_POINTS) + { + real dt = t / ptsL; + Point3 cur = p1 * (1 - dt) + p2 * dt; + + Point3 pd = cur - p; + if (pd.length() < dist) + { + dist = pd.length(); + dest = cur; + out_t = splineLen + t; + } + } + + if (proj_t) + *proj_t = out_t; + + return dest; +} + +SplinePointObject *SplineObject::getNearestPoint(Point3 &p) +{ + if (!points.size()) + return NULL; + + Point3 diff = points[0]->getPt() - p; + real dist = diff.length(); + int id = 0; + + for (int i = 1; i < points.size(); i++) + { + diff = points[i]->getPt() - p; + real k = diff.length(); + if (k < dist) + { + dist = k; + id = i; + } + } + + return points[id]; +} + +bool SplineObject::lineIntersIgnoreY(Point3 &p1, Point3 &p2) +{ + for (int i = 0; i < (int)points.size() - 1; i++) + { + Point3 pp1 = points[i]->getPt(); + Point3 pp2 = points[i + 1]->getPt(); + + if (lines_inters_ignore_Y(p1, p2, pp1, pp2)) + return true; + } + + return false; +} + +real SplineObject::getTotalLength() +{ + real total = 0; + + if (poly) + { + for (int i = 0; i < points.size(); i++) + { + Point3 p1 = points[i]->getPt(), p2; + if (i == points.size() - 1) + p2 = points[0]->getPt(); + else + p2 = points[i + 1]->getPt(); + + Point3 diff = p2 - p1; + total += diff.length(); + } + } + else + { + getSpline(); + total = bezierSpline.getLength(); + } + + return total; +} + +real SplineObject::getSplineTAtPoint(int id) +{ + real tt = 0; + for (int i = 0; i < id; i++) + tt += bezierSpline.segs[i].len; + + return tt; +} + +bool SplineObject::isDirReversed(Point3 &p1, Point3 &p2) +{ + real t1 = 0, t2 = 1; + getProjPoint(p1, &t1); + getProjPoint(p2, &t2); + + if (t1 > t2) + return true; + + return false; +} + +bool SplineObject::intersects(const BBox2 &r, bool mark_segments) +{ + if (!(BBox2(Point2(splBox[0].x, splBox[0].z), Point2(splBox[1].x, splBox[1].z)) & r)) + return false; + if (poly) + return true; + + + if (mark_segments) + { + bool isect = false; + for (int i = 0; i < segSph.size(); i++) + if (segSph[i] & BBox3(Point3(r[0].x, segSph[i].c.y - segSph[i].r, r[0].y), Point3(r[1].x, segSph[i].c.y + segSph[i].r, r[1].y))) + { + isect = true; + pointChanged(i); + } + return isect; + } + + for (int i = 0; i < segSph.size(); i++) + if (segSph[i] & BBox3(Point3(r[0].x, segSph[i].c.y - segSph[i].r, r[0].y), Point3(r[1].x, segSph[i].c.y + segSph[i].r, r[1].y))) + return true; + return false; +} + +void SplineObject::reApplyModifiers(bool apply_now, bool force) +{ + if (splineInactive) + return; + if (!force && !isAffectingHmap()) + { + modifChanged = false; + return; + } + + BBox3 b = splBox; + float addr = props.modifParams.width + props.modifParams.smooth; + Point3 add(addr, 0, addr); + + b[0] -= add; + b[1] += add; + splBoxPrev += b; + + HmapLandPlugin::self->invalidateFinalBox(splBoxPrev); + + splBoxPrev = splBox; + splBoxPrev[0] -= add; + splBoxPrev[1] += add; + + modifChanged = false; + if (apply_now) + HmapLandPlugin::self->applyHmModifiers(); +} + +void SplineObject::pointChanged(int pt_idx) +{ + if (pt_idx >= 0 && pt_idx + 1 <= points.size()) + { + points[pt_idx]->segChanged = true; + if (points[pt_idx]->isCross) + ((HmapLandObjectEditor *)getObjEditor())->markCrossRoadChanged(points[pt_idx]); + } + else if (pt_idx == -1) + for (int i = 0; i < points.size(); i++) + points[i]->segChanged = true; + splineChanged = true; + if (getObjEditor()) + ((HmapLandObjectEditor *)getObjEditor())->splinesChanged = true; +} +void SplineObject::markModifChanged() +{ + modifChanged = true; + if (getObjEditor()) + ((HmapLandObjectEditor *)getObjEditor())->splinesChanged = true; + DAGORED2->invalidateViewportCache(); +} +void SplineObject::markAssetChanged(int i) +{ + // debug("markAssetChanged: %d", i); + prepareSplineClassInPoints(); + + pointChanged(i); + if (!points[i]->isCross && i > 0) + pointChanged(i - 1); + i++; + + for (; i < points.size(); i++) + { + pointChanged(i); + + if (points[i]->hasSplineClass() && points[i]->getSplineClass()) + break; + } +} + +void SplineObject::updateChangedSegmentsRoadGeom() +{ + splineclass::RoadData *asset_prev = NULL, *asset = NULL; + if (isClosed()) + asset_prev = getRoad(points[points.size() - 2]); + + int start_seg = 0; + asset = getRoad(points[0]); + + // update all segments + for (int i = 1; i < (int)points.size() - 1; i++) + { + splineclass::RoadData *asset_next = getRoad(points[i]); + if (asset_next != asset) + { + generateRoadSegments(start_seg, i, asset_prev, asset, asset_next); + start_seg = i; + asset_prev = asset; + asset = asset_next; + } + } + + generateRoadSegments(start_seg, points.size() - 1, asset_prev, asset, isClosed() ? getRoad(points[0]) : NULL); + + if (!isClosed()) + points.back()->removeRoadGeom(); +} + +void SplineObject::updateChangedSegmentsLoftGeom() +{ + int start_seg = 0; + for (int i = 1; i < (int)points.size() - 1; i++) + { + if (points[i]->getSplineClass() != points[start_seg]->getSplineClass()) + { + for (int j = start_seg; j < i; j++) + if (points[j]->segChanged) + { + generateLoftSegments(start_seg, i); + break; + } + start_seg = i; + } + } + + for (int j = start_seg; j < points.size(); j++) + if (points[j]->segChanged) + { + generateLoftSegments(start_seg, points.size() - (poly ? 0 : 1)); + break; + } + + if (!isClosed() && !poly) + points.back()->removeLoftGeom(); +} + +UndoRedoObject *SplineObject::makePointListUndo() +{ + class UndoPointsListChange : public UndoRedoObject + { + public: + PtrTab pt; + Ptr s; + + UndoPointsListChange(SplineObject *_s) : s(_s), pt(_s->points) {} + + virtual void restore(bool save_redo) + { + PtrTab pt1(s->points); + s->points = pt; + for (int i = pt.size() - 1; i >= 0; i--) + pt[i]->arrId = i; + pt = pt1; + s->pointChanged(-1); + } + + virtual void redo() + { + PtrTab pt1(s->points); + s->points = pt; + for (int i = pt.size() - 1; i >= 0; i--) + pt[i]->arrId = i; + pt = pt1; + s->pointChanged(-1); + } + + virtual size_t size() { return sizeof(*this) + pt.size() * 4; } + virtual void accepted() {} + virtual void get_description(String &s) { s = "UndoSplinePtListChange"; } + }; + + return new (midmem) UndoPointsListChange(this); +} + + +SplineObject *SplineObject::clone() +{ + Ptr obj = new SplineObject(poly); + obj->setEditLayerIdx(EditLayerProps::activeLayerIdx[obj->lpIndex()]); + + getObjEditor()->setUniqName(obj, getName()); + getObjEditor()->addObject(obj); + + for (int i = 0; i < points.size(); i++) + { + Ptr p = new SplinePointObject; + p->arrId = i; + p->spline = obj; + getObjEditor()->addObject(p); + p->setWtm(points[i]->getWtm()); + p->setProps(points[i]->getProps()); + } + obj->props.blkGenName = props.blkGenName; + obj->markAssetChanged(0); + return obj; +} + +void SplineObject::putMoveUndo() +{ + HmapLandObjectEditor *ed = (HmapLandObjectEditor *)getObjEditor(); + if (!ed->isCloneMode()) + __super::putMoveUndo(); +} + +void SplineObject::attachTo(SplineObject *s, int to_idx) +{ + UndoAttachSpline *undoAttach = new UndoAttachSpline(s, this, (HmapLandObjectEditor *)getObjEditor()); + + getObjEditor()->getUndoSystem()->put(points[0]->makePropsUndoObj()); + getObjEditor()->getUndoSystem()->put(points.back()->makePropsUndoObj()); + + getObjEditor()->getUndoSystem()->put(undoAttach); + + if (to_idx == -1) + append_items(s->points, points.size(), points.data()); + else + insert_items(s->points, to_idx, points.size(), points.data()); + + for (int i = 0; i < s->points.size(); i++) + { + s->points[i]->spline = s; + s->points[i]->arrId = i; + } + + if (to_idx == 0) + s->props.blkGenName = props.blkGenName; + + clear_and_shrink(points); + getObjEditor()->removeObject(this); + + s->prepareSplineClassInPoints(); + s->pointChanged(-1); + s->getSpline(); +} + +void SplineObject::makeMonoUp() +{ + float prevPosY = points[0]->getPt().y; + for (int i = 1; i < points.size(); i++) + { + Point3 curPos = points[i]->getPt(); + if (curPos.y < prevPosY) + { + curPos.y = prevPosY; + points[i]->setPos(curPos); + } + else + prevPosY = curPos.y; + } +} +void SplineObject::makeMonoDown() +{ + float prevPosY = points[0]->getPt().y; + for (int i = 1; i < points.size(); i++) + { + Point3 curPos = points[i]->getPt(); + if (curPos.y > prevPosY) + { + curPos.y = prevPosY; + points[i]->setPos(curPos); + } + else + prevPosY = curPos.y; + } +} +void SplineObject::makeLinearHt() +{ + BezierSpline2d s; + getSplineXZ(s); + if (s.leng < 1e-3) + return; + + float h0 = points[0]->getPt().y; + float h1 = points.back()->getPt().y; + + for (int i = 1; i < s.segs.size(); ++i) + points[i]->setPos(Point3::xVz(points[i]->getPt(), lerp(h0, h1, s.segs[i - 1].tlen / s.leng))); +} +void SplineObject::applyCatmull(bool xz, bool y) +{ + if (!xz && !y) + return; + + SplinePointObject *catmul[4]; + BezierSplineInt sp; + Point3 v[4]; + int pn = points.size(); + + for (int i = -1; i < pn - 2; i++) + { + for (int j = 0; j < 4; j++) + catmul[j] = points[(poly || isClosed()) ? (i + j + pn) % pn : clamp(i + j, 0, pn - 1)]; + + for (int j = 0; j < 4; j++) + v[j] = catmul[j]->getPt(); + sp.calculateCatmullRom(v); + sp.calculateBack(v); + + Point3 pi0 = v[0] - v[1], pi1 = v[2] - v[3]; + if (xz && y) + { + catmul[1]->setRelBezierIn(pi0); + catmul[1]->setRelBezierOut(-pi0); + catmul[2]->setRelBezierIn(pi1); + catmul[2]->setRelBezierOut(-pi1); + } + else if (xz) + { + catmul[1]->setRelBezierIn(Point3::xVz(pi0, catmul[1]->getProps().relIn.y)); + catmul[1]->setRelBezierOut(Point3::xVz(-pi0, catmul[1]->getProps().relOut.y)); + catmul[2]->setRelBezierIn(Point3::xVz(pi1, catmul[2]->getProps().relIn.y)); + catmul[2]->setRelBezierOut(Point3::xVz(-pi1, catmul[2]->getProps().relOut.y)); + } + else if (y) + { + catmul[1]->setRelBezierIn(Point3::xVz(catmul[1]->getProps().relIn, pi0.y)); + catmul[1]->setRelBezierOut(Point3::xVz(catmul[1]->getProps().relOut, -pi0.y)); + catmul[2]->setRelBezierIn(Point3::xVz(catmul[2]->getProps().relIn, pi1.y)); + catmul[2]->setRelBezierOut(Point3::xVz(catmul[2]->getProps().relOut, -pi1.y)); + } + } + for (int i = 0; i < points.size(); i++) + { + points[i]->markChanged(); + if (getObjEditor()) + getObjEd().updateCrossRoads(points[i]); + } +} + +static void buildSegment(Tab &out_pts, const BezierSplinePrecInt3d &seg, float seg_len, bool is_end_segment, float min_step, + float max_step, float curvature_strength) +{ + if (min_step < 0.001f) + min_step = 0.001f; + + if (seg_len < min_step) + { + out_pts.push_back(seg.point(0)); + if (is_end_segment) + out_pts.push_back(seg.point(1)); + return; + } + + // calculate spline points + const Point3 endPoint = seg.point(1.f); + const float step = min_step / 10; + + bool curvatureStop = false; + float min_cosn = 1.f - (0.01f / curvature_strength); + + Point3 lastPt = seg.point(0.f); + float lastS = 0; + out_pts.push_back(lastPt); + + for (float s = step; s < seg_len; s += step) + { + const float curT = seg.getTFromS(s); + Point3 current = seg.point(curT); + const Point3 tang = normalize(seg.tang(curT)); + + float targetLength = s - lastS; + + Point3 t2 = normalize(current - lastPt); + + float cosn = tang * t2; + if (cosn < min_cosn) + curvatureStop = 1; + + if (targetLength >= max_step || (curvatureStop && targetLength >= min_step)) + { + out_pts.push_back(current); + lastPt = current; + lastS = s; + + curvatureStop = false; + } + } + + if (is_end_segment) + out_pts.push_back(seg.point(1)); +} + +void SplineObject::getSmoothPoly(Tab &pts) +{ + if (!poly) + return; + if (!props.poly.smooth) + { + pts.reserve(points.size()); + for (int i = 0; i < points.size(); i++) + pts.push_back(points[i]->getPt()); + return; + } + + getSpline(); + const BezierSplinePrec3d &path = ::toPrecSpline(bezierSpline); + + for (int i = 0; i < path.segs.size(); i++) + buildSegment(pts, path.segs[i], path.segs[i].len, false, props.poly.minStep, props.poly.maxStep, props.poly.curvStrength); +} + +struct SplineCrossPtDesc +{ + int splIdx, segIdx; + float locT; + static int cmp(const SplineCrossPtDesc *a, const SplineCrossPtDesc *b) + { + if (a->splIdx != b->splIdx) + return a->splIdx - b->splIdx; + if (a->segIdx != b->segIdx) + return b->segIdx - a->segIdx; + if (a->locT < b->locT) + return 1; + return a->locT > b->locT ? -1 : 0; + } +}; +static void add_when_differs(Tab &cpt, const SplineCrossPtDesc &d) +{ + if (d.locT < 1e-6 || d.locT > 1.f - 1e-5) + return; + for (int i = 0; i < cpt.size(); i++) + if (cpt[i].splIdx == d.splIdx && cpt[i].segIdx == d.segIdx && fabsf(cpt[i].locT - d.locT) < 1e-4) + return; + cpt.push_back(d); +} +static int find_crosses(const Point2 &lp0, const Point2 &cp0, const BezierSplinePrecInt3d &seg1, float step, + Tab &cpt, int _si, int _i, float _lti0, float _lti1, int _sj, int _j) +{ + Point2 resp; + int cnum = 0; + Point2 lp1 = Point2::xz(seg1.point(0.f)), cp1 = lp1; + float lt1 = 0; + for (float s = step, seg_len = seg1.len - step; s <= seg_len; s += step) + { + const float curT1 = seg1.getTFromS(s); + cp1 = Point2::xz(seg1.point(curT1)); + if (get_lines_intersection(lp0, cp0, lp1, cp1, &resp)) + { + SplineCrossPtDesc d0 = {_si, _i, lerp(_lti0, _lti1, ((resp - lp0) * (cp0 - lp0)) / (cp0 - lp0).lengthSq())}; + SplineCrossPtDesc d1 = {_sj, _j, lerp(lt1, curT1, ((resp - lp1) * (cp1 - lp1)) / (cp1 - lp1).lengthSq())}; + cnum++; + add_when_differs(cpt, d0); + add_when_differs(cpt, d1); + } + lp1 = cp1; + lt1 = curT1; + } + cp1 = Point2::xz(seg1.point(1.f)); + if (get_lines_intersection(lp0, cp0, lp1, cp1, &resp)) + { + SplineCrossPtDesc d0 = {_si, _i, lerp(_lti0, _lti1, ((resp - lp0) * (cp0 - lp0)) / (cp0 - lp0).lengthSq())}; + SplineCrossPtDesc d1 = {_sj, _j, lerp(lt1, 1.f, ((resp - lp1) * (cp1 - lp1)) / (cp1 - lp1).lengthSq())}; + cnum++; + add_when_differs(cpt, d0); + add_when_differs(cpt, d1); + } + return cnum; +} + +int SplineObject::makeSplinesCrosses(dag::ConstSpan spls) +{ + Tab cpt; + const float step = 4; + int cnum = 0; + for (int si = 0; si < spls.size(); si++) + spls[si]->getSpline(); + + for (int si = 0; si < spls.size(); si++) + for (int sj = si + 1; sj < spls.size(); sj++) + { + if (!(spls[si]->getSplineBox() & spls[sj]->getSplineBox())) + continue; + for (int i = 0; i < spls[si]->segSph.size(); i++) + for (int j = 0; j < spls[sj]->segSph.size(); j++) + { + if (!(spls[si]->segSph[i] & spls[sj]->segSph[j])) + continue; + + // finally test intersection of spline[si].seg[i] and spline[sj].seg[j] + BezierSplinePrecInt3d seg0 = ::toPrecSpline(spls[si]->bezierSpline).segs[i]; + BezierSplinePrecInt3d seg1 = ::toPrecSpline(spls[sj]->bezierSpline).segs[j]; + + Point3 lp0 = seg0.point(0.f); + float lt0 = 0; + for (float s = step, seg_len = seg0.len - step; s <= seg_len; s += step) + { + const float curT0 = seg0.getTFromS(s); + Point3 cp0 = seg0.point(curT0); + cnum += find_crosses(Point2::xz(lp0), Point2::xz(cp0), seg1, step, cpt, si, i, lt0, curT0, sj, j); + lp0 = cp0; + lt0 = curT0; + } + cnum += find_crosses(Point2::xz(lp0), Point2::xz(seg0.point(1.f)), seg1, step, cpt, si, i, lt0, 1.f, sj, j); + } + } + if (!cpt.size()) + return 0; + + sort(cpt, &SplineCrossPtDesc::cmp); + spls[0]->getObjEditor()->getUndoSystem()->begin(); + Point3 p_pos; + for (int i = 0; i < cpt.size(); i++) + { + float locT = cpt[i].locT; + if (i > 0 && cpt[i - 1].splIdx == cpt[i].splIdx && cpt[i - 1].segIdx == cpt[i].segIdx) + locT /= cpt[i - 1].locT; + spls[cpt[i].splIdx]->refine(cpt[i].segIdx, locT, p_pos); + } + spls[0]->getObjEditor()->getUndoSystem()->accept(String(0, "Make %d crosspoints for %d splines", cnum, spls.size())); + + return cnum; +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSplineObject.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSplineObject.h new file mode 100644 index 000000000..1887330b4 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSplineObject.h @@ -0,0 +1,365 @@ +#ifndef __GAIJIN_HEIGHTMAPLAND_PLUGIN_SPLINE_OBJECT__ +#define __GAIJIN_HEIGHTMAPLAND_PLUGIN_SPLINE_OBJECT__ +#pragma once + + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "common.h" +#include "hmlLayers.h" + +class HeightMapStorage; +class LoftObject; +class DagSpline; +class SplinePointObject; +class HmapLandObjectEditor; +class IObjEntity; +class DebugPrimitivesVbuffer; + +static constexpr unsigned CID_HMapSplineObject = 0xD7BAAB6Au; // SplineObject + + +typedef HierBitMap2d> HmapBitmap; + +namespace objgenerator +{ +class LandClassData; +} +namespace landclass +{ +class AssetData; +} +namespace splineclass +{ +class AssetData; +class RoadData; +} // namespace splineclass + +enum +{ + MODIF_NONE = 0, + MODIF_SPLINE, + MODIF_HMAP, + + LAYER_ORDER_MAX = 16 +}; + +class SplineObject : public RenderableEditableObject +{ +protected: + bool created; + +public: + bool splineInactive = false; + +protected: + ~SplineObject(); + +public: + enum + { + STAGE_START, + STAGE_GEN_POLY, + STAGE_GEN_LOFT, + STAGE_FINISH = 3 + }; + + struct ModifParams + { + real width; + real smooth; + real offsetPow; + Point2 offset; + bool additive; + }; + + struct PolyGeom + { + typedef FaceNGr Triangle; + + PolyGeom(); + ~PolyGeom(); + + void createMeshes(const char *parent_name, SplineObject &spline); + static void recalcLighting(GeomObject *go); + void clear(); + void renderLines(); + + GeomObject *mainMesh, *borderMesh; + Tab centerTri, borderTri; + Tab verts; + + bool altGeom; + float bboxAlignStep; + }; + + SplineObject(bool make_poly); + + virtual void update(real dt) {} + virtual void beforeRender() {} + virtual void render() {} + virtual void renderTrans() {} + virtual bool isSelectedByRectangle(IGenViewportWnd *vp, const EcRect &rect) const; + virtual bool isSelectedByPointClick(IGenViewportWnd *vp, int x, int y) const; + virtual bool getWorldBox(BBox3 &box) const; + virtual void fillProps(PropertyContainerControlBase &op, DClassID for_class_id, dag::ConstSpan objects); + virtual void onPPChange(int pid, bool edit_finished, PropPanel2 &panel, dag::ConstSpan objects); + virtual void onPPBtnPressed(int pid, PropPanel2 &panel, dag::ConstSpan objects); + virtual void moveObject(const Point3 &delta, IEditorCoreEngine::BasisType basis); + virtual void rotateObject(const Point3 &delta, const Point3 &origin, IEditorCoreEngine::BasisType basis); + virtual void scaleObject(const Point3 &delta, const Point3 &origin, IEditorCoreEngine::BasisType basis); + virtual void putMoveUndo(); + virtual void onRemove(ObjectEditor *); + virtual void onAdd(ObjectEditor *objEditor); + virtual Point3 getPos() const { return splineCenter(); } + + EO_IMPLEMENT_RTTI(CID_HMapSplineObject); + + + void getSpline(); + void getSpline(DagSpline &spline); + void getSplineXZ(BezierSpline2d &spline2d); + + void updateRoadBox(); + void updateLoftBox(); + + void getSmoothPoly(Tab &pts); + + void gatherStaticGeometry(StaticGeometryContainer &cont, int flags, bool collision, int layer, int stage); + static void gatherStaticGeom(StaticGeometryContainer &cont, const StaticGeometryContainer &geom, int flags, int id, int name_idx1, + int stage); + static void gatherStaticGeomLayered(StaticGeometryContainer &cont, const StaticGeometryContainer &geom, int flags, int id, + int name_idx1, int layer, int stage); + + void gatherLoftLandPts(Tab &loft_pt_cloud, Tab &water_border_polys, Tab &hmap_sweep_polys); + + void renderLines(bool opaque_pass, const Frustum &frustum); + void regenerateVBuf(); + + void render(DynRenderBuffer *db, const TMatrix4 >m, const Point2 &s, const Frustum &frustum, int &cnt); + + bool getPosOnSpline(IGenViewportWnd *vp, int x, int y, float max_dist, int *out_segid = NULL, float *out_local_t = NULL, + Point3 *out_p = NULL) const; + + void onPointRemove(int id); + void addPoint(SplinePointObject *pt); + + void refine(int seg_id, real loc_t, Point3 &p_pos); + void split(int pt_id); + + void save(DataBlock &blk); + void load(const DataBlock &blk, bool use_undo); + + void regenerateObjects(); + void onCreated(bool gen = true); + void reverse(); + void renderGeom(bool opaque, int layer, const Frustum &); + bool isSelfCross(); + void updateFullLoft(); + BBox3 getGeomBox(); + BBox3 getGeomBoxChanges(); + + void gatherPolyGeomLoftTags(OAHashNameMap &loft_tags); + + real getTotalLength(); + + void putObjTransformUndo(); + + void prepareSplineClassInPoints(); + + void pointChanged(int pt_idx); + void markModifChanged(); + void markModifChangedWhenUsed() + { + if (isAffectingHmap()) + markModifChanged(); + } + void markAssetChanged(int start_pt_idx); + void invalidateSplineCurve() + { + pointChanged(-1); + getSpline(); + } + + void updateSpline(int stage); + void updateChangedSegmentsRoadGeom(); + void updateChangedSegmentsLoftGeom(); + + bool pointInsidePoly(const Point2 &p); + void applyHmapModifier(HeightMapStorage &hm, Point2 hm_ofs, float hm_cell_size, IBBox2 &out_dirty, const IBBox2 &dirty_clip, + HmapBitmap *bmp = NULL); + + Point3 getProjPoint(const Point3 &p, real *proj_t = NULL); + Point3 getPolyClosingProjPoint(Point3 &p, real *proj_t = NULL); + SplinePointObject *getNearestPoint(Point3 &p); + real getSplineTAtPoint(int id); + bool lineIntersIgnoreY(Point3 &p1, Point3 &p2); + + void movePointByNormal(Point3 &p, int id, SplineObject *flatt_spl); + void triangulatePoly(); + bool calcPolyPlane(Point4 &plane); + + void splitOnTwoPolys(int pt1, int pt2); + void buildInnerSpline(Tab &out_pts, float offset, float pts_y, float eps); + + bool isDirReversed(Point3 &p1, Point3 &p2); + + SplineObject *clone(); + + inline bool isClosed() { return points.size() > 2 && points[0].get() == points.back().get(); } + inline bool isPoly() { return poly; } + inline bool isCreated() { return created; } + inline bool isPolyHmapAlign() { return props.poly.hmapAlign; } + inline int getModifType() { return props.modifType; } + inline int getEffModifType() { return poly ? (props.poly.hmapAlign ? MODIF_HMAP : MODIF_NONE) : props.modifType; } + inline BezierSpline3d &getBezierSpline() { return bezierSpline; } + inline const BezierSpline3d &getBezierSpline() const { return bezierSpline; } + inline const char *getBlkGenName() { return props.blkGenName; } + inline real getPolyObjRot() { return props.poly.objRot; } + inline Point2 getPolyObjOffs() { return props.poly.objOffs; } + inline bool isExportable() { return props.exportable; } + inline bool isAffectingHmap() { return isPoly() ? isPolyHmapAlign() : getModifType() == MODIF_HMAP; } + + inline void setPolyHmapAlign(bool a) { props.poly.hmapAlign = a; } + inline void setModifType(int t) { props.modifType = t; } + inline void setBlkGenName(const char *n) { props.blkGenName = n; } + inline void setPolyObjRot(real rot) { props.poly.objRot = rot; } + inline void setPolyObjOffs(Point2 offs) { props.poly.objOffs = offs; } + inline void setExportable(bool ex) { props.exportable = ex; } + inline void setCornerType(int t) { props.cornerType = t; } + inline void setRandomSeed(int seed) { props.rndSeed = seed; } + + void loadModifParams(const DataBlock &blk); + void attachTo(SplineObject *s, int to_idx = -1); + + Point3 splineCenter() const; + bool intersects(const BBox2 &r, bool mark_segments); + const BBox3 &getSplineBox() const { return splBox; } + + void reApplyModifiers(bool apply_now = true, bool force = false); + + bool onAssetChanged(landclass::AssetData *data); + bool onAssetChanged(splineclass::AssetData *data); + UndoRedoObject *makePointListUndo(); + + void resetSplineClass(); + void changeAsset(const char *asset_name, bool put_undo); + const objgenerator::LandClassData *getLandClass() const { return landClass; } + + void makeMonoUp(); + void makeMonoDown(); + void makeLinearHt(); + void applyCatmull(bool xz, bool y); + + void setEditLayerIdx(int idx); + int getEditLayerIdx() const { return editLayerIdx; } + int lpIndex() const { return poly ? EditLayerProps::PLG : EditLayerProps::SPL; }; + + static int makeSplinesCrosses(dag::ConstSpan spls); + + PtrTab points; + PolyGeom polyGeom; + IObjEntity *csgGen; + IBBox2 lastModifArea, lastModifAreaDet; + + Tab cablesPool; + + bool splineChanged; + bool modifChanged; + shaders::OverrideStateId zFuncLessStateId; + +public: + struct Props + { + String blkGenName; + int rndSeed; + int perInstSeed = 0; + + ModifParams modifParams; + short modifType; + bool maySelfCross; + + struct PolyProps + { + Point2 objOffs; + real objRot; + float curvStrength; + float minStep, maxStep; + bool hmapAlign, smooth; + } poly; + + short cornerType; // -1=polyline, 0=smooth 1st deriv., 1=smooth 2nd deriv. + bool exportable; + bool useForNavMesh; + float navMeshStripeWidth; + + String notes; + int layerOrder; + float scaleTcAlong; + }; + const Props &getProps() const { return props; } + const int getLayer() const { return min(LAYER_ORDER_MAX - 1, props.layerOrder); } + + static int polygonSubtypeMask; + static int splineSubtypeMask; + static int tiledByPolygonSubTypeId; + static int splineSubTypeId; + static int roadsSubtypeMask; + + static bool isSplineCacheValid; + +protected: + Props props; + int editLayerIdx = 0; + + void generateRoadSegments(int start_idx, int end_idx, const splineclass::RoadData *asset_prev, splineclass::RoadData *asset, + const splineclass::RoadData *asset_next); + void generateLoftSegments(int start_idx, int end_idx); + + HmapLandObjectEditor &getObjEd() const { return *(HmapLandObjectEditor *)getObjEditor(); } + static HmapLandObjectEditor &getObjEd(ObjectEditor *oe) { return *(HmapLandObjectEditor *)oe; } + + void placeObjectsInsidePolygon(); + + void onLayerOrderChanged(); + + BezierSpline3d bezierSpline; + + Tab segSph; + bool poly; + bool firstApply; + + SplineObject *flattenBySpline; + + BSphere3 splSph; + BBox3 splBox, splBoxPrev; + BBox3 loftBox, roadBox; + BBox3 geomBoxPrev; + float splStep; + + objgenerator::LandClassData *landClass; + + DebugPrimitivesVbuffer *bezierBuf; +}; + +struct SplineObjectRec +{ + SplineObject *s; + Tab p1, p2; + + int k; + + SplineObjectRec() : p1(tmpmem), p2(tmpmem) { k = 0; } +}; + +#endif //__GAIJIN_HEIGHTMAPLAND_PLUGIN_SPLINE_OBJECT__ diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSplinePoint.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSplinePoint.cpp new file mode 100644 index 000000000..dc98388a2 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSplinePoint.cpp @@ -0,0 +1,988 @@ +#include "hmlSplinePoint.h" +#include "hmlSplineObject.h" +#include "hmlPlugin.h" +#include "hmlSplineUndoRedo.h" + +#include +#include +#include <3d/dag_drv3d.h> + +#include +#include + +#include "hmlCm.h" +#include "common.h" +#include + +#include + +#include + +class HmapLandObjectEditor; + + +E3DCOLOR SplinePointObject::norm_col(200, 10, 10), SplinePointObject::norm_col_start_point(10, 10, 200), + SplinePointObject::sel_col(255, 255, 255), SplinePointObject::sel2_col(190, 190, 190), SplinePointObject::hlp_col(10, 200, 10); +TEXTUREID SplinePointObject::texPt = BAD_TEXTUREID; +float SplinePointObject::ptScreenRad = 7.0; +int SplinePointObject::ptRenderPassId = -1; +SplinePointObject::Props *SplinePointObject::defaultProps = NULL; + +enum +{ + PID_USEDEFSET = 1, + PID_GENBLKNAME, + PID_EFFECTIVE_ASSET, + PID_FUSE_POINTS, + PID_LEVEL_TANGENTS, + PID_SCALE_H, + PID_SCALE_W, + PID_OPACITY, + PID_TC3U, + PID_TC3V, + PID_FOLLOW, + PID_ROADBHV, + PID_CORNER_TYPE, + PID_LEVEL_POINTS, +}; + +void SplinePointObject::Props::defaults() +{ + pt = Point3(0, 0, 0); + relIn = Point3(0, 0, 0); + relOut = Point3(0, 0, 0); + useDefSet = true; + attr.scale_h = attr.scale_w = attr.opacity = 1.0f; + attr.tc3u = attr.tc3v = 1.0f; + attr.followOverride = -1; + attr.roadBhvOverride = -1; + cornerType = -2; +} + +void SplinePointObject::initStatics() +{ + if (texPt == BAD_TEXTUREID) + { + texPt = dagRender->addManagedTexture(::make_full_start_path("../commonData/tex/point.tga")); + dagRender->acquireManagedTex(texPt); + } + if (ptRenderPassId == -1) + ptRenderPassId = dagGeom->getShaderVariableId("editor_rhv_tex_pass"); + if (!defaultProps) + { + defaultProps = new Props; + defaultProps->defaults(); + } + SplinePointObject::ptScreenRad = float(hdpi::_pxS(7)); +} + + +SplinePointObject::SplinePointObject() : selObj(SELOBJ_POINT), targetSelObj(SELOBJ_POINT) +{ + objFlags |= FLG_WANTRESELECT; + props = *defaultProps; + props.pt = getPos(); + + arrId = -1; + spline = NULL; + visible = true; + isCross = false; + isRealCross = false; + segChanged = false; + roadGeom = NULL; + roadGeomBox.setempty(); + tmpUpDir = Point3(0, 1, 0); + ppanel_ptr = NULL; +} + +SplinePointObject::~SplinePointObject() { resetSplineClass(); } + +void SplinePointObject::renderPts(DynRenderBuffer &dynBuf, const TMatrix4 >m, const Point2 &s, bool start) +{ + if (!visible) + return; + + E3DCOLOR rendCol = isSelected() ? (selObj == SELOBJ_POINT ? sel_col : sel2_col) : (start ? norm_col_start_point : norm_col); + + renderPoint(dynBuf, toPoint4(props.pt, 1) * gtm, s * ptScreenRad, rendCol); + + if (isSelected() && !spline->isPoly() && spline->getProps().cornerType > -1) + { + renderPoint(dynBuf, toPoint4(props.pt + props.relIn, 1) * gtm, s * ptScreenRad * 0.6, selObj == SELOBJ_IN ? sel_col : hlp_col); + renderPoint(dynBuf, toPoint4(props.pt + props.relOut, 1) * gtm, s * ptScreenRad * 0.6, selObj == SELOBJ_OUT ? sel_col : hlp_col); + } +} +void SplinePointObject::renderPoint(DynRenderBuffer &db, const Point4 &p, const Point2 &s, E3DCOLOR c) +{ + if (p.w > 0.0) + { + Point3 dx(s.x, 0, 0); + Point3 dy(0, s.y, 0); + Point3 p3(p.x / p.w, p.y / p.w, p.z / p.w); + if (p3.z > 0 && p3.z < 1) + dagRender->dynRenderBufferDrawQuad(db, p3 - dx - dy, p3 - dx + dy, p3 + dx + dy, p3 + dx - dy, c, 1, 1); + } +} + +bool SplinePointObject::isSelectedByRectangle(IGenViewportWnd *vp, const EcRect &rect) const +{ + if (spline && EditLayerProps::layerProps[spline->getEditLayerIdx()].hide) + return false; + if (pt_intersects(props.pt, ptScreenRad, rect, vp)) + { + (int &)targetSelObj = SELOBJ_POINT; + return true; + } + + if (isSelected() && spline->getProps().cornerType > -1) + { + if (pt_intersects(props.pt + props.relIn, ptScreenRad * 0.6, rect, vp)) + { + (int &)targetSelObj = SELOBJ_IN; + return true; + } + if (pt_intersects(props.pt + props.relOut, ptScreenRad * 0.6, rect, vp)) + { + (int &)targetSelObj = SELOBJ_OUT; + return true; + } + } + return false; +} +bool SplinePointObject::isSelectedByPointClick(IGenViewportWnd *vp, int x, int y) const +{ + if (spline && EditLayerProps::layerProps[spline->getEditLayerIdx()].hide) + return false; + if (pt_intersects(props.pt, ptScreenRad, x, y, vp)) + { + (int &)targetSelObj = SELOBJ_POINT; + return true; + } + + if (isSelected() && spline->getProps().cornerType > -1) + { + if (pt_intersects(props.pt + props.relIn, ptScreenRad * 0.6, x, y, vp)) + { + (int &)targetSelObj = SELOBJ_IN; + return true; + } + if (pt_intersects(props.pt + props.relOut, ptScreenRad * 0.6, x, y, vp)) + { + (int &)targetSelObj = SELOBJ_OUT; + return true; + } + } + return false; +} +bool SplinePointObject::getWorldBox(BBox3 &box) const +{ + box.setempty(); + box += props.pt - Point3(0.3, 0.3, 0.3); + box += props.pt + Point3(0.3, 0.3, 0.3); + return true; +} + +void SplinePointObject::fillProps(PropertyContainerControlBase &op, DClassID for_class_id, + dag::ConstSpan objects) +{ + ppanel_ptr = &op; + if (!spline) + return; + + bool one_type = true; + int one_layer = -1; + + for (int i = 0; i < objects.size(); ++i) + if (SplinePointObject *o = RTTI_cast(objects[i])) + { + if (!o->spline) + one_layer = -2; + else if (one_layer == -1) + one_layer = o->spline->getEditLayerIdx(); + else if (one_layer != o->spline->getEditLayerIdx()) + one_layer = -2; + } + else + { + one_layer = -2; + one_type = false; + break; + } + + if (one_layer < 0) + op.createStatic(-1, "Edit layer: --multiple selected--"); + else + op.createStatic(-1, String(0, "Edit layer: %s", EditLayerProps::layerProps[one_layer].name())); + + if (one_type) + { + op.createCheckBox(PID_USEDEFSET, "Use default spline settings", props.useDefSet); + + op.createEditFloat(PID_SCALE_H, "Scale Height", props.attr.scale_h); + op.createEditFloat(PID_SCALE_W, "Scale Width", props.attr.scale_w); + op.createTrackFloat(PID_OPACITY, "Opacity", props.attr.opacity, 0.0f, 1.0f, 0.01f); + op.createEditFloat(PID_TC3U, "TC3.u", props.attr.tc3u); + op.createEditFloat(PID_TC3V, "TC3.v", props.attr.tc3v); + + op.setMinMaxStep(PID_SCALE_H, 0.0f, 1e6f, 0.01f); + op.setMinMaxStep(PID_SCALE_W, 0.0f, 1e6f, 0.01f); + op.setMinMaxStep(PID_OPACITY, 0.0f, 1.0f, 0.01f); + + { + op.createIndent(); + + PropertyContainerControlBase &followGrp = *op.createRadioGroup(PID_FOLLOW, "Follow type override"); + followGrp.createRadio(-1, "Default (as in asset)"); + followGrp.createRadio(0, "No follow"); + followGrp.createRadio(1, "Follow hills"); + followGrp.createRadio(2, "Follow hollows"); + followGrp.createRadio(3, "Follow landscape"); + op.setInt(PID_FOLLOW, props.attr.followOverride); + + PropertyContainerControlBase &roadGrp = *op.createRadioGroup(PID_ROADBHV, "Road behavior override"); + roadGrp.createRadio(-1, "Default (as in asset)"); + roadGrp.createRadio(0, "Not a road"); + roadGrp.createRadio(1, "Follow as road"); + op.setInt(PID_ROADBHV, props.attr.roadBhvOverride); + + op.createIndent(); + op.createStatic(-1, "Spline class asset"); + op.createButton(PID_GENBLKNAME, ::dd_get_fname(props.blkGenName), !props.useDefSet); + + if (props.useDefSet) + { + op.createStatic(-1, "Effective spline class asset"); + op.createButton(PID_EFFECTIVE_ASSET, ::dd_get_fname(getEffectiveAsset())); + } + else + { + op.createStatic(-1, "Previous spline class asset"); + op.createButton(PID_EFFECTIVE_ASSET, ::dd_get_fname(getEffectiveAsset(-1))); + } + } + + op.createSeparator(0); + PropertyContainerControlBase &cornerGrp = *op.createRadioGroup(PID_CORNER_TYPE, "Corner type"); + cornerGrp.createRadio(-2, "As spline (default)"); + cornerGrp.createRadio(-1, "Corner"); + cornerGrp.createRadio(0, "Smooth tangent"); + cornerGrp.createRadio(1, "Smooth curvature"); + op.setInt(PID_CORNER_TYPE, props.cornerType); + + op.createSeparator(0); + op.createButton(PID_LEVEL_TANGENTS, String(64, "Level tangents (%d points)", objects.size())); + if (objects.size() > 1) + { + op.createButton(PID_LEVEL_POINTS, String(64, "Level %d points (set average .y)", objects.size())); + op.createButton(PID_FUSE_POINTS, String(64, "Fuse %d points", objects.size())); + } + } + + int eff_disp = props.useDefSet ? 0 : -1; + for (int i = 0; i < objects.size(); ++i) + { + SplinePointObject *o = RTTI_cast(objects[i]); + if (!o) + continue; + + if (o->props.useDefSet != props.useDefSet) + op.resetById(PID_USEDEFSET); + if (stricmp(o->props.blkGenName, props.blkGenName)) + op.setCaption(PID_GENBLKNAME, ""); + + if (o->props.useDefSet == props.useDefSet) + if (stricmp(o->getEffectiveAsset(eff_disp), getEffectiveAsset(eff_disp))) + op.setCaption(PID_EFFECTIVE_ASSET, ""); + + if (o->props.cornerType != props.cornerType) + op.resetById(PID_CORNER_TYPE); + } +} + +void SplinePointObject::onPPChange(int pid, bool edit_finished, PropPanel2 &panel, dag::ConstSpan objects) +{ + if (!edit_finished) + return; + + if (pid == PID_USEDEFSET) + { + bool val = panel.getBool(pid); + for (int i = 0; i < objects.size(); ++i) + { + SplinePointObject *o = RTTI_cast(objects[i]); + if (!o || o->props.useDefSet == val) + continue; + getObjEditor()->getUndoSystem()->put(new UndoChangeAsset(o->spline, o->arrId)); + + o->props.useDefSet = val; + o->resetSplineClass(); + if (o->spline) + o->spline->markAssetChanged(o->arrId); + + if (o->props.useDefSet) + if (ISplineGenObj *gen = o->getSplineGen()) + gen->clearLoftGeom(); + } + getObjEditor()->invalidateObjectProps(); + } + + if ((pid == PID_SCALE_H) || (pid == PID_SCALE_W) || (pid == PID_OPACITY) || (pid == PID_TC3U) || (pid == PID_TC3V)) + { + float val = panel.getFloat(pid); + for (int i = 0; i < objects.size(); ++i) + { + SplinePointObject *o = RTTI_cast(objects[i]); + if (!o) + continue; + + getObjEditor()->getUndoSystem()->put(new UndoPropsChange(o)); + if (pid == PID_SCALE_H) + o->props.attr.scale_h = val; + if (pid == PID_SCALE_W) + o->props.attr.scale_w = val; + if (pid == PID_OPACITY) + o->props.attr.opacity = val; + if (pid == PID_TC3U) + o->props.attr.tc3u = val; + if (pid == PID_TC3V) + o->props.attr.tc3v = val; + if (o->spline) + o->markChanged(); + } + } + if (pid == PID_FOLLOW) + { + int val = panel.getInt(pid); + for (int i = 0; i < objects.size(); ++i) + { + SplinePointObject *o = RTTI_cast(objects[i]); + if (!o) + continue; + + getObjEditor()->getUndoSystem()->put(new UndoPropsChange(o)); + o->props.attr.followOverride = val; + if (o->spline) + o->markChanged(); + } + } + if (pid == PID_ROADBHV) + { + int val = panel.getInt(pid); + for (int i = 0; i < objects.size(); ++i) + { + SplinePointObject *o = RTTI_cast(objects[i]); + if (!o) + continue; + + getObjEditor()->getUndoSystem()->put(new UndoPropsChange(o)); + o->props.attr.roadBhvOverride = val; + if (o->spline) + o->markChanged(); + } + } + if (pid == PID_CORNER_TYPE) + { + int val = panel.getInt(pid); + for (int i = 0; i < objects.size(); ++i) + { + SplinePointObject *o = RTTI_cast(objects[i]); + if (!o) + continue; + + getObjEditor()->getUndoSystem()->put(new UndoPropsChange(o)); + o->props.cornerType = val; + if (o->spline) + { + o->markChanged(); + o->spline->invalidateSplineCurve(); + } + } + } +} +void SplinePointObject::onPPBtnPressed(int pid, PropPanel2 &panel, dag::ConstSpan objects) +{ + if (pid == PID_GENBLKNAME || pid == PID_EFFECTIVE_ASSET) + { + if (!spline) + return; + + int eff_disp = (pid == PID_GENBLKNAME || props.useDefSet) ? 0 : -1; + const char *asset_name = getEffectiveAsset(eff_disp); + + asset_name = DAEDITOR3.selectAssetX(asset_name, "Select splineclass", "spline"); + + for (int i = 0; i < objects.size(); i++) + { + SplinePointObject *o = RTTI_cast(objects[i]); + if (!o || o->props.useDefSet != props.useDefSet) + continue; + o->setEffectiveAsset(asset_name, true, eff_disp); + } + panel.setText(pid, asset_name); + IEditorCoreEngine::get()->invalidateViewportCache(); + } + else if (pid == PID_FUSE_POINTS || pid == PID_LEVEL_POINTS) + { + Point3 newPos(0, 0, 0); + int pointsCount = 0; + for (int i = 0; i < objects.size(); ++i) + { + SplinePointObject *o = RTTI_cast(objects[i]); + G_ASSERT(o && "Select not only spline points"); + + newPos += o->getPt(); + pointsCount++; + } + + G_ASSERT(pointsCount && "Select 0 points"); + newPos = Point3(newPos.x / pointsCount, newPos.y / pointsCount, newPos.z / pointsCount); + for (int i = 0; i < objects.size(); ++i) + { + SplinePointObject *o = RTTI_cast(objects[i]); + + if (o->spline) + { + o->putMoveUndo(); + o->spline->putObjTransformUndo(); + } + + if (pid == PID_FUSE_POINTS) + o->setPos(newPos); + else if (pid == PID_LEVEL_POINTS) + o->setPos(Point3::xVz(o->getPt(), newPos.y)); + } + IEditorCoreEngine::get()->invalidateViewportCache(); + } + else if (pid == PID_LEVEL_TANGENTS) + { + for (int i = 0; i < objects.size(); ++i) + { + SplinePointObject *o = RTTI_cast(objects[i]); + + getObjEditor()->getUndoSystem()->put(new UndoPropsChange(o)); + if (o->spline) + o->spline->putObjTransformUndo(); + + o->props.relIn.y = o->props.relOut.y = 0; + + o->markChanged(); + if (o->spline) + o->spline->getSpline(); + getObjEd().updateCrossRoads(o); + } + IEditorCoreEngine::get()->invalidateViewportCache(); + } +} + +void SplinePointObject::onPPClose(PropertyContainerControlBase &panel, dag::ConstSpan objects) +{ + ppanel_ptr = NULL; +} + +void SplinePointObject::saveProps(const SplinePointObject::Props &props, DataBlock &blk, bool bh) +{ + blk.setBool("useDefSplineGen", props.useDefSet); + blk.setStr("blkGenName", props.blkGenName); + blk.setPoint3("pt", props.pt); + if (fabs(props.attr.scale_h - 1.0f) > 1e-6f) + blk.setReal("scale_h", props.attr.scale_h); + if (fabs(props.attr.scale_w - 1.0f) > 1e-6f) + blk.setReal("scale_w", props.attr.scale_w); + if (fabs(props.attr.opacity - 1.0f) > 1e-6f) + blk.setReal("opacity", props.attr.opacity); + if (fabs(props.attr.tc3u - 1.0f) > 1e-6f) + blk.setReal("tc3u", props.attr.tc3u); + if (fabs(props.attr.tc3v - 1.0f) > 1e-6f) + blk.setReal("tc3v", props.attr.tc3v); + if (props.attr.followOverride != -1) + blk.setInt("followOverride", props.attr.followOverride); + if (props.attr.roadBhvOverride != -1) + blk.setInt("roadBhvOverride", props.attr.roadBhvOverride); + if (bh) + { + blk.setPoint3("in", props.relIn); + blk.setPoint3("out", props.relOut); + } + if (props.cornerType != -2) + blk.setInt("cornerType", props.cornerType); +} +void SplinePointObject::loadProps(SplinePointObject::Props &props, const DataBlock &blk) +{ + props.useDefSet = blk.getBool("useDefSplineGen", props.useDefSet); + props.blkGenName = blk.getStr("blkGenName", props.blkGenName); + + props.pt = blk.getPoint3("pt", props.pt); + props.relIn = blk.getPoint3("in", Point3(0, 0, 0)); + props.relOut = blk.getPoint3("out", Point3(0, 0, 0)); + props.attr.scale_h = blk.getReal("scale_h", 1.0f); + props.attr.scale_w = blk.getReal("scale_w", 1.0f); + props.attr.opacity = blk.getReal("opacity", 1.0f); + props.attr.tc3u = blk.getReal("tc3u", 1.0f); + props.attr.tc3v = blk.getReal("tc3v", 1.0f); + props.attr.followOverride = blk.getInt("followOverride", -1); + props.attr.roadBhvOverride = blk.getInt("roadBhvOverride", -1); + props.cornerType = blk.getInt("cornerType", -2); +} +void SplinePointObject::save(DataBlock &blk) { saveProps(props, blk, !spline->isPoly()); } +void SplinePointObject::load(const DataBlock &blk) +{ + loadProps(props, blk); + matrix.setcol(3, props.pt); +} + +Point3 SplinePointObject::getPtEffRelBezierIn() const +{ + int t = spline->getProps().cornerType; + if (props.cornerType != -2) + t = props.cornerType; + if (t >= 0) + return t == 0 ? props.relIn : (props.relIn - props.relOut) * 0.5f; + + int pn = spline->points.size(); + if (pn < 2) + return Point3(0, 0, 0); + if (arrId > 0) + return normalize(spline->points[arrId - 1]->props.pt - props.pt) * 0.05; + return normalize(props.pt - spline->points[arrId + 1]->props.pt) * 0.05; +} +Point3 SplinePointObject::getPtEffRelBezierOut() const +{ + int t = spline->getProps().cornerType; + if (props.cornerType != -2) + t = props.cornerType; + if (t >= 0) + return t == 0 ? props.relOut : (props.relOut - props.relIn) * 0.5f; + + int pn = spline->points.size(); + if (pn < 2) + return Point3(0, 0, 0); + if (arrId + 1 < pn) + return normalize(spline->points[arrId + 1]->props.pt - props.pt) * 0.05; + return normalize(props.pt - spline->points[arrId - 1]->props.pt) * 0.05; +} + +void SplinePointObject::setWtm(const TMatrix &wtm) +{ + __super::setWtm(wtm); + + if (selObj == SELOBJ_POINT) + props.pt = getPos(); + else if (selObj == SELOBJ_IN) + { + props.relIn = getPos() - props.pt; + props.relOut = -length(props.relOut) * normalize(props.relIn); + } + else if (selObj == SELOBJ_OUT) + { + props.relOut = getPos() - props.pt; + props.relIn = -length(props.relIn) * normalize(props.relOut); + } +} + +void SplinePointObject::onAdd(ObjectEditor *objEditor) +{ + if (spline) + spline->addPoint(this); + + getObjEd(objEditor).updateCrossRoadsOnPointAdd(this); + if (getObjEditor()) + getObjEd(objEditor).updateCrossRoads(this); +} + +void SplinePointObject::onRemove(ObjectEditor *objEditor) +{ + resetSplineClass(); + getObjEd(objEditor).updateCrossRoadsOnPointRemove(this); + + if (spline) + spline->onPointRemove(arrId); +} + + +void SplinePointObject::selectObject(bool select) +{ + __super::selectObject(select); + + if (select && selObj != targetSelObj) + { + selObj = targetSelObj; + if (selObj == SELOBJ_POINT) + matrix.setcol(3, props.pt); + else if (selObj == SELOBJ_IN) + matrix.setcol(3, props.relIn + props.pt); + else if (selObj == SELOBJ_OUT) + matrix.setcol(3, props.relOut + props.pt); + if (objEditor) + { + objEditor->onObjectGeomChange(this); + objEditor->updateGizmo(); + } + targetSelObj = SELOBJ_POINT; + } + + if (!select && selObj != SELOBJ_POINT) + { + targetSelObj = selObj = SELOBJ_POINT; + matrix.setcol(3, props.pt); + } +} + +Point3 SplinePointObject::getUpDir() const { return Point3(0, 1, 0); } + +int SplinePointObject::linkCount() +{ + if (arrId < 0 || arrId > spline->points.size() - 1) + return -1; + else if (arrId == 0 || arrId == spline->points.size() - 1) + return 1; + else + return 2; +} + +SplinePointObject *SplinePointObject::getLinkedPt(int id) +{ + if (arrId < 0 || arrId >= spline->points.size()) + return NULL; + + if (id == 0) + { + if (arrId == 0) + return NULL; + else + return spline->points[arrId - 1]; + } + else if (id == 1) + { + if (arrId == spline->points.size() - 1) + return NULL; + else + return spline->points[arrId + 1]; + } + return NULL; +} + +void SplinePointObject::moveObject(const Point3 &delta, IEditorCoreEngine::BasisType basis) +{ + __super::putMoveUndo(); + if (spline) + spline->putObjTransformUndo(); + __super::moveObject(delta, basis); + + objectWasMoved = true; + + if (wingw::is_key_pressed(wingw::V_CONTROL)) + { + IGenViewportWnd *wnd = DAGORED2->getCurrentViewport(); + HmapLandObjectEditor *ed = (HmapLandObjectEditor *)getObjEditor(); + + bool is = false; + for (int i = 0; i < ed->splinesCount(); i++) + { + for (int j = 0; j < ed->getSpline(i)->points.size(); j++) + { + if (this == ed->getSpline(i)->points[j]) + continue; + + real ddist = ed->screenDistBetweenPoints(wnd, this, ed->getSpline(i)->points[j]); + if (ddist <= 16 && ddist > 0) + { + setPos(ed->getSpline(i)->points[j]->getPos()); + is = true; + break; + } + } + if (is) + break; + } + } + + if (spline) + markChanged(); +} + +void SplinePointObject::scaleObject(const Point3 &delta, const Point3 &origin, IEditorCoreEngine::BasisType basis) +{ + static float old_h = props.attr.scale_h; + static float old_w = props.attr.scale_w; + + props.attr.scale_h += delta.y - 1.0f; + + if (fabs(delta.x - 1.0f) > 0.01f) + props.attr.scale_w += delta.x - 1.0f; + else + props.attr.scale_w += delta.z - 1.0f; + + if (((old_h != props.attr.scale_h) || (old_w != props.attr.scale_w)) && (ppanel_ptr)) + { + ppanel_ptr->setFloat(PID_SCALE_H, props.attr.scale_h); + ppanel_ptr->setFloat(PID_SCALE_W, props.attr.scale_w); + } + + old_h = props.attr.scale_h; + old_w = props.attr.scale_w; +} + +bool SplinePointObject::setPos(const Point3 &p) +{ + bool ret = __super::setPos(p); + + if (spline) + spline->getSpline(); + + markChanged(); + if (getObjEditor()) + getObjEd().updateCrossRoads(this); + + return ret; +} + + +void SplinePointObject::putMoveUndo() +{ + __super::putMoveUndo(); + getObjEditor()->getUndoSystem()->put(makePropsUndoObj()); + if (spline) + spline->putObjTransformUndo(); +} + + +void SplinePointObject::putRotateUndo() +{ + __super::putRotateUndo(); + getObjEditor()->getUndoSystem()->put(makePropsUndoObj()); +} + + +void SplinePointObject::putScaleUndo() +{ + __super::putScaleUndo(); + getObjEditor()->getUndoSystem()->put(makePropsUndoObj()); +} + + +void SplinePointObject::swapHelpers() +{ + Point3 p = props.relIn; + setRelBezierIn(props.relOut); + setRelBezierOut(p); +} + +BBox3 SplinePointObject::getGeomBox(bool render_loft, bool render_road) +{ + BBox3 worldBox; + worldBox.setempty(); + if (render_loft) + if (ISplineGenObj *gen = getSplineGen()) + worldBox += gen->loftGeomBox; + if (render_road) + worldBox += roadGeomBox; + return worldBox; +} + +void SplinePointObject::renderRoadGeom(bool opaque) +{ + if (roadGeom) + opaque ? dagGeom->geomObjectRender(*roadGeom) : dagGeom->geomObjectRenderTrans(*roadGeom); +} + +void SplinePointObject::resetSplineClass() +{ + clearSegment(); + destroy_it(splineGenObj); + effSplineClass = nullptr; +} +splineclass::AssetData *SplinePointObject::prepareSplineClass(const char *def_blk_name, splineclass::AssetData *prev) +{ + if (hasSplineClass()) + def_blk_name = props.blkGenName; + + if (def_blk_name && def_blk_name[0]) + importGenerationParams(def_blk_name); + else if (hasSplineClass()) + resetSplineClass(); + else + { + resetSplineClass(); + effSplineClass = prev; + } + + return effSplineClass; +} +void SplinePointObject::importGenerationParams(const char *blkname) +{ + effSplineClass = nullptr; + if (!blkname || !*blkname) + { + resetSplineClass(); + return; + } + + static int spline_atype = DAEDITOR3.getAssetTypeId("spline"); + if (!splineGenObj) + if (DagorAsset *a = DAEDITOR3.getAssetByName(blkname, spline_atype)) + splineGenObj = DAEDITOR3.createEntity(*a); + ISplineGenObj *gen = getSplineGen(); + if (!gen) + return; + + IAssetService *srv = DAGORED2->queryEditorInterface(); + splineclass::AssetData *a = srv ? srv->getSplineClassData(blkname) : NULL; + + gen->splineLayer = spline->getLayer(); + setEditLayerIdx(spline->getEditLayerIdx()); + if (gen->splineClass != a) + { + if (srv) + srv->releaseSplineClassData(gen->splineClass); + gen->splineClass = a; + clearSegment(); + } + else if (srv && a) + srv->releaseSplineClassData(a); + + effSplineClass = gen->splineClass; +} +void SplinePointObject::clearSegment() +{ + if (ISplineGenObj *gen = getSplineGen()) + gen->clear(); + removeRoadGeom(); +} + +void SplinePointObject::removeRoadGeom() +{ + dagGeom->deleteGeomObject(roadGeom); + updateRoadBox(); +} + +void SplinePointObject::updateRoadBox() +{ + if (roadGeom) + roadGeomBox = dagGeom->geomObjectGetBoundBox(*roadGeom); + else + roadGeomBox.setempty(); + if (spline) + spline->updateRoadBox(); +} + +GeomObject &SplinePointObject::getClearedRoadGeom() +{ + removeRoadGeom(); + if (!roadGeom) + return *(roadGeom = dagGeom->newGeomObject(midmem)); + dagGeom->geomObjectClear(*roadGeom); + return *roadGeom; +} + +void SplinePointObject::removeLoftGeom() +{ + if (ISplineGenObj *gen = getSplineGen()) + { + gen->clearLoftGeom(); + if (spline) + spline->updateLoftBox(); + } +} + +void SplinePointObject::markChanged() +{ + segChanged = true; + if (spline) + { + if (spline->points.size()) // spline->points.size() may be 0 when spline is being removed + { + if (arrId > 0) + spline->points[arrId - 1]->segChanged = true; + if (arrId + 1 < spline->points.size()) + spline->points[arrId + 1]->segChanged = true; + } + spline->splineChanged = true; + } + if (getObjEditor()) + getObjEd().splinesChanged = true; +} + +void SplinePointObject::pointChanged() +{ + if (spline) + spline->pointChanged(-1); +} + +const char *SplinePointObject::getEffectiveAsset(int ofs) const +{ + if (!spline) + return ""; + + for (int i = arrId + ofs; i >= 0; i--) + if (spline->points[i]->hasSplineClass()) + return spline->points[i]->props.blkGenName; + return !spline->isPoly() ? spline->getProps().blkGenName.str() : ""; +} + +void SplinePointObject::setEffectiveAsset(const char *asset_name, bool _undo, int ofs) +{ + if (!spline) + return; + + for (int i = arrId + ofs; i >= 0; i--) + if (spline->points[i]->hasSplineClass()) + { + SplinePointObject *o = spline->points[i]; + if (_undo) + getObjEditor()->getUndoSystem()->put(new UndoChangeAsset(o->spline, o->arrId)); + + o->props.blkGenName = asset_name; + if (!asset_name) + o->props.useDefSet = false; + o->resetSplineClass(); + o->spline->markAssetChanged(o->arrId); + return; + } + + if (!spline->isPoly()) + spline->changeAsset(asset_name, _undo); + else + { + SplinePointObject *o = spline->points[0]; + if (_undo) + getObjEditor()->getUndoSystem()->put(new UndoChangeAsset(o->spline, o->arrId)); + + o->props.blkGenName = asset_name; + if (!asset_name) + o->props.useDefSet = false; + o->resetSplineClass(); + o->spline->markAssetChanged(o->arrId); + } +} + +void SplinePointObject::FlattenY() +{ + props.relIn.y = 0; + props.relOut.y = 0; +} + +void SplinePointObject::FlattenAverage(float mul) +{ + props.relIn.y *= mul; + props.relOut.y *= mul; +} + +void SplinePointObject::UndoPropsChange::restore(bool save_redo) +{ + if (save_redo) + redoProps = obj->props; + obj->props = oldProps; + obj->pointChanged(); + if (obj->spline) + obj->spline->invalidateSplineCurve(); + obj->getObjEd().invalidateObjectProps(); +} + +void SplinePointObject::UndoPropsChange::redo() +{ + obj->props = redoProps; + obj->pointChanged(); + if (obj->spline) + obj->spline->invalidateSplineCurve(); + obj->getObjEd().invalidateObjectProps(); +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSplinePoint.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSplinePoint.h new file mode 100644 index 000000000..2294c9af3 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSplinePoint.h @@ -0,0 +1,262 @@ +// Copyright 2023 by Gaijin Games KFT, All rights reserved. +#ifndef _DE2_PLUGIN_ROADS_SPLINEOBJECTS_H_ +#define _DE2_PLUGIN_ROADS_SPLINEOBJECTS_H_ +#pragma once + +#include +#include +#include +#include <3d/dag_texMgr.h> +#include + +#include +#include +#include +#include + +#include + +class ObjLibMaterialListMgr; +class DynRenderBuffer; +class TMatrix4; +class Point2; +class Point4; +class SplineObject; +class LoftObject; +class HmapLandObjectEditor; + +class PropertyContainerControlBase; + +class GeomObject; + +static inline Point4 toPoint4(const Point3 &p, real w) { return Point4(p.x, p.y, p.z, w); } + +static bool pt_intersects(const Point3 &p, float rad, int x, int y, IGenViewportWnd *vp) +{ + BBox2 ptBox; + Point2 pt; + + if (!vp->worldToClient(p, pt)) + return false; + ptBox[0] = pt - Point2(rad, rad); + ptBox[1] = pt + Point2(rad, rad); + return ptBox & Point2(x, y); +} + +static bool pt_intersects(const Point3 &p, float rad, const EcRect &rect, IGenViewportWnd *vp) +{ + BBox2 ptBox; + BBox2 rectBox; + Point2 pt; + + if (!vp->worldToClient(p, pt)) + return false; + ptBox[0] = pt - Point2(rad, rad); + ptBox[1] = pt + Point2(rad, rad); + + rectBox[0].x = rect.l; + rectBox[1].x = rect.r; + rectBox[0].y = rect.t; + rectBox[1].y = rect.b; + + return ptBox & rectBox; +} + +class SplinePointObject; + +static constexpr unsigned CID_SplinePointObject = 0x48839E05u; // SplinePointObject + +// +// Spline point +// +class SplinePointObject : public RenderableEditableObject +{ +protected: + ~SplinePointObject(); + +public: + SplinePointObject(); + + virtual void update(float) {} + virtual void beforeRender() {} + virtual void render() {} + virtual void renderTrans() {} + void renderPts(DynRenderBuffer &dynBuf, const TMatrix4 >m, const Point2 &s, bool start = false); + + virtual bool isSelectedByRectangle(IGenViewportWnd *vp, const EcRect &rect) const; + virtual bool isSelectedByPointClick(IGenViewportWnd *vp, int x, int y) const; + virtual bool getWorldBox(BBox3 &box) const; + + virtual void fillProps(PropertyContainerControlBase &op, DClassID for_class_id, dag::ConstSpan objects); + virtual void onPPChange(int pid, bool edit_finished, PropPanel2 &panel, dag::ConstSpan objects); + virtual void onPPBtnPressed(int pid, PropPanel2 &panel, dag::ConstSpan objects); + virtual void onPPClose(PropertyContainerControlBase &panel, dag::ConstSpan objects); + + // restrict rotate/scale transformations to BASIS_Local/selCenter + + virtual void moveObject(const Point3 &delta, IEditorCoreEngine::BasisType basis); + virtual void rotateObject(const Point3 &delta, const Point3 &origin, IEditorCoreEngine::BasisType basis) {} + virtual void scaleObject(const Point3 &delta, const Point3 &origin, IEditorCoreEngine::BasisType basis); + virtual void putMoveUndo(); + virtual void putRotateUndo(); + virtual void putScaleUndo(); + + virtual void save(DataBlock &blk); + virtual void load(const DataBlock &blk); + + virtual bool mayRename() { return false; } + virtual bool mayDelete() { return true; } + virtual void setWtm(const TMatrix &wtm); + + virtual void onRemove(ObjectEditor *); + virtual void onAdd(ObjectEditor *objEditor); + + virtual void selectObject(bool select = true); + + virtual bool setPos(const Point3 &p); + + EO_IMPLEMENT_RTTI(CID_SplinePointObject) + + Point3 getPt() const { return props.pt; } + Point3 getBezierIn() const { return props.pt + getPtEffRelBezierIn(); } + Point3 getBezierOut() const { return props.pt + getPtEffRelBezierOut(); } + Point3 getUpDir() const; + float getRoadHalfWidth() const { return 0; } + + void setRelBezierIn(const Point3 &p) { props.relIn = p; } + void setRelBezierOut(const Point3 &p) { props.relOut = p; } + + Point3 getPtEffRelBezierIn() const; + Point3 getPtEffRelBezierOut() const; + + void FlattenY(); + void FlattenAverage(float mul); + + void pointChanged(); + void swapHelpers(); + + int linkCount(); + SplinePointObject *getLinkedPt(int id); + + UndoRedoObject *makePropsUndoObj() { return new UndoPropsChange(this); } + +public: + struct Props + { + SimpleString blkGenName; + Point3 pt, relIn, relOut; + bool useDefSet; + short cornerType; // -2=def as spline, -1=polyline, 0=smooth 1st deriv., 1=smooth 2nd deriv. + splineclass::Attr attr; + + void defaults(); + }; + + static void renderPoint(DynRenderBuffer &db, const Point4 &p, const Point2 &s, E3DCOLOR c); + static void saveProps(const Props &p, DataBlock &blk, bool bezier_helpers); + static void loadProps(Props &p, const DataBlock &blk); + + static void initStatics(); + + BBox3 getGeomBox(bool render_loft, bool render_road); + void renderRoadGeom(bool opaque); + + void setBlkGenName(const char *name) + { + props.blkGenName = name; + props.useDefSet = (name == NULL); + } + + splineclass::AssetData *prepareSplineClass(const char *def_name, splineclass::AssetData *prev); + void resetSplineClass(); + void clearSegment(); + + bool hasSplineClass() const { return !props.useDefSet; } + const splineclass::AssetData *getSplineClass() const { return effSplineClass; } + ISplineGenObj *getSplineGen() { return splineGenObj ? splineGenObj->queryInterface() : nullptr; } + void setEditLayerIdx(int idx) { splineGenObj ? splineGenObj->setEditLayerIdx(idx) : (void)0; } + + const char *getEffectiveAsset(int ofs = 0) const; + void setEffectiveAsset(const char *asset_name, bool put_undo, int ofs = 0); + + void deleteUnusedPoolsEntities(); + void resetUsedPoolsEntities(); + + GeomObject *getRoadGeom() { return roadGeom; } + + GeomObject &getClearedRoadGeom(); + void removeRoadGeom(); + void updateRoadBox(); + + void removeLoftGeom(); + + void markChanged(); + const Props &getProps() const { return props; } + void setProps(const Props &p) { props = p; } + + bool getAltLocalDir(Point3 &out_dir) const + { + switch (selObj) + { + case SELOBJ_IN: out_dir = normalize(props.relIn); return true; + case SELOBJ_OUT: out_dir = normalize(props.relOut); return true; + } + return false; + } + + + short int arrId; + unsigned short visible : 1, segChanged : 1; + // real cross (mean, not road joint and not mere spline/road cross) must be checked together with isCross + unsigned short isCross : 1, isRealCross : 1; + SplineObject *spline; + Point3 tmpUpDir; //< computed when generating straight segments, used when generating cross roads + + static E3DCOLOR norm_col, sel_col, sel2_col, hlp_col, norm_col_start_point; + static TEXTUREID texPt; + static float ptScreenRad; + static int ptRenderPassId; + + static Props *defaultProps; + +protected: + Props props; + + splineclass::AssetData *effSplineClass = nullptr; + IObjEntity *splineGenObj = nullptr; + GeomObject *roadGeom; + BBox3 roadGeomBox; + + enum + { + SELOBJ_IN = -1, + SELOBJ_POINT = 0, + SELOBJ_OUT = 1 + }; + int selObj, targetSelObj; + + PropertyContainerControlBase *ppanel_ptr; + + class UndoPropsChange : public UndoRedoObject + { + Ptr obj; + SplinePointObject::Props oldProps, redoProps; + + public: + UndoPropsChange(SplinePointObject *o) : obj(o) { oldProps = redoProps = obj->props; } + + virtual void restore(bool save_redo); + virtual void redo(); + + virtual size_t size() { return sizeof(*this); } + virtual void accepted() {} + virtual void get_description(String &s) { s = "UndoSpolinePointPropsChange"; } + }; + + void importGenerationParams(const char *blkname); + + HmapLandObjectEditor &getObjEd() const { return *(HmapLandObjectEditor *)getObjEditor(); } + static HmapLandObjectEditor &getObjEd(ObjectEditor *oe) { return *(HmapLandObjectEditor *)oe; } +}; + +#endif diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSplineTriangulation.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSplineTriangulation.cpp new file mode 100644 index 000000000..3765e3dd9 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSplineTriangulation.cpp @@ -0,0 +1,1004 @@ +#include "hmlSplineObject.h" +#include "hmlSplinePoint.h" +#include "hmlObjectsEditor.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// #include + +#define ERROR_ANGLE 5 + +static Point2 to_point2(const Point3 &p) { return Point2(p.x, p.z); } +static Point3 planeProj(const Point4 &plane, const Point2 &p) +{ + Point3 ret = Point3(p.x, 0, p.y); + ret.y = (-plane.w - plane.x * p.x - plane.z * p.y) / plane.y; + + return ret; +} +static Point3 planeProj(const Point4 &plane, const Point3 &p) { return planeProj(plane, to_point2(p)); } + +static bool triangulateArbitraryPoly(Tab &pts, Tab &tris, const char *poly_name); + +int get_open_poly_intersect(dag::ConstSpan poly, const Point2 &p0, const Point2 &p1, Point2 &ip) +{ + int idx = -1; + for (int i = 0, ie = poly.size() - 1; i < ie; i++) + if (get_lines_intersection(poly[i], poly[i + 1], p0, p1, &ip)) + idx = i; + return idx; +} + +int is_open_poly_intersect_excluding(dag::ConstSpan poly, const Point2 &p0, const Point2 &p1, int excl_idx) +{ + Point2 ip; + for (int i = 0, ie = poly.size() - 1; i < ie; i++) + { + if (i == excl_idx || i + 1 == excl_idx) + continue; + + if (get_lines_intersection(poly[i], poly[i + 1], p0, p1, &ip)) + return i; + } + + return -1; +} + +int get_fence_intersect(dag::ConstSpan poly, dag::ConstSpan inner, dag::ConstSpan in_idx, const Point2 &p0, + const Point2 &p1) +{ + int idx = -1; + for (int i = poly.size() - 1; i >= 0; i--) + if (is_lines_intersect(poly[i], inner[in_idx[i]], p0, p1)) + idx = in_idx[i]; + return idx; +} + +static void process_poly(dag::ConstSpan poly, float bw, Tab &inner_poly) +{ + Tab inner(tmpmem); + Tab innerIdx(tmpmem); + Point2 dir = normalize(poly[0] - poly.back()); + Point2 lastN(-dir.y, dir.x), nextN, avgN; + Point2 inp, ipt; + + innerIdx.resize(poly.size()); + inner.reserve(poly.size()); + for (int i = 0; i < poly.size(); i++) + { + int i1 = (i + 1) % poly.size(); + dir = normalize(poly[i1] - poly[i]); + nextN = Point2(-dir.y, dir.x); + avgN = normalize(lastN + nextN); + lastN = nextN; + + inp = poly[i] + avgN * (bw / 0.9); + if (inner.size() < 2) + { + innerIdx[i] = inner.size(); + inner.push_back(inp); + } + else + { + int idx = get_open_poly_intersect(make_span_const(inner).first(inner.size() - 1), inner.back(), inp, ipt); + int idx2 = get_fence_intersect(make_span_const(poly).first(i), inner, innerIdx, inp, poly[i]); + + // if (idx == -1) + // idx = get_open_poly_intersect(inner, poly[i], inp, ipt); + + if (idx2 >= 0) + { + idx = idx2; + ipt = inner[idx]; + } + + if (idx == -1) + { + innerIdx[i] = inner.size(); + inner.push_back(inp); + } + else + { + inner[idx + 1] = ipt; + innerIdx[i] = idx + 1; + + if (i == poly.size() - 1 && idx == 0) + { + inner[0] = ipt; + inner[poly.size() - 1] = ipt; + } + else + { + erase_items(inner, idx + 2, inner.size() - idx - 2); + for (int k = i - 1; k >= 0; k--) + if (innerIdx[k] > idx + 1) + innerIdx[k] = idx + 1; + else + break; + } + } + } + } + + inner_poly.resize(poly.size()); + for (int i = 0; i < poly.size(); i++) + inner_poly[i] = poly[i] * 0.1 + inner[innerIdx[i]] * 0.9; +} + + +static real get_contour_length(dag::ConstSpan cont) +{ + real ret = 0; + for (int i = 0; i < cont.size(); i++) + { + int idx = (i + 1) % cont.size(); + ret += (cont[idx] - cont[i]).length(); + } + + return ret; +} + + +static void get_contour_positions(dag::ConstSpan cont, Tab &pos) +{ + pos.resize(cont.size()); + real ln = 0; + pos[0] = 0; + for (int i = 1; i < cont.size(); i++) + { + ln += (cont[i] - cont[i - 1]).length(); + pos[i] = ln; + } +} + + +SplineObject::PolyGeom::PolyGeom() : centerTri(midmem), borderTri(midmem), verts(midmem) +{ + mainMesh = dagGeom->newGeomObject(); + borderMesh = dagGeom->newGeomObject(); + altGeom = false; + bboxAlignStep = 1.0; +} + +SplineObject::PolyGeom::~PolyGeom() +{ + clear(); + if (mainMesh) + dagGeom->deleteGeomObject(mainMesh); + + if (borderMesh) + dagGeom->deleteGeomObject(borderMesh); +} + +void SplineObject::PolyGeom::clear() +{ + centerTri.clear(); + borderTri.clear(); + + clear_and_shrink(verts); + + if (mainMesh) + dagGeom->geomObjectClear(*mainMesh); + + if (borderMesh) + dagGeom->geomObjectClear(*borderMesh); +} + +void SplineObject::PolyGeom::renderLines() +{ + if (!verts.size()) + return; + + for (int i = 0; i < centerTri.size(); i++) + { + dagRender->renderLine(verts[centerTri[i][0]], verts[centerTri[i][1]], E3DCOLOR(255, 255, 0, 100)); + dagRender->renderLine(verts[centerTri[i][1]], verts[centerTri[i][2]], E3DCOLOR(255, 255, 0, 100)); + dagRender->renderLine(verts[centerTri[i][2]], verts[centerTri[i][0]], E3DCOLOR(255, 255, 0, 100)); + } + + for (int i = 0; i < borderTri.size(); i++) + { + dagRender->renderLine(verts[borderTri[i][0]], verts[borderTri[i][1]], E3DCOLOR(255, 0, 100, 100)); + dagRender->renderLine(verts[borderTri[i][1]], verts[borderTri[i][2]], E3DCOLOR(255, 0, 100, 100)); + dagRender->renderLine(verts[borderTri[i][2]], verts[borderTri[i][0]], E3DCOLOR(255, 0, 100, 100)); + } +} + +void SplineObject::PolyGeom::createMeshes(const char *parent_name, SplineObject &spline) +{ + landclass::PolyGeomGenData &genGeom = *spline.landClass->data->genGeom; + + if (centerTri.size()) + { + Ptr sm = NULL; + IAssetService *assetSrv = DAGORED2->queryEditorInterface(); + if (assetSrv) + sm = assetSrv->getMaterialData(genGeom.mainMat); + + if (!sm) + { + DAEDITOR3.conError("can't find material %s", genGeom.mainMat.str()); + return; + } + + // debug(">> shader: %s, class: %s",(char*)name, (char*)sm->className); + + int nn = centerTri.size(); + + Mesh *mesh = dagGeom->newMesh(); + + if (borderTri.size()) + mesh->vert = make_span_const(verts).first(verts.size() / 2); + else + mesh->vert = verts; + + mesh->face.resize(nn); + + for (int i = 0; i < nn; i++) + { + mesh->face[i].set(centerTri[i][0], centerTri[i][1], centerTri[i][2]); + mesh->face[i].mat = 1; + } + + for (int i = 0; i < genGeom.mainUV.size(); i++) + { + int ch = genGeom.mainUV[i].chanIdx - 1; + mesh->tvert[ch].resize(mesh->vert.size()); + mesh->tface[ch].resize(nn); + + for (int j = 0; j < nn; j++) + { + mesh->tface[ch][j].t[0] = mesh->face[j].v[0]; + mesh->tface[ch][j].t[1] = mesh->face[j].v[1]; + mesh->tface[ch][j].t[2] = mesh->face[j].v[2]; + } + + int tp = genGeom.mainUV[i].type; + if (tp == 0) // planar + { + Point2 sz = genGeom.mainUV[i].size; + real rotW = genGeom.mainUV[i].rotationW; + + for (int j = 0; j < mesh->tvert[ch].size(); j++) + { + Point3 p = mesh->vert[j] + Point3(genGeom.mainUV[i].offset.x, 0, genGeom.mainUV[i].offset.y); + + mesh->tvert[ch][j] = genGeom.mainUV[i].swapUV ? Point2(p.z / sz.y, p.x / sz.x) : Point2(p.x / sz.x, p.z / sz.y); + + Point3 rr = Point3(mesh->tvert[ch][j].x, 0, mesh->tvert[ch][j].y); + rr = rotyTM(DEG_TO_RAD * rotW) * rr; + + mesh->tvert[ch][j] = Point2(rr.x, rr.z); + } + } + } + + + mesh->calc_ngr(); + mesh->calc_vertnorms(); + for (int i = 0; i < mesh->vertnorm.size(); ++i) + mesh->vertnorm[i] = -mesh->vertnorm[i]; + for (int i = 0; i < mesh->facenorm.size(); ++i) + mesh->facenorm[i] = -mesh->facenorm[i]; + + MaterialDataList *mdl = new MaterialDataList; + mdl->addSubMat(sm); + + StaticGeometryContainer *g = dagGeom->newStaticGeometryContainer(); + + String node_name(128, "poly mesh %s", parent_name); + dagGeom->objCreator3dAddNode(node_name, mesh, mdl, *g); + + StaticGeometryContainer *geom = mainMesh->getGeometryContainer(); + for (int i = 0; i < g->nodes.size(); ++i) + { + StaticGeometryNode *node = g->nodes[i]; + + node->flags = genGeom.flags | StaticGeometryNode::FLG_NO_RECOMPUTE_NORMALS; + node->normalsDir = genGeom.normalsDir; + if (genGeom.stage) + node->script.setInt("stage", genGeom.stage); + if (!genGeom.layerTag.empty()) + node->script.setStr("layerTag", genGeom.layerTag); + + dagGeom->staticGeometryNodeCalcBoundBox(*node); + dagGeom->staticGeometryNodeCalcBoundSphere(*node); + + geom->addNode(dagGeom->newStaticGeometryNode(*node, tmpmem)); + } + + dagGeom->deleteStaticGeometryContainer(g); + + mainMesh->setTm(TMatrix::IDENT); + + recalcLighting(mainMesh); + + mainMesh->notChangeVertexColors(true); + dagGeom->geomObjectRecompile(*mainMesh); + mainMesh->notChangeVertexColors(false); + } + + if (borderTri.size()) + { + Ptr sm = NULL; + IAssetService *assetSrv = DAGORED2->queryEditorInterface(); + if (assetSrv) + sm = assetSrv->getMaterialData(genGeom.borderMat); + + if (!sm) + { + DAEDITOR3.conError("can't find material %s", genGeom.borderMat.str()); + return; + } + + // debug(">> shader: %s, class: %s",(char*)name, (char*)sm->className); + + int nn = borderTri.size(); + + Mesh *mesh = dagGeom->newMesh(); + mesh->vert = verts; + mesh->setnumfaces(nn); + + for (int i = 0; i < nn; i++) + { + mesh->face[i].set(borderTri[i][0], borderTri[i][1], borderTri[i][2]); + mesh->face[i].mat = 1; + } + + for (int i = 0; i < genGeom.borderUV.size(); i++) + { + int ch = genGeom.borderUV[i].chanIdx - 1; + mesh->tvert[ch].resize(mesh->vert.size()); + mesh->tface[ch].resize(nn); + + for (int j = 0; j < nn; j++) + { + mesh->tface[ch][j].t[0] = mesh->face[j].v[0]; + mesh->tface[ch][j].t[1] = mesh->face[j].v[1]; + mesh->tface[ch][j].t[2] = mesh->face[j].v[2]; + } + + int tp = genGeom.borderUV[i].type; + if (tp == 0) // planar + { + Point2 sz = genGeom.borderUV[i].size; + real rotW = genGeom.borderUV[i].rotationW; + + for (int j = 0; j < mesh->tvert[ch].size(); j++) + { + Point3 p = mesh->vert[j] + Point3(genGeom.borderUV[i].offset.x, 0, genGeom.borderUV[i].offset.y); + + mesh->tvert[ch][j] = genGeom.borderUV[i].swapUV ? Point2(p.z / sz.y, p.x / sz.x) : Point2(p.x / sz.x, p.z / sz.y); + + Point3 rr = Point3(mesh->tvert[ch][j].x, 0, mesh->tvert[ch][j].y); + rr = rotyTM(DEG_TO_RAD * rotW) * rr; + + mesh->tvert[ch][j] = Point2(rr.x, rr.z); + } + } + else if (tp == 1) // spline + { + real vsize = genGeom.borderUV[i].sizeV; + + real len = get_contour_length(make_span_const(verts).subspan(verts.size() / 2, verts.size() / 2)); + + if (genGeom.borderUV[i].autotilelength) + { + int dl = (int)len % (int)vsize; + int tln = len - dl; + vsize = len * genGeom.borderUV[i].sizeV / tln; + } + + Tab contPos(tmpmem); + get_contour_positions(make_span_const(verts).subspan(verts.size() / 2, verts.size() / 2), contPos); + + for (int j = 0; j < mesh->vert.size(); j++) + { + real tu, tv; + if (j < mesh->vert.size() / 2) // inner contour + { + tv = contPos[j] / vsize; + tu = 0; + } + else + { + tv = contPos[j - mesh->vert.size() / 2] / vsize; + tu = genGeom.borderUV[i].tileU; + } + + if (genGeom.borderUV[i].swapUV) + { + mesh->tvert[ch][j].x = tu; + mesh->tvert[ch][j].y = tv; + } + else + { + mesh->tvert[ch][j].x = tv; + mesh->tvert[ch][j].y = tu; + } + } + } + } + + mesh->calc_ngr(); + mesh->calc_vertnorms(); + for (int i = 0; i < mesh->vertnorm.size(); ++i) + mesh->vertnorm[i] = -mesh->vertnorm[i]; + for (int i = 0; i < mesh->facenorm.size(); ++i) + mesh->facenorm[i] = -mesh->facenorm[i]; + + MaterialDataList *mdl = new MaterialDataList; + + mdl->addSubMat(sm); + + StaticGeometryContainer *g = dagGeom->newStaticGeometryContainer(); + + String node_name(128, "poly mesh %s", parent_name); + dagGeom->objCreator3dAddNode(node_name, mesh, mdl, *g); + if (!g->nodes.size()) + return; + + StaticGeometryContainer *geom = borderMesh->getGeometryContainer(); + for (int i = 0; i < g->nodes.size(); ++i) + { + StaticGeometryNode *node = g->nodes[i]; + + node->flags = genGeom.flags | StaticGeometryNode::FLG_NO_RECOMPUTE_NORMALS; + node->normalsDir = genGeom.normalsDir; + if (genGeom.stage) + node->script.setInt("stage", genGeom.stage); + if (!genGeom.layerTag.empty()) + node->script.setStr("layerTag", genGeom.layerTag); + + dagGeom->staticGeometryNodeCalcBoundBox(*node); + dagGeom->staticGeometryNodeCalcBoundSphere(*node); + + geom->addNode(dagGeom->newStaticGeometryNode(*node, tmpmem)); + } + + dagGeom->deleteStaticGeometryContainer(g); + + borderMesh->setTm(TMatrix::IDENT); + + recalcLighting(borderMesh); + + borderMesh->notChangeVertexColors(true); + dagGeom->geomObjectRecompile(*borderMesh); + borderMesh->notChangeVertexColors(false); + } +} + + +void SplineObject::PolyGeom::recalcLighting(GeomObject *go) +{ + if (!go) + return; + + const StaticGeometryContainer &geom = *go->getGeometryContainer(); + + ISceneLightService *ltService = DAGORED2->queryEditorInterface(); + + if (!ltService) + return; + + Color3 ltCol1, ltCol2, ambCol; + Point3 ltDir1, ltDir2; + + ltService->getDirectLight(ltDir1, ltCol1, ltDir2, ltCol2, ambCol); + + for (int ni = 0; ni < geom.nodes.size(); ++ni) + { + const StaticGeometryNode *node = geom.nodes[ni]; + + if (node && node->mesh) + { + Mesh &mesh = node->mesh->mesh; + + mesh.cvert.resize(mesh.face.size() * 3); + mesh.cface.resize(mesh.face.size()); + + Point3 normal; + + for (int f = 0; f < mesh.face.size(); ++f) + { + for (unsigned v = 0; v < 3; ++v) + { + normal = mesh.vertnorm[mesh.facengr[f][v]]; + + const int vi = f * 3 + v; + + Color3 resColor = ambCol; + real k = normal * ltDir1; + if (k > 0) + resColor += ltCol1 * k; + k = normal * ltDir2; + if (k > 0) + resColor += ltCol2 * k; + + mesh.cvert[vi] = ::color4(resColor, 1); + mesh.cface[f].t[v] = vi; + } + } + } + } +} + +void SplineObject::movePointByNormal(Point3 &p, int id, SplineObject *flatt_spl) +{ + landclass::PolyGeomGenData &genGeom = *landClass->data->genGeom; + + Tab pts(tmpmem); + pts.resize(points.size()); + for (int i = 0; i < points.size(); i++) + pts[i] = points[i]->getPt(); + + make_clockwise_coords(make_span(pts)); + + Point3 pt0 = (id == 0 ? pts.back() : pts[id - 1]); + Point3 pt1 = (id == pts.size() - 1 ? pts[0] : pts[id + 1]); + + Point3 first = p - pt0; + Point3 second = pt1 - p; + + real projT = 0; + Point3 ds1 = p - flatt_spl->getProjPoint(p, &projT); + Point3 dst1 = flatt_spl->getBezierSpline().get_tang(projT); + Point3 up = flatt_spl->isDirReversed(p, pt1) ? ds1 % dst1 : dst1 % ds1; + + Point3 norm1 = first % up; + norm1.normalize(); + Point3 norm2 = second % up; + norm2.normalize(); + + Point3 resNorm = norm1 + norm2; + resNorm.normalize(); + + p += resNorm * genGeom.borderWidth; +} + +bool SplineObject::calcPolyPlane(Point4 &plane) +{ + Point3 planeNorm = Point3(0, 0, 0); + + for (int i = 0; i < points.size(); i++) + { + Point3 pt0 = points[i == 0 ? points.size() - 1 : i - 1]->getPt(); + Point3 pt1 = points[(i + 1) % points.size()]->getPt(); + + Point3 vec1 = points[i]->getPt() - pt0; + vec1.normalize(); + Point3 vec2 = pt1 - points[i]->getPt(); + vec2.normalize(); + + if (points.size() < 4) + { + real dot = vec1 * vec2; + if (fabs(acos(dot)) < ERROR_ANGLE * DEG_TO_RAD) + { + DAEDITOR3.conError("Angle between segments %d and %d < %d degreeds", i - 1, i, ERROR_ANGLE); + return false; + } + } + + Point3 cross = vec1 % vec2; + if (cross.y < 0) + cross = -cross; + + cross.normalize(); + + planeNorm += cross; + } + + planeNorm.normalize(); + + Point3 sc = splineCenter(); + + real planeD = -sc.x * planeNorm.x - sc.y * planeNorm.y - sc.z * planeNorm.z; + plane = Point4(planeNorm.x, planeNorm.y, planeNorm.z, planeD); + + return true; +} + +void SplineObject::triangulatePoly() +{ + if (polyGeom.mainMesh || polyGeom.borderMesh) + HmapLandObjectEditor::geomBuildCntPoly++; + + polyGeom.clear(); + + int n = points.size(); + if (n < 3) + return; + + if (landClass && landClass->data && landClass->data->csgGen) + { + destroy_it(csgGen); + csgGen = DAEDITOR3.cloneEntity(landClass->data->csgGen); + csgGen->setSubtype(polygonSubtypeMask); + csgGen->setTm(points[0]->getWtm()); + if (ICsgEntity *c = csgGen->queryInterface()) + { + Tab p; + p.resize(points.size() - (isClosed() ? 1 : 0)); + for (int i = 0; i < p.size(); i++) + p[i] = points[i]->getPt(); + c->setFoundationPath(make_span(p), isClosed()); + } + } + + if (!landClass || !landClass->data || !landClass->data->genGeom) + return; + if (landClass->data->genGeom->waterSurface) + return; + + landclass::PolyGeomGenData &genGeom = *landClass->data->genGeom; + bool border = (fabs(genGeom.borderWidth) > 1e-3); + + if (flattenBySpline) + { + SplineObject *s = flattenBySpline; + + for (int i = 0; i < points.size(); i++) + { + Point3 ddest = s->getProjPoint(points[i]->getPt()); + + Point3 npos = points[i]->getPt(); + npos.y = ddest.y; + points[i]->setPos(npos); + } + + Point3 first = points[0]->getPt(); + Point3 second = points[1]->getPt(); + + Point3 last1 = first, last2 = s->getProjPoint(first); + Point3 lastb1 = first; + + for (int i = 1; i < points.size(); i++) + { + if (!s->lineIntersIgnoreY(first, second)) + { + Point3 p1 = first; + Point3 dpP1 = p1; + + real startT = 0; + Point3 sp1 = s->getProjPoint(p1, &startT); + + if (border) + movePointByNormal(p1, i, flattenBySpline); + + Point3 p2 = second; + Point3 dpP2 = p2; + + real endT = 0; + Point3 sp2 = s->getProjPoint(p2, &endT); + + if (border) + { + int tid = (i == points.size() - 1 ? 0 : i + 1); + bool extr = false; + + if (!extr) + movePointByNormal(p2, tid, flattenBySpline); + } + + int isteps = 10; + real step = (endT - startT) / (real)isteps; + + bool reverse = false; + if (startT > endT) + reverse = true; + + if (fabs(step) > 1e-3) + { + int j = 0; + for (real t = startT; reverse ? t >= endT : t <= endT; t += step, j++) + { + real dt = (real)j / (real)isteps; + Point3 pp1 = p1 * (1 - dt) + p2 * dt; + Point3 pp2 = s->getBezierSpline().get_pt(t); + + Point3 newb1 = dpP1 * (1 - dt) + dpP2 * dt; + + int idx = polyGeom.verts.size(); + polyGeom.verts.push_back(last1); + polyGeom.verts.push_back(last2); + polyGeom.verts.push_back(pp2); + polyGeom.verts.push_back(pp1); + + PolyGeom::Triangle *ptri = &polyGeom.centerTri[append_items(polyGeom.centerTri, 2)]; + ptri[0][0] = idx + 0; + ptri[0][1] = idx + 1; + ptri[0][2] = idx + 2; + ptri[1][0] = idx + 2; + ptri[1][1] = idx + 3; + ptri[1][2] = idx + 0; + + last1 = pp1; + last2 = pp2; + + lastb1 = newb1; + } + } + } + + first = second; + second = (i == points.size() - 1 ? points[0]->getPt() : points[i + 1]->getPt()); + } + } + else + { + Tab pts_3(tmpmem); + Tab pts(tmpmem); + getSmoothPoly(pts_3); + + n = pts_3.size(); + pts.resize(n); + for (int i = 0; i < n; i++) + pts[i].set_xz(pts_3[i]); + + bool reverced = (triang_area(pts) < 0.0f); + if (reverced) + { + Tab npts(tmpmem); + npts.resize(pts.size()); + for (int i = 0; i < n; i++) + npts[i] = pts[n - i - 1]; + pts = npts; + } + + Point4 plane; + if (!calcPolyPlane(plane)) + return; + + if (!border) + { + if (!triangulateArbitraryPoly(pts, polyGeom.centerTri, getName())) + { + if (pts.size() > 3) + DAEDITOR3.conError("can't triangulate poly: %d pts", pts.size()); + return; + } + for (int i = 0; i < pts_3.size(); i++) + polyGeom.verts.push_back(pts_3[reverced ? pts_3.size() - i - 1 : i]); + } + else + { + Point2 intersection; + for (int i = 0; i < n; i++) + { + Point2 pt0 = pts[i]; + Point2 pt1 = pts[i == n - 1 ? 0 : i + 1]; + + for (int k = 0; k < n; k++) + { + if (k == i || k == i + 1 || k + 1 == i) + continue; + + Point2 pt2 = pts[k]; + Point2 pt3 = pts[k == n - 1 ? 0 : k + 1]; + + if (get_lines_intersection(pt0, pt1, pt2, pt3, &intersection)) + { + DAEDITOR3.conError("There are self-intersections on segments %d and %d", i, k); + return; + } + } + } + + // make border + + Tab npts(tmpmem); + process_poly(pts, genGeom.borderWidth, npts); + + if (!npts.size()) + return; + + for (int i = 0; i < npts.size(); i++) + polyGeom.verts.push_back(planeProj(plane, npts[i])); + polyGeom.verts.resize(polyGeom.verts.size() + 1); + polyGeom.verts.back() = polyGeom.verts[0]; + + if (!triangulateArbitraryPoly(npts, polyGeom.centerTri, getName())) + { + if (pts.size() > 3) + DAEDITOR3.conError("can't triangulate poly(border): %d pts", pts.size()); + return; + } + + int offs = npts.size() + 1; + + for (int i = 0; i < pts.size(); i++) + polyGeom.verts.push_back(planeProj(plane, pts[i])); + polyGeom.verts.resize(polyGeom.verts.size() + 1); + polyGeom.verts.back() = polyGeom.verts[offs]; + + int invalidTriangles = 0; + + for (int i = 0; i < pts.size(); i++) + { + int idx1 = i, idx2 = offs + i + 1, idx3 = offs + i; + int idx4 = i, idx5 = i + 1, idx6 = offs + i + 1; + int idx = is_open_poly_intersect_excluding(pts, to_point2(polyGeom.verts[idx1]), to_point2(polyGeom.verts[idx2]), i + 1); + if (idx >= 0) + { + invalidTriangles++; + logerr("selfcross %d: seg %d, " FMT_P2 "-" FMT_P2 "", invalidTriangles, idx, P2D(pts[idx]), + P2D(pts[(idx + 1) % pts.size()])); + // continue; + } + + PolyGeom::Triangle *ptri = &polyGeom.borderTri[append_items(polyGeom.borderTri, 2)]; + ptri[0][0] = i; + ptri[0][1] = offs + i + 1; + ptri[0][2] = offs + i; + + ptri[1][0] = i; + ptri[1][1] = i + 1; + ptri[1][2] = offs + i + 1; + } + + if (invalidTriangles) + DAEDITOR3.conError("There are invalid triangles in polygon %s," + " %d segments, see details in debug", + getName(), invalidTriangles); + } + } + + polyGeom.createMeshes(getName(), *this); + if (polyGeom.mainMesh || polyGeom.borderMesh) + HmapLandObjectEditor::geomBuildCntPoly++; +} + +void SplineObject::buildInnerSpline(Tab &out_pts, float offset, float pts_y, float eps) +{ + int n = points.size(); + if (n < 3) + return; + + Tab pts_3(tmpmem); + Tab pts(tmpmem); + getSmoothPoly(pts_3); + + n = pts_3.size(); + pts.resize(n); + for (int i = 0; i < n; i++) + pts[i].set_xz(pts_3[i]); + + bool rev = (triang_area(pts) < 0.0f); + if (rev) + for (int i = 0; i < n; i++) + pts[i].set_xz(pts_3[n - i - 1]); + + Point2 intersection; + for (int i = 0; i < n; i++) + { + Point2 pt0 = pts[i]; + Point2 pt1 = pts[i == n - 1 ? 0 : i + 1]; + + for (int k = 0; k < n; k++) + { + if (k == i || k == i + 1 || k + 1 == i) + continue; + + Point2 pt2 = pts[k]; + Point2 pt3 = pts[k == n - 1 ? 0 : k + 1]; + + if (get_lines_intersection(pt0, pt1, pt2, pt3, &intersection)) + { + DAEDITOR3.conError("There are self-intersections on segments %d and %d", i, k); + return; + } + } + } + + // make border + Tab npts(tmpmem); + process_poly(pts, offset, npts); + + if (!npts.size()) + return; + + if (eps < 1e-6) + { + out_pts.resize(npts.size()); + for (int i = 0; i < npts.size(); i++) + out_pts[i].set_xVy(npts[i], pts_y); + return; + } + + { + Tab pt(tmpmem); + Tab ptmark(tmpmem); + int n = npts.size(), original_n = n; + pt.resize(n * 2); + ptmark.resize(n); + mem_set_0(ptmark); + + for (int i = 0; i < n; i++) + { + pt[i] = npts[i].x; + pt[i + n] = npts[i].y; + } + ReducePoints(pt.data(), pt.data() + n, n, ptmark.data(), eps); + + out_pts.clear(); + out_pts.reserve(n); + for (int i = 0; i < n; i++) + if (ptmark[i]) + out_pts.push_back().set(pt[i], pts_y, pt[i + n]); + } +} + +static bool triangulateArbitraryPoly(Tab &pts, Tab &tris, const char *poly_name) +{ + int nv = pts.size(); + + int *V = new int[nv]; + for (int i = 0; i < nv; i++) + V[i] = i; + + /* remove nv-2 Vertices, creating 1 triangle every time */ + int count = 2 * nv; + + /* error detection */ + for (int m = 0, v = nv - 1; nv > 2;) + { + /* if we loop, it is probably a non-simple polygon */ + if (0 >= (count--)) + { + DAEDITOR3.conError(">> ERROR: bad polygon, can't triangulate %s", poly_name); + return false; + } + + /* three consecutive vertices in current polygon, */ + int u = v; + if (nv <= u) + u = 0; /* previous */ + + v = u + 1; + if (nv <= v) + v = 0; /* new v */ + + int w = v + 1; + if (nv <= w) + w = 0; /* next */ + + if (triang_snip(pts, u, v, w, nv, V)) + { + int a, b, c, s, t; + + /* true names of the vertices */ + a = V[u]; + b = V[v]; + c = V[w]; + + /* output Triangle */ + + SplineObject::PolyGeom::Triangle &ptri = tris.push_back(); + ptri[0] = c; + ptri[1] = b; + ptri[2] = a; + + m++; + + /* remove v from remaining polygon */ + for (s = v, t = v + 1; t < nv; s++, t++) + V[s] = V[t]; + + nv--; + + /* resest error detection counter */ + count = 2 * nv; + } + } + delete[] V; + return true; +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSplineUndoRedo.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSplineUndoRedo.h new file mode 100644 index 000000000..735fb2a0e --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/hmlSplineUndoRedo.h @@ -0,0 +1,422 @@ +#include "hmlSplineObject.h" + +class UndoRefineSpline : public UndoRedoObject +{ +public: + SplineObject *s; + Ptr p; + + int idx, idx2, idx21; + SplinePointObject::Props startPr1, startPr2; + SplinePointObject::Props endPr1, endPr2; + + UndoRefineSpline(SplineObject *s_, SplinePointObject *p_, int idx_, SplinePointObject::Props &startPr1_, + SplinePointObject::Props &startPr2_, SplinePointObject::Props &endPr1_, SplinePointObject::Props &endPr2_) : + s(s_), idx(idx_), p(p_), startPr1(startPr1_), startPr2(startPr2_), endPr1(endPr1_), endPr2(endPr2_) + { + idx2 = (idx + 2) % s->points.size(); + } + + ~UndoRefineSpline() { p = NULL; } + + virtual void restore(bool save_redo) + { + for (int i = 0; i < s->points.size(); i++) + s->points[i]->arrId = i; + + s->points[idx]->setProps(startPr1); + s->points[idx]->setPos(s->points[idx]->getPt()); + s->points[idx2]->setProps(startPr2); + s->points[idx2]->setPos(s->points[idx2]->getPt()); + + s->prepareSplineClassInPoints(); + s->pointChanged(-1); + s->getSpline(); + } + + virtual void redo() + { + s->points[idx]->setProps(endPr1); + s->points[idx]->setPos(s->points[idx]->getPt()); + s->points[idx2]->setProps(endPr2); + s->points[idx2]->setPos(s->points[idx2]->getPt()); + + s->prepareSplineClassInPoints(); + s->pointChanged(-1); + s->getSpline(); + } + + virtual size_t size() { return sizeof(*this); } + virtual void accepted() {} + virtual void get_description(String &s) { s = "UndoRefineSpline"; } +}; + + +class UndoSplitSpline : public UndoRedoObject +{ +public: + SplineObject *o1, *o2; + int idx; + HmapLandObjectEditor *ed; + Ptr p; + + UndoSplitSpline(SplineObject *o1_, SplineObject *o2_, int idx_, HmapLandObjectEditor *ed_) : o1(o1_), o2(o2_), ed(ed_), idx(idx_) + { + ed->addObject(o2); + + p = new SplinePointObject; + p->spline = o2; + + redo(); + ed->addObject(p); + } + + ~UndoSplitSpline() { p = NULL; } + + virtual void restore(bool save_redo) + { + for (int i = 1; i < o2->points.size(); i++) + { + o2->points[i]->spline = o1; + o2->points[i]->arrId = o1->points.size(); + o1->points.push_back(o2->points[i]); + } + + clear_and_shrink(o2->points); + + for (int i = 0; i < o1->points.size(); i++) + o1->points[i]->arrId = i; + + o1->prepareSplineClassInPoints(); + o1->pointChanged(-1); + o1->getSpline(); + ed->unselectAll(); + o1->selectObject(true); + } + + virtual void redo() + { + const char *assetBlkName = o1->getBlkGenName(); + for (int i = 1; i <= idx; i++) + if (o1->points[i]->hasSplineClass()) + assetBlkName = o1->points[i]->getProps().blkGenName; + + p->setProps(o1->points[idx]->getProps()); + p->arrId = 0; + + p->setPos(p->getPt()); + + o2->setBlkGenName(assetBlkName); + + for (int i = idx + 1; i < o1->points.size(); i++) + { + o1->points[i]->arrId = o2->points.size(); + o2->points.push_back(o1->points[i]); + o1->points[i]->spline = o2; + } + + erase_items(o1->points, idx + 1, o1->points.size() - idx - 1); + + for (int i = 0; i < o1->points.size(); i++) + o1->points[i]->arrId = i; + + o1->prepareSplineClassInPoints(); + o1->pointChanged(-1); + o1->getSpline(); + + ed->unselectAll(); + + o2->pointChanged(-1); + o2->prepareSplineClassInPoints(); + o2->getSpline(); + o2->selectObject(); + } + + virtual size_t size() { return sizeof(*this); } + virtual void accepted() {} + virtual void get_description(String &s) { s = "UndoSplitSpline"; } +}; + + +class UndoSplitPoly : public UndoRedoObject +{ +public: + SplineObject *o1, *o2; + int idx1, idx2; + HmapLandObjectEditor *ed; + Ptr p1, p2; + + UndoSplitPoly(SplineObject *o1_, SplineObject *o2_, int idx1_, int idx2_, HmapLandObjectEditor *ed_) : + o1(o1_), o2(o2_), ed(ed_), idx1(idx1_), idx2(idx2_) + { + const char *assetBlkName1 = o1->getBlkGenName(); + for (int i = 1; i <= idx1; i++) + { + if (!o1->points[i]->getProps().blkGenName.empty()) + assetBlkName1 = o1->points[i]->getProps().blkGenName; + else if (!o1->points[i]->getProps().useDefSet) + assetBlkName1 = NULL; + } + + const char *assetBlkName2 = assetBlkName1; + for (int i = idx1 + 1; i <= idx2; i++) + { + if (!o1->points[i]->getProps().blkGenName.empty()) + assetBlkName2 = o1->points[i]->getProps().blkGenName; + else if (!o1->points[i]->getProps().useDefSet) + assetBlkName2 = NULL; + } + + ed->addObject(o2); + + p1 = new SplinePointObject; + p1->spline = o2; + p1->setProps(o1->points[idx1]->getProps()); + p1->setPos(p1->getPt()); + + p2 = new SplinePointObject; + p2->spline = o2; + p2->setProps(o1->points[idx2]->getProps()); + p2->setPos(p2->getPt()); + + p1->arrId = 0; + ed->addObject(p1); + + for (int i = idx1 + 1; i < idx2; i++) + { + o1->points[i]->arrId = o2->points.size(); + o2->points.push_back(o1->points[i]); + o1->points[i]->spline = o2; + } + + p2->arrId = o2->points.size(); + ed->addObject(p2); + + int eraseCnt = idx2 - idx1 - 1; + erase_items(o1->points, idx1 + 1, eraseCnt); + for (int i = 0; i < o1->points.size(); i++) + o1->points[i]->arrId = i; + + o1->pointChanged(-1); + o1->getSpline(); + o1->selectObject(false); + + o2->pointChanged(-1); + o2->getSpline(); + o2->selectObject(); + + p1->setBlkGenName(assetBlkName1); + p2->setBlkGenName(assetBlkName2); + } + + ~UndoSplitPoly() + { + p1 = NULL; + p2 = NULL; + } + + virtual void restore(bool save_redo) + { + for (int i = 1; i < (int)o2->points.size() - 1; i++) + { + o2->points[i]->spline = o1; + o2->points[i]->arrId = insert_items(o1->points, idx1 + i, 1, &o2->points[i]); + } + + for (int i = 0; i < o1->points.size(); i++) + o1->points[i]->arrId = i; + + clear_and_shrink(o2->points); + + o1->pointChanged(-1); + o1->getSpline(); + o1->selectObject(true); + + p2->arrId = 1; + } + + virtual void redo() + { + for (int i = idx1 + 1; i < idx2; i++) + { + o1->points[i]->arrId = insert_items(o2->points, i - idx1, 1, &o1->points[i]); + o1->points[i]->spline = o2; + } + + int eraseCnt = idx2 - idx1 - 1; + erase_items(o1->points, idx1 + 1, eraseCnt); + for (int i = 0; i < o1->points.size(); i++) + o1->points[i]->arrId = i; + + for (int i = 0; i < o2->points.size(); i++) + o2->points[i]->arrId = i; + + o1->pointChanged(-1); + o1->getSpline(); + o1->selectObject(false); + + o2->pointChanged(-1); + o2->getSpline(); + o2->selectObject(); + } + + virtual size_t size() { return sizeof(*this); } + virtual void accepted() {} + virtual void get_description(String &s) { s = "UndoSplitPoly"; } +}; + + +class UndoReverse : public UndoRedoObject +{ +public: + Tab spls; + + UndoReverse(dag::ConstSpan spls_) : spls(tmpmem) { spls = spls_; } + + virtual ~UndoReverse() { spls.clear(); } + + virtual void restore(bool save_redo) + { + for (int i = 0; i < spls.size(); i++) + spls[i]->reverse(); + } + + virtual void redo() + { + for (int i = 0; i < spls.size(); i++) + spls[i]->reverse(); + } + + virtual size_t size() { return sizeof(*this); } + virtual void accepted() {} + virtual void get_description(String &s) { s = "UndoReverse"; } +}; + +class UndoAttachSpline : public UndoRedoObject +{ +public: + SplineObject *o1, *o2; + HmapLandObjectEditor *ed; + int cnt; + + UndoAttachSpline(SplineObject *o1_, SplineObject *o2_, HmapLandObjectEditor *ed_) : o1(o1_), o2(o2_), ed(ed_) + { + cnt = o2->points.size(); + } + + virtual void restore(bool save_redo) + { + int offs = o1->points.size() - cnt; + for (int i = 0; i < cnt; i++) + { + o1->points[offs + i]->spline = o2; + o1->points[offs + i]->arrId = o2->points.size(); + o2->points.push_back(o1->points[offs + i]); + } + erase_items(o1->points, offs, cnt); + + for (int i = 0; i < o1->points.size(); i++) + o1->points[i]->arrId = i; + + for (int i = 0; i < o2->points.size(); i++) + o2->points[i]->arrId = i; + + o1->pointChanged(-1); + o1->getSpline(); + + o2->pointChanged(-1); + o2->getSpline(); + } + + virtual void redo() + { + append_items(o1->points, o2->points.size(), o2->points.data()); + + for (int i = 0; i < o1->points.size(); i++) + { + o1->points[i]->spline = o1; + o1->points[i]->arrId = i; + } + + clear_and_shrink(o2->points); + + o1->pointChanged(-1); + o1->getSpline(); + } + + virtual size_t size() { return sizeof(*this); } + virtual void accepted() {} + virtual void get_description(String &s) { s = "UndoAttachSpline"; } +}; + +class UndoChangeAsset : public UndoRedoObject +{ +public: + Ptr s; + String assetName; + bool useDefSet; + int idx; + + UndoChangeAsset(SplineObject *_s, int _idx) : s(_s), idx(_idx), useDefSet(false) + { + if (idx == -1) + assetName = s->getProps().blkGenName; + else + { + assetName = s->points[idx]->getProps().blkGenName; + useDefSet = s->points[idx]->getProps().useDefSet; + } + } + + virtual void restore(bool save_redo) + { + String tmp; + bool tmp_use = false; + + if (save_redo) + { + if (idx == -1) + tmp = s->getProps().blkGenName; + else + { + tmp = s->points[idx]->getProps().blkGenName; + tmp_use = s->points[idx]->getProps().useDefSet; + } + } + + if (idx == -1) + { + s->setBlkGenName(assetName); + if (s->isPoly()) + s->resetSplineClass(); + else if (s->points.size() > 0) + { + s->points[0]->resetSplineClass(); + s->markAssetChanged(0); + } + } + else + { + SplinePointObject::Props p = s->points[idx]->getProps(); + p.blkGenName = assetName; + p.useDefSet = useDefSet; + s->points[idx]->setProps(p); + s->points[idx]->resetSplineClass(); + s->markAssetChanged(idx); + } + + if (save_redo) + { + assetName = tmp; + useDefSet = tmp_use; + } + + s->getObjEditor()->invalidateObjectProps(); + } + + virtual void redo() { restore(true); } + + virtual size_t size() { return sizeof(*this); } + virtual void accepted() {} + virtual void get_description(String &s) { s = "UndoChangeAsset"; } +}; diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/importLandMesh.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/importLandMesh.cpp new file mode 100644 index 000000000..15beed2eb --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/importLandMesh.cpp @@ -0,0 +1,2422 @@ +#include +#include +#include +#include +#include +#include +#include "editorLandRayTracer.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <3d/dag_drv3d.h> +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#include "hmlPlugin.h" +#include "hmlSplineObject.h" +#include "landMeshMap.h" +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +static const int MD5_LEN = 16; +extern bool allow_debug_bitmap_dump; +extern bool guard_det_border; +#define BOTTOM_LOD_HEIGHT 20 +#define ABOVE_LOD_HEIGHT 2.f +enum +{ + BOTTOM_ABOVE = 0, + BOTTOM_BELOW = 1, + BOTTOM_COUNT +}; + +LandMeshMap::LandMeshMap() : + size(0, 0), origin(0, 0), cellSize(0), land_rmesh(midmem), editorLandTracer(NULL), materials(midmem), textures(tmpmem) +{ + gameLandTracer = NULL; + landMatSG = new StaticGeometryMaterial; + landMatSG->name = "LandMeshGenerated@hmap"; + landMatSG->className = "land_mesh"; + + landBottomMatSG = new StaticGeometryMaterial; + landBottomMatSG->name = "LandMeshBottomGenerated"; + landBottomMatSG->className = "land_mesh"; + landBottomMatSG->scriptText = "bottom=1"; + + landBottomDeepMatSG = new StaticGeometryMaterial; + landBottomDeepMatSG->name = "LandMeshBottomLodGenerated"; + landBottomDeepMatSG->className = "land_mesh"; + landBottomDeepMatSG->scriptText = "bottom=2"; + + landBottomBorderMatSG = new StaticGeometryMaterial; + landBottomBorderMatSG->name = "LandMeshBottomLodGenerated"; + landBottomBorderMatSG->className = "land_mesh"; + landBottomBorderMatSG->scriptText = "bottom=-1"; + + addMaterial(landMatSG, NULL, NULL); + addMaterial(landBottomMatSG, NULL, NULL); + addMaterial(landBottomDeepMatSG, NULL, NULL); + addMaterial(landBottomBorderMatSG, NULL, NULL); + collisionNode = NULL; +} + +LandMeshMap::~LandMeshMap() { clear(true); } + +void LandMeshMap::gatherExportToDagGeometry(StaticGeometryContainer &container) +{ + MaterialDataList *mdl = new MaterialDataList; + for (int materialNo = 0; materialNo < getMaterialsCount(); materialNo++) + mdl->addSubMat(new MaterialData(getMaterialData(materialNo))); + + for (unsigned int cellNo = 0; cellNo < getCells().size(); cellNo++) + { + String nodeName(100, "LandMesh%02d", cellNo); + StaticGeometryContainer *tmpContainer = dagGeom->newStaticGeometryContainer(); // This horrors are taken from + // SplineObject::PolyGeom::createMeshes. + Mesh *mesh = dagGeom->newMesh(); + *mesh = *getCells()[cellNo].land_mesh; + dagGeom->objCreator3dAddNode(nodeName, mesh, mdl, *tmpContainer); + for (unsigned int nodeNo = 0; nodeNo < tmpContainer->nodes.size(); nodeNo++) + { + StaticGeometryNode *node = tmpContainer->nodes[nodeNo]; + dagGeom->staticGeometryNodeCalcBoundBox(*node); + dagGeom->staticGeometryNodeCalcBoundSphere(*node); + container.addNode(dagGeom->newStaticGeometryNode(*node, tmpmem)); + } + dagGeom->deleteStaticGeometryContainer(tmpContainer); + } +} + +void LandMeshMap::buildCollisionNode(Mesh &m) {} + +void LandMeshMap::addStaticCollision(StaticGeometryContainer &cont) {} + +void LandMeshMap::getStats(int &min_faces, int &max_faces, int &total_faces) +{ + max_faces = 0; + min_faces = 1 << 30; + total_faces = 0; + + for (int i = 0; i < cells.size(); ++i) + { + int nf = 0; + if (cells[i].land_mesh) + nf = cells[i].land_mesh->face.size(); + if (cells[i].combined_mesh) + nf += cells[i].combined_mesh->face.size(); + + if (nf > max_faces) + max_faces = nf; + + if (nf < min_faces) + min_faces = nf; + + total_faces += nf; + } +} + +void LandMeshMap::clear(bool clear_tracer) +{ + dagGeom->deleteStaticGeometryNode(collisionNode); + + for (int i = 0; i < land_rmesh.size(); ++i) + if (land_rmesh[i]) + dagGeom->destroyShaderMesh(land_rmesh[i]); + + clear_and_shrink(land_rmesh); + + for (int i = 0; i < cells.size(); ++i) + { + if (cells[i].land_mesh) + delete (cells[i].land_mesh); + if (cells[i].combined_mesh) + delete (cells[i].combined_mesh); + if (cells[i].decal_mesh) + delete (cells[i].decal_mesh); + if (cells[i].patches_mesh) + delete (cells[i].patches_mesh); + } + clear_and_shrink(cells); + if (clear_tracer) + { + del_it(editorLandTracer); + del_it(gameLandTracer); + } + + clear_and_shrink(materials); + addMaterial(landMatSG, NULL, NULL); + addMaterial(landBottomMatSG, NULL, NULL); + addMaterial(landBottomDeepMatSG, NULL, NULL); + addMaterial(landBottomBorderMatSG, NULL, NULL); + clear_and_shrink(textures); + + size = IPoint2(0, 0); +} + + +ShaderMesh *LandMeshMap::getLandShaderMesh(int x, int y, bool do_create, bool offseted) +{ + if (!offseted) + { + x -= origin.x; + y -= origin.y; + } + + if (x < 0 || y < 0 || x >= size.x || y >= size.y) + return NULL; + + ShaderMesh *&m = land_rmesh[y * size.x + x]; + + if (do_create && !m) + { + Mesh *gm = cells[y * size.x + x].land_mesh; + if (gm->vert.size() > 65535 && gm->face.size() * 3 > 65535) + { + DAEDITOR3.conError("too big mesh (%d vert, %d faces), cannot make land shadermesh", gm->vert.size(), gm->face.size()); + return NULL; + } + if (!landMat) + { + MaterialData mat; + mat.className = "land_mesh"; + landMat = dagGeom->newShaderMaterial(mat); + if (!landMat) + { + DAEDITOR3.conError("can't create shader material <%s>", mat.className.str()); + return NULL; + } + } + + m = dagGeom->createSimpleShaderMesh(*gm, landMat); + } + return m; +} + +BBox3 LandMeshMap::getBBox(int x, int y, float *sphere_radius) +{ + x -= origin.x; + y -= origin.y; + + if (x < 0 || x >= size.x || y < 0 || y >= size.y) + return BBox3(); + if (sphere_radius) + *sphere_radius = 0.5 * length(cells[x + y * size.x].box.width()); + return cells[x + y * size.x].box; +} + +// traceRay +bool LandMeshMap::traceRay(const Point3 &p, const Point3 &dir, real &t, Point3 *normal) const +{ + return editorLandTracer && editorLandTracer->traceRay(p, dir, t, normal); +} + +bool LandMeshMap::getHeight(const Point2 &p, real &ht, Point3 *normal) const +{ + return editorLandTracer && editorLandTracer->getHeight(p, ht, normal); +} + +void LandMeshMap::setEditorLandRayTracer(EditorLandRayTracer *lrt) +{ + if (editorLandTracer) + delete editorLandTracer; + editorLandTracer = lrt; +} +void LandMeshMap::setGameLandRayTracer(LandRayTracer *lrt) +{ + if (gameLandTracer) + delete gameLandTracer; + gameLandTracer = lrt; +} + +MaterialData LandMeshMap::getMaterialData(uint32_t matNo) const +{ + MaterialData matNull; + if (matNo >= materials.size() && !materials[matNo]) + { + matNull.className = "land_mesh"; + matNull.matName = "default_lmesh"; + return matNull; + } + StaticGeometryMaterial &gm = *materials[matNo]; + + matNull.matName = gm.name; + matNull.matScript = gm.scriptText; + matNull.className = gm.className; + + if ((gm.flags & (MatFlags::FLG_2SIDED | MatFlags::FLG_REAL_2SIDED)) == (MatFlags::FLG_2SIDED | MatFlags::FLG_REAL_2SIDED)) + matNull.flags = 0; + else + matNull.flags = (gm.flags & MatFlags::FLG_2SIDED) ? MATF_2SIDED : 0; + + matNull.mat.amb = gm.amb; + matNull.mat.diff = gm.diff; + matNull.mat.spec = gm.spec; + matNull.mat.emis = gm.emis; + matNull.mat.power = gm.power; + + for (int ti = 0; ti < StaticGeometryMaterial::NUM_TEXTURES && ti < MAXMATTEXNUM; ++ti) //-V560 + { + if (!gm.textures[ti]) + continue; + matNull.mtex[ti] = dagRender->addManagedTexture(gm.textures[ti]->fileName); + } + //== + // fixme: todo valid + // data.className="land_mesh"; + return matNull; +} + +int LandMeshMap::addTexture(StaticGeometryTexture *texture) +{ + if (!texture) + return -1; + for (int i = 0; i < textures.size(); ++i) + if (textures[i] == texture) + return i; + textures.push_back(texture); + return textures.size() - 1; +} + +int LandMeshMap::addMaterial(StaticGeometryMaterial *material, bool *clipmap_only, bool *has_vertex_opacity, int node_layer, + bool *is_height_patch) +{ + if (clipmap_only) + *clipmap_only = false; + if (!material) + return -1; + + if (!strstr(material->className.str(), "land_mesh")) + return -1; + bool is_decal = false; + bool is_patch = false; + if (strstr(material->className.str(), "height_patch")) + is_patch = true; + else if (strstr(material->className.str(), "decal")) + is_decal = true; + else if (strstr(material->scriptText.str(), "render_landmesh_combined")) + { + CfgReader c; + c.getdiv_text(String(128, "[q]\r\n%s\r\n", material->scriptText.str()), "q"); + if (!c.getbool("render_landmesh_combined", 1)) + is_decal = true; + } + if (has_vertex_opacity && strstr(material->scriptText.str(), "vertex_opacity")) + { + CfgReader c; + c.getdiv_text(String(128, "[q]\r\n%s\r\n", material->scriptText.str()), "q"); + if (c.getbool("vertex_opacity", 0)) + *has_vertex_opacity = true; + else + *has_vertex_opacity = false; + } + if (clipmap_only) + *clipmap_only = is_decal; + if (is_height_patch) + *is_height_patch = is_patch; + + Ptr copyMaterial = new StaticGeometryMaterial(*material); + if (node_layer != -1 && !strstr(copyMaterial->scriptText, "node_layer=")) // Add spline layer only for comparison to avoid joining of + // the meshes from different layers. + copyMaterial->scriptText = String(0, "%snode_layer=%d\r\n", copyMaterial->scriptText.str(), node_layer); + + for (int i = 0; i < materials.size(); ++i) + if (materials[i]->equal(*copyMaterial)) + return i; + + for (int i = 0; i < StaticGeometryMaterial::NUM_TEXTURES; ++i) + addTexture(material->textures[i]); + + if (strcmp("land_mesh", material->className.str()) != 0) + { + if (is_decal && !strstr(material->className.str(), "decal")) + copyMaterial->className = String(128, "%s_decal", material->className.str()); + } + debug("adding material = %s", copyMaterial->className.str()); + materials.push_back(copyMaterial); + return materials.size() - 1; +} + +static void getWorldMeshes(Node &n, Tab &meshes) +{ + if ((n.flags & NODEFLG_RENDERABLE) && n.obj && n.obj->isSubOf(OCID_MESHHOLDER)) + { + MeshHolderObj &mh = *(MeshHolderObj *)n.obj; + if (mh.mesh) + { + Mesh &m = *mh.mesh; + for (int i = 0; i < m.vert.size(); ++i) + m.vert[i] = n.wtm * m.vert[i]; + + meshes.push_back(&n); + } + } + + for (int i = 0; i < n.child.size(); ++i) + if (n.child[i]) + getWorldMeshes(*n.child[i], meshes); +} + +//----------------------------------------------------------------------------- + +class DelaunayHeightMap : public delaunay::Map +{ + HeightMapStorage &heightmap; + +public: + DelaunayHeightMap(HeightMapStorage &map) : heightmap(map) {} + virtual int width() { return heightmap.getInitialMap().getMapSizeX(); } + virtual int height() { return heightmap.getInitialMap().getMapSizeY(); } + + virtual float eval(int i, int j) { return heightmap.getFinalData(i, j); } +}; + +class DelaunayImportanceMask : public delaunay::ImportMask +{ +public: + DelaunayImportanceMask(IBitMaskImageMgr::BitmapMask *in_mask, objgenerator::HugeBitmask *excl_mask, float mask_scale, int hmap_width, + int hmap_height) : + mask(in_mask), exclMask(excl_mask), maskScale(0.125f * mask_scale / 255.0), hmapWidth(hmap_width), hmapHeight(hmap_height) + { + G_ASSERT(mask); + G_ASSERT(mask->getBitsPerPixel() == 8); + } + + virtual float apply(int x, int y, float val) + { + if (exclMask && x >= 0 && y >= 0 && x < exclMask->getW() && y < exclMask->getH() && exclMask->get(x, y)) + return -0.1f; + + float maskVal = + maskScale * mask->getMaskPixel8(x * mask->getWidth() / hmapWidth, mask->getHeight() - y * mask->getHeight() / hmapHeight - 1); + + return val * (maskVal + 1.f); + } + + void addHash(md5_state_t *state) const + { + md5_append(state, (unsigned char *)&hmapWidth, sizeof(int)); + md5_append(state, (unsigned char *)&hmapHeight, sizeof(int)); + md5_append(state, (unsigned char *)&maskScale, sizeof(float)); + HmapLandPlugin::bitMaskImgMgr->calcBitMaskMD5(*mask, state); + if (exclMask) + { + int w = exclMask->getW(); + unsigned char *row = new unsigned char[w]; + for (int y = 0, ye = exclMask->getH(); y < ye; y++) + { + for (int x = 0; x < w; x++) + row[x] = exclMask->get(x, y); + md5_append(state, row, w); + } + delete[] row; + } + } + +protected: + IBitMaskImageMgr::BitmapMask *mask; + objgenerator::HugeBitmask *exclMask; + int hmapWidth, hmapHeight; + float maskScale; +}; + +static void saveCache(const char *fnameData, MemoryChainedData *mem, unsigned char *hash) +{ + if (!mem) + return; + + unsigned char md5Hash[MD5_LEN]; + + // Data + FullFileSaveCB fileData(fnameData); + if (!fileData.fileHandle) + return; + write_zeros(fileData, MD5_LEN * 2); + + md5_state_t hashState; + md5_init(&hashState); + + MemoryChainedData *ptr = mem; + while ((ptr) && (ptr->used > 0)) + { + fileData.write(ptr->data, ptr->used); + md5_append(&hashState, (unsigned char *)ptr->data, ptr->used); + ptr = ptr->next; + } + + md5_finish(&hashState, md5Hash); + // Hash + fileData.seekto(0); + fileData.write(md5Hash, MD5_LEN); + fileData.write(hash, MD5_LEN); +} + +static void loadCache(const char *fnameData, MemoryChainedData *&mem, unsigned char *cur_hash) +{ + if (!::dd_file_exist(fnameData)) + return; + + unsigned char md5Hash[MD5_LEN]; + unsigned char hash[MD5_LEN]; + + // Hash + FullFileLoadCB fileData(fnameData); + fileData.tryRead(md5Hash, MD5_LEN); + fileData.tryRead(hash, MD5_LEN); + if (fileData.tell() != MD5_LEN * 2) + return; + + if (memcmp(cur_hash, hash, MD5_LEN) != 0) + return; + + // Data + MemorySaveCB memSave(NULL, false); + + static const int BUFFER_SIZE = 32 << 10; + unsigned char buf[BUFFER_SIZE]; + + md5_state_t hashState; + md5_init(&hashState); + + for (;;) + { + int read = fileData.tryRead(buf, BUFFER_SIZE); + if (!read) + break; + memSave.write(buf, read); + md5_append(&hashState, buf, read); + } + + md5_finish(&hashState, hash); + + if (memcmp(hash, md5Hash, MD5_LEN) != 0) + { + MemoryChainedData::deleteChain(memSave.getMem()); + CoolConsole &con = DAGORED2->getConsole(); + con.addMessage(ILogWriter::NOTE, "cache file is damaged!"); + return; + } + + mem = memSave.getMem(); +} + +static void calculateHashForFile(md5_state_t &state, const char *file_path) +{ + FullFileLoadCB file(file_path); + if (!file.fileHandle) + return; + + const int BUFFER_SIZE = 65536; + SmallTab buff; + clear_and_resize(buff, BUFFER_SIZE); + + int used = 1; + while (used) + { + used = file.tryRead(buff.data(), BUFFER_SIZE); + md5_append(&state, buff.data(), used); + } +} + +void LandMeshMap::getMd5HashForGenerate(unsigned char *md5_hash, HeightMapStorage &heightmap, float error_threshold, int point_limit, + float cell, const Point3 &ofs, const DelaunayImportanceMask *mask, dag::ConstSpan add_pts, + dag::ConstSpan water_border_polys) +{ + md5_state_t state; + md5_init(&state); + + md5_append(&state, (unsigned char *)&error_threshold, sizeof(float)); + md5_append(&state, (unsigned char *)&point_limit, sizeof(int)); + md5_append(&state, (unsigned char *)&cell, sizeof(float)); + md5_append(&state, (unsigned char *)&ofs, sizeof(Point3)); + + md5_append(&state, (unsigned char *)&heightmap.heightScale, sizeof(float)); + md5_append(&state, (unsigned char *)&heightmap.heightOffset, sizeof(float)); + + if (mask) + mask->addHash(&state); + else + md5_append(&state, ZERO_PTR(), 8); + + float *row = new float[heightmap.getMapSizeX()]; + for (int y = 0, ey = heightmap.getMapSizeY(); y < ey; y++) + { + for (int x = 0, ex = heightmap.getMapSizeX(); x < ex; x++) + row[x] = heightmap.getFinalData(x, y); + md5_append(&state, (unsigned char *)row, sizeof(float) * heightmap.getMapSizeX()); + } + delete[] row; + + md5_append(&state, (unsigned char *)add_pts.data(), data_size(add_pts)); + md5_append(&state, (unsigned char *)water_border_polys.data(), data_size(water_border_polys)); + md5_finish(&state, md5_hash); +} + +// return true if loaded from cache +static bool delaunayGenerateCached(LandMeshMap &land, HeightMapStorage &heightmap, float error_threshold, int point_limit, + delaunay::Map *hmap, Mesh &mesh_out, float cell, const Point3 &ofs, DelaunayImportanceMask *mask, dag::ConstSpan add_pts, + dag::ConstSpan water_border_polys) +{ + CoolConsole &con = DAGORED2->getConsole(); + + String fnameData(DAGORED2->getPluginFilePath(HmapLandPlugin::self, "delaunayGen.cache.bin")); + + unsigned char currentHash[MD5_LEN]; + land.getMd5HashForGenerate(currentHash, heightmap, error_threshold, point_limit, cell, ofs, mask, add_pts, water_border_polys); + + MemoryChainedData *cachedData = NULL; + + ::loadCache(fnameData, cachedData, currentHash); + + if (!cachedData) + { + con.addMessage(ILogWriter::REMARK, "triangulation. processing..."); + + delaunay::load(error_threshold, point_limit, hmap, mesh_out, cell, ofs, mask); + Tab add_bottom_pts(tmpmem); + + bool need_re_delaunay = water_border_polys.size() + add_pts.size() > 0; + int re_delaunay_iter = 0; + float close_bottom_pt_dist2 = 2 * 2; + + int old_fc = mesh_out.face.size(); + int old_vc = mesh_out.vert.size(); + + while (need_re_delaunay && re_delaunay_iter < 10) + { + debug_flush(true); + + int time0l = dagTools->getTimeMsec(); + mesh_out.face.resize(0); + + ctl::PointList boundary; + boundary.push_back({ofs.x, ofs.z}); + boundary.push_back({ofs.x + heightmap.getMapSizeX() * cell, ofs.z}); + boundary.push_back({ofs.x + heightmap.getMapSizeX() * cell, ofs.z + heightmap.getMapSizeY() * cell}); + boundary.push_back({ofs.x, ofs.z + heightmap.getMapSizeY() * cell}); + + ctl::DelaunayTriangulation dt{boundary, 64 << 10}; + + ctl::PointList poly_pts; + for (int i = 0; i < water_border_polys.size(); i++) + if (water_border_polys[i].x > 1e12f) + { + auto points = make_span_const(&water_border_polys[i + 1], unsigned(water_border_polys[i].y)); + bool closed = water_border_polys[i].z < 0.5f; + // debug("add new border %d pts, closed=%d", points.size(), closed); + poly_pts.clear(); + poly_pts.reserve(points.size()); + for (const auto &p : points) + poly_pts.push_back({p.x, p.z, p.y}); + if (closed) + poly_pts.push_back({poly_pts[0]}); + dt.InsertConstrainedLineString(poly_pts); + i += points.size(); + } + + for (const auto &v : mesh_out.vert) + dt.InsertConstrainedPoint({v.x, v.z, v.y}); + for (const auto &v : add_pts) + dt.InsertConstrainedPoint({v.x, v.z, v.y}); + for (const auto &v : add_bottom_pts) + dt.InsertConstrainedPoint({v.x, v.z, v.y}); + + ctl::TIN tin(&dt); + + debug(""); + debug("out: %d vert, %d tri", tin.verts.size(), tin.triangles.size() / 3); + debug_flush(false); + double water_lev = HmapLandPlugin::self->getWaterSurfLevel(); + + need_re_delaunay = false; + int prev_bottom_pts = add_bottom_pts.size(); + for (int i = 0; i < tin.triangles.size(); i += 3) + { + int vi0 = tin.triangles[i + 0]; + int vi1 = tin.triangles[i + 1]; + int vi2 = tin.triangles[i + 2]; + double h0 = tin.verts[vi0].z - water_lev; + double h1 = tin.verts[vi1].z - water_lev; + double h2 = tin.verts[vi2].z - water_lev; + if (fabs(h0) > 0.2 || fabs(h1) > 0.2 || fabs(h2) > 0.2) + continue; + if (h0 < -0.1 && h1 < -0.1 && h2 < -0.1) + continue; + + Point2 cp = (Point2::xy(tin.verts[vi0]) + Point2::xy(tin.verts[vi1]) + Point2::xy(tin.verts[vi2])) / 3.0f; + + if (!HmapLandPlugin::self->isPointUnderWaterSurf(cp.x, cp.y)) + continue; + + float cph = water_lev - 0.3; + if (get_height_midpoint_heightmap(*HmapLandPlugin::self, cp, cph, NULL)) + cph = (cph > water_lev - 0.3) ? water_lev - 0.3 : (cph + water_lev - 0.3) * 0.5; + + // debug("tri %d: " FMT_P3 " (cp=" FMT_P2 ", h=%.3f)", i, h0, h1, h2, P2D(cp), cph); + + bool found_close = false; + for (int j = 0; j < add_bottom_pts.size(); j++) + if (lengthSq(Point2::xz(add_bottom_pts[j]) - cp) < close_bottom_pt_dist2) + { + found_close = true; + break; + } + if (!found_close) + add_bottom_pts.push_back().set(cp.x, cph, cp.y); + need_re_delaunay = true; + } + if (need_re_delaunay && prev_bottom_pts == add_bottom_pts.size()) + { + need_re_delaunay = false; + DAEDITOR3.conWarning("Triangulation gives inconsistent heights, but iteration is useless"); + } + + if (need_re_delaunay) + { + re_delaunay_iter++; + debug("reapply delaunay %d, bottom_pts=%d", re_delaunay_iter, add_bottom_pts.size()); + close_bottom_pt_dist2 /= 4; + continue; + } + + mesh_out.vert.resize(tin.verts.size()); + mesh_out.face.reserve(tin.triangles.size() / 3); + for (int i = 0; i < mesh_out.vert.size(); i++) + mesh_out.vert[i].set_xzy(tin.verts[i]); + + int bottom_faces = 0, deep_bottom_faces = 0, border_faces = 0; + for (int i = 0; i < tin.triangles.size(); i += 3) + { + Face &f = mesh_out.face.push_back(); + f.v[0] = tin.triangles[i + 0]; + f.v[2] = tin.triangles[i + 1]; + f.v[1] = tin.triangles[i + 2]; + f.mat = BOTTOM_ABOVE; + f.smgr = 1; + float upper_lev = water_lev + ABOVE_LOD_HEIGHT; + if (tin.verts[f.v[0]].z <= upper_lev || tin.verts[f.v[1]].z <= upper_lev || tin.verts[f.v[2]].z <= upper_lev) + if (tin.verts[f.v[0]].z <= water_lev && tin.verts[f.v[1]].z <= water_lev && tin.verts[f.v[2]].z <= water_lev) + bottom_faces++; + } + debug("deduced water_lev=%.3f, bottom faces: %d(deep=%d)/%d, border=%d", water_lev, bottom_faces, deep_bottom_faces, + border_faces, mesh_out.face.size()); + + DAEDITOR3.conNote("re-applied delaunay for %d points for %.1f sec (%d extra verts, %d extra faces, %d re-iter)", + mesh_out.vert.size(), (dagTools->getTimeMsec() - time0l) / 1000.f, mesh_out.vert.size() - old_vc, + mesh_out.face.size() - old_fc, re_delaunay_iter); + } + + MemorySaveCB memSave(NULL, false); + mesh_out.saveData(memSave); + ::saveCache(fnameData, memSave.getMem(), currentHash); + debug_flush(false); + return false; + } + else + { + con.addMessage(ILogWriter::REMARK, "triangulation. getting from cache..."); + + MemoryLoadCB memLoad(cachedData, true); + mesh_out.loadData(memLoad); + return true; + } +} + +static void split(Mesh &from, Mesh &pos, float A, float B, float C, float D, float eps) +{ + Mesh neg; + from.split(neg, pos, A, B, C, D, eps); + from = neg; //==can be optimized + /*from.optimize_tverts(); + pos.optimize_tverts();*/ +} + +class OptimizeJob : public cpujobs::IJob +{ + landmesh::Cell &cell; + +public: + OptimizeJob(landmesh::Cell &c) : cell(c) {} + static BBox3 calc_mesh_bbox(const Mesh &m) + { + BBox3 box; + for (int fi = 0; fi < m.getFace().size(); ++fi) + { + box += m.getVert()[m.getFace()[fi].v[0]]; + box += m.getVert()[m.getFace()[fi].v[1]]; + box += m.getVert()[m.getFace()[fi].v[2]]; + } + return box; + } + virtual void doJob() + { + // fixme: check if land mesh can has unused vertex + cell.land_mesh->kill_unused_verts(0.0005f); // only saves few vertices + cell.land_mesh->kill_bad_faces(); + + cell.box = calc_mesh_bbox(*cell.land_mesh); + + if (cell.combined_mesh) + { + cell.combined_mesh->kill_unused_verts(0.0005f); + cell.combined_mesh->kill_bad_faces(); + cell.box += calc_mesh_bbox(*cell.combined_mesh); + } + if (cell.patches_mesh) + { + cell.patches_mesh->kill_unused_verts(0.0005f); + cell.patches_mesh->kill_bad_faces(); + cell.box += calc_mesh_bbox(*cell.patches_mesh); + } + } + virtual void releaseJob() { delete this; } +}; + +class Point2Deref : public Point2 +{ +public: + Point3 getPt() const { return Point3::x0y(*this); } +}; + +#if 1 +static void write_tif(objgenerator::HugeBitmask &m, const char *fname) +{ + IBitMaskImageMgr::BitmapMask img; + int w = m.getW(), h = m.getH(); + HmapLandPlugin::bitMaskImgMgr->createBitMask(img, w, h, 1); + + for (int y = 0; y < h; y++) + for (int x = 0; x < w; x++) + img.setMaskPixel1(x, y, m.get(x, y) ? 128 : 0); + + HmapLandPlugin::bitMaskImgMgr->saveImage(img, ".", fname); + HmapLandPlugin::bitMaskImgMgr->destroyImage(img); +} +#endif + +struct LandMeshCombinedMat +{ + int id; + bool clipmapOnly; + bool has_vertex_opacity; +}; + +static EditorLandRayTracer *generate_editor_land_tracer(Mesh &mesh, Point3 offset) +{ + int t0 = dagTools->getTimeMsec(); + EditorLandRayTracer *lrt = new EditorLandRayTracer; + int minGrid = 511, maxGrid = 511; + BBox3 landBox; + for (int i = 0; i < mesh.vert.size(); i++) + landBox += mesh.vert[i]; + Mesh *pMesh = &mesh; + bool built = lrt->build(1, 1, max(landBox.width().x, landBox.width().z), offset, landBox, make_span(&pMesh, 1), + make_span((Mesh **)NULL, 0), minGrid, maxGrid, false); + if (!built) + { + DAEDITOR3.conError("Can't build editor landtracer."); + delete lrt; + return NULL; + } + DAEDITOR3.conRemark("build editor landtracer for landmesh for %dms", dagTools->getTimeMsec() - t0); + return lrt; +} + +bool HmapLandPlugin::generateLandMeshMap(LandMeshMap &map, CoolConsole &con, bool import_sgeom, LandRayTracer **game_tracer, + bool strip_det_hmap_from_tracer) +{ + // landMeshMap.clear(); + if (!heightMap.isFileOpened()) + return true; + bool generate_ok = true; + + guard_det_border = false; + con.startLog(); + int time0 = dagTools->getTimeMsec(); + + con.setActionDesc("delaunay triangulate..."); + + DelaunayHeightMap hmap(heightMap); + + + DelaunayImportanceMask *mask = NULL; + IBitMaskImageMgr::BitmapMask impLayerMask; + objgenerator::HugeBitmask *exclMask = NULL; + + int time0l = dagTools->getTimeMsec(); + Tab loft_pt_cloud(tmpmem); + Tab water_border_polys(tmpmem); + Tab hmap_sweep_polys(tmpmem); + Tab det_hmap_border(tmpmem); + + loft_pt_cloud.reserve(4096); + + IDagorEdCustomCollider *coll = this; + int prev_exp_type = exportType; + + DAGORED2->setColliders(make_span(&coll, 1), 0x7FFFFFFF); + exportType = EXPORT_HMAP; + + rebuildWaterSurface(&loft_pt_cloud, &water_border_polys, &hmap_sweep_polys); + if (!detDivisor) + strip_det_hmap_from_tracer = false; + if (strip_det_hmap_from_tracer) + { + int time0l = dagTools->getTimeMsec(); + + con.setActionDesc("build delaunay constraints around detailed HMAP area..."); + int step = 32; + int w = (detRectC[1].x - detRectC[0].x) / step, h = (detRectC[1].y - detRectC[0].y) / step; + // debug("detRectC=%@ div=%d step=%d", detRectC, detDivisor, step); + float csz = gridCellSize / detDivisor; + + int base = append_items(water_border_polys, w * 2 + h * 2 + 2); + mem_set_0(make_span(water_border_polys).subspan(base)); + // debug("%dx%d base=%d sz=%d", w, h, base, water_border_polys.size()-base); + water_border_polys[base].set(1.1e12f, w * 2 + h * 2 + 1, 0.f); + for (int x = detRectC[0].x, i = 0; x <= detRectC[1].x; x += step, i++) + { + water_border_polys[base + 1 + i].set_xVy(heightMapOffset + Point2(x, detRectC[0].y) * csz, + heightMap.getFinalData(x / detDivisor, detRectC[0].y / detDivisor)); + water_border_polys[base + 1 + 2 * w + h - i].set_xVy(heightMapOffset + Point2(x, detRectC[1].y) * csz, + heightMap.getFinalData(x / detDivisor, detRectC[1].y / detDivisor)); + } + for (int y = detRectC[0].y + step, i = 0; y < detRectC[1].y; y += step, i++) + { + water_border_polys[base + 1 + 2 * w + 2 * h - 1 - i].set_xVy(heightMapOffset + Point2(detRectC[0].x, y) * csz, + heightMap.getFinalData(detRectC[0].x / detDivisor, y / detDivisor)); + water_border_polys[base + 1 + w + 1 + i].set_xVy(heightMapOffset + Point2(detRectC[1].x, y) * csz, + heightMap.getFinalData(detRectC[1].x / detDivisor, y / detDivisor)); + } + water_border_polys[base + w * 2 + h * 2 + 1] = water_border_polys[base + 1]; + det_hmap_border = make_span_const(water_border_polys).subspan(base + 1); + + // for (int i = base; i < water_border_polys.size(); i ++) + // debug("border[%d] %@", i, water_border_polys[i]); + + con.setActionDesc("backsync border of detailed HMAP with landmesh..."); + float ht, t; + + for (int x = detRectC[0].x, i = 0; x < detRectC[1].x; x++, i++) + { + t = x + 1 < detRectC[1].x ? float(i % step) / step : 1.0f; + ht = lerp(water_border_polys[base + 1 + i / step].y, water_border_polys[base + 1 + i / step + 1].y, t); + // heightMapDet.setInitialData(x,detRectC[0].y, ht); + heightMapDet.setFinalData(x, detRectC[0].y, ht); + if ((x % detDivisor) == 0) + { + // heightMap.setInitialData(x/detDivisor, detRectC[0].y/detDivisor, ht); + heightMap.setFinalData(x / detDivisor, detRectC[0].y / detDivisor, ht); + } + + ht = lerp(water_border_polys[base + 1 + 2 * w + h - i / step].y, water_border_polys[base + 1 + 2 * w + h - i / step - 1].y, t); + // heightMapDet.setInitialData(x,detRectC[1].y-1, ht); + heightMapDet.setFinalData(x, detRectC[1].y - 1, ht); + if ((x % detDivisor) == 0) + { + // heightMap.setInitialData(x/detDivisor, detRectC[1].y/detDivisor, ht); + heightMap.setFinalData(x / detDivisor, detRectC[1].y / detDivisor, ht); + } + } + for (int y = detRectC[0].y, i = 0; y < detRectC[1].y; y++, i++) + { + t = y + 1 < detRectC[1].y ? float(i % step) / step : 1.0f; + ht = lerp(water_border_polys[base + 1 + 2 * w + 2 * h - i / step].y, + water_border_polys[base + 1 + 2 * w + 2 * h - i / step - 1].y, t); + // heightMapDet.setInitialData(detRectC[0].x, y, ht); + heightMapDet.setFinalData(detRectC[0].x, y, ht); + if ((y % detDivisor) == 0) + { + // heightMap.setInitialData(detRectC[0].x/detDivisor, y/detDivisor, ht); + heightMap.setFinalData(detRectC[0].x / detDivisor, y / detDivisor, ht); + } + + ht = lerp(water_border_polys[base + 1 + w + i / step].y, water_border_polys[base + 1 + w + i / step + 1].y, t); + // heightMapDet.setInitialData(detRectC[1].x-1, y, ht); + heightMapDet.setFinalData(detRectC[1].x - 1, y, ht); + if ((y % detDivisor) == 0) + { + // heightMap.setInitialData(detRectC[1].x/detDivisor, y/detDivisor, ht); + heightMap.setFinalData(detRectC[1].x / detDivisor, y / detDivisor, ht); + } + } + DAEDITOR3.conNote("updated heightMap/heightMapDet finalData for %.2f sec", (dagTools->getTimeMsec() - time0l) / 1000.f); + updateHeightMapTex(false); + updateHeightMapTex(true); + } + + exportType = prev_exp_type; + DAGORED2->restoreEditorColliders(); + + if (loft_pt_cloud.size()) + DAEDITOR3.conNote("gathered %d points from lofts for %.1f sec", loft_pt_cloud.size(), (dagTools->getTimeMsec() - time0l) / 1000.f); + + if (hmap_sweep_polys.size() || water_border_polys.size() || loft_pt_cloud.size()) + exclMask = new objgenerator::HugeBitmask(hmap.width(), hmap.height()); + if (hmap_sweep_polys.size() && exclMask) + { + Tab pts(tmpmem); + + for (int i = 0; i < hmap_sweep_polys.size(); i++) + if (hmap_sweep_polys[i].x > 1e12f) + { + pts.resize(hmap_sweep_polys[i].y); + debug("add new sweep %d pts", pts.size()); + i++; + for (int j = 0; j < pts.size(); j++, i++) + pts[j] = static_cast(&hmap_sweep_polys[i]); + + rasterize_poly_2_nz(*exclMask, pts, heightMapOffset.x, heightMapOffset.y, 1.0f / gridCellSize); + i--; + } + } + for (int i = 0; i < loft_pt_cloud.size() && exclMask; i++) + { + int cx = floorf((loft_pt_cloud[i].x - heightMapOffset.x) / gridCellSize + 0.5f); + int cy = floorf((loft_pt_cloud[i].z - heightMapOffset.y) / gridCellSize + 0.5f); + if (fabs(cx * gridCellSize + heightMapOffset.x - loft_pt_cloud[i].x) + + fabs(cy * gridCellSize + heightMapOffset.y - loft_pt_cloud[i].z) > + 0.2) + continue; + if (cx >= 0 && cy >= 0 && cx < hmap.width() && cy < hmap.height()) + exclMask->set(cx, cy); + } + + for (int i = 0; i < water_border_polys.size() && exclMask; i++) + if (water_border_polys[i].x > 1e12f) + { + i++; + int s_i = i, e_i = s_i + water_border_polys[i - 1].y - 1; + float eps = max(gridCellSize / 8.0f, 0.6f); + for (; i <= e_i; i++) + { + int cx = floorf((water_border_polys[i].x - heightMapOffset.x) / gridCellSize + 0.5f); + int cy = floorf((water_border_polys[i].z - heightMapOffset.y) / gridCellSize + 0.5f); + if (cx >= 0 && cy >= 0 && cx < hmap.width() && cy < hmap.height() && + fabs(cx * gridCellSize + heightMapOffset.x - water_border_polys[i].x) + + fabs(cy * gridCellSize + heightMapOffset.y - water_border_polys[i].z) < + eps) + exclMask->set(cx, cy); + + if (i > s_i) + { + Point2 p0(water_border_polys[i].x, water_border_polys[i].z), pt; + Point2 dir(water_border_polys[i - 1].x - p0.x, water_border_polys[i - 1].z - p0.y); + float len = dir.length(); + for (float t = 0.1, len = dir.length(); t < len; t += 0.1) //-V1034 + { + pt.set(p0.x + dir.x * t / len, p0.y + dir.y * t / len); + cx = floorf((pt.x - heightMapOffset.x) / gridCellSize + 0.5f); + cy = floorf((pt.y - heightMapOffset.y) / gridCellSize + 0.5f); + if (cx >= 0 && cy >= 0 && cx < hmap.width() && cy < hmap.height() && + fabs(cx * gridCellSize + heightMapOffset.x - pt.x) + fabs(cy * gridCellSize + heightMapOffset.y - pt.y) < eps) + exclMask->set(cx, cy); + } + } + } + + if (water_border_polys[s_i - 1].z < 0.5f) + { + Point2 p0(water_border_polys[s_i].x, water_border_polys[s_i].z), pt; + Point2 dir(water_border_polys[e_i].x - p0.x, water_border_polys[e_i].z - p0.y); + float len = dir.length(); + for (float t = 0.1, len = dir.length(); t < len; t += 0.1) //-V1034 + { + pt.set(p0.x + dir.x * t / len, p0.y + dir.y * t / len); + int cx = floorf((pt.x - heightMapOffset.x) / gridCellSize + 0.5f); + int cy = floorf((pt.y - heightMapOffset.y) / gridCellSize + 0.5f); + if (cx >= 0 && cy >= 0 && cx < hmap.width() && cy < hmap.height() && + fabs(cx * gridCellSize + heightMapOffset.x - pt.x) + fabs(cy * gridCellSize + heightMapOffset.y - pt.y) < eps) + exclMask->set(cx, cy); + } + } + i--; + } + if (allow_debug_bitmap_dump && exclMask) + write_tif(*exclMask, "../../exclMask.tif"); + + + if (impLayerIdx >= 0) + { + bitMaskImgMgr->createBitMask(impLayerMask, landClsMap.getMapSizeX(), landClsMap.getMapSizeY(), 8); + for (int y = 0, d = impLayerMask.getHeight() - 1; y < impLayerMask.getHeight(); y++, d--) + for (int x = 0; x < impLayerMask.getWidth(); x++) + impLayerMask.setMaskPixel8(x, d, getImpLayerDesc().getLayerData(landClsMap.getData(x, y))); + bitMaskImgMgr->saveImage(impLayerMask, getInternalName(), "importanceMask_lc"); + + mask = new DelaunayImportanceMask(&impLayerMask, exclMask, importanceMaskScale, hmap.width(), hmap.height()); + } + else + for (unsigned int imageNo = 0; imageNo < scriptImages.size(); imageNo++) + { + if (stricmp(scriptImages[imageNo]->getName(), "importanceMask") == 0) + { + mask = new DelaunayImportanceMask(scriptImages[imageNo], exclMask, importanceMaskScale, hmap.width(), hmap.height()); + + break; + } + } + + Point3 ofs(heightMapOffset[0], 0, heightMapOffset[1]); + Mesh mesh; + bool loadedFromCache = ::delaunayGenerateCached(map, heightMap, meshErrorThreshold, numMeshVertices, &hmap, mesh, gridCellSize, ofs, + mask, loft_pt_cloud, water_border_polys); + + delete mask; + del_it(exclMask); + if (impLayerIdx >= 0) + bitMaskImgMgr->destroyImage(impLayerMask); + + con.addMessage(ILogWriter::REMARK, "Triangulated in %g seconds", (dagTools->getTimeMsec() - time0) / 1000.0f); + debug("Triangulated in %g seconds (%d faces, %d verts)", (dagTools->getTimeMsec() - time0) / 1000.0f, mesh.face.size(), + mesh.vert.size()); + if (!mesh.face.size()) + { + DAEDITOR3.conError("Failed to triangulate land; try changing settings (HMAP height, ocean, etc.)"); + landMeshMap.resize(0, 0, 0, 0, 0); + generate_ok = false; + } + + if (!loadedFromCache || !landMeshMap.getEditorLandRayTracer()) + { + EditorLandRayTracer *lrt = generate_ok ? ::generate_editor_land_tracer(mesh, ofs) : NULL; + landMeshMap.setEditorLandRayTracer(lrt); + } + if (generate_ok && applyHtConstraintBitmask(mesh)) + { + EditorLandRayTracer *lrt = ::generate_editor_land_tracer(mesh, ofs); + landMeshMap.setEditorLandRayTracer(lrt); + } + + if (strip_det_hmap_from_tracer && generate_ok) + { + int time0l = dagTools->getTimeMsec(); + float csz = gridCellSize / detDivisor; + + con.setActionDesc("smoothing borders (%.0f m) of detailed HMAP with landmesh %@...", gridCellSize * 2, detRectC); + + BuildableStaticSceneRayTracer lrt(Point3(256, 128, 256), 4); + lrt.setCullFlags(StaticSceneRayTracer::CULL_BOTH); + G_VERIFY(lrt.addmesh(mesh.vert.data(), mesh.vert.size(), (unsigned *)mesh.face.data(), elem_size(mesh.face), mesh.face.size(), + NULL, true)); + for (int y = detRectC[0].y; y < detRectC[1].y; y++) + for (int x = detRectC[0].x; x < detRectC[1].x; x++) + { + int min_border_dist = min(y - detRectC[0].y, detRectC[1].y - y - 1); + min_border_dist = min(min_border_dist, x - detRectC[0].x); + min_border_dist = min(min_border_dist, detRectC[1].x - x - 1); + if (min_border_dist > detDivisor * 2) + continue; + + float ht0 = heightMapDet.getInitialData(x, y), ht = ht0 - 200; + Point3 pos = ofs + Point3::xVy(Point2(x, y) * csz, ht0 + 200); + if (x + 1 == detRectC[1].x) + pos.x += csz; + if (y + 1 == detRectC[1].y) + pos.z += csz; + + if (lrt.getHeightBelow(pos, ht) < 0) + ht = ht0; + ht = lerp(ht, ht0, max(min_border_dist - 1, 0) * 0.5f / detDivisor); + // heightMapDet.setInitialData(x, y, ht); + heightMapDet.setFinalData(x, y, ht); + } + DAEDITOR3.conNote("updated heightMap/heightMapDet finalData for %.2f sec", (dagTools->getTimeMsec() - time0l) / 1000.f); + updateHeightMapTex(false); + updateHeightMapTex(true); + } + + float epsilon = 0.00001f; + con.setActionDesc("Setting normals..."); + + BBox3 mapBox; + int totalMeshFaces = 0, totalMeshVerts = 0; + + for (int vi = 0; vi < mesh.vert.size(); ++vi) + mapBox += mesh.vert[vi] - ofs; + + if (hasWaterSurface) + { + if (mapBox[1].y < waterSurfaceLevel + 0.01 - ofs.y) + DAEDITOR3.conError("upper land mesh point is %.3f, maybe underwater", mapBox[1].y + ofs.y); + else if (mapBox[1].y < waterSurfaceLevel + 1 - ofs.y) + DAEDITOR3.conWarning("upper land mesh point is %.3f, nearly underwater", mapBox[1].y + ofs.y); + } + totalMeshFaces += mesh.face.size(); + totalMeshVerts += mesh.vert.size(); + // + mesh.calc_ngr(); + mesh.calc_vertnorms(); + // for (int i = 0; i < mesh.vertnorm.size(); ++i) + // mesh.vertnorm[i] = -mesh.vertnorm[i]; + mesh.facengr.resize(mesh.face.size()); + mesh.vertnorm.resize(mesh.vert.size()); + for (int i = 0; i < mesh.vert.size(); ++i) + { + real h, hl, hr, hu, hd, hr2, hu2; + int x = (mesh.vert[i].x - ofs.x) / gridCellSize; + int y = (mesh.vert[i].z - ofs.z) / gridCellSize; + h = heightMap.getFinalData(x, y); + hl = heightMap.getFinalData(x - 1, y); + hr = heightMap.getFinalData(x + 1, y); + hu = heightMap.getFinalData(x, y + 1); + hd = heightMap.getFinalData(x, y - 1); + mesh.vertnorm[i] = -normalize(Point3(hr - hl, -2 * gridCellSize, hu - hd)); + } + + for (int i = 0; i < mesh.face.size(); ++i) + { + mesh.facengr[i][0] = mesh.face[i].v[0]; + mesh.facengr[i][1] = mesh.face[i].v[1]; + mesh.facengr[i][2] = mesh.face[i].v[2]; + } + + float meshCellSize = getMeshCellSize(); + + int mapx0 = int(floorf(mapBox[0].x / meshCellSize)); + int mapy0 = int(floorf(mapBox[0].z / meshCellSize)); + int mapx1 = int(ceilf(mapBox[1].x / meshCellSize)); + int mapy1 = int(ceilf(mapBox[1].z / meshCellSize)); + + LandMeshMap &cells = landMeshMap; + cells.resize(mapx0, mapy0, mapx1, mapy1, meshCellSize); + + Tab meshes(tmpmem); + Bitarray should_collide(tmpmem); + Tab nodes(tmpmem); + Tab> matUsed(tmpmem); + Tab shouldRemoveUndegroundFaces(tmpmem); + Tab isDecal(tmpmem); + Tab isPatch(tmpmem); + int combined_meshes = 0, decal_meshes = 0; + + StaticGeometryContainer *geoCont = dagGeom->newStaticGeometryContainer(); + int reported_has_vertex_opacity = 0; + + if (import_sgeom) + { + con.setActionDesc("gather static visual..."); + con.startProgress(); + + DataBlock applicationBlk(DAGORED2->getWorkspace().getAppPath()); + bool joinSplineMeshes = applicationBlk.getBlockByNameEx("heightMap")->getBool("joinSplineMeshes", true); + + con.setTotal(DAGORED2->getPluginCount()); + // DEBUG_DUMP_VAR(geomLoftBelowAll); + if (geomLoftBelowAll) + { + int oldCount = should_collide.size(); + // debug("%s.gatherStaticVisualGeometry", self->getInternalName()); + self->gatherStaticVisualGeometry(*geoCont); + should_collide.resize(geoCont->nodes.size() + 1); + should_collide.set(oldCount, should_collide.size() - oldCount, 0); + } + for (int i = 0; i < DAGORED2->getPluginCount(); ++i) + { + con.setDone(i); + IGenEditorPlugin *plugin = DAGORED2->getPlugin(i); + + IGatherStaticGeometry *geom = plugin->queryInterface(); + if (!geom) + continue; + if (geomLoftBelowAll && plugin == self) + continue; + int oldCount = should_collide.size(); + + // debug("%s.gatherStaticVisualGeometry", plugin->getInternalName()); + geom->gatherStaticVisualGeometry(*geoCont); + should_collide.resize(geoCont->nodes.size() + 1); + + unsigned v = 0; + if (stricmp(plugin->getInternalName(), "_prefabEntMgr") == 0) + { + con.addMessage(ILogWriter::REMARK, "adding only %s to collision", (const char *)plugin->getInternalName()); + v = 1; + } + should_collide.set(oldCount, should_collide.size() - oldCount, v); + } + con.endProgress(); + meshes.reserve(geoCont->nodes.size() + 1); + nodes.reserve(geoCont->nodes.size() + 1); + matUsed.reserve(geoCont->nodes.size() + 1); + + con.setActionDesc("finding valid static geom..."); + con.startProgress(); + + con.setTotal(geoCont->nodes.size() / 32); + + StaticGeometryMaterial *prevSplineMat = NULL; + int splineBatch = 0; + + for (int i = 0; i < geoCont->nodes.size(); ++i) + { + if (!(i & 31)) + con.setDone(i / 32); + + StaticGeometryNode *node = geoCont->nodes[i]; + + if (!node) + { + erase_items(geoCont->nodes, i, 1); + --i; + continue; + } + if (!node->mesh->mesh.check_mesh()) + { + con.addMessage(ILogWriter::WARNING, "node mesh <%s> is invalid.", (const char *)node->name); + erase_items(geoCont->nodes, i, 1); + --i; + continue; + } + SmallTab matsUsedNode; + clear_and_resize(matsUsedNode, node->mesh->mats.size()); + int mats_used = 0, vertex_opacity_used = 0; + bool hasClipmapOnly = false; + bool hasCombined = false; + + int nodeLayer = -1; + int splineLayer = node->script.getInt("splineLayer", -1); + if (splineLayer != -1) // Each spline has splineLayer >= 0. + { + if (joinSplineMeshes) + { + if (node->mesh->mats.size() && node->mesh->mats[0] && (!prevSplineMat || !node->mesh->mats[0]->equal(*prevSplineMat))) + { + prevSplineMat = node->mesh->mats[0]; + splineBatch++; + } + int loftLayer = node->script.getInt("layer", 0); + nodeLayer = loftLayer * LAYER_ORDER_MAX + splineLayer // Split meshes by layers. + + splineBatch * LAYER_ORDER_MAX * LAYER_ORDER_MAX; // Do not join meshes if another mesh is between them to avoid + // changing the render order. + } + else + nodeLayer = i; + } + + bool isHeightPatch = false; + bool hasPatchNodesOnly = true; + for (int mi = 0; mi < node->mesh->mats.size(); ++mi) + { + bool isPatchNode = false; + matsUsedNode[mi].id = landMeshMap.addMaterial(node->mesh->mats[mi], &matsUsedNode[mi].clipmapOnly, + &matsUsedNode[mi].has_vertex_opacity, nodeLayer, &isPatchNode); + +#if 0 + debug("node=%d, name='%s', splineLayer=%d, splineBatch=%d, nodeLayer=0x%08X, mi=%d, matId=%d", + i, node->name.str(), splineLayer, splineBatch, nodeLayer, mi, matsUsedNode[mi].id); +#endif + + if (matsUsedNode[mi].id >= 0) + { + mats_used++; + if (matsUsedNode[mi].has_vertex_opacity) + vertex_opacity_used++; + } + hasClipmapOnly |= matsUsedNode[mi].clipmapOnly; + hasCombined |= !matsUsedNode[mi].clipmapOnly; + isHeightPatch |= isPatchNode; + if (!isPatchNode) + hasPatchNodesOnly = false; + } + + if (isHeightPatch && !hasPatchNodesOnly) + con.addMessage(ILogWriter::ERROR, "node mesh <%s> has both height patches and other nodes!", (const char *)node->name); + if (hasClipmapOnly && hasCombined) + con.addMessage(ILogWriter::ERROR, "node mesh <%s> has both decals and landmesh_combined nodes. Currently not supported!", + (const char *)node->name); + if (vertex_opacity_used != 0 && vertex_opacity_used != mats_used) + { + if (reported_has_vertex_opacity < 16) + con.addMessage(ILogWriter::NOTE, "node mesh <%s> has partial vertex opacity!", node->name); + reported_has_vertex_opacity++; + } + + if (!mats_used) + { + erase_items(geoCont->nodes, i, 1); + --i; + continue; + } + + nodes.push_back(node); + + meshes.push_back(&node->mesh->mesh); + matUsed.push_back(matsUsedNode); + shouldRemoveUndegroundFaces.push_back(!hasClipmapOnly); + isDecal.push_back(hasClipmapOnly); + isPatch.push_back(isHeightPatch); + if (hasClipmapOnly) + decal_meshes++; + else + combined_meshes++; + } + con.endProgress(); + } + if (reported_has_vertex_opacity) + con.addMessage(ILogWriter::NOTE, "encountered %d errors with vertex opacity!", reported_has_vertex_opacity); + meshes.push_back(&mesh); + nodes.push_back(NULL); + con.addMessage(ILogWriter::NOTE, "%d decal meshes, %d combined meshes found", decal_meshes, combined_meshes); + if (import_sgeom) + con.addMessage(ILogWriter::NOTE, "Meshes joining: %d -> %d", geoCont->nodes.size(), landMeshMap.getMaterialsCount()); + + // for (int i = 0; i < mesh.face.size(); ++i) + // mesh.face[i].mat = 0; + + int totalAllFaces = 0; + int totalFaces = 0, totalVerts = 0; + for (int mi = 0; mi < meshes.size(); ++mi) + { + if (!meshes[mi]) + continue; + totalAllFaces += meshes[mi]->face.size(); + // if (!meshes[mi] || + // (nodes[mi] && !(nodes[mi]->flags&StaticGeometryNode::FLG_COLLIDABLE && should_collide[mi]))) + // continue; + totalVerts += meshes[mi]->vert.size(); + totalFaces += meshes[mi]->face.size(); + } + + int time1 = dagTools->getTimeMsec(); + con.setActionDesc("cutting meshes..."); + con.startProgress(); + con.setTotal(totalAllFaces); + Tab vert2Cell(tmpmem); + Mesh tmpmesh; + for (int mi = 0, cfaces = 0; mi < meshes.size(); ++mi) + { + // Node &node=*meshes[mi]; + Mesh *usemesh = meshes[mi]; + if (nodes[mi]) + { + tmpmesh = nodes[mi]->mesh->mesh; + usemesh = &tmpmesh; + if (tmpmesh.vertnorm.empty()) + { + // Generate normals for cliffs, castles and road ends. + tmpmesh.calc_ngr(); + tmpmesh.calc_vertnorms(); + } + /*else + { + // Invert road normals. + //fixme: should not be needed if uses mesh.transform() + for (unsigned int normNo = 0; normNo < usemesh->vertnorm.size(); normNo++) + usemesh->vertnorm[normNo] = -usemesh->vertnorm[normNo]; + }*/ + Mesh &mesh = tmpmesh; + mesh.transform(nodes[mi]->wtm); + bool has_vertex_opacity = false; + if (usemesh->tface[1].size()) + for (int mat = 0; mat < matUsed[mi].size(); ++mat) + if (matUsed[mi][mat].has_vertex_opacity) + { + has_vertex_opacity = true; + break; + } + int opaque_tvert = -1; + for (int vi = 0; vi < mesh.face.size(); ++vi) + { + int mat = mesh.face[vi].mat; + if (mat >= matUsed[mi].size()) + mat = matUsed[mi].size() - 1; + mesh.face[vi].mat = matUsed[mi][mat].id; + if (has_vertex_opacity && !matUsed[mi][mat].has_vertex_opacity) + { + if (opaque_tvert < 0) + { + opaque_tvert = usemesh->tvert[1].size(); + usemesh->tvert[1].push_back(Point2(1, 1)); + } + mesh.tface[1][vi].t[0] = mesh.tface[1][vi].t[1] = mesh.tface[1][vi].t[2] = opaque_tvert; + } + } + if (!has_vertex_opacity) + { + mesh.tface[1].resize(mesh.face.size()); + mem_set_0(mesh.tface[1]); + mesh.tvert[1].push_back(Point2(1, 1)); + } + if (shouldRemoveUndegroundFaces[mi]) + { + Bitarray facesAbove; + if (markUndergroundFaces(tmpmesh, facesAbove, NULL)) + tmpmesh.removeFacesFast(facesAbove); + } + } + + Mesh &mesh = *usemesh; + + int numRemoved = 0; + int origFaceCount = mesh.face.size(); + BBox3 meshBox; + for (int vi = 0; vi < mesh.vert.size(); ++vi) + meshBox += mesh.vert[vi]; + if (nodes[mi]) + { + for (int fi = mesh.face.size() - 1; fi >= 0; --fi) + if (mesh.face[fi].mat >= landMeshMap.getMaterialsCount()) + { + int j = fi - 1; + for (; j >= 0; --j) + if (mesh.face[j].mat < landMeshMap.getMaterialsCount()) + break; + j++; + mesh.removeFacesFast(j, fi - j + 1); + fi = j; + } + } + if (!mesh.face.size()) + { + cfaces += origFaceCount; + con.setDone(cfaces); + continue; + } + + // can be optimized by using binary(quad) tree of splits. + Mesh *prevY = new Mesh, *nextY = NULL; + split(mesh, *prevY, 0, 0, 1.f, -ofs.z, epsilon); + + if (!prevY->face.size()) + { + cfaces += origFaceCount; + con.setDone(cfaces); + continue; + } + + for (int cellY = 0; cellY < cells.getNumCellsY(); ++cellY) + { + if (nextY) + { + del_it(prevY); + prevY = nextY; + nextY = NULL; + } + if (!prevY->face.size()) + break; + nextY = new Mesh; + split(*prevY, *nextY, 0.f, 0.f, 1.f, + -((cellY + 1) * meshCellSize - ((cellY == cells.getNumCellsY() - 1) ? gridCellSize : 0) + ofs.z), epsilon); + if (!prevY->face.size()) + continue; + Mesh *prevX = new Mesh, *nextX = NULL; + split(*prevY, *prevX, 1.f, 0.f, 0.f, -ofs.x, epsilon); + if (!prevX->face.size()) + { + del_it(prevX); + continue; + } + prevX->optimize_tverts(-1.0); + for (int cellX = 0; cellX < cells.getNumCellsX(); ++cellX) + { + if (nextX) + { + del_it(prevX); + prevX = nextX; + nextX = NULL; + } + BBox3 cellBox; + cellBox[0] = ofs + Point3(cellX * cells.getCellSize(), MIN_REAL, cellY * cells.getCellSize()); + cellBox[1] = cellBox[0]; + cellBox[1].y = MAX_REAL; + cellBox[1] += Point3(cells.getCellSize(), 0, cells.getCellSize()); + if (!(meshBox & cellBox)) + continue; + + Mesh *destmesh = NULL; + if (!nodes[mi]) + destmesh = cells.getCellLandMesh(cellX, cellY, true); + else if (isPatch[mi]) + destmesh = cells.getCellPatchesMesh(cellX, cellY, true); + else + { + // fixme: we can support meshes with both decals and combineds! + if (isDecal[mi]) + destmesh = cells.getCellDecalMesh(cellX, cellY, true); + else + destmesh = cells.getCellCombinedMesh(cellX, cellY, true); + } + + if (!destmesh) + continue; + + Mesh &cellm = *destmesh; + if (!prevX->face.size()) + break; + nextX = new Mesh; + split(*prevX, *nextX, 1.f, 0.f, 0.f, + -((cellX + 1) * meshCellSize - ((cellX == cells.getNumCellsX() - 1) ? gridCellSize : 0) + ofs.x), epsilon); + if (!prevX->face.size()) + continue; + if (nodes[mi]) + prevX->optimize_tverts(-1.0); + cellm.attach(*prevX); + } + del_it(prevX); + del_it(nextX); + } + del_it(prevY); + del_it(nextY); + cfaces += mesh.face.size(); + con.setDone(cfaces); + } + + con.endProgress(); + con.addMessage(ILogWriter::REMARK, "Cutted in %g seconds", (dagTools->getTimeMsec() - time1) / 1000.0f); + + dagGeom->deleteStaticGeometryContainer(geoCont); + + int minFaces, maxFaces; + cells.getStats(minFaces, maxFaces, totalFaces); + + con.addMessage(ILogWriter::NOTE, "%dx%d cells, %d min, %d max, %d total faces", cells.getNumCellsX(), cells.getNumCellsY(), minFaces, + maxFaces, totalFaces); + + dag::Span cm = cells.getCells(); + + con.setActionDesc("optimizing meshes..."); + int time2 = dagTools->getTimeMsec(); + // multithreading: + const int max_cores = 128; + bool started[max_cores]; + int coresId[max_cores]; + int cores_count = 0; + for (int ci = 0; ci < min(max_cores, cpujobs::get_core_count()); ++ci) + if (!cpujobs::start_job_manager(ci, 32768)) + started[ci] = false; + else + { + started[ci] = true; + coresId[cores_count] = ci; + cores_count++; + } + int current_core = 0; + if (generate_ok && cores_count) + { + for (int i = 0; i < cm.size(); ++i) + { + cpujobs::add_job(coresId[current_core], new OptimizeJob(cm[i])); + current_core++; + current_core %= cores_count; + } + int iterations = 1000; + for (int ci = cores_count - 1; ci >= 0; --ci) + { + while (cpujobs::is_job_manager_busy(coresId[ci])) + { + ::sleep_msec(10); + iterations--; + if (!iterations) + { + cores_count = 0; + break; + } + } + cpujobs::stop_job_manager(coresId[ci], cores_count ? true : false); + } + if (!cores_count) + con.addMessage(ILogWriter::WARNING, "infinite run"); + } + if (generate_ok && !cores_count) + { + con.startProgress(); + con.setTotal(cm.size()); + for (int i = 0; i < cm.size(); ++i) + { + OptimizeJob job(cm[i]); + job.doJob(); + con.setDone(i + 1); + } + con.endProgress(); + } + con.addMessage(ILogWriter::REMARK, "Optimized in %g seconds", (dagTools->getTimeMsec() - time2) / 1000.0f); + int totalOutSize = 0; + landBox.setempty(); + SmallTab cellLandMeshes; + clear_and_resize(cellLandMeshes, cm.size()); + SmallTab cellCombinedMeshes; + clear_and_resize(cellCombinedMeshes, cm.size()); + for (int i = 0; i < cm.size(); ++i) + { + if (strip_det_hmap_from_tracer && cm[i].box[0].x + gridCellSize >= detRect[0].x && cm[i].box[1].x - gridCellSize <= detRect[1].x && + cm[i].box[0].z + gridCellSize >= detRect[0].y && cm[i].box[1].z - gridCellSize <= detRect[1].y) + { + debug("strip landMesh cell[%d] %@ (replaced by detaled HMAP)", i, cm[i].box); + cellLandMeshes[i] = NULL; + cellCombinedMeshes[i] = NULL; + if (game_tracer && cm[i].combined_mesh && cm[i].combined_mesh->getFaceCount()) + { + cellCombinedMeshes[i] = cm[i].combined_mesh; + for (int j = 0; j < cellCombinedMeshes[i]->vert.size(); j++) + landBox += cellCombinedMeshes[i]->vert[j]; + } + } + else + { + cellLandMeshes[i] = cm[i].land_mesh; + cellCombinedMeshes[i] = cm[i].combined_mesh; + landBox += cm[i].box; + } + } + + { + con.setActionDesc("building land tracer..."); + LandRayTracer *lrt = new LandRayTracer; + landMeshMap.setGameLandRayTracer(lrt); + int minGrid = 8, maxGrid = 32; + bool built = lrt->build(cells.getNumCellsX(), cells.getNumCellsY(), meshCellSize, ofs, landBox, cellLandMeshes, cellCombinedMeshes, + minGrid, maxGrid, true); + if (!built) + { + landMeshMap.setGameLandRayTracer(NULL); + DAEDITOR3.conError("Can't build landtracer."); + } + if (game_tracer) + { + *game_tracer = lrt = new LandRayTracer; + built = lrt->build(cells.getNumCellsX(), cells.getNumCellsY(), meshCellSize, ofs, landBox, cellLandMeshes, cellCombinedMeshes, + minGrid, maxGrid, false); + if (!built) + { + del_it(game_tracer[0]); + DAEDITOR3.conError("Can't build game landtracer."); + generate_ok = false; + } + } + } + if (strip_det_hmap_from_tracer) + { + mem_set_0(cellCombinedMeshes); + + int minGrid = 8, maxGrid = 32; + EditorLandRayTracer *lrt = new EditorLandRayTracer; + if (lrt->build(cells.getNumCellsX(), cells.getNumCellsY(), meshCellSize, ofs, landBox, cellLandMeshes, cellCombinedMeshes, minGrid, + maxGrid, true)) + landMeshMap.setEditorLandRayTracer(lrt); + else + { + delete lrt; + DAEDITOR3.conError("Can't build landtracer for editor (with stripped DET HMAP), resetting main landtracer."); + landMeshMap.setEditorLandRayTracer(nullptr); + } + } + + landBox.setempty(); + for (int cellY = 0; cellY < cells.getNumCellsY(); ++cellY) + for (int cellX = 0; cellX < cells.getNumCellsX(); ++cellX) + landBox += cells.getBBox(cellX, cellY); + + float y0 = 0.5 * (landBox[1].y + landBox[0].y); + float denominator = landBox[1].y - landBox[0].y; + float inv_scale = denominator > REAL_EPS ? 2.f / denominator : 0.f; + Point3 cellScale(2.f / cells.getCellSize(), inv_scale, 2.f / cells.getCellSize()); + Point3 invCellScale(1.0f / cellScale.x, 1.0f / cellScale.y, 1.0f / cellScale.z); + debug("compress landMesh ht=(%.3f, %.3f), eps=%.4f ofs=%@", landBox[0].y, landBox[1].y, denominator / 65536, ofs); + for (int cellY = 0; cellY < cells.getNumCellsY(); ++cellY) + for (int cellX = 0; cellX < cells.getNumCellsX(); ++cellX) + { + Point3 cellOfs((cellX + 0.5) * cells.getCellSize(), y0, (cellY + 0.5) * cells.getCellSize()); + cellOfs += ofs; + + Mesh *cellm = cells.getCellLandMesh(cellX, cellY, true); + if (cellm) + compress_land_position(cellOfs, cellScale, *cellm, false); + + cellm = cells.getCellDecalMesh(cellX, cellY, false); + if (cellm) + compress_land_position(cellOfs, cellScale, *cellm, true); //== get from material + + cellm = cells.getCellCombinedMesh(cellX, cellY, false); + if (cellm) + compress_land_position(cellOfs, cellScale, *cellm, true); //== get from material + + cellm = cells.getCellPatchesMesh(cellX, cellY, false); + if (cellm) + compress_land_position(cellOfs, cellScale, *cellm, true); //== get from material + } + + // resync border taking into account landmesh vertex quantization + if (strip_det_hmap_from_tracer) + { + int step = 32, w = (detRectC[1].x - detRectC[0].x) / step, h = (detRectC[1].y - detRectC[0].y) / step; + + for (int i = 0; i < det_hmap_border.size(); i++) + { + short sy = real2int(clamp((det_hmap_border[i].y - y0) * inv_scale, -1.f, 1.f) * 32767.0); + det_hmap_border[i].y = (sy / 32767.0) * denominator / 2 + y0; + } + + float ht, t; + for (int x = detRectC[0].x, i = 0; x < detRectC[1].x; x++, i++) + { + t = x + 1 < detRectC[1].x ? float(i % step) / step : 1.0f; + ht = lerp(det_hmap_border[i / step].y, det_hmap_border[i / step + 1].y, t); + heightMapDet.setFinalData(x, detRectC[0].y, ht); + + ht = lerp(det_hmap_border[2 * w + h - i / step].y, det_hmap_border[2 * w + h - i / step - 1].y, t); + heightMapDet.setFinalData(x, detRectC[1].y - 1, ht); + } + for (int y = detRectC[0].y, i = 0; y < detRectC[1].y; y++, i++) + { + t = y + 1 < detRectC[1].y ? float(i % step) / step : 1.0f; + ht = lerp(det_hmap_border[2 * w + 2 * h - i / step].y, det_hmap_border[2 * w + 2 * h - i / step - 1].y, t); + heightMapDet.setFinalData(detRectC[0].x, y, ht); + + ht = lerp(det_hmap_border[w + i / step].y, det_hmap_border[w + i / step + 1].y, t); + heightMapDet.setFinalData(detRectC[1].x - 1, y, ht); + } + updateHeightMapTex(true); + } + + cells.setOffset(ofs); + con.endProgress(); + con.endLog(); + if (!generate_ok) + landMeshMap.clear(true); + guard_det_border = true; + + if (generate_ok) + rebuildLandmeshDump(); + return generate_ok; +} + +void HmapLandPlugin::clearTexCache() +{ + if (landMeshRenderer) + hmlService->resetTexturesLandMesh(*landMeshRenderer); + + if (lmlightmapTexId != BAD_TEXTUREID) + dagRender->releaseManagedTexVerified(lmlightmapTexId, lmlightmapTex); + if (landMeshManager) + for (int i = 0; i < landMeshManager->getDetailMap().cells.size(); i++) + mem_set_ff(landMeshManager->getDetailMap().cells[i].detTexIds); +} +void HmapLandPlugin::refillTexCache() +{ + if (!landMeshManager) + return; + for (int i = 0; i < landMeshManager->getDetailMap().cells.size(); i++) + updateLandDetailTexture(i); +} + +void HmapLandPlugin::updateLandDetailTexture(unsigned i) +{ + if (!landMeshManager || landMeshManager->getDetailMap().cells.size() <= i) + return; + + LoadElement &element = landMeshManager->getDetailMap().cells[i]; + int num_elems_x = landMeshManager->getDetailMap().sizeX; + int elemSize = landMeshManager->getDetailMap().texElemSize; + int texSize = landMeshManager->getDetailMap().texSize; + + bool done; + loadLandDetailTexture(i % num_elems_x, i / num_elems_x, (Texture *)element.tex1, (Texture *)element.tex2, element.detTexIds, &done, + texSize, elemSize); +} + +void HmapLandPlugin::resetTexCacheRect(const IBBox2 &box_) +{ + if (!landMeshManager) + return; + + int num_elems_x = landMeshManager->getDetailMap().sizeX; + int elemSize = landMeshManager->getDetailMap().texElemSize; + + IBBox2 box = box_; + if (detDivisor) + box[0] /= detDivisor, box[1] /= detDivisor; + + for (int y = box[0].y; y <= box[1].y; y += elemSize) + for (int x = box[0].x; x <= box[1].x; x += elemSize) + { + int i = (x / elemSize) + (y / elemSize) * num_elems_x; + updateLandDetailTexture(i); + } +} + +float HmapLandPlugin::getLandCellSize() const { return landMeshMap.getCellSize(); } + +Point3 HmapLandPlugin::getOffset() const { return landMeshMap.getOffset(); } + +int HmapLandPlugin::getNumCellsX() const { return landMeshMap.getNumCellsX(); } + +int HmapLandPlugin::getNumCellsY() const { return landMeshMap.getNumCellsY(); } + +IPoint2 HmapLandPlugin::getCellOrigin() const { return landMeshMap.getOrigin(); } + +const IBBox2 *HmapLandPlugin::getExclCellBBox() +{ + static IBBox2 bb; + if (!detDivisor) + return NULL; + bb[0].set_xy((detRect[0] - heightMapOffset) / getLandCellSize()); + bb[1].set_xy((detRect[1] - heightMapOffset) / getLandCellSize()); + return &bb; +} + +bool HmapLandPlugin::validateBuild(int target, ILogWriter &rep, PropPanel2 *params) +{ + if (!useMeshSurface || exportType == EXPORT_PSEUDO_PLANE) + return true; +#if defined(USE_LMESH_ACES) + int ox = landMeshMap.getOffset().x / landMeshMap.getCellSize(); + int oz = landMeshMap.getOffset().z / landMeshMap.getCellSize(); + if (landMeshMap.getOrigin().x || landMeshMap.getOrigin().y) + { + DAEDITOR3.conError("Landmesh: origin must be zero, but is %d,%d", landMeshMap.getOrigin().x || landMeshMap.getOrigin().y); + return false; + } + if (fabs(landMeshMap.getOffset().x - ox * landMeshMap.getCellSize()) + + fabs(landMeshMap.getOffset().z - oz * landMeshMap.getCellSize()) > + 0.1) + { + DAEDITOR3.conError("Landmesh: offset=" FMT_P3 " is not multiple of cellSize=%.3f", P3D(landMeshMap.getOffset()), + landMeshMap.getCellSize()); + return false; + } +#endif + return true; +} + +bool HmapLandPlugin::addUsedTextures(ITextureNumerator &tn) +{ + if (!useMeshSurface || exportType == EXPORT_PSEUDO_PLANE) + return true; + + String prj; + DAGORED2->getProjectFolderPath(prj); + String ltmap_fn = ::make_full_path(prj, "builtScene/lightmap.tga"); + + DataBlock app_blk; + if (!app_blk.load(DAGORED2->getWorkspace().getAppPath())) + DAEDITOR3.conError("cannot read <%s>", DAGORED2->getWorkspace().getAppPath()); + const DataBlock *cvtBlk = app_blk.getBlockByNameEx("heightMap")->getBlockByName("lightmapCvtProps"); + + if (cvtBlk) + { + calcGoodLandLighting(); + resetRenderer(); + } + if (::dd_file_exist(ltmap_fn) && cvtBlk) + { + String a_name(0, "%s_lightmap", dd_get_fname(prj)); + DataBlock a_props; + TextureMetaData tmd; + ddsx::Buffer b; + + a_props = *cvtBlk; + a_props.setBool("convert", true); + a_props.setStr("name", ltmap_fn); + tmd.read(a_props, mkbindump::get_target_str(tn.getTargetCode())); + tmd.mqMip -= tmd.hqMip; + tmd.lqMip -= tmd.hqMip; + tmd.hqMip = 0; + + if (DAEDITOR3.getTexAssetBuiltDDSx(a_name + "~lev", a_props, b, tn.getTargetCode(), NULL, &DAGORED2->getConsole())) + tn.addDDSxTexture(tmd.encode("$_lightmap*"), b); + else + DAEDITOR3.conError("failed to build lightmap for export: %s", ltmap_fn); + } + + // bool use_sgeom = false; (code was unused and removed) + + return true; +} + +extern bool hmap_export_tex(mkbindump::BinDumpSaveCB &cb, const char *tex_name, const char *fname, bool clamp, bool gamma1); + +extern int hmap_export_dds_as_ddsx_raw(mkbindump::BinDumpSaveCB &cb, char *data, int size, int w, int h, int bpp, int levels, int fmt, + bool gamma1); + +extern bool aces_export_detail_maps(mkbindump::BinDumpSaveCB &cb, int det_map_w, int det_map_h, int tex_elem_size, + const Tab &landclass_names, int base_ofs, bool optimize_size = false, bool tools_internal = false); + + +class LandRaySaver +{ +public: + static void save(mkbindump::BinDumpSaveCB &cb, LandRayTracer <) + { + cb.writeRaw((void *)"LTdump", 6); + cb.writeInt32e(lt.numCellsX); + cb.writeInt32e(lt.numCellsY); + cb.writeReal(lt.cellSize); + cb.writeReal(lt.offset.x); + cb.writeReal(lt.offset.y); + cb.writeReal(lt.offset.z); + cb.writeReal(lt.bbox[0].x); + cb.writeReal(lt.bbox[0].y); + cb.writeReal(lt.bbox[0].z); + cb.writeReal(lt.bbox[1].x); + cb.writeReal(lt.bbox[1].y); + cb.writeReal(lt.bbox[1].z); + + Tab cellsD(tmpmem); + lt.convertCellsToOut(cellsD); + + cb.writeInt32e(cellsD.size()); + cb.write32ex(cellsD.data(), data_size(cellsD)); + cb.writeInt32e(lt.grid.size()); + cb.writeTabData32e(lt.grid); + cb.writeInt32e(lt.gridHt.size()); + cb.write32ex(lt.gridHt.data(), data_size(lt.gridHt)); + cb.writeInt32e(lt.allFaces.size()); + cb.writeTabData16e(lt.allFaces); + cb.writeInt32e(lt.allVerts.size()); + cb.write32ex(lt.allVerts.data(), data_size(lt.allVerts)); + cb.writeInt32e(lt.faceIndices.size()); + cb.writeTabData16e(lt.faceIndices); + } +}; + +static void exportRayTracersToGame(mkbindump::BinDumpSaveCB &cwr, LandRayTracer *lrt) +{ + int time0 = dagTools->getTimeMsec(); + CoolConsole &con = DAGORED2->getConsole(); + con.setActionDesc("saving lmesh tracers..."); + cwr.beginBlock(); + if (lrt) + { + // todo: add zlib compression + int size = cwr.tell(); + LandRaySaver::save(cwr, *lrt); + size = cwr.tell() - size; + con.addMessage(ILogWriter::NOTE, "landray tracer saved %d bytes", size); + } + else + con.addMessage(ILogWriter::WARNING, "No landray tracer"); + cwr.endBlock(); +} + +extern int exportImageAsDds(mkbindump::BinDumpSaveCB &cb, TexPixel32 *image, int size, int format, int mipmap_count, bool gamma1); + +extern void buildLightTexture(TexPixel32 *image, MapStorage &lightmap, int tex_data_sizex, int tex_data_sizey, int stride, + int map_x, int map_y, bool use_normal_map); + +TEXTUREID HmapLandPlugin::getLightMap() +{ + if (!hasLightmapTex) + return BAD_TEXTUREID; + + if (lmlightmapTexId != BAD_TEXTUREID) //== + return lmlightmapTexId; + if (!lmlightmapTex) + { + lmlightmapTex = + d3d::create_tex(NULL, lightMapScaled.getMapSizeX(), lightMapScaled.getMapSizeY(), TEXFMT_A8R8G8B8, 1, "lmesh_lightmap"); + + d3d_err(lmlightmapTex); + lmlightmapTex->texaddr(TEXADDR_CLAMP); + lmlightmapTexId = dagRender->registerManagedTex(String(32, "lightmap_hmap_%p", lmlightmapTex), lmlightmapTex); + } + + SmallTab image; + clear_and_resize(image, lightMapScaled.getMapSizeX() * lightMapScaled.getMapSizeY()); + buildLightTexture(&image[0], lightMapScaled, lightMapScaled.getMapSizeX(), lightMapScaled.getMapSizeY(), + lightMapScaled.getMapSizeX(), 0, 0, useNormalMap); + + int stride; + uint8_t *p; + if (((Texture *)lmlightmapTex)->lockimg((void **)&p, stride, 0, TEXLOCK_WRITE)) + { + memcpy(p, image.data(), lightMapScaled.getMapSizeX() * lightMapScaled.getMapSizeY() * 4); + ((Texture *)lmlightmapTex)->unlockimg(); + } + return lmlightmapTexId; +} + +int HmapLandPlugin::markUndergroundFaces(MeshData &mesh, Bitarray &facesAbove, TMatrix *wtm) +{ + struct HMDetTR2 + { + int lodDiv; + HMDetTR2() : lodDiv(1) {} + + static Point3 getHeightmapOffset() { return HmapLandPlugin::self->getHeightmapOffset(); } + int getHeightmapSizeX() const { return HMDetTR::getHeightmapSizeX() / lodDiv; } + int getHeightmapSizeY() const { return HMDetTR::getHeightmapSizeY() / lodDiv; } + real getHeightmapCellSize() const { return HMDetTR::getHeightmapCellSize() * lodDiv; } + bool getHeightmapCell5Pt(const IPoint2 &_cell, real &h0, real &hx, real &hy, real &hxy, real &hmid) const + { + IPoint2 cell = _cell * lodDiv; + if (HmapLandPlugin::self->insideDetRectC(cell) && HmapLandPlugin::self->insideDetRectC(cell.x + lodDiv, cell.y + lodDiv)) + { + h0 = HmapLandPlugin::self->heightMapDet.getFinalData(cell.x, cell.y); + hx = HmapLandPlugin::self->heightMapDet.getFinalData(cell.x + lodDiv, cell.y); + hy = HmapLandPlugin::self->heightMapDet.getFinalData(cell.x, cell.y + lodDiv); + hxy = HmapLandPlugin::self->heightMapDet.getFinalData(cell.x + lodDiv, cell.y + lodDiv); + + hmid = (h0 + hx + hy + hxy) * 0.25f; + return true; + } + return false; + } + }; + + if (!mesh.face.size()) + return 0; + EditorLandRayTracer *tracer = landMeshMap.getEditorLandRayTracer(); + if (!tracer) + return 0; + Bitarray vertsBelow; + vertsBelow.resize(mesh.vert.size()); + vertsBelow.reset(); + const float heightEps = max(tracer->getBBox().width().y * 0.0001f, 0.00001f); + const float maxHeight = tracer->getBBox()[1].y + 1.f; + int vertsBelowCnt = 0; + SmallTab vertMem; + Point3 *vertPtr = mesh.vert.data(); + if (wtm) + { + clear_and_resize(vertMem, mesh.vert.size()); + vertPtr = vertMem.data(); + } + dag::Span vert(vertPtr, mesh.vert.size()); + HMDetTR2 det_hm; + for (int vi = 0; vi < mesh.vert.size(); ++vi) + { + if (wtm) + vert[vi] = (*wtm) * mesh.vert[vi]; + float ht = vert[vi].y + heightEps; + float det_ht = ht; + + if (detDivisor && (detRect & Point2::xz(vert[vi]))) + { + if (get_height_midpoint_heightmap(det_hm, Point2::xz(vert[vi]), det_ht, NULL)) + if (det_ht >= ht) + { + vertsBelow.set(vi); + vertsBelowCnt++; + } + } + else if (tracer->getHeightBelow(Point3::xVz(vert[vi], maxHeight), det_ht, NULL)) + { + if (det_ht >= ht) + { + vertsBelow.set(vi); + vertsBelowCnt++; + } + } + } + if (vertsBelowCnt == 0) // nothing to remove + return 0; + facesAbove.resize(mesh.face.size()); + facesAbove.set(); + int facesBelowCnt = 0; + // fixme: optimize, instead of checking each edge as many times, as there adjacent faces, better do this once + for (int fi = 0; fi < mesh.face.size(); ++fi) + { + Face &f = mesh.face[fi]; + if (!vertsBelow[f.v[0]] || !vertsBelow[f.v[1]] || !vertsBelow[f.v[2]]) + continue; + Point3 v0 = vert[f.v[0]], v1 = vert[f.v[1]], v2 = vert[f.v[2]]; + float mint; + mint = 1.00001f; + if (tracer->traceRay(v0, v1 - v0, mint, NULL)) + continue; + mint = 1.00001f; + if (tracer->traceRay(v0, v2 - v0, mint, NULL)) + continue; + mint = 1.00001f; + if (tracer->traceRay(v1, v2 - v1, mint, NULL)) + continue; + if (detDivisor) + { + bool cross = false; + det_hm.lodDiv = 1; + for (int lod = 0; lod < 6; lod++) + { + mint = length(v1 - v0) * 1.00001f; + if (mint >= 1e-6 && ::trace_ray_midpoint_heightmap(det_hm, v0, (v1 - v0) / mint, mint, NULL)) + { + cross = true; + break; + } + mint = length(v2 - v0) * 1.00001f; + if (mint >= 1e-6 && ::trace_ray_midpoint_heightmap(det_hm, v0, (v2 - v0) / mint, mint, NULL)) + { + cross = true; + break; + } + mint = length(v2 - v1) * 1.00001f; + if (mint >= 1e-6 && ::trace_ray_midpoint_heightmap(det_hm, v1, (v2 - v1) / mint, mint, NULL)) + { + cross = true; + break; + } + det_hm.lodDiv <<= 1; + } + if (cross) + continue; + } + + facesAbove.reset(fi); + facesBelowCnt++; + } + return facesBelowCnt; +} + +void HmapLandPlugin::removeInvisibleFaces(StaticGeometryContainer &container) +{ + if (!landMeshMap.getEditorLandRayTracer()) + return; + CoolConsole &con = DAGORED2->getConsole(); + con.setActionDesc("removing undeground faces..."); + con.startProgress(); + + con.setTotal(container.nodes.size() / 128); + int totalFaces = 0, removedFaces = 0; + int time0 = dagTools->getTimeMsec(); + Bitarray facesAbove; + + for (int i = 0; i < container.nodes.size(); ++i) + { + if (!(i & 127)) + con.setDone(i / 128); + + StaticGeometryNode *node = container.nodes[i]; + + if (!node || !node->mesh) + continue; + if (!node->mesh->mesh.check_mesh()) + { + con.addMessage(ILogWriter::WARNING, "node mesh <%s> is invalid.", (const char *)node->name); + continue; + } + MeshData &mesh = node->mesh->mesh; + totalFaces += mesh.face.size(); + facesAbove.eraseall(); + int facesBelowCnt = markUndergroundFaces(mesh, facesAbove, &node->wtm); + if (!facesBelowCnt) + continue; + if (node->mesh->getRefCount() > 1) // clone to remove + { + StaticGeometryMesh *newMesh = new StaticGeometryMesh; + newMesh->mats = node->mesh->mats; + newMesh->mesh = node->mesh->mesh; + newMesh->user_data = node->mesh->user_data; + node->mesh = newMesh; + } + node->mesh->mesh.removeFacesFast(facesAbove); + removedFaces += facesBelowCnt; + } + con.endProgress(); + if (totalFaces) + con.addMessage(ILogWriter::NOTE, "removed %d undeground faces out of %d (%02d%%) in %dms", removedFaces, totalFaces, + removedFaces * 100 / totalFaces, dagTools->getTimeMsec() - time0); + else + con.addMessage(ILogWriter::NOTE, "no faces for removal in %dms", dagTools->getTimeMsec() - time0); +} + +bool HmapLandPlugin::exportLandMesh(mkbindump::BinDumpSaveCB &cb, IWriterToLandmesh *land_modifier, LandRayTracer *landRayTracer, + bool tools_internal) +{ + int time0 = dagTools->getTimeMsec(); + CoolConsole &con = DAGORED2->getConsole(); + if (requireTileTex && tileTexId == BAD_TEXTUREID) + { + con.addMessage(ILogWriter::FATAL, "HeightMap tile texture is missing!"); + return false; + } + con.startLog(); + + // write additional geometry to landmesh + if (land_modifier) + land_modifier->writeToLandmesh(landMeshMap); + + bool game_res_sys_v2 = false; + { + DataBlock app_blk; + if (!app_blk.load(DAGORED2->getWorkspace().getAppPath())) + DAEDITOR3.conError("cannot read <%s>", DAGORED2->getWorkspace().getAppPath()); + game_res_sys_v2 = app_blk.getBlockByNameEx("assets")->getBlockByName("export") != NULL; + } + G_ASSERT(game_res_sys_v2); + cb.writeRaw("lndm", 4); + cb.writeInt32e(4); // version + + cb.writeReal(getGridCellSize()); + cb.writeReal(landMeshMap.getCellSize()); + cb.writeInt32e(landMeshMap.getNumCellsX()); + cb.writeInt32e(landMeshMap.getNumCellsY()); + cb.writeInt32e(landMeshMap.getOffset().x / landMeshMap.getCellSize()); + cb.writeInt32e(landMeshMap.getOffset().z / landMeshMap.getCellSize()); + + // write collision area settings + + cb.writeInt32e(requireTileTex ? 1 : 0); // use tile or don't use tile + + int headerOfs = cb.tell(); + + cb.writeInt32e(0); // mesh data offset + cb.writeInt32e(0); // detail data offset + cb.writeInt32e(0); // tile data offset + cb.writeInt32e(0); // ray tracer data offset + + // export heightmap data + int meshOfs = cb.tell(); + // exportLandMeshToGame(cb, landMeshMap); + { + MaterialData mat; + mat.className = "land_mesh"; + Ptr material = dagGeom->newShaderMaterial(mat); + if (material) + { + struct CountChannels : public ShaderChannelsEnumCB + { + int cnt = 0, code_flags = 0; + void enum_shader_channel(int, int, int, int, int, ChannelModifier, int) override { cnt++; } + }; + CountChannels ch_cnt; + if (!material->enum_channels(ch_cnt, ch_cnt.code_flags) || !ch_cnt.cnt) + { + DAEDITOR3.conNote("stub shader used for '%s', exporting lanmesh without renderable geom", "land_mesh"); + material = nullptr; + } + } + + int numMat = material ? landMeshMap.getMaterialsCount() : 0; + Tab materials(tmpmem); + materials.reserve(numMat); + for (int i = 0; i < numMat; ++i) + materials.push_back(landMeshMap.getMaterialData(i)); + + if (!hmlService->exportToGameLandMesh(cb, landMeshMap.getCells(), materials, lod1TrisDensity, tools_internal)) + return false; + } + DAGORED2->getConsole().addMessage(ILogWriter::REMARK, "exported lmesh geometry in %g seconds (LOD1 density=%d%%)", + (dagTools->getTimeMsec() - time0) / 1000.0, lod1TrisDensity); + time0 = dagTools->getTimeMsec(); + + // export detail maps and textures + int detailDataOfs = cb.tell(); + int dmw = detTexWtMap ? detTexWtMap->getMapSizeX() : landClsMap.getMapSizeX(); + int dmh = detTexWtMap ? detTexWtMap->getMapSizeY() : landClsMap.getMapSizeY(); + int dm_tex_elem_size = (landMeshMap.getCellSize() / gridCellSize) * (detTexWtMap ? 1 : lcmScale); + if (dmw / dm_tex_elem_size != landMeshMap.getNumCellsX() || dmh / dm_tex_elem_size != landMeshMap.getNumCellsY()) + { + DAEDITOR3.conError("bad detMapSz=%dx%d and elemSz=%d gives elems=%dx%d while cells are %dx%d\n" + " (detTexWtMap=%dx%d landClsMap=%dx%d lcmScale=%d)", + dmw, dmh, dm_tex_elem_size, dmw / dm_tex_elem_size, dmh / dm_tex_elem_size, landMeshMap.getNumCellsX(), + landMeshMap.getNumCellsY(), detTexWtMap ? detTexWtMap->getMapSizeX() : 0, detTexWtMap ? detTexWtMap->getMapSizeY() : 0, + landClsMap.getMapSizeX(), landClsMap.getMapSizeY(), lcmScale); + + dm_tex_elem_size = dmw / landMeshMap.getNumCellsX(); + if (dm_tex_elem_size != dmh / landMeshMap.getNumCellsY()) + { + DAEDITOR3.conError("failed to export color/detail maps: corrected elems=%dx%d wile cells is %dx%d", dmw / dm_tex_elem_size, + dmh / dm_tex_elem_size, landMeshMap.getNumCellsX(), landMeshMap.getNumCellsY()); + return false; + } + } + if (!aces_export_detail_maps(cb, dmw, dmh, dm_tex_elem_size, detailTexBlkName, headerOfs, true, tools_internal)) + { + DAEDITOR3.conError("failed to export color/detail maps"); + return false; + } + + DAGORED2->getConsole().addMessage(ILogWriter::REMARK, "exported lmesh detailmaps in %g seconds", + (dagTools->getTimeMsec() - time0) / 1000.0); + time0 = dagTools->getTimeMsec(); + + int tileDataOfs = cb.tell(); + if (requireTileTex) + { + // export tile map + DAGORED2->getConsole().addMessage(ILogWriter::REMARK, "exporting tile map..."); + + hmap_export_tex(cb, tileTexName, tileTexName, false, false); + + cb.writeReal(tileXSize * gridCellSize); + cb.writeReal(tileYSize * gridCellSize); + } + + DAGORED2->getConsole().addMessage(ILogWriter::REMARK, "exported tile tex in %g seconds", (dagTools->getTimeMsec() - time0) / 1000.0); + time0 = dagTools->getTimeMsec(); + + int rayTracerOffset = cb.tell(); + if (!landRayTracer) + rayTracerOffset = headerOfs; + else + { + mkbindump::BinDumpSaveCB cwr_lt(2 << 10, cb.getTarget(), cb.WRITE_BE); + exportRayTracersToGame(cwr_lt, landRayTracer); + + cb.beginBlock(); + MemoryLoadCB mcrd(cwr_lt.getMem(), false); + if (preferZstdPacking && allowOodlePacking) + { + cb.writeInt32e(cwr_lt.getSize()); + oodle_compress_data(cb.getRawWriter(), mcrd, cwr_lt.getSize()); + } + else if (preferZstdPacking) + zstd_compress_data(cb.getRawWriter(), mcrd, cwr_lt.getSize(), 1 << 20, 19); + else + lzma_compress_data(cb.getRawWriter(), 9, mcrd, cwr_lt.getSize()); + cb.endBlock(preferZstdPacking ? (allowOodlePacking ? btag_compr::OODLE : btag_compr::ZSTD) : btag_compr::UNSPECIFIED); + rayTracerOffset += 4; + } + + int resultOffset = cb.tell(); + cb.seekto(headerOfs); + cb.writeInt32e(meshOfs - headerOfs); + cb.writeInt32e(detailDataOfs - headerOfs); + cb.writeInt32e(tileDataOfs - headerOfs); + cb.writeInt32e(rayTracerOffset - headerOfs); + cb.seekto(resultOffset); + con.endLog(); + +#if defined(USE_LMESH_ACES) + if (!useVertTex || vertTexAng0 >= vertTexAng1 || vertTexName.empty()) + cb.writeDwString(""); + else + { + String tex_str(256, "%s*:%s*", vertTexName.str(), vertNmTexName.str()); + if (!useVertTexForHMAP && detDivisor) + tex_str.append("!"); + cb.writeDwString(tex_str); + cb.writeReal(1.f / max(vertTexXZtile, 1e-3f)); + cb.writeReal(1.f / max(vertTexYtile, 1e-3f)); + cb.writeReal(cosf(DEG_TO_RAD * vertTexAng0)); + cb.writeReal(cosf(DEG_TO_RAD * vertTexAng1)); + cb.writeReal(vertTexHorBlend); + cb.writeReal(vertTexYOffset / max(vertTexYtile, 1e-3f)); + cb.writeDwString(String(256, "%s*", vertDetTexName.str())); + cb.writeReal(1.f / max(vertDetTexXZtile, 1e-3f)); + cb.writeReal(1.f / max(vertDetTexYtile, 1e-3f)); + cb.writeReal(vertDetTexYOffset / max(vertDetTexYtile, 1e-3f)); + } +#endif + return true; +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/jamfile b/prog/tools/sceneTools/daEditorX/HeightmapLand/jamfile new file mode 100644 index 000000000..c97d5b0d2 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/jamfile @@ -0,0 +1,15 @@ +Platform ?= win64 ; +Root ?= ../../../../.. ; +Location = prog/tools/sceneTools/daEditorX/HeightmapLand ; +DriverLinkage = dynamic ; +include $(Root)/prog/tools/tools_setup.jam ; + +TargetType = util ; +Target = Hmap_plugin_dll ; + +Dependencies = + $(Root)/$(Location)/jamfile-classic + $(Root)/$(Location)/jamfile-aces +; + +include $(Root)/prog/_jBuild/build.jam ; diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/jamfile-aces b/prog/tools/sceneTools/daEditorX/HeightmapLand/jamfile-aces new file mode 100644 index 000000000..272e5ea86 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/jamfile-aces @@ -0,0 +1,114 @@ +Root ?= ../../../../.. ; +Location = prog/tools/sceneTools/daEditorX/HeightmapLand ; +DriverLinkage = dynamic ; +include $(Root)/prog/tools/tools_setup.jam ; +UseQuirrel = sq3+ ; + +TargetType = dll ; +Target = tools/sceneTools/daEditorX/heightmapLand-aces.dll ; +OutDir = $(Root)/tools/dagor3_cdk/bin/plugins/de3x ; +if $(Platform) = win64 { OutDir = $(Root)/tools/dagor3_cdk/bin64/plugins/de3x ; } + +AddIncludes = + $(Root)/prog/tools/sceneTools/daEditorX/include + $(Root)/prog/tools/sharedInclude + $(Root)/prog/engine/sharedInclude + $(Root)/prog/gameLibs/publicInclude + $(Root)/prog/gameLibs/publicInclude/squirrel + $(Root)/prog/3rdPartyLibs/Recast/Include + $(Root)/prog/3rdPartyLibs/Detour/Include +; + +Sources = + renderLandNormals.cpp + hmlExportHmap.cpp + hmlClipping.cpp + hmlExport.cpp + hmlObject.cpp + hmlLayers.cpp + hmlSplineObject.cpp + hmlSplinePoint.cpp + hmlGenColorMap.cpp + hmlImport.cpp + hmlEventHandler.cpp + hmlIGenEditorPlugin.cpp + hmlMain.cpp + hmlModifiers.cpp + hmlPanel.cpp + hmlPlugin.cpp + hmlExportSizeDlg.cpp + hmlEditorEH.cpp + hmlSplineTriangulation.cpp + hmlSplineModifier.cpp + hmlImportExport.cpp + hmlSplineMask.cpp + hmlLmeshHtConstrMask.cpp + hmlRivers.cpp + common.cpp + loftObject.cpp + hmlEntity.cpp + hmlLight.cpp + hmlHoleObject.cpp + hmlSnow.cpp + LandClassSlotsMgr.cpp + entityCopyDlg.cpp + materialMgr.cpp + buildRoad.cpp + roadsSnapshot.cpp + importLandMesh.cpp + waterSurfGen.cpp + hmlExportSplines.cpp + hmlSelTexDlg.cpp + gpuGrassPanel.cpp + + Brushes/hmlBrush.cpp + Brushes/hmlHillBrush.cpp + Brushes/hmlSmoothBrush.cpp + Brushes/brushMask.cpp + Brushes/hmlAlignBrush.cpp + Brushes/hmlShadowsBrush.cpp + Brushes/hmlScriptBrush.cpp + + objectParam.cpp + + recastNavMesh.cpp +; + + +UseProgLibs = + tools/sceneTools/daEditorX/de3dllCore + tools/libTools/assetMgr + tools/libTools/delaunay + tools/libTools/winGuiWrapper + tools/libTools/staticGeom + tools/libTools/dagFileRW + gameLibs/landMesh + engine/SceneRay + engine/image + engine/perfMon/daProfilerStub + + 3rdPartyLibs/math/DelaunayTriangulator + 3rdPartyLibs/math/clipper-4.x + 3rdPartyLibs/math/misc + 3rdPartyLibs/hash + 3rdPartyLibs/image/tiff-4.4.0 + + 3rdPartyLibs/Recast + 3rdPartyLibs/Detour + gameLibs/pathFinder + gameLibs/pathFinder/tileCache/stub + gameLibs/pathFinder/customNav/stub + gameLibs/recastTools + gameLibs/covers +; + +ImportProgLibs = + tools/libTools/daKernel +; + + +CPPopt = -DUSE_HMAP_ACES=1 -DUSE_LMESH_ACES=1 ; +LINKopt = -def:$(Root)/prog/tools/sceneTools/daEditorX/de3dllCore/de3_plugin.def ; + + +include $(Root)/prog/_jBuild/build.jam ; diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/jamfile-classic b/prog/tools/sceneTools/daEditorX/HeightmapLand/jamfile-classic new file mode 100644 index 000000000..d3d3f4442 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/jamfile-classic @@ -0,0 +1,110 @@ +Root ?= ../../../../.. ; +Location = prog/tools/sceneTools/daEditorX/HeightmapLand ; +DriverLinkage = dynamic ; +include $(Root)/prog/tools/tools_setup.jam ; +UseQuirrel = sq3+ ; + +TargetType = dll ; +Target = tools/sceneTools/daEditorX/heightmapLand.dll ; +OutDir = $(Root)/tools/dagor3_cdk/bin/plugins/de3x ; +if $(Platform) = win64 { OutDir = $(Root)/tools/dagor3_cdk/bin64/plugins/de3x ; } + +AddIncludes = + $(Root)/prog/tools/sceneTools/daEditorX/include + $(Root)/prog/tools/sharedInclude + $(Root)/prog/engine/sharedInclude + $(Root)/prog/gameLibs/publicInclude + $(Root)/prog/gameLibs/publicInclude/squirrel + $(Root)/prog/3rdPartyLibs/Recast/Include + $(Root)/prog/3rdPartyLibs/Detour/Include +; + +Sources = + hmlExportHmap.cpp + hmlClipping.cpp + hmlExport.cpp + hmlObject.cpp + hmlLayers.cpp + hmlSplineObject.cpp + hmlSplinePoint.cpp + hmlGenColorMap.cpp + hmlImport.cpp + hmlEventHandler.cpp + hmlIGenEditorPlugin.cpp + hmlMain.cpp + hmlModifiers.cpp + hmlPanel.cpp + hmlPlugin.cpp + hmlExportSizeDlg.cpp + hmlEditorEH.cpp + hmlSplineTriangulation.cpp + hmlSplineModifier.cpp + hmlImportExport.cpp + hmlSplineMask.cpp + hmlLmeshHtConstrMask.cpp + hmlRivers.cpp + common.cpp + loftObject.cpp + hmlEntity.cpp + hmlLight.cpp + hmlHoleObject.cpp + hmlSnow.cpp + LandClassSlotsMgr.cpp + entityCopyDlg.cpp + materialMgr.cpp + buildRoad.cpp + roadsSnapshot.cpp + importLandMesh.cpp + waterSurfGen.cpp + hmlExportSplines.cpp + hmlSelTexDlg.cpp + gpuGrassPanel.cpp + + Brushes/hmlBrush.cpp + Brushes/hmlHillBrush.cpp + Brushes/hmlSmoothBrush.cpp + Brushes/brushMask.cpp + Brushes/hmlAlignBrush.cpp + Brushes/hmlShadowsBrush.cpp + Brushes/hmlScriptBrush.cpp + + objectParam.cpp + recastNavMesh.cpp +; + +UseProgLibs = + tools/sceneTools/daEditorX/de3dllCore + tools/libTools/assetMgr + tools/libTools/delaunay + tools/libTools/winGuiWrapper + tools/libTools/staticGeom + tools/libTools/dagFileRW + gameLibs/landMesh + engine/SceneRay + engine/image + engine/perfMon/daProfilerStub + + 3rdPartyLibs/math/DelaunayTriangulator + 3rdPartyLibs/math/clipper-4.x + 3rdPartyLibs/math/misc + 3rdPartyLibs/hash + 3rdPartyLibs/image/tiff-4.4.0 + + 3rdPartyLibs/Recast + 3rdPartyLibs/Detour + gameLibs/pathFinder + gameLibs/pathFinder/tileCache/stub + gameLibs/pathFinder/customNav/stub + gameLibs/recastTools + gameLibs/covers +; + +ImportProgLibs = + tools/libTools/daKernel +; + + +LINKopt = -def:$(Root)/prog/tools/sceneTools/daEditorX/de3dllCore/de3_plugin.def ; + + +include $(Root)/prog/_jBuild/build.jam ; diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/landClassSlotsMgr.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/landClassSlotsMgr.cpp new file mode 100644 index 000000000..3b1764e25 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/landClassSlotsMgr.cpp @@ -0,0 +1,869 @@ +#include +#include +#include + +#include "landClassSlotsMgr.h" +#include "hmlPlugin.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static IAssetService *assetSrv = NULL; +static IRendInstGenService *rigenSrv = NULL; +static int tiledByLandclassSubTypeId = -1; + +#define EXPORT_AXIS_STEPS 4 + +#define PSEUDO_PLANE_SIZE 8192 +#define PSEUDO_PLANE_GEN_CELL_SZ 1024 +#define PSEUDO_PLANE_GRID_CELL_SZ 16 + +static bool __stdcall ri_land_get_height(Point3 &pos, Point3 *out_norm) +{ + if (!HmapLandPlugin::self) + return false; + return HmapLandPlugin::self->getHeight(Point2::xz(pos), pos.y, out_norm); +} + +LandClassSlotsManager::LandClassSlotsManager(int layer_count) +{ + grid2world = 1.0; + world0x = 0; + world0y = 0; + + clear_and_resize(layers, layer_count); + mem_set_0(layers); + if (!assetSrv) + assetSrv = DAGORED2->queryEditorInterface(); + if (!rigenSrv) + rigenSrv = DAGORED2->queryEditorInterface(); + tiledByLandclassSubTypeId = IDaEditor3Engine::get().registerEntitySubTypeId("mask_tile"); + + if (rigenSrv) + rigenSrv->setCustomGetHeight(&ri_land_get_height); +} + + +landclass::AssetData *LandClassSlotsManager::setLandClass(int layer_idx, int landclass_idx, const char *asset_name) +{ + if (layer_idx < 0 || layer_idx >= layers.size() || landclass_idx < 0) + return NULL; + + if (!layers[layer_idx]) + { + if (asset_name) + layers[layer_idx] = new (midmem) PerLayer; + else + return NULL; + } + + PerLayer &pl = *layers[layer_idx]; + if (landclass_idx >= pl.cls.size()) + { + if (!asset_name) + return NULL; + + int st = pl.cls.size(); + pl.cls.resize(landclass_idx + 1); + for (int i = st; i < pl.cls.size(); i++) + pl.cls[i] = NULL; + } + + if (!pl.cls[landclass_idx]) + { + if (!asset_name) + return NULL; + + pl.cls[landclass_idx] = new (midmem) PerLayer::Rec(asset_name); + pl.cls[landclass_idx]->reload(); + reinitRIGen(); + return pl.cls[landclass_idx]->landClass; + } + else if (!asset_name) + { + // debug("delete slot %d/%d: %s", layer_idx, landclass_idx, (char*)pl.cls[landclass_idx]->name); + del_it(pl.cls[landclass_idx]); + reinitRIGen(); + DAGORED2->invalidateViewportCache(); + return NULL; + } + else + { + PerLayer::Rec &r = *pl.cls[landclass_idx]; + if (stricmp(r.name, asset_name) == 0) + return r.landClass; + + r.name = asset_name; + r.reload(); + reinitRIGen(); + return r.landClass; + } +} + +void LandClassSlotsManager::reinitRIGen(bool reset_lc_cache) +{ + if (!rigenSrv || !HmapLandPlugin::self) + return; + if (!HmapLandPlugin::self->getlandClassMap().isFileOpened() && !HmapLandPlugin::self->isPseudoPlane()) + return; + + Tab land_cls; + + rigenSrv->releaseRtRIGenData(); + for (int i = 0; i < layers.size(); i++) + { + if (!layers[i]) + continue; + PerLayer &pl = *layers[i]; + for (int j = 0; j < pl.cls.size(); j++) + if (pl.cls[j] && pl.cls[j]->rigenLand) + { + rigenSrv->releaseLandClassGameRes(pl.cls[j]->rigenLand); + pl.cls[j]->rigenLand = NULL; + } + } + if (reset_lc_cache) + rigenSrv->resetLandClassCache(); + + for (int i = 0; i < layers.size(); i++) + { + if (!layers[i]) + continue; + PerLayer &pl = *layers[i]; + for (int j = 0; j < pl.cls.size(); j++) + if (pl.cls[j]) + { + pl.cls[j]->rigenLand = rigenSrv->getLandClassGameRes(pl.cls[j]->name); + land_cls.push_back(pl.cls[j]->rigenLand); + } + } + + DataBlock appBlk(DAGORED2->getWorkspace().getAppPath()); + int lcmap_w = HmapLandPlugin::self->getlandClassMap().getMapSizeX(), lcmap_h = HmapLandPlugin::self->getlandClassMap().getMapSizeY(); + + float gridCellSize = grid2world; + float meshCellSize = HmapLandPlugin::self->getMeshCellSize(); + float w0x = world0x, w0y = world0y; + float border_w = appBlk.getBlockByNameEx("projectDefaults")->getBlockByNameEx("riMgr")->getReal("outerLandBorder", 1024.0f); + outer_border = 0; + if (HmapLandPlugin::self->isPseudoPlane()) + { + lcmap_w = lcmap_h = PSEUDO_PLANE_SIZE / PSEUDO_PLANE_GRID_CELL_SZ; + meshCellSize = PSEUDO_PLANE_GEN_CELL_SZ; + G_ASSERTF(world0x == world0y && world0y == -PSEUDO_PLANE_SIZE / 2, "world0=%g,%g PSEUDO_PLANE_SIZE=%g", world0x, world0y, + PSEUDO_PLANE_SIZE); + G_ASSERTF(grid2world == PSEUDO_PLANE_GRID_CELL_SZ, "grid2world=%g PSEUDO_PLANE_GRID_CELL_SZ=%g", grid2world, + PSEUDO_PLANE_GRID_CELL_SZ); + } + else if (border_w > 0) + { + outer_border = (int)ceilf(border_w / meshCellSize) * int(meshCellSize / gridCellSize); + lcmap_w += outer_border * 2; + lcmap_h += outer_border * 2; + w0x -= outer_border * gridCellSize; + w0y -= outer_border * gridCellSize; + } + + float minGridCellSize = appBlk.getBlockByNameEx("projectDefaults")->getBlockByNameEx("riMgr")->getReal("minGridCellSize", 32); + int minGridCellCount = appBlk.getBlockByNameEx("projectDefaults")->getBlockByNameEx("riMgr")->getInt("minGridCellCount", 4); + + int ri_cell_sz = meshCellSize / gridCellSize; + while (ri_cell_sz > 1 && ri_cell_sz * gridCellSize >= minGridCellSize * 2 && + ((lcmap_w / ri_cell_sz) * (lcmap_h / ri_cell_sz) < minGridCellCount || ri_cell_sz * gridCellSize > 2048 || + (lcmap_w % ri_cell_sz) || (lcmap_h % ri_cell_sz))) + ri_cell_sz /= 2; + + int msq_stride = ((lcmap_w + ri_cell_sz - 1) / ri_cell_sz), msq_plane = msq_stride * ((lcmap_h + ri_cell_sz - 1) / ri_cell_sz); + debug("reinitRIGen: %d cls, riCell: %d (%.1f m), meshCell=%.1f m (number of ri cells: %d, %dx%d at %.1f,%.1f)" + " minGridCellSize=%.0f minGridCellCount=%d", + land_cls.size(), ri_cell_sz, ri_cell_sz * gridCellSize, meshCellSize, msq_plane, msq_stride, msq_plane / msq_stride, w0x, w0y, + minGridCellSize, minGridCellCount); + + rigenSrv->createRtRIGenData(w0x, w0y, grid2world, ri_cell_sz, msq_stride, msq_plane / msq_stride, land_cls, world0x, world0y); + for (int i = 0; i < layers.size(); i++) + { + if (!layers[i]) + continue; + PerLayer &pl = *layers[i]; + for (int j = 0; j < pl.cls.size(); j++) + if (pl.cls[j]) + pl.cls[j]->rigenBm = rigenSrv->getRIGenBitMask(pl.cls[j]->rigenLand); + } + + for (int my = outer_border; my < lcmap_h - outer_border; my++) + for (int mx = outer_border; mx < lcmap_w - outer_border; mx++) + { + unsigned w = HmapLandPlugin::self->getlandClassMap().getData(mx - outer_border, my - outer_border); + + for (int i = layers.size() - 1; i >= 0; i--) + { + if (!layers[i]) + continue; + + PerLayer &pl = *layers[i]; + int idx = landClsLayer[i].getLayerData(w); + if (idx < pl.cls.size() && pl.cls[idx] && pl.cls[idx]->rigenBm) + pl.cls[idx]->rigenBm->set(mx, my); + } + } + rigenSrv->setSweepMask(objgenerator::lcmapExcl.bm, objgenerator::lcmapExcl.ox, objgenerator::lcmapExcl.oz, + objgenerator::lcmapExcl.scale); + rigenSrv->setReinitCallback(&reinitRIGenCallBack, this); +} + +landclass::AssetData *LandClassSlotsManager::getLandClass(int layer_idx, int landclass_idx) +{ + if (layer_idx < 0 || layer_idx >= layers.size() || !layers[layer_idx] || landclass_idx < 0) + return NULL; + + PerLayer &pl = *layers[layer_idx]; + if (landclass_idx >= pl.cls.size() || !pl.cls[landclass_idx]) + return NULL; + return pl.cls[landclass_idx]->landClass; +} + +void LandClassSlotsManager::reloadLandClass(int layer_idx, int landclass_idx) +{ + if (layer_idx < 0 || layer_idx >= layers.size() || !layers[layer_idx] || landclass_idx < 0) + return; + + PerLayer &pl = *layers[layer_idx]; + if (landclass_idx >= pl.cls.size() || !pl.cls[landclass_idx]) + return; + pl.cls[landclass_idx]->reload(); +} + +void LandClassSlotsManager::clear() +{ + for (int i = layers.size() - 1; i >= 0; i--) + del_it(layers[i]); + clear_and_shrink(layers); + outer_border = 0; +} + +landclass::AssetData *LandClassSlotsManager::getAsset(const char *asset_name) +{ + return assetSrv ? assetSrv->getLandClassData(asset_name) : NULL; +} + +void LandClassSlotsManager::releaseAsset(landclass::AssetData *asset) +{ + if (assetSrv && asset) + assetSrv->releaseLandClassData(asset); +} +void LandClassSlotsManager::subscribeLandClassUpdateNotify(IAssetUpdateNotify *n) +{ + if (assetSrv) + assetSrv->subscribeUpdateNotify(n, true, false); +} +void LandClassSlotsManager::unsubscribeLandClassUpdateNotify(IAssetUpdateNotify *n) +{ + if (assetSrv) + assetSrv->unsubscribeUpdateNotify(n, true, false); +} + + +void LandClassSlotsManager::PerLayer::Rec::clearData() +{ + if (assetSrv && landClass) + assetSrv->releaseLandClassData(landClass); + landClass = NULL; + if (rigenSrv) + rigenSrv->releaseLandClassGameRes(rigenLand); + rigenLand = NULL; + rigenBm = NULL; +} + +void LandClassSlotsManager::PerLayer::Rec::reload() +{ + clearData(); + + // debug("reload %s", (char*)name); + if (assetSrv) + landClass = assetSrv->getLandClassData(name); + entHolder.reset(); + changed = true; + DAGORED2->invalidateViewportCache(); +} + +void LandClassSlotsManager::onLandSizeChanged(float gridStep, float ofs_x, float ofs_y, + dag::ConstSpan land_cls_layer) +{ + grid2world = gridStep; + world0x = ofs_x; + world0y = ofs_y; + landClsLayer.set(land_cls_layer.data(), land_cls_layer.size()); + if (HmapLandPlugin::self && HmapLandPlugin::self->isPseudoPlane()) + { + grid2world = PSEUDO_PLANE_GRID_CELL_SZ; + world0x = world0y = -PSEUDO_PLANE_SIZE / 2; + } + + tileSize = 256.0 / gridStep; + if (tileSize < 1) + tileSize = 1; + + // debug("onLandSizeChanged(%.3f, %.3f, %.3f) tileSize=%d", grid2world, world0x, world0y, tileSize); + for (int i = layers.size() - 1; i >= 0; i--) + { + if (!layers[i]) + continue; + + PerLayer &pl = *layers[i]; + for (int j = pl.cls.size() - 1; j >= 0; j--) + if (pl.cls[j]) + pl.cls[j]->entHolder.reset(); + } + if (HmapLandPlugin::self) + reinitRIGen(); + else if (rigenSrv) + rigenSrv->clearRtRIGenData(); +} + +typedef HierBitMap2d> HierBitmap8; + +void LandClassSlotsManager::onLandRegionChanged(int x0, int y0, int x1, int y1, MapStorage &landClsMap, bool all_classes, + bool dont_regenerate, bool finished) +{ + int tx0 = x0 / tileSize, ty0 = y0 / tileSize; + int tx1 = (x1 + tileSize - 1) / tileSize, ty1 = (y1 + tileSize - 1) / tileSize; + float box_sz = grid2world * tileSize; + float world2grid = 1.0 / grid2world; + Tab bmps(tmpmem); + Tab rec(tmpmem); + int lcmap_w = landClsMap.getMapSizeX(), lcmap_h = landClsMap.getMapSizeY(); + // long update handling + int64_t reft = ::ref_time_ticks(); + bool con_shown = false; + int total_cnt = (ty1 - ty0) * (tx1 - tx0); + int done_cnt = 0; + CoolConsole &con = DAGORED2->getConsole(); + int rendInst_atype = DAEDITOR3.getAssetTypeId("rendInst"); + bool rigen_changed = false; + +#define PROGRESS_PT(done) \ + if (con_shown) \ + con.setDone(done); \ + else if (get_time_usec(reft) > 1500000) \ + { \ + con_shown = true; \ + con.startProgress(); \ + con.setTotal(total_cnt); \ + con.setDone(done); \ + con.setActionDesc("Updating landclass tiles..."); \ + } + + int grass_attr = HmapLandPlugin::hmlService->getBitLayerAttrId(HmapLandPlugin::self->getLayersHandle(), "grass"); + for (int i = layers.size() - 1; i >= 0; i--) + { + if (!layers[i]) + continue; + PerLayer &pl = *layers[i]; + for (int j = pl.cls.size() - 1; j >= 0; j--) + if (pl.cls[j]) + { + if ((all_classes || pl.cls[j]->changed) && pl.cls[j]->landClass) + { + pl.cls[j]->tmpBmpIdx = rec.size(); + rec.push_back(pl.cls[j]); + pl.cls[j]->grassLayer = + (grass_attr != -1 && HmapLandPlugin::hmlService->testBitLayerAttr(HmapLandPlugin::self->getLayersHandle(), i, grass_attr)); + } + else + pl.cls[j]->tmpBmpIdx = -1; + } + } + bmps.resize(rec.size()); + for (int c = 0; c < bmps.size(); c++) + bmps[c].resize(tileSize, tileSize); + + // debug("onLandRegionChanged(%d, %d, %d, %d), bmps=%d", x0, y0, x1, y1, bmps.size()); + if (!bmps.size()) + return; + + PROGRESS_PT(0); + for (int ty = ty0; ty < ty1; ty++) + for (int tx = tx0; tx < tx1; tx++, done_cnt++) + { + PROGRESS_PT(done_cnt); + + if (dont_regenerate) + { + bool need_gen = false; + for (int c = 0; c < rec.size(); c++) + { + if (!rec[c]->landClass->tiled && !rec[c]->landClass->planted && !rec[c]->landClass->grass) + continue; + + TiledEntityHolder::Tile *tile = rec[c]->entHolder.getTile(tx, ty); + if (!tile || tile->discarded) + { + need_gen = true; + break; + } + } + if (!need_gen) + continue; + } + + for (int c = 0; c < bmps.size(); c++) + bmps[c].reset(); + + int tmx_end = lcmap_w - tx * tileSize; + int tmy_end = lcmap_h - ty * tileSize; + + if (tmx_end > tileSize) + tmx_end = tileSize; + if (tmy_end > tileSize) + tmy_end = tileSize; + + for (int my = ty * tileSize, tmy = 0; tmy < tmy_end; my++, tmy++) + for (int mx = tx * tileSize, tmx = 0; tmx < tmx_end; mx++, tmx++) + { + unsigned w = landClsMap.getData(mx, my); + + for (int i = layers.size() - 1; i >= 0; i--) + { + if (!layers[i]) + continue; + + PerLayer &pl = *layers[i]; + int idx = landClsLayer[i].getLayerData(w); + bool idx_valid = idx >= 0 && idx < pl.cls.size() && pl.cls[idx]; + if (idx_valid && pl.cls[idx]->tmpBmpIdx != -1) + bmps[pl.cls[idx]->tmpBmpIdx].set(tmx, tmy); + if (idx_valid && pl.cls[idx]->rigenBm && !pl.cls[idx]->rigenBm->get(mx + outer_border, my + outer_border)) + { + rigen_changed = true; + pl.cls[idx]->rigenBm->set(mx + outer_border, my + outer_border); + } + for (int k = 0; k < pl.cls.size(); k++) + if (k != idx && pl.cls[k] && pl.cls[k]->rigenBm && (!idx_valid || pl.cls[idx]->rigenBm != pl.cls[k]->rigenBm) && + pl.cls[k]->rigenBm->get(mx + outer_border, my + outer_border)) + { + rigen_changed = true; + pl.cls[k]->rigenBm->clr(mx + outer_border, my + outer_border); + } + } + } + + for (int c = 0; c < bmps.size(); c++) + { + if (!rec[c]->landClass->tiled && !rec[c]->landClass->planted && !rec[c]->landClass->grass) + { + TiledEntityHolder::Tile *tile = rec[c]->entHolder.getTile(tx, ty); + if (tile) + { + tile->clearAllObjects(); + tile->discarded = false; + } + continue; + } + + TiledEntityHolder::Tile &tile = rec[c]->entHolder.createTile(tx, ty); + if (bmps[c].isEmpty()) + { + tile.clearAllObjects(); + tile.discarded = false; + continue; + } + + if (dont_regenerate && !tile.discarded) + continue; + + if (!rec[c]->landClass->tiled || rec[c]->landClass->tiled->riOnly) + tile.clearObjects(tile.TILED); + else + { + // debug("rec[%d]=%p t=%d,%d", c, rec[c]->landClass->tiled, tx, ty); + if (!tile.pool[tile.TILED].size()) + tile.resize(tile.TILED, rec[c]->landClass->tiled->data.size()); + + tile.beginGenerate(tile.TILED); + objgenerator::generateTiledEntitiesInMaskedRect(*rec[c]->landClass->tiled, tiledByLandclassSubTypeId, 62, + HmapLandPlugin::self, tile.pool[tile.TILED], bmps[c], world2grid, tx * box_sz, ty * box_sz, box_sz, box_sz, world0x, + world0y, rendInst_atype); + tile.endGenerate(tile.TILED); + } + + if (!rec[c]->landClass->planted || rec[c]->landClass->planted->riOnly) + tile.clearObjects(tile.PLANTED); + else + { + // debug("rec[%d]=%p t=%d,%d", c, rec[c]->landClass->planted, tx, ty); + if (!tile.pool[tile.PLANTED].size()) + tile.resize(tile.PLANTED, rec[c]->landClass->planted->ent.size()); + + tile.beginGenerate(tile.PLANTED); + objgenerator::generatePlantedEntitiesInMaskedRect(*rec[c]->landClass->planted, tiledByLandclassSubTypeId, 62, + HmapLandPlugin::self, tile.pool[tile.PLANTED], bmps[c], world2grid, tx * box_sz, ty * box_sz, box_sz, box_sz, world0x, + world0y, 0, rendInst_atype); + tile.endGenerate(tile.PLANTED); + } + + if (!rec[c]->grassLayer || !rec[c]->landClass->grass) + tile.clearGrass(); + else if (finished) + { + if (!tile.grass.size()) + { + clear_and_resize(tile.grass, rec[c]->landClass->grass->data.size()); + for (int i = 0; i < tile.grass.size(); i++) + tile.grass[i] = IDaEditor3Engine::get().cloneEntity(rec[c]->landClass->grass->data[i].entity); + } + + for (int i = 0; i < tile.grass.size(); i++) + { + if (!tile.grass[i]) + continue; + IGrassPlanting *gp = tile.grass[i]->queryInterface(); + if (!gp) + continue; + + gp->startGrassPlanting((tx + 0.5) * box_sz + world0x, (ty + 0.5) * box_sz + world0y, 0.71 * box_sz); + objgenerator::generateGrassInMaskedRect(rec[c]->landClass->grass->data[i], gp, bmps[c], world2grid, tx * box_sz, + ty * box_sz, box_sz, box_sz, world0x, world0y); + if (gp->finishGrassPlanting() == 0) + tile.clearGrass(); + } + } + + tile.discarded = false; + } + } + PROGRESS_PT(done_cnt); + DAGORED2->restoreEditorColliders(); + + if (!dont_regenerate) + { + for (int c = 0; c < rec.size(); c++) + rec[c]->changed = false; + if (rigenSrv && HmapLandPlugin::self && (rigen_changed || all_classes)) + rigenSrv->discardRIGenRect(x0, y0, x1, y1); + } + if (con_shown) + con.endProgress(); +} +void LandClassSlotsManager::regenerateObjects(MapStorage &landClsMap, bool only_changed) +{ + reinitRIGen(); + onLandRegionChanged(0, 0, landClsMap.getMapSizeX(), landClsMap.getMapSizeY(), landClsMap, !only_changed); + + if (HmapLandPlugin::self) + HmapLandPlugin::self->resetLandmesh(); +} + +#include +#include + +#define CHECK_ROHHB 0 + +#if CHECK_ROHHB +template +static void write_bm_tiff(const Bitmap &bm, const char *fn) +{ + int w = bm.getW(), h = bm.getH(); + IBitMaskImageMgr::BitmapMask img; + HmapLandPlugin::bitMaskImgMgr->createBitMask(img, w, h, 1); + + for (int y = 0; y < h; y++) + for (int x = 0; x < w; x++) + img.setMaskPixel1(x, y, bm.get(x, y) ? 128 : 0); + + HmapLandPlugin::bitMaskImgMgr->saveImage(img, ".", String(260, "%s.tif", fn)); + HmapLandPlugin::bitMaskImgMgr->destroyImage(img); +} +#endif + +static void serialize_huge_bm(const objgenerator::HugeBitmask &bm, const char *fn, unsigned target_code) +{ + String base; + DAGORED2->getProjectFolderPath(base); + +#if CHECK_ROHHB + write_bm_tiff(bm, fn); +#endif + + mkbindump::BinDumpSaveCB cwr(1 << 20, target_code, dagor_target_code_be(target_code)); + mkbindump::build_ro_hier_bitmap(cwr, bm, 4, 3); + FullFileSaveCB fcwr(String(260, "%s/%s.bin", base.str(), fn)); + cwr.copyDataTo(fcwr); + fcwr.close(); + +#if CHECK_ROHHB + if (!dagor_target_code_be(target_code)) + { + FullFileLoadCB crd(String(260, "%s/%s.bin", base.str(), fn)); + RoHugeHierBitMap2d<4, 3> *roBm = RoHugeHierBitMap2d<4, 3>::create(crd); + if (roBm) + { + debug("%s %dx%d -> %dx%d", fn, bm.getW(), bm.getH(), roBm->getW(), roBm->getH()); + write_bm_tiff(*roBm, String(260, "%s_rep", fn)); + delete roBm; + } + } +#endif +} + +void LandClassSlotsManager::exportEntityGenDataToFile(MapStorage &land_cls_map, unsigned target_code) +{ + DataBlock appBlk(DAGORED2->getWorkspace().getAppPath()); + String base; + DAGORED2->getProjectFolderPath(base); + dd_mkdir(String(260, "%s/DoNotCommitMe", base.str())); + + DataBlock fileBlk; + fileBlk.setBool("gen", true); + fileBlk.setStr("target", mkbindump::get_target_str(target_code)); + + for (int layer = 0; layer < rigenSrv->getRIGenLayers(); layer++) + exportEntityGenDataLayer(land_cls_map, target_code, appBlk, base, + layer == 0 ? fileBlk : *fileBlk.addNewBlock(String(0, "layer%d", layer)), layer); + + dblk::save_to_text_file_compact(fileBlk, String(260, "%s/DoNotCommitMe/sowedRi.blk", base.str())); +} +void LandClassSlotsManager::exportEntityGenDataLayer(MapStorage &land_cls_map, unsigned target_code, const DataBlock &appBlk, + const char *base, DataBlock &fileBlk, int layer_idx) +{ + Tab bmps(tmpmem); + Tab rec(tmpmem); + Tab rec_remap(tmpmem); + int rec_used = 0; + int lcmap_w = land_cls_map.getMapSizeX(), lcmap_h = land_cls_map.getMapSizeY(); + + float gridCellSize = grid2world; + float meshCellSize = HmapLandPlugin::self->getMeshCellSize(); + float minGridCellSize = appBlk.getBlockByNameEx("projectDefaults")->getBlockByNameEx("riMgr")->getReal("minGridCellSize", 32); + int minGridCellCount = appBlk.getBlockByNameEx("projectDefaults")->getBlockByNameEx("riMgr")->getInt("minGridCellCount", 4); + float w0x = world0x, w0y = world0y; + float border_w = appBlk.getBlockByNameEx("projectDefaults")->getBlockByNameEx("riMgr")->getReal("outerLandBorder", 1024.0f); + outer_border = 0; + if (HmapLandPlugin::self->isPseudoPlane()) + { + lcmap_w = lcmap_h = PSEUDO_PLANE_SIZE / PSEUDO_PLANE_GRID_CELL_SZ; + meshCellSize = PSEUDO_PLANE_GEN_CELL_SZ; + G_ASSERTF(world0x == world0y && world0y == -PSEUDO_PLANE_SIZE / 2, "world0=%g,%g PSEUDO_PLANE_SIZE=%g", world0x, world0y, + PSEUDO_PLANE_SIZE); + G_ASSERTF(grid2world == PSEUDO_PLANE_GRID_CELL_SZ, "grid2world=%g PSEUDO_PLANE_GRID_CELL_SZ=%g", grid2world, + PSEUDO_PLANE_GRID_CELL_SZ); + } + else if (border_w > 0) + { + outer_border = (int)ceilf(border_w / meshCellSize) * int(meshCellSize / gridCellSize); + lcmap_w += outer_border * 2; + lcmap_h += outer_border * 2; + w0x -= outer_border * gridCellSize; + w0y -= outer_border * gridCellSize; + } + + int ri_cell_sz = meshCellSize / gridCellSize; + while (ri_cell_sz > 1 && ri_cell_sz * gridCellSize >= minGridCellSize * 2 && + ((lcmap_w / ri_cell_sz) * (lcmap_h / ri_cell_sz) < minGridCellCount || ri_cell_sz * gridCellSize > 2048 || + (lcmap_w % ri_cell_sz) || (lcmap_h % ri_cell_sz))) + ri_cell_sz /= 2; + if (int div = rigenSrv->getRIGenLayerCellSizeDivisor(layer_idx)) + ri_cell_sz = ri_cell_sz >= div ? ri_cell_sz / div : 1; + + Tab msq(tmpmem); + int msq_stride = (lcmap_w / ri_cell_sz), msq_plane = msq_stride * (lcmap_h / ri_cell_sz); + debug("riCell: %d (%.1f m), meshCell=%.1f m (number of ri cells: %d) minGridCellSize=%.0f minGridCellCount=%d", ri_cell_sz, + ri_cell_sz * gridCellSize, meshCellSize, msq_plane, minGridCellSize, minGridCellCount); + + for (int i = layers.size() - 1; i >= 0; i--) + { + if (!layers[i]) + continue; + PerLayer &pl = *layers[i]; + for (int j = pl.cls.size() - 1; j >= 0; j--) + if (pl.cls[j]) + { + if (pl.cls[j]->landClass && pl.cls[j]->landClass->layerIdx == layer_idx && + (pl.cls[j]->landClass->tiled || pl.cls[j]->landClass->planted)) + { + pl.cls[j]->tmpBmpIdx = rec.size(); + rec.push_back(pl.cls[j]); + } + else + pl.cls[j]->tmpBmpIdx = -1; + } + } + msq.resize(rec.size() * msq_plane); + mem_set_0(msq); + + rec_remap.resize(rec.size()); + mem_set_ff(rec_remap); + + bmps.resize(rec.size()); + for (int c = 0; c < bmps.size(); c++) + bmps[c].resize(lcmap_w, lcmap_h); + for (int my = outer_border; my < lcmap_h - outer_border; my++) + for (int mx = outer_border; mx < lcmap_w - outer_border; mx++) + { + unsigned w = land_cls_map.getData(mx - outer_border, my - outer_border); + + for (int i = layers.size() - 1; i >= 0; i--) + { + if (!layers[i]) + continue; + + PerLayer &pl = *layers[i]; + int idx = landClsLayer[i].getLayerData(w); + if (idx < pl.cls.size() && pl.cls[idx] && pl.cls[idx]->tmpBmpIdx != -1) + { + int j = pl.cls[idx]->tmpBmpIdx; + if (rec_remap[j] < 0) + rec_remap[j] = rec_used++; + bmps[j].set(mx, my); + msq[msq_plane * j + (my / ri_cell_sz) * msq_stride + mx / ri_cell_sz]++; + } + } + } + + Tab mask_remap(tmpmem); + int mask_cnt = 0; + mask_remap.resize(rec.size()); + mem_set_ff(mask_remap); + + for (int i = layers.size() - 1; i >= 0; i--) + { + if (!layers[i]) + continue; + PerLayer &pl = *layers[i]; + for (int j = pl.cls.size() - 1; j >= 0; j--) + { + if (!pl.cls[j] || pl.cls[j]->tmpBmpIdx < 0) + continue; + if (rec_remap[pl.cls[j]->tmpBmpIdx] < 0) + { + DAEDITOR3.conWarning("skip land <%s> from empty layer", pl.cls[j]->name); + continue; + } + DataBlock *b = fileBlk.addNewBlock("mask"); + int idx = rec_remap[pl.cls[j]->tmpBmpIdx]; + b->setStr("mask", String(260, "%s/DoNotCommitMe/mask%d_%03d.bin", base, layer_idx, idx)); + b->setStr("land", pl.cls[j]->name); + serialize_huge_bm(bmps[pl.cls[j]->tmpBmpIdx], String(260, "DoNotCommitMe/mask%d_%03d", layer_idx, idx), target_code); + mask_remap[pl.cls[j]->tmpBmpIdx] = mask_cnt; + int64_t total = 0; + for (int k = 0; k < msq_plane; k++) + total += msq[pl.cls[j]->tmpBmpIdx * msq_plane + k]; + b->setInt64(String(0, "m%d", mask_cnt), total); + mask_cnt++; + } + } + + if (layer_idx == 0) + { + fileBlk.setStr("sweepMask", String(260, "%s/DoNotCommitMe/mask_sweep.bin", base)); + if (objgenerator::lcmapExcl.bm && !outer_border) + serialize_huge_bm(*objgenerator::lcmapExcl.bm, "DoNotCommitMe/mask_sweep", target_code); + else if (objgenerator::lcmapExcl.bm) + { + objgenerator::WorldHugeBitmask excl; + float s = objgenerator::lcmapExcl.scale; + excl.initExplicit(w0x, w0y, s, lcmap_w * gridCellSize * s, lcmap_h * gridCellSize * s); + if (fmodf(outer_border * s, 1.0f) > 0) + { + DAEDITOR3.conError("Landscape/RI: exclusion map is converted with accuracy loss, scale=%g outer_border=%d, map=%dx%d", s, + outer_border, land_cls_map.getMapSizeX(), land_cls_map.getMapSizeY()); + for (int my = 0, h = excl.bm->getH(); my < h; my++) + for (int mx = 0, w = excl.bm->getW(); mx < w; mx++) + if (objgenerator::lcmapExcl.isMarked(my / excl.scale + excl.ox, my / excl.scale + excl.oz)) + excl.bm->set(mx, my); + } + else + for (int my = 0, h = objgenerator::lcmapExcl.bm->getH(), ofs = outer_border * gridCellSize * excl.scale; my < h; my++) + for (int mx = 0, w = objgenerator::lcmapExcl.bm->getW(); mx < w; mx++) + if (objgenerator::lcmapExcl.bm->get(mx, my)) + excl.bm->set(mx + ofs, my + ofs); + serialize_huge_bm(*excl.bm, "DoNotCommitMe/mask_sweep", target_code); + } + else + { + objgenerator::HugeBitmask bm; + bm.resize(128, 128); + serialize_huge_bm(bm, "DoNotCommitMe/mask_sweep", target_code); + } + } + + fileBlk.setInt("maskNum", rec_used); + fileBlk.setInt("riNumW", msq_stride); + fileBlk.setInt("riNumH", msq_plane / msq_stride); + fileBlk.setInt("riCellSz", ri_cell_sz); + fileBlk.setReal("gridCell", gridCellSize); + fileBlk.setReal("gridOfsX", w0x); + fileBlk.setReal("gridOfsZ", w0y); + fileBlk.setReal("densMapPivotX", world0x); + fileBlk.setReal("densMapPivotZ", world0y); + fileBlk.setReal("sweepMaskScale", objgenerator::lcmapExcl.bm ? objgenerator::lcmapExcl.scale : 0); + + for (int row = 0, num_rows = msq_plane / msq_stride; row < num_rows; row++) + { + DataBlock *b_row = fileBlk.addNewBlock("r"); + for (int col = 0; col < msq_stride; col++) + { + int i = row * msq_stride + col; + DataBlock *b = b_row->addNewBlock("c"); + for (int j = 0; j < rec.size(); j++) + if (msq[j * msq_plane + i] && mask_remap[j] >= 0) + b->setInt(String(32, "m%d", mask_remap[j]), msq[j * msq_plane + i]); + } + } +} + +void LandClassSlotsManager::TiledEntityHolder::Tile::clearGrass() +{ + for (int i = 0; i < grass.size(); i++) + destroy_it(grass[i]); + clear_and_shrink(grass); +} +void LandClassSlotsManager::TiledEntityHolder::Tile::clear(int pool_type) +{ + dag::Span &p = pool[pool_type]; + for (int i = 0; i < p.size(); i++) + p[i].landclass::SingleEntityPool::~SingleEntityPool(); + p.reset(); +} + +void LandClassSlotsManager::TiledEntityHolder::Tile::resize(int pool_type, int count) +{ + clear(pool_type); + + dag::Span &p = pool[pool_type]; + p.set(nullptr, count); + p.set((landclass::SingleEntityPool *)memalloc(data_size(p), midmem), count); + for (int i = 0; i < p.size(); i++) + new (&p[i], _NEW_INPLACE) landclass::SingleEntityPool; +} + +void LandClassSlotsManager::TiledEntityHolder::Tile::beginGenerate(int pool_type) +{ + for (int gi = 0; gi < pool[pool_type].size(); gi++) + pool[pool_type][gi].resetUsedEntities(); +} + +void LandClassSlotsManager::TiledEntityHolder::Tile::endGenerate(int pool_type) +{ + for (int gi = 0; gi < pool[pool_type].size(); gi++) + pool[pool_type][gi].deleteUnusedEntities(); +} + +bool LandClassSlotsManager::TiledEntityHolder::Tile::isPoolEmpty(int pool_type) +{ + for (int gi = 0; gi < pool[pool_type].size(); gi++) + if (pool[pool_type][gi].entUsed) + return false; + return true; +} + +LandClassSlotsManager::TiledEntityHolder::TiledEntityHolder() : tiles(5) {} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/landClassSlotsMgr.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/landClassSlotsMgr.h new file mode 100644 index 000000000..0b72ed331 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/landClassSlotsMgr.h @@ -0,0 +1,149 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace landclass +{ +class AssetData; +class SingleEntityPool; +} // namespace landclass + +template +class MapStorage; +struct HmapBitLayerDesc; +class IAssetUpdateNotify; +class IObjEntity; + + +class LandClassSlotsManager +{ + class TiledEntityHolder + { + public: + struct Tile + { + enum + { + TILED, + PLANTED, + POOL_COUNT + }; + + // manually managed pool arrays + dag::Span pool[POOL_COUNT]; + SmallTab grass; + bool discarded; + + Tile() : discarded(true) {} + ~Tile() + { + clear(TILED); + clear(PLANTED); + clearGrass(); + } + + void clear(int pool_type); + void clearGrass(); + void resize(int pool_type, int count); + + void beginGenerate(int pool_type); + void endGenerate(int pool_type); + + void clearObjects(int pool_type) + { + beginGenerate(pool_type); + endGenerate(pool_type); + } + void clearAllObjects() + { + clearObjects(TILED); + clearObjects(PLANTED); + clearGrass(); + } + + bool isPoolEmpty(int pool_type); + }; + + HierGrid2 tiles; + + public: + TiledEntityHolder(); + + void reset() { tiles.clear(); } + Tile *getTile(int tx, int ty) const { return tiles.get_leaf(tx, ty); } + Tile &createTile(int tx, int ty) { return *tiles.create_leaf(tx, ty); } + }; + + struct PerLayer + { + struct Rec + { + landclass::AssetData *landClass; + rendinst::gen::land::AssetData *rigenLand; + EditableHugeBitMap2d *rigenBm; + SimpleString name; + TiledEntityHolder entHolder; + int tmpBmpIdx; + unsigned changed : 1, grassLayer : 1; + + Rec(const char *nm) : name(nm), landClass(NULL), tmpBmpIdx(-1), changed(true), rigenLand(NULL), rigenBm(NULL) {} + ~Rec() { clearData(); } + + void reload(); + void clearData(); + }; + + Tab cls; + + PerLayer() : cls(midmem) {} + ~PerLayer() { clear_all_ptr_items(cls); } + }; + + + SmallTab layers; + float grid2world, world0x, world0y; + int tileSize; + int outer_border = 0; + dag::ConstSpan landClsLayer; + +public: + LandClassSlotsManager(int layer_count); + ~LandClassSlotsManager() { clear(); } + + landclass::AssetData *setLandClass(int layer_idx, int landclass_idx, const char *asset_name); + landclass::AssetData *getLandClass(int layer_idx, int landclass_idx); + void reloadLandClass(int layer_idx, int landclass_idx); + + void reinitRIGen(bool reset_lc_cache = false); + + void onLandSizeChanged(float grid_step, float ofs_x, float ofs_y, dag::ConstSpan land_cls_layer); + + void onLandRegionChanged(int x0, int y0, int x1, int y1, MapStorage &landClsMap, bool all_classes = true, + bool dont_regenerate = false, bool finished = true); + + void regenerateObjects(MapStorage &landClsMap, bool only_changed = true); + + static landclass::AssetData *getAsset(const char *asset_name); + static void releaseAsset(landclass::AssetData *asset); + + static void subscribeLandClassUpdateNotify(IAssetUpdateNotify *n); + static void unsubscribeLandClassUpdateNotify(IAssetUpdateNotify *n); + + void clear(); + + void exportEntityGenDataToFile(MapStorage &land_cls_map, unsigned target_code); + void exportEntityGenDataLayer(MapStorage &land_cls_map, unsigned target_code, const DataBlock &appBlk, const char *base, + DataBlock &fileBlk, int layer_idx); + +protected: + static void __stdcall LandClassSlotsManager::reinitRIGenCallBack(void *arg) + { + reinterpret_cast(arg)->reinitRIGen(true); + } +}; diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/landMeshMap.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/landMeshMap.h new file mode 100644 index 000000000..82f8397df --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/landMeshMap.h @@ -0,0 +1,155 @@ +#pragma once + +#include + +#include +#include + +class IBaseLoad; +class IBaseSave; +class ShaderMesh; +class ShaderMaterial; +class LandRayTracer; +class EditorLandRayTracer; +class MaterialData; +class StaticGeometryTexture; +class StaticGeometryMaterial; +class DelaunayImportanceMask; + +class LandMeshMap +{ +public: + LandMeshMap(); + ~LandMeshMap(); + + void gatherExportToDagGeometry(StaticGeometryContainer &container); + + void getStats(int &min_faces, int &max_faces, int &total_faces); + + void clear(bool clear_tracer); + + bool isEmpty() const { return cells.empty(); } + + void resize(int x0, int y0, int x1, int y1, float cell_size) + { + clear(false); + + size.x = x1 - x0; + G_ASSERT(size.x >= 0); + if (size.x == 0) + ++size.x; + + size.y = y1 - y0; + G_ASSERT(size.y >= 0); + if (size.y == 0) + ++size.y; + + origin.x = x0; + origin.y = y0; + + clear_and_resize(cells, size.x * size.y); + mem_set_0(cells); + + land_rmesh.resize(size.x * size.y); + mem_set_0(land_rmesh); + + cellSize = cell_size; + } + + int getNumCellsX() const { return size.x; } + int getNumCellsY() const { return size.y; } + enum LandType + { + LAND_LAND, + LAND_DECAL, + LAND_COMBINED, + LAND_PATCHES + }; + template + Mesh *getCellTypedMesh(int x, int y, bool do_create = false) + { + if (x < 0 || y < 0 || x >= size.x || y >= size.y) + return NULL; + + Mesh **m = NULL; + if (land_type == LAND_LAND) + m = &cells[y * size.x + x].land_mesh; + else if (land_type == LAND_DECAL) + m = &cells[y * size.x + x].decal_mesh; + else if (land_type == LAND_COMBINED) + m = &cells[y * size.x + x].combined_mesh; + else if (land_type == LAND_PATCHES) + m = &cells[y * size.x + x].patches_mesh; + + if (do_create && !*m) + *m = new (midmem) Mesh(); + + return *m; + } + Mesh *getCellLandMesh(int x, int y, bool do_create = false) { return getCellTypedMesh(x, y, do_create); } + Mesh *getCellDecalMesh(int x, int y, bool do_create = false) { return getCellTypedMesh(x, y, do_create); } + Mesh *getCellCombinedMesh(int x, int y, bool do_create = false) { return getCellTypedMesh(x, y, do_create); } + Mesh *getCellPatchesMesh(int x, int y, bool do_create = false) { return getCellTypedMesh(x, y, do_create); } + + float getCellSize() const { return cellSize; } + + IPoint2 calcCellCoords(const Point3 &p) const { return IPoint2(int(floorf(p.x / cellSize)), int(floorf(p.z / cellSize))); } + + IPoint2 getOrigin() const { return origin; } + + ShaderMesh *getLandShaderMesh(int x, int y, bool do_create, bool offseted); + ShaderMesh *getCombinedShaderMesh(int x, int y, bool do_create, bool offseted) { return NULL; } + ShaderMesh *getDecalShaderMesh(int x, int y, bool do_create, bool offseted) { return NULL; } + BBox3 getBBox(int x, int y, float *sphere_radius = NULL); + + dag::Span getCells() { return make_span(cells); } + EditorLandRayTracer *getEditorLandRayTracer() const { return editorLandTracer; } + LandRayTracer *getGameLandRayTracer() const { return gameLandTracer; } + + void setEditorLandRayTracer(EditorLandRayTracer *lrt); + void setGameLandRayTracer(LandRayTracer *lrt); + MaterialData getMaterialData(uint32_t matNo) const; + + // traceRay + bool traceRay(const Point3 &p, const Point3 &dir, real &t, Point3 *normal) const; + + //! Get maximum height at point (and normal, if needed) + bool getHeight(const Point2 &p, real &ht, Point3 *normal) const; + + int addMaterial(StaticGeometryMaterial *material, bool *clipmap_only, bool *has_vertex_opacity, int node_layer = -1, + bool *is_height_patch = NULL); + int addTexture(StaticGeometryTexture *texture); + + void addStaticCollision(StaticGeometryContainer &cont); + + int getMaterialsCount() const { return materials.size(); } + const char *textureName(int i) const { return textures[i]->fileName; } + int getTexturesCount() const { return textures.size(); } + + void getMd5HashForGenerate(unsigned char *md5_hash, HeightMapStorage &heightmap, float error_threshold, int point_limit, float cell, + const Point3 &ofs, const DelaunayImportanceMask *mask, dag::ConstSpan add_pts, dag::ConstSpan water_border_polys); + + void setOffset(const Point3 &ofs) { offset = ofs; } + Point3 getOffset() const { return offset; } + + void buildCollisionNode(Mesh &m); + +protected: + SmallTab cells; + IPoint2 size, origin; + float cellSize; + Point3 offset; + EditorLandRayTracer *editorLandTracer; + LandRayTracer *gameLandTracer; + PtrTab materials; + PtrTab textures; + + Ptr landMatSG; + Ptr landBottomMatSG; + Ptr landBottomDeepMatSG; + Ptr landBottomBorderMatSG; + StaticGeometryNode *collisionNode; + + Ptr landMat; + Tab land_rmesh; +}; diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/loftObject.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/loftObject.cpp new file mode 100644 index 000000000..b50e1a2fc --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/loftObject.cpp @@ -0,0 +1,137 @@ +#include "hmlSplineObject.h" +#include "hmlSplinePoint.h" +#include "hmlPlugin.h" +#include +#include +#include +#include +#include +#include + +using splineclass::Attr; + +static void recalcLoftLighting(StaticGeometryContainer &geom) +{ + ISceneLightService *ltService = DAGORED2->queryEditorInterface(); + if (!ltService) + return; + + Color3 ltCol1, ltCol2, ambCol; + Point3 ltDir1, ltDir2; + Point3 normal; + + ltService->getDirectLight(ltDir1, ltCol1, ltDir2, ltCol2, ambCol); + + for (int ni = 0; ni < geom.nodes.size(); ++ni) + { + const StaticGeometryNode *node = geom.nodes[ni]; + + if (node && node->mesh) + { + Mesh &mesh = node->mesh->mesh; + + if (!mesh.vertnorm.size()) + { + mesh.calc_vertnorms(); + mesh.calc_ngr(); + } + + mesh.cvert.resize(mesh.face.size() * 3); + mesh.cface.resize(mesh.face.size()); + + for (int f = 0; f < mesh.face.size(); ++f) + { + for (unsigned v = 0; v < 3; ++v) + { + normal = -mesh.vertnorm[mesh.facengr[f][v]]; + + const int vi = f * 3 + v; + + Color3 resColor = ambCol; + real k = normal * ltDir1; + if (k > 0) + resColor += ltCol1 * k; + k = normal * ltDir2; + if (k > 0) + resColor += ltCol2 * k; + + mesh.cvert[vi] = ::color4(resColor, 1); + mesh.cface[f].t[v] = vi; + } + } + } + } +} + +void SplineObject::generateLoftSegments(int start_idx, int end_idx) +{ + if (splineInactive) + return; + ISplineGenObj *gen = points[start_idx]->getSplineGen(); + if (!gen) + return; + + Tab splineScales(midmem); + splineScales.reserve(end_idx - start_idx + 1); + for (int i = start_idx; i <= end_idx; i++) + splineScales.push_back(points[i % points.size()]->getProps().attr); + + gen->generateLoftSegments(getBezierSpline(), name, start_idx, end_idx, (props.modifType == MODIF_SPLINE), splineScales, + props.scaleTcAlong); + updateLoftBox(); +} + +void SplineObject::gatherLoftLandPts(Tab &loft_pt_cloud, Tab &water_border_polys, Tab &hmap_sweep_polys) +{ + if (splineInactive) + return; + + bool place_on_collision = (props.modifType == MODIF_SPLINE); + bool water_surf = HmapLandPlugin::self->hasWaterSurf(); + float water_level = HmapLandPlugin::self->getWaterSurfLevel(); + int start_idx = 0; + int end_idx = points.size() + (poly ? 1 : 0); + int pcnt = points.size(); + + Tab splineScales(midmem); + splineScales.reserve(end_idx - start_idx + 1); + for (int i = start_idx; i <= end_idx; i++) + splineScales.push_back(points[i % points.size()]->getProps().attr); + + BezierSpline2d splineXZ; + getSplineXZ(splineXZ); + + for (int pi = start_idx + 1; pi < end_idx; pi++) + { + if (points[pi % pcnt]->getSplineClass() && points[pi % pcnt]->getSplineClass() == points[start_idx]->getSplineClass()) + { + if (pi < end_idx - 1) + continue; + else + pi++; + } + + if (ISplineGenObj *gen = points[start_idx]->getSplineGen()) + gen->gatherLoftLandPts(loft_pt_cloud, getBezierSpline(), splineXZ, name, start_idx, pi - 1, place_on_collision, + make_span_const(splineScales).subspan(start_idx, pi - start_idx), water_border_polys, hmap_sweep_polys, water_surf, + water_level); + + if (pi < points.size()) + start_idx = pi; + } + + landclass::PolyGeomGenData *genGeom = NULL; + if (poly && landClass && landClass->data) + genGeom = landClass->data->genGeom; + + if (genGeom && genGeom->waterSurface && water_surf) + { + Tab pts(tmpmem); + getSmoothPoly(pts); + + water_border_polys.reserve(pts.size() + 1); + water_border_polys.push_back().set(1.1e12f, pts.size(), genGeom->waterSurfaceExclude); + for (int i = 0; i < pts.size(); i++) + water_border_polys.push_back().set_xVz(pts[i], water_level); + } +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/materialMgr.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/materialMgr.cpp new file mode 100644 index 000000000..124d02219 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/materialMgr.cpp @@ -0,0 +1,81 @@ +#include "materialMgr.h" +#include <3d/dag_materialData.h> +#include +#include +#include +#include +#include + +int ObjLibMaterialListMgr::getMaterialId(const char *mat_asset_name) +{ + int i; + + for (i = 0; i < mat.size(); i++) + if (mat[i] == mat_asset_name) + return i; + i = append_items(mat, 1); + mat[i] = mat_asset_name; + return i; +} + +void ObjLibMaterialListMgr::setDefaultMat0(MaterialDataList &mat) +{ + G_ASSERT(mat.list.size() > 0); + // create default material + Ptr defSm = new MaterialData; + defSm->className = "simple"; + defSm->mat.diff = Color4(1, 1, 1); + defSm->mtex[0] = dagRender->addManagedTexture("../commonData/tex/missing.dds"); + mat.list[0] = defSm; +} + +void ObjLibMaterialListMgr::complementDefaultMat0(MaterialDataList &mat) +{ + if (mat.list.size() >= 2 && !mat.list[0].get()) + { + G_ASSERT(mat.list[1].get()); + mat.list[0] = mat.list[1]; + } +} +void ObjLibMaterialListMgr::reclearDefaultMat0(MaterialDataList &mat) +{ + if (mat.list.size() >= 2 && mat.list[0].get() == mat.list[1].get()) + mat.list[0] = NULL; +} + +MaterialDataList *ObjLibMaterialListMgr::buildMaterialDataList() +{ + MaterialDataList *m = new MaterialDataList; + + // reserve entry for default material + m->addSubMat(NULL); + + Ptr defSm; + + IAssetService *assetSrv = DAGORED2->queryEditorInterface(); + + for (int i = 0; i < mat.size(); i++) + { + Ptr sm = NULL; + + if (assetSrv) + sm = assetSrv->getMaterialData(mat[i]); + + if (!sm) + { + if (!defSm.get()) + { + defSm = new MaterialData; + defSm->className = "simple"; + defSm->mat.diff = Color4(1, 1, 1); + defSm->mtex[0] = dagRender->addManagedTexture("../commonData/tex/missing.dds"); + } + sm = defSm; + DAEDITOR3.conError("can't find material %s", mat[i].str()); + } + + m->addSubMat(sm); + } + + return m; +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/materialMgr.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/materialMgr.h new file mode 100644 index 000000000..bf9cd032b --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/materialMgr.h @@ -0,0 +1,32 @@ +// Copyright 2023 by Gaijin Games KFT, All rights reserved. +#ifndef _DE2_PLUGIN_ROADS_MATERIALMGR_H_ +#define _DE2_PLUGIN_ROADS_MATERIALMGR_H_ +#pragma once + + +#include +#include + +class MaterialDataList; + + +class ObjLibMaterialListMgr +{ +public: + ObjLibMaterialListMgr() : mat(midmem) {} + + void reset() { mat.clear(); } + + int getMaterialId(const char *mat_asset_name); + + MaterialDataList *buildMaterialDataList(); + + static void setDefaultMat0(MaterialDataList &mat); + static void complementDefaultMat0(MaterialDataList &mat); + static void reclearDefaultMat0(MaterialDataList &mat); + +protected: + Tab mat; +}; + +#endif diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/objectParam.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/objectParam.cpp new file mode 100644 index 000000000..d74be4137 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/objectParam.cpp @@ -0,0 +1,211 @@ +#include "objectParam.h" +#include "hmlPlugin.h" +#include "hmlPanel.h" +#include "hmlEntity.h" + +#include +#include +#include + +#include + + +static HmapLandPlugin *&plugin = HmapLandPlugin::self; + +enum GroupEnum +{ + PID_OBJECT_PARAM_GRP, + + PID_OBJECT_PARAM_FX_GRP, + PID_OBJECT_PARAM_PHYS_OBJ_GRP, +}; + +enum ParamEnum +{ + CM_OBJECT_PARAM_ID = 77, + + // FX + ID_FX_MAX_RADIUS, + ID_FX_UPDATE_WHEN_INVISIBLE, + + // PhysObj + ID_PHYS_OBJ_SCRIPT_CLASS, + ID_PHYS_OBJ_ACTIVE, +}; + + +static void fillFxObj(PropPanel2 &panel, dag::ConstSpan selection, bool expanded) +{ + PropertyContainerControlBase &grp = *panel.createGroup(PID_OBJECT_PARAM_FX_GRP, "fx"); + + real radius = -1.f; + int update = -1; + + int cnt = selection.size(); + for (int i = 0; i < cnt; i++) + { + LandscapeEntityObject *leObj = RTTI_cast(selection[i]); + IObjEntity *obj = leObj ? leObj->getEntity() : NULL; + if (!obj) + continue; + + if (radius == -1.f) + radius = leObj->fxProps.maxRadius; + else if (radius != leObj->fxProps.maxRadius) + radius = -2.f; + + if (update == -1) + update = leObj->fxProps.updateWhenInvisible ? 1 : 0; + else if (update != (leObj->fxProps.updateWhenInvisible ? 1 : 0)) + update = 2; + } + + grp.createEditFloat(ID_FX_MAX_RADIUS, "Max radius", radius); + grp.setMinMaxStep(ID_FX_MAX_RADIUS, 0.f, 100000.f, 0.1f); + grp.createCheckBox(ID_FX_UPDATE_WHEN_INVISIBLE, "Update when invisible", update); + + panel.setBool(PID_OBJECT_PARAM_FX_GRP, !expanded); +} + +static void fillPhysObj(PropPanel2 &panel, dag::ConstSpan selection, bool expanded) +{ + PropertyContainerControlBase &grp = *panel.createGroup(PID_OBJECT_PARAM_PHYS_OBJ_GRP, "physObj"); + + String script; + int str = -1; + int active = -1; + + int cnt = selection.size(); + for (int i = 0; i < cnt; i++) + { + LandscapeEntityObject *leObj = RTTI_cast(selection[i]); + IObjEntity *obj = leObj ? leObj->getEntity() : NULL; + if (!obj) + continue; + + if (str == -1) + { + str = 0; + script = leObj->physObjProps.scriptClass; + } + else if (stricmp(leObj->physObjProps.scriptClass, script) != 0) + str = -2; + + if (active == -1) + active = leObj->physObjProps.active ? 1 : 0; + else if (active != (leObj->physObjProps.active ? 1 : 0)) + active = 2; + } + + grp.createEditBox(ID_PHYS_OBJ_SCRIPT_CLASS, "Script class", str < 0 ? "" : script); + grp.createCheckBox(ID_FX_UPDATE_WHEN_INVISIBLE, "Update when invisible", active); + + panel.setBool(PID_OBJECT_PARAM_PHYS_OBJ_GRP, !expanded); +} + + +void ObjectParam::fillParams(PropPanel2 &panel, dag::ConstSpan selection) +{ + if (selection.size() <= 0) + return; + + int id = -1; + + int cnt = selection.size(); + for (int i = 0; i < cnt; i++) + { + LandscapeEntityObject *leObj = RTTI_cast(selection[i]); + IObjEntity *obj = leObj ? leObj->getEntity() : NULL; + if (!obj) + { + id = -1; + break; + } + + id = obj->getAssetTypeId(); + if (id < 0) + break; + } + + PropertyContainerControlBase &grp = *panel.createGroup(PID_OBJECT_PARAM_GRP, "Object Property"); + + static int fxId = IDaEditor3Engine::get().getAssetTypeId("fx"); + static int physObjId = IDaEditor3Engine::get().getAssetTypeId("physObj"); + + bool fxobj = (id == fxId); + bool physobj = (id == physObjId); + fillFxObj(grp, selection, fxobj); + fillPhysObj(grp, selection, physobj); +} + +bool ObjectParam::onPPChange(PropPanel2 &panel, int pid, dag::ConstSpan selection) +{ + // fx + if (pid == ID_FX_MAX_RADIUS) + { + float val = panel.getFloat(pid); + + int cnt = selection.size(); + for (int i = 0; i < cnt; i++) + { + LandscapeEntityObject *leObj = RTTI_cast(selection[i]); + IObjEntity *obj = leObj ? leObj->getEntity() : NULL; + if (!obj) + continue; + + leObj->fxProps.maxRadius = val; + leObj->objectPropsChanged(); + } + } + else if (pid == ID_FX_UPDATE_WHEN_INVISIBLE) + { + bool check = panel.getBool(pid); + + int cnt = selection.size(); + for (int i = 0; i < cnt; i++) + { + LandscapeEntityObject *leObj = RTTI_cast(selection[i]); + IObjEntity *obj = leObj ? leObj->getEntity() : NULL; + if (!obj) + continue; + + leObj->fxProps.updateWhenInvisible = check; + leObj->objectPropsChanged(); + } + } + // physObj + else if (pid == ID_PHYS_OBJ_SCRIPT_CLASS) + { + int cnt = selection.size(); + for (int i = 0; i < cnt; i++) + { + LandscapeEntityObject *leObj = RTTI_cast(selection[i]); + IObjEntity *obj = leObj ? leObj->getEntity() : NULL; + if (!obj) + continue; + + leObj->physObjProps.scriptClass = panel.getText(pid); + leObj->objectPropsChanged(); + } + } + else if (pid == ID_PHYS_OBJ_ACTIVE) + { + bool check = panel.getBool(pid); + + int cnt = selection.size(); + for (int i = 0; i < cnt; i++) + { + LandscapeEntityObject *leObj = RTTI_cast(selection[i]); + IObjEntity *obj = leObj ? leObj->getEntity() : NULL; + if (!obj) + continue; + + leObj->physObjProps.active = check; + leObj->objectPropsChanged(); + } + } + else + return false; + + return true; +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/objectParam.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/objectParam.h new file mode 100644 index 000000000..10dceda58 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/objectParam.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +class PropertyContainerControlBase; + +class ObjectParam +{ +public: + void fillParams(PropPanel2 &panel, dag::ConstSpan selection); + + bool onPPChange(PropPanel2 &panel, int pid, dag::ConstSpan selection); +}; diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/recastNavMesh.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/recastNavMesh.cpp new file mode 100644 index 000000000..3b76ac6cb --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/recastNavMesh.cpp @@ -0,0 +1,2803 @@ +#include "hmlPlugin.h" +#include "hmlSplineObject.h" +#include "hmlSplinePoint.h" +#include "recastNavMesh.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define ZDICT_STATIC_LINKING_ONLY 1 +#include +#include + +#include + +static Tab coversDebugList; +static Tab> edgesDebugList; +static Tab obstaclesDebugList; +static scene::TiledScene coversDebugScene; +static bool exportedCoversDebugListDone = false; +static bool exportedEdgesDebugListDone = false; +static bool exportedNavMeshLoadDone = false; +static bool exportedObstaclesLoadDone = false; + +static Tab thread_alloc; +static int nextThreadId = 0; +thread_local static int threadId = -1; + +static IMemAlloc *get_thread_alloc(int idx) { return idx >= 0 && idx < thread_alloc.size() ? thread_alloc[idx] : midmem; } + +static IMemAlloc *get_thread_alloc() +{ + if (threadId < 0) + threadId = interlocked_increment(nextThreadId); + return get_thread_alloc(threadId - 1); +} + +static void *alloc_for_recast(size_t size, rcAllocHint hint) +{ + void *ptr = get_thread_alloc()->alloc(size + 16); + if (!ptr) + return nullptr; + *(int *)ptr = threadId - 1; + return (char *)ptr + 16; +} + +static void free_for_recast(void *ptr) +{ + if (!ptr) + return; + ptr = (char *)ptr - 16; + int idx = *(int *)(ptr); + get_thread_alloc(idx)->free(ptr); +} + +static void *alloc_for_detour(size_t size, dtAllocHint hint) { return alloc_for_recast(size, RC_ALLOC_PERM); } + +static void free_for_detour(void *ptr) { return free_for_recast(ptr); } + +static void setupRecastDetourAllocators() +{ + // pathfinder sets these to framemem allocator, but we'll use recast/detour + // in a multithreaded manner, thus, we need thread-safe allocators. + threadId = 0; // Make sure that caller of this function will always use midmem allocator. + rcAllocSetCustom(alloc_for_recast, free_for_recast); + dtAllocSetCustom(alloc_for_detour, free_for_detour); +} + +const float MIN_BOTTOM_DEPTH = -50.f; +static const int TILECACHE_MAX_OBSTACLES = 128 * 1024; +static const int TILECACHE_AVG_LAYERS_PER_TILE = 4; // This is averaged number of layers (i.e. number of floors) per-tile. +static const int TILECACHE_MAX_LAYERS_PER_TILE = 32; // This is maximum number of layers per-tile. +// Note that there's also RC_MAX_LAYERS in recast itself, this is the maximum number of layers per-tile library can handle. + +static dtNavMesh *navMesh = NULL; +static dtTileCache *tileCache = NULL; +static pathfinder::TileCacheMeshProcess tcMeshProc; + +struct NavMeshParams +{ + NavmeshExportType navmeshExportType; + float cellSize, cellHeight; + float traceStep; + float agentMaxSlope, agentHeight, agentMaxClimb, agentRadius, agentClimbAfterGluingMeshes; + float edgeMaxLen, edgeMaxError; + float regionMinSize, regionMergeSize; + int vertsPerPoly; + float detailSampleDist, detailSampleMaxError; + pathfinder::NavMeshType navMeshType; + bool usePrefabCollision; + int tileSize; + float bucketSize; + float crossingWaterDepth; + int jlkCovExtraCells; + bool crossObstaclesWithJumplinks; + recastbuild::JumpLinksParams jlkParams; + recastbuild::MergeEdgeParams mergeParams; +}; + +static NavMeshParams navMeshParams[MAX_NAVMESHES]; +static recastbuild::CoversParams covParams; + +static const char *navmeshExportTypeNames[] = {"water", "splines", "height_from_above", "geometry", "water_and_geometry", "invalid"}; +NavmeshExportType navmesh_export_type_name_to_enum(const char *name) +{ + return NavmeshExportType(lup(name, navmeshExportTypeNames, int(NavmeshExportType::COUNT), int(NavmeshExportType::INVALID))); +} + +const char *navmesh_export_type_to_string(NavmeshExportType type) { return navmeshExportTypeNames[int(type)]; } + +/// Recast build context. +class BuildContext : public rcContext +{ + int64_t m_startTime[RC_MAX_TIMERS]; + int m_accTime[RC_MAX_TIMERS]; + +public: + BuildContext() {} //-V730 + virtual ~BuildContext() {} + +protected: + virtual void doResetLog() {} + virtual void doLog(const rcLogCategory category, const char *msg, const int /*len*/) + { + if (category >= RC_LOG_ERROR) + DAEDITOR3.conError("%s", msg); + else if (category >= RC_LOG_PROGRESS) + debug(msg); + } + virtual void doResetTimers() + { + for (int i = 0; i < RC_MAX_TIMERS; ++i) + m_accTime[i] = -1; + } + virtual void doStartTimer(const rcTimerLabel label) { m_startTime[label] = ref_time_ticks(); } + virtual void doStopTimer(const rcTimerLabel label) + { + const int deltaTime = get_time_usec(m_startTime[label]); + if (m_accTime[label] == -1) + m_accTime[label] = deltaTime; + else + m_accTime[label] += deltaTime; + } + virtual int doGetAccumulatedTime(const rcTimerLabel label) const { return m_accTime[label]; } +}; +static BuildContext global_build_ctx; + +static void logLine(rcContext &ctx, rcTimerLabel label, const char *name, const double pc) +{ + const int t = ctx.getAccumulatedTime(label); + if (t >= 0) + ctx.log(RC_LOG_PROGRESS, "%s:\t%.2fms\t(%.1f%%)", name, t / 1000.0f, t * pc); +} + +static void duLogBuildTimes(rcContext &ctx, const int totalTimeUsec) +{ + const double pc = 100.0f / totalTimeUsec; + + ctx.log(RC_LOG_PROGRESS, "Build Times"); + logLine(ctx, RC_TIMER_RASTERIZE_TRIANGLES, "- Rasterize", pc); + logLine(ctx, RC_TIMER_BUILD_COMPACTHEIGHTFIELD, "- Build Compact", pc); + logLine(ctx, RC_TIMER_FILTER_BORDER, "- Filter Border", pc); + logLine(ctx, RC_TIMER_FILTER_WALKABLE, "- Filter Walkable", pc); + logLine(ctx, RC_TIMER_ERODE_AREA, "- Erode Area", pc); + logLine(ctx, RC_TIMER_MEDIAN_AREA, "- Median Area", pc); + logLine(ctx, RC_TIMER_MARK_BOX_AREA, "- Mark Box Area", pc); + logLine(ctx, RC_TIMER_MARK_CONVEXPOLY_AREA, "- Mark Convex Area", pc); + // logLine(ctx, RC_TIMER_MARK_CYLINDER_AREA, "- Mark Cylinder Area", pc); + logLine(ctx, RC_TIMER_BUILD_DISTANCEFIELD, "- Build Distance Field", pc); + logLine(ctx, RC_TIMER_BUILD_DISTANCEFIELD_DIST, " - Distance", pc); + logLine(ctx, RC_TIMER_BUILD_DISTANCEFIELD_BLUR, " - Blur", pc); + logLine(ctx, RC_TIMER_BUILD_REGIONS, "- Build Regions", pc); + logLine(ctx, RC_TIMER_BUILD_REGIONS_WATERSHED, " - Watershed", pc); + logLine(ctx, RC_TIMER_BUILD_REGIONS_EXPAND, " - Expand", pc); + logLine(ctx, RC_TIMER_BUILD_REGIONS_FLOOD, " - Find Basins", pc); + logLine(ctx, RC_TIMER_BUILD_REGIONS_FILTER, " - Filter", pc); + // logLine(ctx, RC_TIMER_BUILD_LAYERS, "- Build Layers", pc); + logLine(ctx, RC_TIMER_BUILD_CONTOURS, "- Build Contours", pc); + logLine(ctx, RC_TIMER_BUILD_CONTOURS_TRACE, " - Trace", pc); + logLine(ctx, RC_TIMER_BUILD_CONTOURS_SIMPLIFY, " - Simplify", pc); + logLine(ctx, RC_TIMER_BUILD_POLYMESH, "- Build Polymesh", pc); + logLine(ctx, RC_TIMER_BUILD_POLYMESHDETAIL, "- Build Polymesh Detail", pc); + logLine(ctx, RC_TIMER_MERGE_POLYMESH, "- Merge Polymeshes", pc); + logLine(ctx, RC_TIMER_MERGE_POLYMESHDETAIL, "- Merge Polymesh Details", pc); + ctx.log(RC_LOG_PROGRESS, "=== TOTAL:\t%.2fms", totalTimeUsec / 1000.0f); +} + +static void init(const DataBlock &blk, int nav_mesh_idx) +{ + setupRecastDetourAllocators(); + NavMeshParams &nmParams = navMeshParams[nav_mesh_idx]; + + nmParams.navmeshExportType = navmesh_export_type_name_to_enum(blk.getStr("navmeshExportType", "invalid")); + + nmParams.cellSize = blk.getReal("cellSize", 2.0f); + nmParams.traceStep = blk.getReal("traceStep", blk.getReal("cellSize", 2.f)); + nmParams.cellHeight = blk.getReal("cellHeight", 0.125f); + nmParams.agentMaxSlope = blk.getReal("agentMaxSlope", 30.0f); + nmParams.agentHeight = blk.getReal("agentHeight", 3.0f); + nmParams.agentMaxClimb = blk.getReal("agentMaxClimb", 1.5f); + nmParams.agentClimbAfterGluingMeshes = blk.getReal("agentClimbAfterGluingMeshes", 0.1f); + nmParams.agentRadius = blk.getReal("agentRadius", 2.0f); + nmParams.edgeMaxLen = blk.getReal("edgeMaxLen", 128.0f); + nmParams.edgeMaxError = blk.getReal("edgeMaxError", 2.0f); + nmParams.regionMinSize = blk.getReal("regionMinSize", 9.0f); + nmParams.regionMergeSize = blk.getReal("regionMergeSize", 100.0f); + nmParams.vertsPerPoly = blk.getInt("vertsPerPoly", 3); + nmParams.detailSampleDist = blk.getReal("detailSampleDist", 3.0f); + nmParams.detailSampleMaxError = blk.getReal("detailSampleMaxError", 0.25f); + nmParams.usePrefabCollision = blk.getBool("usePrefabCollision", true); + nmParams.crossingWaterDepth = blk.getReal("crossingWaterDepth", 0.f); + nmParams.crossObstaclesWithJumplinks = blk.getBool("crossObstaclesWithJumplinks", false); + + nmParams.jlkCovExtraCells = blk.getInt("jlkExtraCells", 32); + nmParams.jlkParams.enabled = blk.getBool("jumpLinksEnabled", false); + nmParams.jlkParams.jumpHeight = blk.getReal("jumpLinksHeight", 2.0f) * 2.f; // up + down + const float typoDefJumpLinksLength = blk.getReal("jumpLinksLenght", 2.5f); + nmParams.jlkParams.jumpLength = blk.getReal("jumpLinksLength", typoDefJumpLinksLength); + nmParams.jlkParams.width = blk.getReal("jumpLinksWidth", 1.0f); + nmParams.jlkParams.deltaHeightThreshold = blk.getReal("jumpLinksDeltaHeightTreshold", 0.5f); + nmParams.jlkParams.complexJumpTheshold = blk.getReal("complexJumpTheshold", 0.0f); + nmParams.jlkParams.linkDegAngle = cosf(DegToRad(blk.getReal("jumpLinksMergeAngle", 15.0f))); + nmParams.jlkParams.linkDegDist = cosf(DegToRad(blk.getReal("jumpLinksMergeDist", 5.0f))); + nmParams.jlkParams.agentRadius = nmParams.agentRadius; + nmParams.jlkParams.crossObstaclesWithJumplinks = blk.getBool("crossObstaclesWithJumplinks", false); + + covParams.enabled = nav_mesh_idx == 0 && blk.getBool("coversEnabled", false); + if (covParams.enabled) + { + covParams.typeGen = blk.getInt("coversTypeGen", recastbuild::COVERS_TYPEGEN_BASIC); + covParams.maxHeight = blk.getReal("coversMaxHeight", 2.0f); + covParams.minHeight = blk.getReal("coversMinHeight", 1.0f); + covParams.minWidth = blk.getReal("coversWidth", 1.0f); + covParams.minDepth = blk.getReal("coversDepth", 1.0f); + covParams.agentMaxClimb = nmParams.agentMaxClimb; + covParams.shootWindowHeight = blk.getReal("coversShootWindow", 0.4f); + covParams.minCollTransparent = blk.getReal("coversTransparent", 0.8f); + covParams.deltaHeightThreshold = blk.getReal("coversDeltaHeightTreshold", 0.2f); + covParams.shootDepth = blk.getReal("coversShootDepth", 3.0f); + covParams.shootHeight = blk.getReal("coversShootHeight", 1.5f); + covParams.mergeDist = blk.getReal("coversMergeDist", 0.3f); + + // covParams.maxVisibleBox == navarea; + covParams.openingTreshold = blk.getReal("openingTreshold", 0.9f); + covParams.boxOffset = blk.getReal("visibleBoxOffset", 1.f); + + covParams.testPos.x = blk.getReal("coversTestX", 0.0f); + covParams.testPos.y = blk.getReal("coversTestY", 0.0f); + covParams.testPos.z = blk.getReal("coversTestZ", 0.0f); + } + + auto sqr = [](float val) -> float { return val * val; }; + nmParams.mergeParams.enabled = blk.getBool("simplificationEdgeEnabled", true); + nmParams.mergeParams.walkPrecision = blk.getPoint2("walkPrecision", Point2(nmParams.agentRadius, nmParams.agentMaxClimb)); + nmParams.mergeParams.maxExtrudeErrorSq = sqr(blk.getReal("extrudeError", 0.4f)); + nmParams.mergeParams.extrudeLimitSq = sqr(blk.getReal("extrudeLimit", 0.3f)); + nmParams.mergeParams.safeCutLimitSq = sqr(blk.getReal("safeCutLimit", 0.5f)); + nmParams.mergeParams.unsafeCutLimitSq = sqr(blk.getReal("unsafeCutLimit", 0.2f)); + nmParams.mergeParams.unsafeMaxCutSpace = blk.getReal("maxUnsafeCutSpace", 1.f); + + nmParams.navMeshType = + (pathfinder::NavMeshType)blk.getInt("navMeshType", blk.getBool("tiled", false) ? pathfinder::NMT_TILED : pathfinder::NMT_SIMPLE); + nmParams.tileSize = blk.getInt("tileCells", 128); + if (nmParams.navMeshType == pathfinder::NMT_TILECACHED) + nmParams.tileSize = rcMin(nmParams.tileSize, 255); + nmParams.bucketSize = blk.getReal("bucketSize", 200.0f); +} + +static void saveBmTga(HierBitMap2d>> &bm, const char *name) +{ + int w = bm.getW(), h = bm.getH(); + if (!w || !h) + return; + Tab pix; + pix.resize(w * h); + mem_set_ff(pix); + + for (int y = 0; y < h; y++) + for (int x = 0; x < w; x++) + pix[y * w + x].l = bm.get(x, y) ? 128 : 0; + + save_tga8a(name, pix.data(), w, h, elem_size(pix) * w); +} + +struct NavmeshTCTile +{ + NavmeshTCTile() = default; + NavmeshTCTile(int idx, uint32_t uncompressedOffset, uint32_t uncompressedSize) : + idx(idx), uncompressedOffset(uncompressedOffset), uncompressedSize(uncompressedSize) + {} + + int idx; + uint32_t uncompressedOffset; + uint32_t uncompressedSize; +}; + +struct NavmeshBucket +{ + BBox2 bbox; + Tab tileIds; + Tab tcTiles; + uint32_t dataSize = 0; +}; + +struct NavmeshBucketsKeyHasher +{ + size_t operator()(const eastl::pair &key) const + { + return (size_t)(((uint32_t)key.second * 16777619) ^ (uint32_t)key.first); + } +}; + +template +using SamplesTab = dag::Vector; + +static void save_navmesh_bucket_format(const dtNavMesh *mesh, const NavMeshParams &nav_mesh_params, dtTileCache *tc, + dag::ConstSpan obstacles, BinDumpSaveCB &cwr) +{ + ska::flat_hash_map, NavmeshBucket, NavmeshBucketsKeyHasher> buckets; + + Point2 orig(mesh->getParams()->orig[0], mesh->getParams()->orig[2]); + + SamplesTab samplesBuffer; + Tab samplesSizes; + const float bucketSize = nav_mesh_params.bucketSize; + + for (int i = 0; i < mesh->getMaxTiles(); ++i) + { + const dtMeshTile *tile = mesh->getTile(i); + if (!tile || !tile->header || !tile->dataSize) + continue; + Point2 lower(tile->header->bmin[0], tile->header->bmin[2]); + Point2 upper(tile->header->bmax[0], tile->header->bmax[2]); + Point2 pt = lower - orig; + NavmeshBucket &bucket = buckets[eastl::make_pair(pt.x / bucketSize, pt.y / bucketSize)]; + bucket.tileIds.push_back(i); + bucket.bbox += lower; + bucket.bbox += upper; + bucket.dataSize += sizeof(dtTileRef) + sizeof(int) + tile->dataSize; + } + size_t resv_samples_sz = 0; + for (int i = 0; i < tc->getTileCount(); ++i) + { + const dtCompressedTile *tile = tc->getTile(i); + if (tile && tile->header && tile->dataSize) + resv_samples_sz += (int)tile->header->width * (int)tile->header->height * 4; //+maxUncompressedSize + } + samplesBuffer.reserve(eastl::max(resv_samples_sz, 2u << 20u)); + samplesSizes.reserve(tc->getTileCount()); + for (int i = 0; i < tc->getTileCount(); ++i) + { + const dtCompressedTile *tile = tc->getTile(i); + if (!tile || !tile->header || !tile->dataSize) + continue; + BBox3 aabb = pathfinder::tilecache_calc_tile_bounds(tc->getParams(), tile->header); + Point2 lower = Point2::xz(aabb.lim[0]); + Point2 upper = Point2::xz(aabb.lim[1]); + Point2 pt = lower - orig; + NavmeshBucket &bucket = buckets[eastl::make_pair(pt.x / bucketSize, pt.y / bucketSize)]; + + uint32_t maxUncompressedSize = (int)tile->header->width * (int)tile->header->height * 4; + size_t off = samplesBuffer.size(); + samplesBuffer.resize(off + maxUncompressedSize); + int sz = 0; + dtStatus status = tc->getCompressor()->decompress(tile->compressed, tile->compressedSize, (uint8_t *)(samplesBuffer.data() + off), + maxUncompressedSize, &sz); + G_ASSERT(status == DT_SUCCESS); + G_ASSERT(sz <= maxUncompressedSize); + samplesBuffer.resize(off + sz); + samplesSizes.push_back(sz); + + bucket.tcTiles.push_back(NavmeshTCTile(i, (uint32_t)off, sz)); + bucket.bbox += lower; + bucket.bbox += upper; + } + debug("samplesBuffer.size=%dK capacity=%uK resv_samples_sz=%uK", samplesBuffer.size() >> 10, samplesBuffer.capacity() >> 10, + resv_samples_sz >> 10); + + Tab dictBuffer; + // 16K dict seems to be the best option for us. + dictBuffer.resize(16 * 1024); + + ZDICT_fastCover_params_t params; + memset(¶ms, 0, sizeof(params)); + params.d = 8; + params.steps = 4; + /* Default to level 6 since no compression level information is available */ + params.zParams.compressionLevel = -1; + + // Unfortunately we need ALL of our tiles uncompressed in order to build nice + // dict, currently this bumps mem usage from 14G to 17G for 2048x2048 meter navmesh. + // m.b. not an issue right now, since level builders have enough mem, but m.b. we'll want + // to do something about it in the future. + size_t dictSize = ZDICT_optimizeTrainFromBuffer_fastCover(dictBuffer.data(), dictBuffer.size(), samplesBuffer.data(), + samplesSizes.data(), samplesSizes.size(), ¶ms); + G_ASSERT(!ZDICT_isError(dictSize)); + + ZSTD_CDict *cDict = ZSTD_createCDict(dictBuffer.data(), dictSize, -1); + ZSTD_CCtx *cctx = ZSTD_createCCtx(); + size_t res = ZSTD_CCtx_loadDictionary(cctx, dictBuffer.data(), dictSize); + G_ASSERT(!ZSTD_isError(res)); + + // 2 upper bits is coding format, 30th bit is already used for whole zstd packing specification, we'll use + // 31th to indicate bucket format. + cwr.writeInt32e(0 | 0x80000000); + + // Params. + cwr.writeRaw(mesh->getParams(), sizeof(dtNavMeshParams)); + cwr.writeRaw(tc->getParams(), sizeof(dtTileCacheParams)); + + // Write obstacles resource name hashes. + ska::flat_hash_set obsResNameHashes; + for (const NavMeshObstacle &obs : obstacles) + obsResNameHashes.insert(obs.resNameHash); + cwr.writeInt32e((uint32_t)obsResNameHashes.size()); + for (uint32_t h : obsResNameHashes) + cwr.writeInt32e(h); + + // Write zstd dict. + cwr.writeInt32e((int)dictSize); + cwr.writeRaw(dictBuffer.data(), (int)dictSize); + + Tab tmpBuffer; + + // Write per-bucket data. + cwr.writeInt32e((uint32_t)buckets.size()); + for (const auto &it : buckets) + { + const NavmeshBucket &bucket = it.second; + + // Write bucket header. + cwr.writeFloat32e(bucket.bbox.lim[0].x); + cwr.writeFloat32e(bucket.bbox.lim[0].y); + cwr.writeFloat32e(bucket.bbox.lim[1].x); + cwr.writeFloat32e(bucket.bbox.lim[1].y); + + cwr.beginBlock(); + + // Write tile cache data, re-compress using dict. + cwr.writeInt32e((uint32_t)bucket.tcTiles.size()); + for (const NavmeshTCTile &tct : bucket.tcTiles) + { + const dtCompressedTile *tile = tc->getTile(tct.idx); + tmpBuffer.resize(ZSTD_compressBound(tct.uncompressedSize)); + size_t newCompressedSize = ZSTD_compress_usingCDict(cctx, tmpBuffer.data(), tmpBuffer.size(), + samplesBuffer.data() + tct.uncompressedOffset, tct.uncompressedSize, cDict); + G_ASSERT(!ZSTD_isError(newCompressedSize)); + cwr.writeInt32e(tile->dataSize - tile->compressedSize + (int)newCompressedSize); + cwr.writeRaw(tile->data, tile->dataSize - tile->compressedSize); + cwr.writeRaw(tmpBuffer.data(), (int)newCompressedSize); + } + + // Write navmesh data, compress the old way with zstd stream. + uint32_t dataSize = sizeof(int) + bucket.dataSize; + cwr.writeInt32e(dataSize); + BinDumpSaveCB dcwr(2 << 20, cwr.getTarget() ? cwr.getTarget() : _MAKE4C('PC'), cwr.WRITE_BE); + dcwr.writeInt32e((uint32_t)bucket.tileIds.size()); + for (int i : bucket.tileIds) + { + const dtMeshTile *tile = mesh->getTile(i); + dcwr.writeInt64e(mesh->getTileRef(tile)); + dcwr.writeInt32e(tile->dataSize); + dcwr.writeRaw(tile->data, tile->dataSize); + } + DynamicMemGeneralSaveCB save(midmem); + dcwr.copyDataTo(save); + InPlaceMemLoadCB crd(save.data(), save.size()); + zstd_compress_data(cwr.getRawWriter(), crd, dataSize, 1 << 20, 19); + + cwr.endBlock(); + } + + ZSTD_freeCCtx(cctx); + ZSTD_freeCDict(cDict); +} + +static void save_navmesh(const dtNavMesh *mesh, const NavMeshParams &nav_mesh_params, dtTileCache *tc, + dag::ConstSpan obstacles, BinDumpSaveCB &cwr, const int compress_ratio) +{ + int64_t reftSave = ref_time_ticks_qpc(); + if (tc && (nav_mesh_params.bucketSize > 0.0f)) + { + // TODO: Bucket format for tile cached navmesh should be the only one, + // remove tile cached code path below later. + save_navmesh_bucket_format(mesh, nav_mesh_params, tc, obstacles, cwr); + return; + } + int numTiles = 0; + int numTCTiles = 0; + int numObsResNameHashes = 0; + ska::flat_hash_set obsResNameHashes; + uint32_t dataSize = sizeof(int) + sizeof(dtNavMeshParams); + for (int i = 0; i < mesh->getMaxTiles(); ++i) + { + const dtMeshTile *tile = mesh->getTile(i); + if (!tile || !tile->header || !tile->dataSize) + continue; + dataSize += sizeof(dtTileRef) + sizeof(int) + tile->dataSize; + numTiles++; + } + if (tc) + { + dataSize += sizeof(int) + sizeof(dtTileCacheParams); + for (int i = 0; i < tc->getTileCount(); ++i) + { + const dtCompressedTile *tile = tc->getTile(i); + if (!tile || !tile->header || !tile->dataSize) + continue; + dataSize += sizeof(int) + tile->dataSize; + numTCTiles++; + } + for (const NavMeshObstacle &obs : obstacles) + obsResNameHashes.insert(obs.resNameHash); + numObsResNameHashes = (int)obsResNameHashes.size(); + dataSize += sizeof(int) + sizeof(uint32_t) * numObsResNameHashes; + } + + BinDumpSaveCB dcwr(2 << 20, cwr.getTarget() ? cwr.getTarget() : _MAKE4C('PC'), cwr.WRITE_BE); + dcwr.writeRaw(mesh->getParams(), sizeof(dtNavMeshParams)); + if (tc) + { + dcwr.writeRaw(tc->getParams(), sizeof(dtTileCacheParams)); + dcwr.writeInt32e(numTiles); + dcwr.writeInt32e(numTCTiles); + dcwr.writeInt32e(numObsResNameHashes); + DEBUG_DUMP_VAR(numTiles); + DEBUG_DUMP_VAR(numTCTiles); + DEBUG_DUMP_VAR(numObsResNameHashes); + } + else + { + dcwr.writeInt32e(numTiles); + DEBUG_DUMP_VAR(numTiles); + } + + // Store tiles. + for (int i = 0; i < mesh->getMaxTiles(); ++i) + { + const dtMeshTile *tile = mesh->getTile(i); + if (!tile || !tile->header || !tile->dataSize) + continue; + + dcwr.writeInt64e(mesh->getTileRef(tile)); + dcwr.writeInt32e(tile->dataSize); + dcwr.writeRaw(tile->data, tile->dataSize); + } + if (tc) + { + for (int i = 0; i < tc->getTileCount(); ++i) + { + const dtCompressedTile *tile = tc->getTile(i); + if (!tile || !tile->header || !tile->dataSize) + continue; + + dcwr.writeInt32e(tile->dataSize); + dcwr.writeRaw(tile->data, tile->dataSize); + } + for (uint32_t h : obsResNameHashes) + dcwr.writeInt32e(h); + } + DEBUG_DUMP_VAR(dataSize); + cwr.writeInt32e(dataSize | (HmapLandPlugin::preferZstdPacking ? 0x40000000 : 0)); + DynamicMemGeneralSaveCB save(midmem); + dcwr.copyDataTo(save); + InPlaceMemLoadCB crd(save.data(), save.size()); + int64_t reftCompress = ref_time_ticks_qpc(); + int compressedSize = 0; + if (HmapLandPlugin::preferZstdPacking) + compressedSize = zstd_compress_data(cwr.getRawWriter(), crd, dataSize, 1 << 20, compress_ratio); + else + compressedSize = lzma_compress_data(cwr.getRawWriter(), compress_ratio, crd, dataSize); + DAEDITOR3.conNote("Saved navmesh for time %.2f sec, compressed by %.2f%% (%.2fkb/%.2fkb, for %.2f sec) with ratio %i", + get_time_usec_qpc(reftSave) / 1000000.0, (float)compressedSize / dataSize * 100.f, compressedSize / 1024.f, dataSize / 1024.f, + get_time_usec_qpc(reftCompress) / 1000000.0, compress_ratio); +} + +static void save_covers(const Tab &covers, BinDumpSaveCB &cwr) +{ + BinDumpSaveCB dcwr(2 << 20, cwr.getTarget() ? cwr.getTarget() : _MAKE4C('PC'), cwr.WRITE_BE); + + int dataSize = (int)covers.size() * (int)sizeof(covers::Cover); + dcwr.writeRaw(covers.data(), dataSize); + + cwr.writeInt32e(dataSize | (HmapLandPlugin::preferZstdPacking ? 0x40000000 : 0)); + DynamicMemGeneralSaveCB save(midmem); + dcwr.copyDataTo(save); + InPlaceMemLoadCB crd(save.data(), save.size()); + if (HmapLandPlugin::preferZstdPacking) + zstd_compress_data(cwr.getRawWriter(), crd, dataSize, 1 << 20, 19); + else + lzma_compress_data(cwr.getRawWriter(), 9, crd, dataSize); +} + +static void save_debug_edges(const Tab>> &debugEdges, BinDumpSaveCB &cwr) +{ + BinDumpSaveCB dcwr(2 << 20, cwr.getTarget() ? cwr.getTarget() : _MAKE4C('PC'), cwr.WRITE_BE); + + int dataSize = 0; + int pairSize = (int)sizeof(eastl::pair); + for (const auto &edgesList : debugEdges) + { + dataSize += (int)edgesList.size() * pairSize; + for (const auto &edge : edgesList) + dcwr.writeRaw(&edge, pairSize); + } + + cwr.writeInt32e(dataSize | (HmapLandPlugin::preferZstdPacking ? 0x40000000 : 0)); + DynamicMemGeneralSaveCB save(midmem); + dcwr.copyDataTo(save); + InPlaceMemLoadCB crd(save.data(), save.size()); + if (HmapLandPlugin::preferZstdPacking) + zstd_compress_data(cwr.getRawWriter(), crd, dataSize, 1 << 20, 19); + else + lzma_compress_data(cwr.getRawWriter(), 9, crd, dataSize); +} + +static bool load_debug_edges(IGenLoad &crd, Tab> &debug_edges) +{ + clear_and_shrink(debug_edges); + + unsigned pairSize = (unsigned)sizeof(eastl::pair); + unsigned dataSize = crd.readInt(); + unsigned fmt = 0; + if ((dataSize & 0xC0000000) == 0x40000000) + { + fmt = 1; + dataSize &= ~0xC0000000; + } + + if (dataSize % pairSize) + { + logerr_ctx("Could not load debug edges: broken data: data size = %d, debug edges size = %d", dataSize, pairSize); + return false; + } + if (!dataSize) + return false; + + IGenLoad *dcrd = (fmt == 1) ? (IGenLoad *)new (alloca(sizeof(ZstdLoadCB)), _NEW_INPLACE) ZstdLoadCB(crd, crd.getBlockRest()) + : (IGenLoad *)new (alloca(sizeof(LzmaLoadCB)), _NEW_INPLACE) LzmaLoadCB(crd, crd.getBlockRest()); + + debug_edges.resize(dataSize / pairSize); + dcrd->read(debug_edges.data(), dataSize); + dcrd->ceaseReading(); + dcrd->~IGenLoad(); + return true; +} + +static void save_debug_obstacles(const Tab &obstacles, BinDumpSaveCB &cwr) +{ + cwr.writeInt32e(obstacles.size()); + cwr.writeTabDataRaw(obstacles); +} + +static void load_debug_obstacles(IGenLoad &crd, Tab &obstacles) +{ + clear_and_shrink(obstacles); + crd.readTab(obstacles); +} + + +static void load_pathfinder(const HmapLandPlugin *plugin, int nav_mesh_idx, const DataBlock &nav_mesh_props) +{ + String fileName; + pathfinder::NavMeshType type{unsigned( + nav_mesh_props.getInt("navMeshType", nav_mesh_props.getBool("tiled", false) ? pathfinder::NMT_TILED : pathfinder::NMT_SIMPLE))}; + + switch (type) + { + case pathfinder::NMT_TILECACHED: fileName = "navMeshTiled3"; break; + case pathfinder::NMT_TILED: fileName = "navMeshTiled2"; break; + case pathfinder::NMT_SIMPLE: fileName = "navMesh2"; break; + default: G_ASSERT(false); break; + } + + fileName += (nav_mesh_idx == 0 ? String(".PC.bin") : String(50, "_%d.PC.bin", nav_mesh_idx + 1)); + + FullFileLoadCB fcrd(DAGORED2->getPluginFilePath(plugin, fileName)); + + if (fcrd.fileHandle) + { + fcrd.beginBlock(); + if (!pathfinder::loadNavMesh(fcrd, type)) + DAEDITOR3.conError("failed to load NavMesh from %s", fcrd.getTargetName()); + fcrd.endBlock(); + } +} + +static bool finalize_navmesh_tile(const NavMeshParams &nav_mesh_params, BuildContext &ctx, const rcConfig &cfg, + recastnavmesh::OffMeshConnectionsStorage &conn_storage, recastnavmesh::RecastTileContext &tile_ctx, int tx, int ty, + Tab &tile_data) +{ + // + // Step 1. Build polygons mesh from contours. + // + + // Build polygon navmesh from the contours. + tile_ctx.pmesh = rcAllocPolyMesh(); + if (!tile_ctx.pmesh) + { + ctx.log(RC_LOG_ERROR, "buildNavigation: Out of memory 'tile_ctx.pmesh'."); + tile_ctx.clearIntermediate(&tile_data); + return false; + } + if (!rcBuildPolyMesh(&ctx, *tile_ctx.cset, cfg.maxVertsPerPoly, *tile_ctx.pmesh)) + { + ctx.log(RC_LOG_ERROR, "buildNavigation: Could not triangulate contours."); + tile_ctx.clearIntermediate(&tile_data); + return false; + } + + // + // Step 2. Create detail mesh which allows to access approximate height on each polygon. + // + + tile_ctx.dmesh = rcAllocPolyMeshDetail(); + if (!tile_ctx.dmesh) + { + ctx.log(RC_LOG_ERROR, "buildNavigation: Out of memory 'pmdtl'."); + tile_ctx.clearIntermediate(&tile_data); + return false; + } + + if (!rcBuildPolyMeshDetail(&ctx, *tile_ctx.pmesh, *tile_ctx.chf, cfg.detailSampleDist, cfg.detailSampleMaxError, *tile_ctx.dmesh)) + { + ctx.log(RC_LOG_ERROR, "buildNavigation: Could not build detail mesh."); + tile_ctx.clearIntermediate(&tile_data); + return false; + } + + rcFreeCompactHeightfield(tile_ctx.chf); + tile_ctx.chf = NULL; + rcFreeContourSet(tile_ctx.cset); + tile_ctx.cset = NULL; + + // + // (Optional) Step 3. Create Detour data from Recast poly mesh. + // + + // The GUI may allow more max points per polygon than Detour can handle. + // Only build the detour navmesh if we do not exceed the limit. + if ((cfg.maxVertsPerPoly <= DT_VERTS_PER_POLYGON) && (tile_ctx.pmesh->npolys > 0)) + { + for (int i = 0; i < tile_ctx.pmesh->npolys; ++i) + tile_ctx.pmesh->flags[i] = 1; + + dtNavMeshCreateParams params; + memset(¶ms, 0, sizeof(params)); + params.verts = tile_ctx.pmesh->verts; + params.vertCount = tile_ctx.pmesh->nverts; + params.polys = tile_ctx.pmesh->polys; + params.polyAreas = tile_ctx.pmesh->areas; + params.polyFlags = tile_ctx.pmesh->flags; + params.polyCount = tile_ctx.pmesh->npolys; + params.nvp = tile_ctx.pmesh->nvp; + params.detailMeshes = tile_ctx.dmesh->meshes; + params.detailVerts = tile_ctx.dmesh->verts; + params.detailVertsCount = tile_ctx.dmesh->nverts; + params.detailTris = tile_ctx.dmesh->tris; + params.detailTriCount = tile_ctx.dmesh->ntris; + if (nav_mesh_params.jlkParams.enabled) + { + params.offMeshConVerts = conn_storage.m_offMeshConVerts; + params.offMeshConRad = conn_storage.m_offMeshConRads; + params.offMeshConDir = conn_storage.m_offMeshConDirs; + params.offMeshConAreas = conn_storage.m_offMeshConAreas; + params.offMeshConFlags = conn_storage.m_offMeshConFlags; + params.offMeshConUserID = conn_storage.m_offMeshConId; + params.offMeshConCount = conn_storage.m_offMeshConCount; + } + params.walkableHeight = nav_mesh_params.agentHeight; + params.walkableRadius = nav_mesh_params.agentRadius; + params.walkableClimb = nav_mesh_params.agentClimbAfterGluingMeshes; + params.tileX = tx; + params.tileY = ty; + params.tileLayer = 0; + rcVcopy(params.bmin, tile_ctx.pmesh->bmin); + rcVcopy(params.bmax, tile_ctx.pmesh->bmax); + params.cs = cfg.cs; + params.ch = cfg.ch; + params.buildBvTree = false; + + unsigned char *navData = 0; + int navDataSize = 0; + if (!dtCreateNavMeshData(¶ms, &navData, &navDataSize)) + { + ctx.log(RC_LOG_ERROR, "Could not build Detour navmesh."); + tile_ctx.clearIntermediate(&tile_data); + return false; + } + tile_ctx.clearIntermediate(&tile_data); + recastnavmesh::BuildTileData td; + td.navMeshData = navData; + td.navMeshDataSz = navDataSize; + tile_data.push_back(td); + return true; + } + + tile_ctx.clearIntermediate(&tile_data); + return true; +} + +static bool finalize_navmesh_tilecached_tile(const NavMeshParams &nav_mesh_params, BuildContext &ctx, const rcConfig &cfg, + recastnavmesh::OffMeshConnectionsStorage &conn_storage, recastnavmesh::RecastTileContext &tile_ctx, + dag::ConstSpan obstacles, int tx, int ty, Tab &tile_data) +{ + dtTileCacheAlloc tcAllocator; + pathfinder::TileCacheCompressor tcComp; + tcComp.reset(nav_mesh_params.bucketSize > 0.0f); + float agentRadius = nav_mesh_params.agentRadius; + float agentHeight = nav_mesh_params.agentHeight; + float agentMaxClimb = nav_mesh_params.agentMaxClimb; + + auto fn = [&](dag::ConstSpan obstacles, const rcConfig &cfg, dtTileCacheLayer &layer, + const dtTileCacheLayerHeader &header) { + for (const auto &obs : obstacles) + { + Point3 c = obs.box.center(); + Point3 ext = obs.box.width() * 0.5f; + float coshalf = cosf(0.5f * obs.yAngle); + float sinhalf = sinf(-0.5f * obs.yAngle); + float rotAux[2] = {coshalf * sinhalf, coshalf * coshalf - 0.5f}; + pathfinder::tilecache_apply_obstacle_padding(cfg.cs, Point2(agentRadius, agentHeight), c, ext); + dtMarkBoxArea(layer, header.bmin, cfg.cs, cfg.ch, &c.x, &ext.x, rotAux, 0); + } + }; + + return recastnavmesh::finalize_navmesh_tilecached_tile(ctx, cfg, &tcAllocator, &tcComp, + nav_mesh_params.jlkParams.enabled ? &conn_storage : nullptr, tile_ctx, tx, ty, agentMaxClimb, agentHeight, agentRadius, obstacles, + tile_data, fn); +} + +static bool prepare_tile_context(const NavMeshParams &nav_mesh_params, BuildContext &ctx, rcConfig &cfg, + recastnavmesh::RecastTileContext &tile_ctx, dag::ConstSpan vertices, dag::ConstSpan indices, + dag::ConstSpan transparent, const BBox3 &box, int gw, int gh, int override_tile_size, bool build_cset) +{ + // + // Step 1. Initialize build config. + // + memset(&cfg, 0, sizeof(cfg)); + cfg.cs = nav_mesh_params.cellSize; + cfg.ch = nav_mesh_params.cellHeight; + cfg.walkableSlopeAngle = nav_mesh_params.agentMaxSlope; + cfg.walkableHeight = (int)ceilf(nav_mesh_params.agentHeight / cfg.ch); + cfg.walkableClimb = (int)ceilf(nav_mesh_params.agentMaxClimb / cfg.ch); + cfg.walkableRadius = (int)ceilf(nav_mesh_params.agentRadius / cfg.cs); + cfg.maxEdgeLen = (int)(nav_mesh_params.edgeMaxLen / nav_mesh_params.cellSize); + cfg.maxSimplificationError = clamp(nav_mesh_params.edgeMaxError / nav_mesh_params.cellSize, 1.1f, 1.5f); + cfg.minRegionArea = int(nav_mesh_params.regionMinSize * sqr(safeinv(nav_mesh_params.cellSize))); + cfg.mergeRegionArea = int(nav_mesh_params.regionMergeSize * sqr(safeinv(nav_mesh_params.cellSize))); + cfg.maxVertsPerPoly = nav_mesh_params.vertsPerPoly; + cfg.tileSize = (nav_mesh_params.navMeshType > pathfinder::NMT_SIMPLE) ? override_tile_size : 0; + cfg.borderSize = (nav_mesh_params.navMeshType > pathfinder::NMT_SIMPLE) ? cfg.walkableRadius + 3 : 0; + cfg.width = gw > 0 ? gw : cfg.tileSize + cfg.borderSize * 2; + cfg.height = gh > 0 ? gh : cfg.tileSize + cfg.borderSize * 2; + cfg.detailSampleDist = nav_mesh_params.detailSampleDist < 0.9f ? 0 : nav_mesh_params.cellSize * nav_mesh_params.detailSampleDist; + cfg.detailSampleMaxError = nav_mesh_params.cellHeight * nav_mesh_params.detailSampleMaxError; + + BBox3 expandedBox(box); + expandedBox.inflate(cfg.borderSize * cfg.cs); + rcVcopy(cfg.bmin, &expandedBox.lim[0].x); + rcVcopy(cfg.bmax, &expandedBox.lim[1].x); + + ctx.log(RC_LOG_PROGRESS, "Building navigation:"); + ctx.log(RC_LOG_PROGRESS, " - %d x %d cells", cfg.width, cfg.height); + ctx.log(RC_LOG_PROGRESS, " - %.1fK verts, %.1fK tris", vertices.size() / 1000.0f, indices.size() / 3 / 1000.0f); + + return recastnavmesh::prepare_tile_context(ctx, cfg, tile_ctx, vertices, indices, transparent, build_cset); +} + +static bool prepare_tile(const NavMeshParams &nav_mesh_params, BuildContext &ctx, rcConfig &cfg, + recastnavmesh::RecastTileContext &tile_ctx, dag::ConstSpan vertices, dag::ConstSpan indices, + dag::ConstSpan transparent, const BBox3 &box, int gw, int gh, bool build_cset, bool with_extra_cells) +{ + tile_ctx.clearIntermediate(nullptr); + + if (!with_extra_cells) + return prepare_tile_context(nav_mesh_params, ctx, cfg, tile_ctx, vertices, indices, transparent, box, gw, gh, + nav_mesh_params.tileSize, build_cset); + + // By specifying 0.499 factor in SplitTileGeomJob we're making sure that + // extra half of tile of geometry gets fetched for each tile on each side, thus, we can + // add extra cells here and use this "extended" tile context for calculating offmesh links and + // covers, this solves "no covers / offmesh links on tile boundaries" problem. + // We can use resulting offmesh links right away when building "narrower" navmesh, since navmesh strips down all + // offmesh links that don't belong to tile. For covers, we handle this manually down below after all tiles + // are processed. + + const int extraCells = min((nav_mesh_params.tileSize - 1) / 2, nav_mesh_params.jlkCovExtraCells); + BBox3 extBox = box; + const float cellSize = nav_mesh_params.cellSize; + extBox.lim[0] -= Point3(extraCells * cellSize, 0.0f, extraCells * cellSize); + extBox.lim[1] += Point3(extraCells * cellSize, 0.0f, extraCells * cellSize); + + const int extTileSize = nav_mesh_params.tileSize + extraCells * 2; + + return prepare_tile_context(nav_mesh_params, ctx, cfg, tile_ctx, vertices, indices, transparent, extBox, gw, gh, extTileSize, + build_cset); +} + +static bool isCustomJumpLink(const SplineObject *spline) +{ + return !spline->points.empty() && spline->points.front()->getSplineClass() != nullptr && + spline->points.front()->getSplineClass()->isCustomJumplink; +} + +static Tab get_relevant_custom_jumplinks(const BBox3 &box, const HmapLandObjectEditor *objEd) +{ + Tab relevantJumplinks; + const int splinesCount = objEd->splinesCount(); + for (int i = 0; i < splinesCount; ++i) + { + const auto &spline = objEd->getSpline(i); + if (!isCustomJumpLink(spline)) + continue; + + const auto &points = spline->points; + if (points.size() != 2) + { + logerr("Custom spline jumplink should consist out of two points, but has %d points. Skipping", int(points.size())); + continue; + } + + const auto &splineSegments = spline->getBezierSpline().segs; + if (splineSegments.size() != 1) + { + logerr("Custom spline jumplink should consist out of two points and one segment, but has %d segments. Skipping", + int(splineSegments.size())); + continue; + } + + const Point3 &jumpLinkStart = splineSegments.front().sk[0]; + const Point3 jumpLinkEnd = splineSegments.front().point(1.0f); + if (box & jumpLinkStart) + relevantJumplinks.push_back({jumpLinkStart, jumpLinkEnd}); + else if (box & jumpLinkEnd) + relevantJumplinks.push_back({jumpLinkEnd, jumpLinkStart}); + } + return relevantJumplinks; +} + +static bool rasterize_and_build_navmesh_tile(const NavMeshParams &nav_mesh_params, recastnavmesh::RecastTileContext &tile_ctx, + dag::ConstSpan vertices, dag::ConstSpan indices, dag::ConstSpan transparent, + dag::ConstSpan obstacles, const ska::flat_hash_map &obstacle_flags_by_res_name_hash, + const BBox3 &box, Tab &covers, Tab> &edges_out, int tx, int ty, + Tab &tileData, const HmapLandObjectEditor *objEd, int gw = -1, int gh = -1) +{ + const bool needCov = covParams.enabled; + const bool needJlkCov = nav_mesh_params.jlkParams.enabled || needCov; + const bool useExtraCells = + (nav_mesh_params.navMeshType > pathfinder::NMT_SIMPLE) && needJlkCov && (nav_mesh_params.jlkCovExtraCells > 0); + const bool useTransparent = needCov && !transparent.empty(); + + rcConfig cfg; + BuildContext ctx; + bool preparedOKForNavMesh = false; + const Tab noTransparent; + + // + // Build covers and off mesh connections (jump links) from edges contours. + // + recastnavmesh::OffMeshConnectionsStorage connStorage; + if (needJlkCov) + { + if (!prepare_tile(nav_mesh_params, ctx, cfg, tile_ctx, vertices, indices, noTransparent, box, gw, gh, true, useExtraCells)) + return false; + preparedOKForNavMesh = !useExtraCells; + + Tab edges; + recastbuild::build_edges(edges, tile_ctx.cset, tile_ctx.chf, nav_mesh_params.mergeParams, &edges_out); + + if (nav_mesh_params.jlkParams.enabled) + recastbuild::build_jumplinks_connstorage(connStorage, edges, nav_mesh_params.jlkParams, tile_ctx.chf, tile_ctx.solid); + + const Tab customJumplinks = get_relevant_custom_jumplinks(box, objEd); + add_custom_jumplinks(connStorage, edges, customJumplinks); + + if (nav_mesh_params.jlkParams.crossObstaclesWithJumplinks && obstacle_flags_by_res_name_hash.size() > 0) + { + Tab crossObstacles; + for (auto &o : obstacles) + { + if (obstacle_flags_by_res_name_hash.find(o.resNameHash) != obstacle_flags_by_res_name_hash.end()) + { + uint32_t f = obstacle_flags_by_res_name_hash.find(o.resNameHash)->second; + if (f & ObstacleFlags::CROSS_WITH_JL) + crossObstacles.push_back({o.box, o.yAngle}); + } + } + cross_obstacles_with_jumplinks(connStorage, edges, box, nav_mesh_params.jlkParams, crossObstacles); + } + if (obstacle_flags_by_res_name_hash.size() > 0) + { + Tab disableJLObstacles; + for (auto &o : obstacles) + { + if (obstacle_flags_by_res_name_hash.find(o.resNameHash) != obstacle_flags_by_res_name_hash.end()) + { + uint32_t f = obstacle_flags_by_res_name_hash.find(o.resNameHash)->second; + if (f & ObstacleFlags::DISABLE_JL_AROUND) + disableJLObstacles.push_back({o.box, o.yAngle}); + } + } + disable_jumplinks_around_obstacle(connStorage, disableJLObstacles); + } + + if (needCov) + { + if (useTransparent) + { + rcConfig cfg2; + recastnavmesh::RecastTileContext tile_ctx2; + if (!prepare_tile(nav_mesh_params, ctx, cfg2, tile_ctx2, vertices, indices, transparent, box, gw, gh, true, useExtraCells)) + { + tile_ctx2.clearIntermediate(nullptr); + return false; + } + + recastbuild::build_covers(covers, box, edges, covParams, tile_ctx.chf, tile_ctx.solid, tile_ctx2.chf, tile_ctx2.solid, + &edges_out); + tile_ctx2.clearIntermediate(nullptr); + } + else + { + recastbuild::build_covers(covers, box, edges, covParams, tile_ctx.chf, tile_ctx.solid, tile_ctx.chf, tile_ctx.solid, + &edges_out); + } + } + } + + if (nav_mesh_params.navMeshType == pathfinder::NMT_TILECACHED) + { + Tab cutIndices(get_thread_alloc()); + cutIndices.reserve(indices.size()); + for (int idx : indices) + { + bool ign = false; + for (const NavMeshObstacle &obs : obstacles) + { + if (obs.vtxStart == -1) + continue; + if ((idx >= obs.vtxStart) && (idx < obs.vtxStart + obs.vtxCount)) + { + ign = true; + break; + } + } + if (!ign) + cutIndices.push_back(idx); + } + + // Calculate tilecached navmesh with obstacles stripped out. + tile_ctx.clearIntermediate(nullptr); + if (!prepare_tile_context(nav_mesh_params, ctx, cfg, tile_ctx, vertices, cutIndices, noTransparent, box, gw, gh, + nav_mesh_params.tileSize, false)) + return false; + + return finalize_navmesh_tilecached_tile(nav_mesh_params, ctx, cfg, connStorage, tile_ctx, obstacles, tx, ty, tileData); + } + + if (!preparedOKForNavMesh) + { + if (!prepare_tile(nav_mesh_params, ctx, cfg, tile_ctx, vertices, indices, noTransparent, box, gw, gh, true, false)) + return false; + } + else + { + rcFreeHeightField(tile_ctx.solid); + tile_ctx.solid = NULL; + } + + return finalize_navmesh_tile(nav_mesh_params, ctx, cfg, connStorage, tile_ctx, tx, ty, tileData); +} + +static WinCritSec buildJobCc; +class SplitTileGeomJob : public cpujobs::IJob +{ +public: + BBox3 landBBox; + int th = 1; + int tw = 1; + Tab> &outIndices; + Tab> &outTransparent; + Tab> &outTileObstacles; + dag::ConstSpan inTransparent; + dag::ConstSpan inVertices; + dag::ConstSpan inIndices; + IPoint2 indexRange; + float tcs = 1.f; + dag::ConstSpan inObstacles; + + SplitTileGeomJob(const BBox3 land_box, int in_tw, int in_th, Tab> &out_ind, Tab> &out_transparent, + Tab> &out_obstacles, dag::ConstSpan in_vertices, dag::ConstSpan in_indices, + dag::ConstSpan in_transparent, const IPoint2 &index_range, float in_tcs, dag::ConstSpan in_obstacles) : + landBBox(land_box), + th(in_th), + tw(in_tw), + outIndices(out_ind), + outTransparent(out_transparent), + outTileObstacles(out_obstacles), + inTransparent(in_transparent), + inVertices(in_vertices), + inIndices(in_indices), + indexRange(index_range), + tcs(in_tcs), + inObstacles(in_obstacles) + {} + + struct TileIndex + { + Point2 tilePos; + int idx; + }; + + virtual void doJob() + { + G_ASSERTF(outIndices.size() == th * tw, "Incorrect arrays %d expected, got %d", th * tw, outIndices.size()); + + float invStep = safeinv(tcs); + Point2 landBase = Point2::xz(landBBox.lim[0]); + auto getPosTileIdx = [this](const Point2 &pos_v2) -> int { + return clamp(int(pos_v2.x), 0, this->tw - 1) + clamp(int(pos_v2.y), 0, this->th - 1) * this->tw; + }; + auto getTileIdx = [&landBase, invStep, this](const Point3 &pos) -> TileIndex { + Point2 vp2 = invStep * (Point2::xz(pos) - landBase); + return {vp2, clamp(int(vp2.x), 0, this->tw - 1) + clamp(int(vp2.y), 0, this->th - 1) * this->tw}; + }; + Tab tileIndices(midmem); + tileIndices.reserve((indexRange.y - indexRange.x) * 4); + Tab triCount; + triCount.resize(outIndices.size()); + mem_set_0(triCount); + tileIndices.resize((indexRange.y - indexRange.x) * 4); + mem_set_ff(tileIndices); + for (int idx = indexRange.x; idx < indexRange.y; idx += 3) + { + int tileIndicesBase = (idx - indexRange.x) * 4; + int tileIndexLast = tileIndicesBase; + for (int i = 0; i < 3; ++i) + { + TileIndex tileIdx = getTileIdx(inVertices[inIndices[idx + i]]); + for (int y = -1; y <= +1; ++y) + for (int x = -1; x <= +1; ++x) + { + int tidx = getPosTileIdx(tileIdx.tilePos + Point2(0.499f * float(x), 0.499f * float(y))); + bool found = false; + for (int ti = tileIndicesBase; ti < tileIndexLast && !found; ++ti) + found |= tileIndices[ti] == tidx; + + if (!found) + { + tileIndices[tileIndexLast] = tidx; + ++tileIndexLast; + } + } + } + for (int i = tileIndicesBase; i < tileIndexLast; ++i) + triCount[tileIndices[i]]++; + } + Tab> indices(midmem); + Tab> transparent(midmem); + indices.reserve(outIndices.size()); + indices.resize(outIndices.size()); + transparent.reserve(outTransparent.size()); + transparent.resize(outTransparent.size()); + + for (int i = 0; i < indices.size(); ++i) + indices[i].reserve(triCount[i] * 3); + auto pushToTile = [&indices, &transparent, this](int tidx, int v0, int v1, int v2, bool transp) { + auto &ind = indices[tidx]; + if (transp) + { + const int indNext = (int)ind.size(); + auto &tr = transparent[tidx]; + if (!tr.empty() && indNext == tr.back().x + tr.back().y) + tr.back().y += 3; + else + tr.push_back({indNext, 3}); + } + ind.push_back(v0); + ind.push_back(v1); + ind.push_back(v2); + }; + auto checkTransparent = [&](int idx, int &tr_idx, int tr_num) { + while (tr_idx < tr_num) + { + IPoint2 tr = inTransparent[tr_idx]; + const int ti = idx - tr.x; + if (ti < 0) + return false; + if (ti < tr.y) + return true; + ++tr_idx; + } + return false; + }; + int trIdx = 0; + const int trNum = (int)inTransparent.size(); + auto tidxToCoord = [this](int idx) { return IPoint2(idx % this->tw, idx / this->tw); }; + auto coordToTidx = [this](int x, int y) { return x + y * this->tw; }; + for (int idx = indexRange.x; idx < indexRange.y; idx += 3) + { + bool transp = checkTransparent(idx, trIdx, trNum); + int vert0 = inIndices[idx + 0]; + int vert1 = inIndices[idx + 1]; + int vert2 = inIndices[idx + 2]; + IPoint2 minC = IPoint2(INT_MAX, INT_MAX); + IPoint2 maxC = IPoint2(INT_MIN, INT_MIN); + for (int ti = (idx - indexRange.x) * 4; ti < (idx + 3 - indexRange.x) * 4; ++ti) + if (tileIndices[ti] >= 0) + { + IPoint2 coord = tidxToCoord(tileIndices[ti]); + minC.x = min(minC.x, coord.x); + minC.y = min(minC.y, coord.y); + maxC.x = max(maxC.x, coord.x); + maxC.y = max(maxC.y, coord.y); + } + for (int x = minC.x; x <= maxC.x; ++x) + for (int y = minC.y; y <= maxC.y; ++y) + pushToTile(coordToTidx(x, y), vert0, vert1, vert2, transp); + } + + Tab> tileObstacles(midmem); + tileObstacles.resize(outTileObstacles.size()); + + for (const NavMeshObstacle &obs : inObstacles) + { + int tileIdx = 0; + for (int i = 0; i < th; ++i) + for (int j = 0; j < tw; ++j) + { + Point2 p1 = landBase + Point2(j, i) * tcs; + Point2 p2 = p1 + Point2(tcs, tcs); + BBox2 tileBox(p1, p2); + BBox2 obsBox(Point2::xz(obs.aabb.lim[0]), Point2::xz(obs.aabb.lim[1])); + if (tileBox & obsBox) + tileObstacles[tileIdx].push_back(obs); + ++tileIdx; + } + } + + WinAutoLock lock(buildJobCc); + for (int i = 0; i < transparent.size(); ++i) + { + if (transparent[i].empty()) + continue; + const int indRebase = (int)outIndices[i].size(); + outTransparent[i].reserve(outTransparent[i].size() + transparent[i].size()); + for (int j = 0; j < transparent[i].size(); ++j) + { + IPoint2 tr = transparent[i][j]; + tr.x += indRebase; + outTransparent[i].push_back(tr); + } + } + for (int i = 0; i < indices.size(); ++i) + { + if (indices[i].empty()) + continue; + outIndices[i].reserve(outIndices[i].size() + indices[i].size()); + for (int j = 0; j < indices[i].size(); ++j) + outIndices[i].push_back(indices[i][j]); + } + for (int i = 0; i < tileObstacles.size(); ++i) + { + if (tileObstacles[i].empty()) + continue; + outTileObstacles[i].reserve(outTileObstacles[i].size() + tileObstacles[i].size()); + for (int j = 0; j < tileObstacles[i].size(); ++j) + outTileObstacles[i].push_back(tileObstacles[i][j]); + } + } + virtual void releaseJob() { delete this; } +}; + +class DropDownTileJob : public cpujobs::IJob +{ +public: + const int pointDimensionsCount = 3; + const dtMeshTile *tile; + Point3 startPointOffset, traceDir; + float traceLen, traceOffset; + + int vertexProcessed, detailVertexProcessed; + + DropDownTileJob(const dtMeshTile *tile, const Point3 &start_point_offset, const Point3 &trace_dir, float trace_len, + float trace_offset) : + tile(tile), + startPointOffset(start_point_offset), + traceDir(trace_dir), + traceLen(trace_len), + traceOffset(trace_offset), + vertexProcessed(0), + detailVertexProcessed(0) + {} + + void dropPointOnCollision(float *vertex) + { + float t = traceLen + traceOffset; + Point3 point(vertex, Point3::CTOR_FROM_PTR); + if (IEditorCoreEngine::get()->traceRay(point + startPointOffset, traceDir, t, nullptr, false)) + { + point += traceDir * (t - traceOffset); + memcpy(vertex, &point[0], sizeof(float) * pointDimensionsCount); + } + } + + virtual void doJob() + { + const int tileVertsCount = tile->header->vertCount; + vertexProcessed += tileVertsCount; + for (int j = 0; j < tileVertsCount; ++j) + dropPointOnCollision(&tile->verts[j * pointDimensionsCount]); + const int detailTileVertsCount = tile->header->detailVertCount; + detailVertexProcessed += detailTileVertsCount; + for (int j = 0; j < detailTileVertsCount; ++j) + dropPointOnCollision(&tile->detailVerts[j * pointDimensionsCount]); + } + + virtual void releaseJob() { delete this; } +}; + +class BuildTileJob : public cpujobs::IJob +{ + recastnavmesh::RecastTileContext tileCtx; + BBox3 tileBox; + int nmIdx = 0; + const NavMeshParams &nmParams; + dag::ConstSpan vertices; + dag::ConstSpan indices; + dag::ConstSpan transparent; + dag::ConstSpan obstacles; + Tab tileData; + const ska::flat_hash_map obstacleFlags; + const HmapLandObjectEditor *objEd; + +public: + bool haveProblems = false; + int x = 0; + int y = 0; + Tab &finishedJobs; + Tab &covers; + Tab> &edges_out; + + BuildTileJob(int in_x, int in_y, const BBox3 &box, int in_nav_mesh_idx, dag::ConstSpan in_vertices, + dag::ConstSpan in_indices, dag::ConstSpan in_transparent, dag::ConstSpan in_obstacles, + const ska::flat_hash_map &obstacle_flags_by_res_name_hash, Tab &finished_jobs, + Tab &in_covers, Tab> &in_edges_out, const HmapLandObjectEditor *object_editor) : + x(in_x), + y(in_y), + tileBox(box), + nmParams(navMeshParams[in_nav_mesh_idx]), + vertices(in_vertices), + indices(in_indices), + transparent(in_transparent), + obstacles(in_obstacles), + finishedJobs(finished_jobs), + covers(in_covers), + edges_out(in_edges_out), + obstacleFlags(obstacle_flags_by_res_name_hash), + objEd(object_editor) + {} + + virtual void doJob() + { + haveProblems = !rasterize_and_build_navmesh_tile(nmParams, tileCtx, vertices, indices, transparent, obstacles, obstacleFlags, + tileBox, covers, edges_out, x, y, tileData, objEd); + WinAutoLock lock(buildJobCc); + finishedJobs.push_back(this); + } + virtual void releaseJob() + { + for (const recastnavmesh::BuildTileData &td : tileData) + { + navMesh->removeTile(navMesh->getTileRefAt(x, y, td.layer), NULL, NULL); + if (td.tileCacheData) + if (dtStatusFailed(tileCache->addTile(td.tileCacheData, td.tileCacheDataSz, DT_COMPRESSEDTILE_FREE_DATA, 0))) + dtFree(td.tileCacheData); + if (td.navMeshData) + if (dtStatusFailed(navMesh->addTile(td.navMeshData, td.navMeshDataSz, DT_TILE_FREE_DATA, 0, nullptr))) + dtFree(td.navMeshData); + } + delete this; + } +}; + +class CheckCoversJob : public cpujobs::IJob +{ +public: + IPoint2 range; + Tab &covers; + Tab &unavailableCovers; + dtNavMeshQuery *navQuery; + + static constexpr float maxRadiusThreshold = 500.0f; + static constexpr int aroundCountTreshold = 50; + static constexpr int countTreshold = 20; + + CheckCoversJob(IPoint2 range_in, Tab &covers_in, Tab &unavailable_covers_in) : + range(range_in), covers(covers_in), unavailableCovers(unavailable_covers_in), navQuery(nullptr) + {} + + virtual void doJob() + { + if (!pathfinder::isLoaded()) + return; + + navQuery = dtAllocNavMeshQuery(); + if (!navQuery) + { + logerr_ctx("Could not create NavMeshQuery"); + return; + } + + if (dtStatusFailed(navQuery->init(pathfinder::getNavMeshPtr(), 2048))) + { + logerr_ctx("Could not init Detour navmesh query"); + return; + } + + for (int i = range[0]; i < range[1]; i++) + { + int checkedCov = 0, totalCov = 0; + Point3 posi = lerp(covers[i].groundLeft, covers[i].groundRight, 0.5f); + + float radTreshold = 100.0f / 2.0f; + float radTresholdSq = sqr(radTreshold); + + int aroundCount = 0; + while (aroundCount < aroundCountTreshold && radTreshold < maxRadiusThreshold) + { + radTreshold *= 2.0f; + radTresholdSq = sqr(radTreshold); + + aroundCount = 0; + for (int j = 0; j < covers.size(); j++) + { + if (j == i) + continue; + Point3 posj = lerp(covers[j].groundLeft, covers[j].groundRight, 0.5f); + if (lengthSq(posi - posj) > radTresholdSq) + continue; + ++aroundCount; + } + } + + pathfinder::NavParams params; + params.enable_jumps = true; + for (int j = 0; j < covers.size(); j++) + { + if (j == i) + continue; + + Point3 posj = lerp(covers[j].groundLeft, covers[j].groundRight, 0.5f); + if (lengthSq(posi - posj) > radTresholdSq) + continue; + ++totalCov; + + if (pathfinder::check_path(navQuery, posi, posj, Point3(0.5f, FLT_MAX, 0.5f), params, 0.5f, 1.f)) + if (++checkedCov > countTreshold) + break; + } + + if (checkedCov < countTreshold && float(checkedCov) / float(totalCov) < 0.5f) + unavailableCovers.push_back(i); + } + + dtFreeNavMeshQuery(navQuery); + } + virtual void releaseJob() + { + navQuery = NULL; + delete this; + } +}; + +static void gather_collider_plugins(const NavMeshParams &nav_mesh_params, Tab &coll) +{ + for (int i = 0, coll_cnt = DAGORED2->getCustomCollidersCount(); i < coll_cnt; ++i) + if (IDagorEdCustomCollider *p = DAGORED2->getCustomCollider(i)) + if (strcmp(p->getColliderName(), "(srv) Render instance entities") == 0 || + (nav_mesh_params.usePrefabCollision && strcmp(p->getColliderName(), "(srv) Prefab entities") == 0) || + strcmp(p->getColliderName(), "SGeometry") == 0) + coll.push_back(p); +} + +static void prepare_collider_plugins(const Tab &coll) +{ + for (IDagorEdCustomCollider *c : coll) + c->prepareCollider(); +} + +static void setup_collider_plugins(const Tab &coll, const BBox3 &box) +{ + DAGORED2->setColliders(coll, 0xFFFFFFFF); + // pregen all RI to get proper cuts for navigation mesh + for (int i = 0; i < coll.size(); ++i) + coll[i]->setupColliderParams(1, box); +} + +static void gather_static_coll(StaticGeometryContainer &cont) +{ + for (int i = 0, plugin_cnt = IEditorCoreEngine::get()->getPluginCount(); i < plugin_cnt; ++i) + { + IGenEditorPlugin *plugin = DAGORED2->getPlugin(i); + IGatherStaticGeometry *geom = plugin->queryInterface(); + IGatherCollision *gatherColl = plugin->queryInterface(); + if (geom) + geom->gatherStaticCollisionGeomEditor(cont); + } +} + +static void calc_colliders_buffer_size(int &vert, int &ind, const StaticGeometryContainer &cont) +{ + for (int i = 0; i < cont.nodes.size(); ++i) + { + vert += cont.nodes[i]->mesh->mesh.vert.size(); + ind += cont.nodes[i]->mesh->mesh.face.size() * 3; + } +} + +static void gather_colliders_meshes(Tab &vertices, Tab &indices, Tab &transparent, + Tab &obstacles, const ska::flat_hash_map *&obstacle_flags_by_res_name_hash, + const StaticGeometryContainer &cont, const BBox3 &box) +{ + for (int i = 0; i < cont.nodes.size(); ++i) + { + StaticGeometryNode &n = *cont.nodes[i]; + Mesh mesh = n.mesh->mesh; + const TMatrix &wtm = n.wtm; + int idxBase = vertices.size(); + for (int j = 0; j < mesh.vert.size(); ++j) + vertices.push_back(wtm * mesh.vert[j]); + for (int j = 0; j < mesh.face.size(); ++j) + for (int k = 0; k < 3; ++k) + indices.push_back(mesh.face[j].v[k] + idxBase); + } + + for (int i = 0, plugin_cnt = IEditorCoreEngine::get()->getPluginCount(); i < plugin_cnt; ++i) + { + IGenEditorPlugin *plugin = DAGORED2->getPlugin(i); + IGatherCollision *gatherColl = plugin->queryInterface(); + if (!gatherColl) + continue; + int64_t refdet = ref_time_ticks_qpc(); + gatherColl->gatherCollision(box, vertices, indices, transparent, obstacles); + DAEDITOR3.conNote("Gathered geom for %.2f sec", get_time_usec_qpc(refdet) / 1000000.0); + gatherColl->getObstaclesFlags(obstacle_flags_by_res_name_hash); + } +} + +bool HmapLandPlugin::buildAndWriteSingleNavMesh(BinDumpSaveCB &cwr, int nav_mesh_idx) +{ + NavMeshParams &nmParams = navMeshParams[nav_mesh_idx]; + DataBlock &nmProps = navMeshProps[nav_mesh_idx]; + const bool needsDebugEdges = nav_mesh_idx == 0; + + if (!nmProps.getBool("export", false) && cwr.getTarget()) + return true; + + init(nmProps, nav_mesh_idx); + if (nmParams.navmeshExportType == NavmeshExportType::INVALID) + { + DAEDITOR3.conError("Invalid navmesh export type, please choose appropriate type of navmesh export"); + return false; + } + clearNavMesh(); + + dtTileCacheAlloc tcAllocator; + pathfinder::TileCacheCompressor tcComp; + tcComp.reset(nmParams.bucketSize > 0.0f); + + float water_lev = hasWaterSurface ? waterSurfaceLevel : (nmProps.getBool("hasWater", false) ? nmProps.getReal("waterLev", 0) : -1e6); + float min_h = 0, max_h = water_lev; + + if (nmParams.navmeshExportType == NavmeshExportType::WATER || nmParams.navmeshExportType == NavmeshExportType::WATER_AND_GEOMETRY) + water_lev = nmProps.getReal("waterLev", 0); + + int nav_area_type = nmProps.getInt("navArea", 0); + if (nav_area_type < 0 || nav_area_type > 2) + { + DAEDITOR3.conWarning("Incorrect navArea=%d, changing to 1", nav_area_type); + nmProps.setInt("navArea", nav_area_type = 1); + } + + BBox2 nav_area; + if (nav_area_type == 1 && detDivisor) + nav_area = detRect; + else if (nav_area_type == 2) + { + nav_area[0] = nmProps.getPoint2("rect0", Point2(0, 0)); + nav_area[1] = nmProps.getPoint2("rect1", Point2(1000, 1000)); + } + else + { + nav_area[0].set_xz(landBox[0]); + nav_area[1].set_xz(landBox[1]); + } + + if (covParams.enabled) + { + covParams.maxVisibleBox[0] = Point3(nav_area[0].x, -500.f, nav_area[0].y); + covParams.maxVisibleBox[1] = Point3(nav_area[1].x, 500.f, nav_area[1].y); + } + + int width = nav_area.width().x / nmParams.traceStep; + int length = nav_area.width().y / nmParams.traceStep; + if (width <= 0 || width >= 4096 || length <= 0 || length >= 4096) + { + DAEDITOR3.conError("Incorrect grid size %dx%d (for area %@ with traceStep=%.2f)", width, length, nav_area, nmParams.traceStep); + return false; + } + + int64_t reft = ref_time_ticks_qpc(); + + Tab coll(tmpmem); + gather_collider_plugins(nmParams, coll); + BBox3 collidersBox(Point3::xVy(nav_area[0], -FLT_MAX), Point3::xVy(nav_area[1], FLT_MAX)); + setup_collider_plugins(coll, collidersBox); + prepare_collider_plugins(coll); + Tab vertices; + Tab indices; + Tab transparent; + Tab obstacles; + const ska::flat_hash_map obstacleFlagsDefault; + const ska::flat_hash_map *obstacleFlags = nullptr; + const bool useDetailGeometry = + nmParams.navmeshExportType == NavmeshExportType::GEOMETRY || nmParams.navmeshExportType == NavmeshExportType::WATER_AND_GEOMETRY; + if (useDetailGeometry) + { + int64_t refdet = ref_time_ticks_qpc(); + setup_collider_plugins(coll, collidersBox); + int vertCount = 0; + int indCount = 0; + StaticGeometryContainer geoCont; + gather_static_coll(geoCont); + calc_colliders_buffer_size(vertCount, indCount, geoCont); + vertices.reserve(vertCount); + indices.reserve(indCount); + + gather_colliders_meshes(vertices, indices, transparent, obstacles, obstacleFlags, geoCont, collidersBox); + + for (int i = 0; i < coll.size(); ++i) + coll[i]->setupColliderParams(0, BBox3()); + DAGORED2->restoreEditorColliders(); + for (int i = 0; i < vertices.size(); ++i) + { + inplace_min(min_h, vertices[i].y); + inplace_max(max_h, vertices[i].y); + } + DAEDITOR3.conNote("Built detail geom for %.2f sec, %d vertices", get_time_usec_qpc(refdet) / 1000000.0, vertices.size()); + } + + if (!obstacleFlags) + obstacleFlags = &obstacleFlagsDefault; + + { + // Leave only obstacles that are higher than 'agentMaxClimb'. + // 'agentMaxClimb' is somewhat confusing name, it describes how high + // ledges can be before the character can no longer step up on them. + // So if the character CAN step up on them, there's no point in making an obstacle. + Tab filteredObstacles; + filteredObstacles.reserve(obstacles.size()); + for (const NavMeshObstacle &obstacle : obstacles) + if (!pathfinder::tilecache_ri_obstacle_too_low(obstacle.aabb.width().y, nmParams.agentMaxClimb)) + filteredObstacles.push_back(obstacle); + filteredObstacles.swap(obstacles); + } + + { + Point2 worldPosOfs = nav_area[0]; + + float startXfloat = worldPosOfs.x, startZfloat = worldPosOfs.y; + + HierBitMap2d>> splBm; + BezierSpline2d s2d_src; + splBm.resize(width, length); + + int64_t refsplines = ref_time_ticks_qpc(); + for (int i = 0; i < objEd.splinesCount(); i++) + { + SplineObject *sobj = objEd.getSpline(i); + float def_hw = sobj->getProps().useForNavMesh ? sobj->getProps().navMeshStripeWidth / 2 : -1; + if (sobj->isPoly()) + continue; + + int w = width, h = length; + float sx = 1.0f / nmParams.traceStep; + sobj->getSplineXZ(s2d_src); + BezierSplinePrec2d &s2d = toPrecSpline(s2d_src); + float splineLen = s2d.getLength(), st; + + const splineclass::AssetData *a = sobj->points[0]->getSplineClass(); + int seg = 0, hw0 = (a && a->navMeshStripeWidth > 0) ? int(a->navMeshStripeWidth / 2 * sx) : def_hw * sx; + + for (float s = 0.0; s < splineLen; s += 0.5 / sx) //-V1034 + { + int n_seg = s2d.findSegment(s, st); + if (seg != n_seg) + { + a = sobj->points[n_seg]->getSplineClass(); + hw0 = (a && a->navMeshStripeWidth > 0) ? int(a->navMeshStripeWidth / 2 * sx) : def_hw * sx; + seg = n_seg; + } + if (hw0 <= 0) + continue; + + Point2 p = s2d.segs[n_seg].point(st); + Point2 t = normalize(s2d.segs[n_seg].tang(st)); + Point2 n(t.y / sx, -t.x / sx); + for (int i = -hw0 + 1; i <= hw0 - 1; i++) + { + float px = p.x + n.x * i - startXfloat, pz = p.y + n.y * i - startZfloat; + int ix = int(px * sx) - 1, ixe = ix + 3 <= w ? ix + 3 : w; + int iy = int(pz * sx) - 1, iye = iy + 3 <= h ? iy + 3 : h; + for (iy = iy < 0 ? 0 : iy, ix = ix < 0 ? 0 : ix; iy < iye; iy++) + for (int x = ix; x < ixe; x++) + splBm.set(x, iy); + } + } + } + DAEDITOR3.conNote("Built splines geom for %.2f sec", get_time_usec_qpc(refsplines) / 1000000.0); + // if (use_splines) + // saveBmTga(splBm, "splMask.tga"); + + DEBUG_DUMP_VAR(landMeshMap.getEditorLandRayTracer()); + DEBUG_DUMP_VAR(landMeshMap.getGameLandRayTracer()); + DEBUG_DUMP_VAR(water_lev); + + int idxBase = vertices.size(); + vertices.resize(vertices.size() + length * width); + const int indicesBase = indices.size(); + indices.resize(indicesBase + (length - 1) * (width - 1) * 6); + + float *v = &vertices[idxBase].x; + + int64_t refhmap = ref_time_ticks_qpc(); + for (int z = 0; z < length; z++) + for (int x = 0; x < width; x++, v += 3) + { + v[0] = startXfloat + nmParams.traceStep * x; + v[1] = 8192; + v[2] = startZfloat + nmParams.traceStep * z; + if ((nmParams.navmeshExportType == NavmeshExportType::SPLINES && !splBm.get(x, z)) || + (!getHeight(Point2(v[0], v[2]), v[1], NULL) && !landMeshMap.getHeight(Point2(v[0], v[2]), v[1], NULL))) + v[1] = water_lev - 1 - nmParams.crossingWaterDepth; + else + { + const float aboveHt = 200; + real dist = aboveHt; + if ((nmParams.navmeshExportType == NavmeshExportType::WATER || + nmParams.navmeshExportType == NavmeshExportType::WATER_AND_GEOMETRY) && + v[1] < MIN_BOTTOM_DEPTH) + v[1] = MIN_BOTTOM_DEPTH; + if (!useDetailGeometry && DAGORED2->traceRay(Point3(v[0], v[1] + aboveHt, v[2]), Point3(0, -1, 0), dist, NULL, false)) + v[1] += aboveHt - dist; + if (nmParams.navmeshExportType == NavmeshExportType::WATER || + nmParams.navmeshExportType == NavmeshExportType::WATER_AND_GEOMETRY) + v[1] = max(v[1], water_lev); + inplace_max(max_h, v[1]); + inplace_min(min_h, v[1]); + } + } + + v = &vertices[idxBase].y; + int *indicesPtr = &indices[indicesBase]; + for (int z = 0, zwidth = idxBase; z + 1 < length; z++, v += 3, zwidth += width) + for (int x = 0, zwidthplusx = zwidth; x + 1 < width; x++, v += 3, zwidthplusx++) + { + if (nmParams.navmeshExportType == NavmeshExportType::WATER || + nmParams.navmeshExportType == NavmeshExportType::WATER_AND_GEOMETRY) + { + if (v[0] <= water_lev && v[width * 3 + 3] <= water_lev && v[3] <= water_lev) + { + *(indicesPtr++) = zwidthplusx; + *(indicesPtr++) = zwidthplusx + width + 1; + *(indicesPtr++) = zwidthplusx + 1; + } + if (v[0] <= water_lev && v[width * 3] <= water_lev && v[width * 3 + 3] <= water_lev) + { + *(indicesPtr++) = zwidthplusx; + *(indicesPtr++) = zwidthplusx + width; + *(indicesPtr++) = zwidthplusx + width + 1; + } + } + else + { + if (v[0] > water_lev - nmParams.crossingWaterDepth && v[width * 3 + 3] > water_lev - nmParams.crossingWaterDepth && + v[3] > water_lev - nmParams.crossingWaterDepth) + { + *(indicesPtr++) = zwidthplusx; + *(indicesPtr++) = zwidthplusx + width + 1; + *(indicesPtr++) = zwidthplusx + 1; + } + if (v[0] > water_lev - nmParams.crossingWaterDepth && v[width * 3] > water_lev - nmParams.crossingWaterDepth && + v[width * 3 + 3] > water_lev - nmParams.crossingWaterDepth) + { + *(indicesPtr++) = zwidthplusx; + *(indicesPtr++) = zwidthplusx + width; + *(indicesPtr++) = zwidthplusx + width + 1; + } + } + } + G_ASSERT(indices.capacity() >= indicesBase + (indicesPtr - &indices[indicesBase])); + indices.resize(indicesBase + (indicesPtr - &indices[indicesBase])); + DAEDITOR3.conNote("Built hmap geom for %.2f sec", get_time_usec_qpc(refhmap) / 1000000.0); + + for (int i = 0, plugin_cnt = IEditorCoreEngine::get()->getPluginCount(); i < plugin_cnt; ++i) + { + IGenEditorPlugin *plugin = DAGORED2->getPlugin(i); + IGatherGroundHoles *holesMgr = plugin->queryInterface(); + if (!holesMgr) + continue; + Tab holes; + holesMgr->gatherGroundHoles(holes); + DAEDITOR3.conNote("Ground holes: %d", holes.size()); + int64_t refholes = ref_time_ticks_qpc(); + int *indicesEnd = indices.end(); + for (int *indPtr = &indices[indicesBase]; indPtr < indicesEnd; indPtr += 3) + for (const GroundHole &hole : holes) + if (hole.check(Point2::xz(vertices[indPtr[0]])) || hole.check(Point2::xz(vertices[indPtr[1]])) || + hole.check(Point2::xz(vertices[indPtr[2]]))) + { + indicesEnd -= 3; + indPtr[0] = indicesEnd[0]; + indPtr[1] = indicesEnd[1]; + indPtr[2] = indicesEnd[2]; + break; + } + indices.resize(indicesEnd - &indices[0]); + DAEDITOR3.conNote("Cut ground holes for %.2f sec", get_time_usec_qpc(refholes) / 1000000.0); + } + } + if (!useDetailGeometry) + { + for (int i = 0; i < coll.size(); ++i) + coll[i]->setupColliderParams(0, BBox3()); + DAGORED2->restoreEditorColliders(); + } + + DAEDITOR3.conNote("Built collision %dx%d for %.2f sec (minH/maxH/waterH/crossing=%.1f/%.1f/%.1f/%.1f) nTri=%d vVert=%d", width, + length, get_time_usec_qpc(reft) / 1000000.0, min_h, max_h, water_lev, nmParams.crossingWaterDepth, indices.size() / 3, + vertices.size()); + + BBox3 landBBox; + if (nmParams.navmeshExportType == NavmeshExportType::WATER) + { + landBBox[0].set_xVy(nav_area[0], min_h - 1); + landBBox[1].set_xVy(nav_area[1], min(max_h, water_lev) + 1); + } + else + { + landBBox[0].set_xVy(nav_area[0], max(min_h, water_lev) - 1); + landBBox[1].set_xVy(nav_area[1], max_h + 1); + } + DEBUG_DUMP_VAR(landBBox); + + + // Set the area where the navigation will be build. + // Here the bounds of the input mesh are used, but the + // area could be specified by an user defined box, etc. + int gw, gh; + rcCalcGridSize(&landBBox.lim[0].x, &landBBox.lim[1].x, nmParams.cellSize, &gw, &gh); + + // Reset build times gathering. + global_build_ctx.resetTimers(); + + // Start the build process. + global_build_ctx.startTimer(RC_TIMER_TOTAL); + + Tab> coversLists(midmem); + coversLists.reserve(1); + coversLists.push_back().reserve(100); + + Tab>> debugEdgesLists(midmem); + debugEdgesLists.reserve(1); + debugEdgesLists.push_back().reserve(100); + + navMesh = dtAllocNavMesh(); + if (!navMesh) + { + global_build_ctx.log(RC_LOG_ERROR, "Could not create Detour navmesh"); + return false; + } + if (nmParams.navMeshType > pathfinder::NMT_SIMPLE) + { + // Tiled calculation + const int ts = nmParams.tileSize; + const int tw = (gw + ts - 1) / ts; + const int th = (gh + ts - 1) / ts; + const float tcs = nmParams.tileSize * nmParams.cellSize; + + DEBUG_DUMP_VAR(ts); + DEBUG_DUMP_VAR(tw); + DEBUG_DUMP_VAR(th); + DEBUG_DUMP_VAR(tcs); + + dtNavMeshParams params; + rcVcopy(params.orig, &landBBox.lim[0].x); + params.tileWidth = tcs; + params.tileHeight = tcs; + if (nmParams.navMeshType == pathfinder::NMT_TILED) + { + params.maxTiles = th * tw; + params.maxPolys = 1 << (32 - 16 - 2); + } + else + { + G_ASSERT(nmParams.navMeshType == pathfinder::NMT_TILECACHED); + params.maxTiles = th * tw * TILECACHE_AVG_LAYERS_PER_TILE; + params.maxPolys = 1 << (32 - 16 - 2); + } + DEBUG_DUMP_VAR(params.maxPolys); + if (!navMesh->init(¶ms)) + { + global_build_ctx.log(RC_LOG_ERROR, "Could not init Detour navmesh"); + clearNavMesh(); + return false; + } + int cores_count = cpujobs::get_core_count(); + DAEDITOR3.conNote("Building nav mesh with Recast/Detour with %d/%d cores", cores_count, cpujobs::get_core_count()); + int numSplits = cores_count * 2; + Tab> tileIndices; + Tab> tileTransparent; + Tab> tileObstacles; + tileIndices.resize(th * tw); + tileTransparent.resize(th * tw); + tileObstacles.resize(th * tw); + int64_t refsplit = ref_time_ticks_qpc(); + DAEDITOR3.conNote("vert data size %.2f MB, indices data size %.2f MB", data_size(vertices) * 0.000001f, + data_size(indices) * 0.000001f); + if (cores_count) + { + threadpool::init(cores_count, get_bigger_pow2(max(th * tw, numSplits)), 128 << 10); + thread_alloc.resize(cores_count); + for (int i = 0; i < cores_count; ++i) + thread_alloc[i] = MspaceAlloc::create(nullptr, 32 << 20, false); + } + Tab splitJobs(tmpmem); + for (int i = 0; i < numSplits; ++i) + { + int triCount = indices.size() / 3; + IPoint2 indexRange(i * (triCount / (numSplits - 1)) * 3, (i + 1) * (triCount / (numSplits - 1)) * 3); + if (indexRange.y > indices.size()) + indexRange.y = indices.size(); + IPoint2 obstaclesRange(i * ((float)obstacles.size() / (float)(numSplits - 1)), + (i + 1) * ((float)obstacles.size() / (float)(numSplits - 1))); + obstaclesRange.x = min((int)obstacles.size(), max(i, obstaclesRange.x)); + obstaclesRange.y = min((int)obstacles.size(), max(obstaclesRange.x + 1, obstaclesRange.y)); + + SplitTileGeomJob *job = new SplitTileGeomJob(landBBox, tw, th, tileIndices, tileTransparent, tileObstacles, vertices, indices, + transparent, indexRange, tcs, make_span_const(&obstacles[obstaclesRange.x], obstaclesRange.y - obstaclesRange.x)); + threadpool::add(job); + splitJobs.push_back(job); + } + if (!cores_count) + { + SplitTileGeomJob job(landBBox, tw, th, tileIndices, tileTransparent, tileObstacles, vertices, indices, transparent, + IPoint2(0, indices.size()), tcs, obstacles); + job.doJob(); + } + else + { + threadpool::wake_up_all(); + for (int i = 0; i < splitJobs.size(); ++i) + threadpool::wait(splitJobs[i]); + for (int i = 0; i < splitJobs.size(); ++i) + splitJobs[i]->releaseJob(); + } + int64_t dataSize = 0; + for (int i = 0; i < tileIndices.size(); ++i) + dataSize += data_size(tileIndices[i]); + DAEDITOR3.conNote("total data size for tiles indices %.2f MB", dataSize * 0.000001f); + + DAEDITOR3.conNote("Split tiles in %.2f sec", get_time_usec_qpc(refsplit) / 1000000.0); + clear_and_shrink(indices); // we don't need those indices anymore + + if (cores_count) + { + int threadCount = th * tw; + coversLists.reserve(threadCount); + debugEdgesLists.reserve(threadCount); + for (int i = 0; i < threadCount - 1; ++i) + { + coversLists.push_back().reserve(100); + debugEdgesLists.push_back().reserve(100); + ; + } + } + + if (nmParams.navMeshType == pathfinder::NMT_TILECACHED) + { + tileCache = dtAllocTileCache(); + if (!tileCache) + { + global_build_ctx.log(RC_LOG_ERROR, "Could not create Detour tile cache"); + clearNavMesh(); + return false; + } + + dtTileCacheParams tcparams; + memset(&tcparams, 0, sizeof(tcparams)); + rcVcopy(tcparams.orig, &landBBox.lim[0].x); + tcparams.cs = nmParams.cellSize; + tcparams.ch = nmParams.cellHeight; + tcparams.width = nmParams.tileSize; + tcparams.height = nmParams.tileSize; + tcparams.walkableHeight = nmParams.agentHeight; + tcparams.walkableRadius = nmParams.agentRadius; + tcparams.walkableClimb = nmParams.agentMaxClimb; + tcparams.maxSimplificationError = clamp(nmParams.edgeMaxError / nmParams.cellSize, 1.1f, 1.5f); + tcparams.maxTiles = tw * th * TILECACHE_AVG_LAYERS_PER_TILE; + tcparams.maxObstacles = TILECACHE_MAX_OBSTACLES; + + tcMeshProc.setNavMesh(navMesh); + tcMeshProc.setNavMeshQuery(nullptr); + tcMeshProc.setTileCache(tileCache); + tcMeshProc.forceStaticLinks(); + dtStatus status = tileCache->init(&tcparams, &tcAllocator, &tcComp, &tcMeshProc); + if (dtStatusFailed(status)) + { + global_build_ctx.log(RC_LOG_ERROR, "Could not init Detour tile cache"); + clearNavMesh(); + return false; + } + + DAEDITOR3.conNote("Number of stationary obstacles %d, max - %d", (int)obstacles.size(), TILECACHE_MAX_OBSTACLES); + + if ((int)obstacles.size() > (TILECACHE_MAX_OBSTACLES * 4 / 5)) + global_build_ctx.log(RC_LOG_WARNING, + "Way too many stationary obstacles (%d), it would make sense to raise TILECACHE_MAX_OBSTACLES value", (int)obstacles.size()); + } + Tab tileJobs(tmpmem); + Tab finishedJobs(tmpmem); + bool haveProblems = false; + for (int y = 0; y < th; ++y) + for (int x = 0; x < tw; ++x) + { + int threadId = y * tw + x; + BBox3 tileBox = BBox3(landBBox.lim[0] + Point3(x * tcs, 0.f, y * tcs), + Point3::xVz(landBBox.lim[0] + Point3((x + 1) * tcs, 0.f, (y + 1) * tcs), landBBox.lim[1].y)); + if (!cores_count) + { + BuildTileJob job(x, y, tileBox, nav_mesh_idx, vertices, tileIndices[threadId], tileTransparent[threadId], + tileObstacles[threadId], *obstacleFlags, finishedJobs, coversLists[0], debugEdgesLists[0], &objEd); + job.doJob(); + haveProblems = job.haveProblems; + job.releaseJob(); + continue; + } + BuildTileJob *job = new BuildTileJob(x, y, tileBox, nav_mesh_idx, vertices, tileIndices[threadId], tileTransparent[threadId], + tileObstacles[threadId], *obstacleFlags, finishedJobs, coversLists[threadId], debugEdgesLists[threadId], &objEd); + tileJobs.push_back(job); + threadpool::add(job); + } + if (cores_count) + { + threadpool::wake_up_all(); + while (!tileJobs.empty()) + { + Tab jobsToFinalize(tmpmem); + { + WinAutoLock lock(buildJobCc); + jobsToFinalize = eastl::move(finishedJobs); + } + for (BuildTileJob *j : jobsToFinalize) + { + threadpool::wait(j); // should be already finished, but additional protection, so we'll not try to release job which is not + // done yet. + haveProblems |= j->haveProblems; + j->releaseJob(); + erase_item_by_value(tileJobs, j); + } + if (finishedJobs.empty()) + sleep_msec(10); // give some space for threadpool to complete it's job + } + } + + if (haveProblems) + global_build_ctx.log(RC_LOG_ERROR, "Navmesh was built with problems, check text error log!"); + + reft = ref_time_ticks_qpc(); + int pos = cwr.tell(); + + BinDumpSaveCB dcwr(2 << 20, cwr.getTarget() ? cwr.getTarget() : _MAKE4C('PC'), cwr.WRITE_BE); + + if (nmProps.getBool("dropNavmeshOnCollision", false)) + { + reft = ref_time_ticks_qpc(); + + for (int i = 0, plugin_cnt = IEditorCoreEngine::get()->getPluginCount(); i < plugin_cnt; ++i) + if (IDagorEdCustomCollider *p = DAGORED2->getCustomCollider(i)) + if (strcmp(p->getColliderName(), "HeightMap") == 0) + coll.push_back(p); + + BBox3 collidersBox(Point3::xVy(nav_area[0], -FLT_MAX), Point3::xVy(nav_area[1], FLT_MAX)); + setup_collider_plugins(coll, collidersBox); + + constexpr int pointDimensionsCount = 3; + const float traceOffset = nmProps.getReal("dropNavmeshTraceOffset", 0.3f); + const float traceLen = nmProps.getReal("dropNavmeshTraceLen", 0.3f); + const Point3 downDir(0.f, -1.f, 0.f); + const Point3 startPointOffset = -downDir * traceOffset; + const int maxTiles = navMesh->getMaxTiles(); + Tab dropDownTileJobs(tmpmem); + + int tilesProcessed = 0; + int vertexProcessed = 0; + int detailVertexProcessed = 0; + for (int i = 0; i < maxTiles; ++i) + { + const dtMeshTile *tile = ((const dtNavMesh *)navMesh)->getTile(i); + if (tile && tile->header) + { + ++tilesProcessed; + DropDownTileJob *job = new DropDownTileJob(tile, startPointOffset, downDir, traceLen, traceOffset); + dropDownTileJobs.push_back(job); + if (cores_count) + threadpool::add(job); + } + } + if (cores_count) + threadpool::wake_up_all(); + for (DropDownTileJob *j : dropDownTileJobs) + { + if (cores_count) + threadpool::wait(j); // should be already finished, but additional protection, so we'll not try to release job which is not + // done yet. + else + j->doJob(); + vertexProcessed += j->vertexProcessed; + detailVertexProcessed += j->detailVertexProcessed; + j->releaseJob(); + } + clear_and_shrink(dropDownTileJobs); + DAEDITOR3.conNote("Dropping navmesh points on collision done in %.2f sec", get_time_usec_qpc(reft) / 1000000.0); + DAEDITOR3.conNote("Dropping navmesh points: tiles processed: %i", tilesProcessed); + DAEDITOR3.conNote("Dropping navmesh points: vertex processed: %i", vertexProcessed); + DAEDITOR3.conNote("Dropping navmesh points: detail vertex processed: %i", detailVertexProcessed); + + for (int i = 0; i < coll.size(); ++i) + coll[i]->setupColliderParams(0, BBox3()); + DAGORED2->restoreEditorColliders(); + coll.pop_back(); + } + + if (nmParams.jlkParams.enabled && tileCache && nmProps.getBool("generateOverLinks", true)) + { + bool haveDataForOverLinks = false; + eastl::unique_ptr ladders; + + if (nmProps.getBool("generateOverLinksForLadders", true)) + { + ladders.reset(new scene::TiledScene()); + + int numLadders = 0; + int64_t refTime = ref_time_ticks_qpc(); + for (int i = 0, plugin_cnt = IEditorCoreEngine::get()->getPluginCount(); i < plugin_cnt; ++i) + { + IGenEditorPlugin *plugin = DAGORED2->getPlugin(i); + IGatherGameLadders *laddersMgr = plugin->queryInterface(); + if (!laddersMgr) + continue; + Tab laddersArr; + laddersMgr->gatherGameLadders(laddersArr); + for (GameLadder &ladder : laddersArr) + { + const int numLadderSteps = ladder.ladderStepsCount; + mat44f m; + v_mat44_make_from_43cu_unsafe(m, ladder.tm[0]); + ladders->allocate(m, /*pool*/ 0, /*flags*/ numLadderSteps); + ++numLadders; + } + } + if (numLadders > 0) + haveDataForOverLinks = true; + DAEDITOR3.conNote("Gathered %d ladders in %.2f sec", numLadders, get_time_usec_qpc(refTime) / 1000000.0); + } + + int numTilesNotEmpty = 0; + int numTilesWithData = 0; + int numTilesProcessed = 0; + int numTilesProblems = 0; + int numObstacleProblems = 0; + + const int64_t overLinksRefTime = ref_time_ticks(); + if (haveDataForOverLinks) + { + dtNavMeshQuery *navQuery = dtAllocNavMeshQuery(); + if (navQuery && dtStatusFailed(navQuery->init(navMesh, 4096))) + { + dtFreeNavMeshQuery(navQuery); + navQuery = nullptr; + } + + for (const auto &obs : obstacles) + { + Point3 c = obs.box.center(); + Point3 ext = obs.box.width() * 0.5f; + pathfinder::tilecache_apply_obstacle_padding(nmParams.cellSize, Point2(nmParams.agentRadius, nmParams.agentHeight), c, ext); + dtObstacleRef ref; + dtStatus status = tileCache->addBoxObstacle(&c.x, &ext.x, obs.yAngle, &ref); + if (dtStatusFailed(status)) + ++numObstacleProblems; + else + { + bool upToDate = false; + while (!upToDate) + { + // NB: Pass nullptr as navmesh to avoid real tiles rebuilding here + status = tileCache->update(0.f, nullptr, &upToDate); + if (dtStatusFailed(status)) + ++numObstacleProblems; + } + } + } + int tcObstacles = 0; + if (numObstacleProblems > 0) + global_build_ctx.log(RC_LOG_ERROR, "Problems with adding Detour obstacles for overlinks!"); + + tcMeshProc.setLadders(ladders.get()); + tcMeshProc.setNavMeshQuery(navQuery); + + const int maxTiles = navMesh->getMaxTiles(); + for (int i = 0; i < maxTiles; ++i) + { + const dtMeshTile *tile = ((const dtNavMesh *)navMesh)->getTile(i); + if (!tile || !tile->header) + continue; + + ++numTilesNotEmpty; + + bool shouldRebuild = false; + if (ladders.get()) + { + BBox3 box; + pathfinder::TileCacheMeshProcess::calcQueryLaddersBBox(box, tile->header->bmin, tile->header->bmax); + bbox3f bbox = v_ldu_bbox3(box); + ladders->boxCull(bbox, 0, 0, [&](scene::node_index idx, mat44f_cref tm) { shouldRebuild = true; }); + } + if (!shouldRebuild) + continue; + + ++numTilesWithData; + + const int tileX = tile->header->x; + const int tileY = tile->header->y; + const int tileLayer = tile->header->layer; + const dtCompressedTile *ctile = tileCache->getTileAt(tileX, tileY, tileLayer); + if (!ctile) + ++numTilesProblems; + else + { + const dtCompressedTileRef ctileRef = tileCache->getTileRef(ctile); + dtStatus status = tileCache->buildNavMeshTile(ctileRef, navMesh); + if (dtStatusFailed(status)) + ++numTilesProblems; + ++numTilesProcessed; + } + } + if (numTilesProblems > 0) + global_build_ctx.log(RC_LOG_ERROR, "Problems with rebuilding Detour tiles for overlinks!"); + + tcMeshProc.setNavMeshQuery(nullptr); + tcMeshProc.setLadders(nullptr); + + if (navQuery) + { + dtFreeNavMeshQuery(navQuery); + navQuery = nullptr; + } + } + + if (numTilesProcessed > 0 || numTilesProblems > 0 || numObstacleProblems > 0) + { + const int overLinksTimeUsec = get_time_usec(overLinksRefTime); + debug("NavMesh: rebuilded %d tiles for overlinks in %.2f sec (%d problems, %d non-empty tiles, %d tiles with data)", + numTilesProcessed, overLinksTimeUsec / 1000000.0, numTilesProblems, numTilesNotEmpty, numTilesWithData); + } + } + + save_navmesh(navMesh, nmParams, tileCache, obstacles, dcwr, nmProps.getInt("navmeshCompressRatio", 19)); + + String fileName(tileCache ? "navMeshTiled3" : "navMeshTiled2"); + fileName += (nav_mesh_idx == 0 ? String(".") : String(50, "_%d.", nav_mesh_idx + 1)); + fileName += mkbindump::get_target_str(dcwr.getTarget()); + fileName += ".bin"; + FullFileSaveCB fcwr(DAGORED2->getPluginFilePath(this, fileName)); + fcwr.beginBlock(); + dcwr.copyDataTo(fcwr); + fcwr.endBlock(); + fcwr.close(); + + if (cwr.getTarget()) + { + cwr.beginTaggedBlock(tileCache ? _MAKE4C('Lnv3') : _MAKE4C('Lnv2')); + dcwr.copyDataTo(cwr.getRawWriter()); + cwr.align8(); + cwr.endBlock(); + DAEDITOR3.conNote("Packed nav data: %dK (for %.2f sec)", (cwr.tell() - pos) >> 10, get_time_usec_qpc(reft) / 1000000.0); + } + } + else + { + Tab tileData; + recastnavmesh::RecastTileContext tctx; + rasterize_and_build_navmesh_tile(nmParams, tctx, vertices, indices, transparent, obstacles, *obstacleFlags, landBBox, + coversLists[0], debugEdgesLists[0], 0, 0, tileData, &objEd, gw, gh); + if (!tileData.empty()) + { + bool dtStatus = navMesh->init(tileData[0].navMeshData, tileData[0].navMeshDataSz, DT_TILE_FREE_DATA); + if (!dtStatus) + { + dtFree(tileData[0].navMeshData); + dtFreeNavMesh(navMesh); + global_build_ctx.log(RC_LOG_ERROR, "Could not init Detour navmesh"); + return false; + } + reft = ref_time_ticks_qpc(); + int pos = cwr.tell(); + + BinDumpSaveCB dcwr(2 << 20, cwr.getTarget() ? cwr.getTarget() : _MAKE4C('PC'), cwr.WRITE_BE); + dcwr.writeInt32e(tileData[0].navMeshDataSz | (preferZstdPacking ? 0x40000000 : 0)); + InPlaceMemLoadCB crd(tileData[0].navMeshData, tileData[0].navMeshDataSz); + if (preferZstdPacking) + zstd_compress_data(dcwr.getRawWriter(), crd, tileData[0].navMeshDataSz, 1 << 20, 19); + else + lzma_compress_data(dcwr.getRawWriter(), 9, crd, tileData[0].navMeshDataSz); + + String fileName("navMesh2"); + fileName += (nav_mesh_idx == 0 ? String(".") : String(50, "_%d.", nav_mesh_idx + 1)); + fileName += mkbindump::get_target_str(dcwr.getTarget()); + fileName += ".bin"; + FullFileSaveCB fcwr(DAGORED2->getPluginFilePath(this, fileName)); + fcwr.beginBlock(); + dcwr.copyDataTo(fcwr); + fcwr.endBlock(); + fcwr.close(); + + if (cwr.getTarget()) + { + cwr.beginTaggedBlock(_MAKE4C('Lnav')); + dcwr.copyDataTo(cwr.getRawWriter()); + cwr.align8(); + cwr.endBlock(); + + DAEDITOR3.conNote("Packed nav data: %dK (for %.2f sec)", (cwr.tell() - pos) >> 10, get_time_usec_qpc(reft) / 1000000.0); + } + } + else + { + clearNavMesh(); + return false; + } + } + + if (needsDebugEdges) + { + BinDumpSaveCB dcwr(2 << 20, cwr.getTarget() ? cwr.getTarget() : _MAKE4C('PC'), cwr.WRITE_BE); + save_debug_edges(debugEdgesLists, dcwr); + String fileName("debug_edges"); + fileName += (nav_mesh_idx == 0 ? String(".") : String(50, "_%d.", nav_mesh_idx + 1)); // -V547 + fileName += mkbindump::get_target_str(dcwr.getTarget()); + fileName += ".bin"; + + FullFileSaveCB fcwr(DAGORED2->getPluginFilePath(this, fileName)); + fcwr.beginBlock(); + dcwr.copyDataTo(fcwr); + fcwr.endBlock(); + fcwr.close(); + } + + { + BinDumpSaveCB dcwr(2 << 20, cwr.getTarget() ? cwr.getTarget() : _MAKE4C('PC'), cwr.WRITE_BE); + save_debug_obstacles(obstacles, dcwr); + String fileName("debug_obstacles"); + fileName += (nav_mesh_idx == 0 ? String(".") : String(50, "_%d.", nav_mesh_idx + 1)); + fileName += mkbindump::get_target_str(dcwr.getTarget()); + fileName += ".bin"; + + FullFileSaveCB fcwr(DAGORED2->getPluginFilePath(this, fileName)); + fcwr.beginBlock(); + dcwr.copyDataTo(fcwr); + fcwr.endBlock(); + fcwr.close(); + } + + if (covParams.enabled) + { + load_pathfinder(this, nav_mesh_idx, nmProps); + + const int64_t coverRefTime = ref_time_ticks(); + int totalSize = 0; + for (const auto &coversList : coversLists) + totalSize += (int)coversList.size(); + + Tab covers(tmpmem); + covers.reserve(totalSize); + for (auto &coversStrip : coversLists) + for (auto &cover : coversStrip) + covers.push_back(cover); + + recastbuild::fit_intersecting_covers(covers, 0, nav_area, covParams); + + const int coverTimeUsec = get_time_usec(coverRefTime); + DAEDITOR3.conNote("Simplified covers for %.2f sec", coverTimeUsec / 1000000.0); + + int cores_count = cpujobs::get_core_count(); + Tab> unavailableCovers(tmpmem); + + if ((nmParams.navMeshType > pathfinder::NMT_SIMPLE) && cores_count) + { + int numSplits = cores_count * 2; + unavailableCovers.resize(numSplits); + + int checkCount = (int)covers.size() / numSplits; + int checkIt = 0; + Tab checkCoversJobs(tmpmem); + for (int i = 0; i < numSplits; ++i) + { + if (i == numSplits - 1) + checkCount = (int)covers.size() - ((numSplits - 1) * checkCount); + + int nextCheckIt = checkIt + checkCount; + unavailableCovers[i] = Tab(tmpmem); + unavailableCovers[i].reserve(checkCount); + CheckCoversJob *job = new CheckCoversJob({checkIt, nextCheckIt}, covers, unavailableCovers[i]); + threadpool::add(job); + checkCoversJobs.push_back(job); + + checkIt = nextCheckIt; + } + + threadpool::wake_up_all(); + for (int i = 0; i < checkCoversJobs.size(); ++i) + threadpool::wait(checkCoversJobs[i]); + for (int i = 0; i < checkCoversJobs.size(); ++i) + checkCoversJobs[i]->releaseJob(); + } + else + { + unavailableCovers.push_back(Tab(tmpmem)).reserve(covers.size()); + CheckCoversJob job({0, (int)covers.size()}, covers, unavailableCovers[0]); + job.doJob(); + } + + int numRemoved = 0; + for (auto &unavCoversList : unavailableCovers) + for (int idx : unavCoversList) + if (idx >= 0 && idx < covers.size()) + covers[idx].hLeft = -1.0f; + for (int i = 0; i < (int)covers.size(); ++i) + if (covers[i].hLeft < 0.0f) + { + covers[i] = covers.back(); + covers.pop_back(); + --i; + ++numRemoved; + } + + debug("Covers: final count %d, removed %d in %.2f sec", (int)covers.size(), numRemoved, coverTimeUsec / 1000000.0); + + BinDumpSaveCB dcwr(2 << 20, cwr.getTarget() ? cwr.getTarget() : _MAKE4C('PC'), cwr.WRITE_BE); + save_covers(covers, dcwr); + + FullFileSaveCB fcwr(DAGORED2->getPluginFilePath(this, "covers.") + mkbindump::get_target_str(dcwr.getTarget()) + ".bin"); + fcwr.beginBlock(); + dcwr.copyDataTo(fcwr); + fcwr.endBlock(); + fcwr.close(); + + if (cwr.getTarget()) + { + cwr.beginTaggedBlock(_MAKE4C('CVRS')); + dcwr.copyDataTo(cwr.getRawWriter()); + cwr.align8(); + cwr.endBlock(); + } + } + + global_build_ctx.stopTimer(RC_TIMER_TOTAL); + + // Show performance stats. + duLogBuildTimes(global_build_ctx, global_build_ctx.getAccumulatedTime(RC_TIMER_TOTAL)); + + DAEDITOR3.conNote("Built nav mesh with Recast/Detour for %.2f sec", global_build_ctx.getAccumulatedTime(RC_TIMER_TOTAL) / 1000000.0); + + clearNavMesh(); + + if (cpujobs::get_core_count() && (nmParams.navMeshType > pathfinder::NMT_SIMPLE)) + { + for (MspaceAlloc *ta : thread_alloc) + ta->destroy(); + clear_and_shrink(thread_alloc); + nextThreadId = 0; + threadpool::shutdown(); + } + + return true; +} + +bool HmapLandPlugin::buildAndWriteNavMesh(BinDumpSaveCB &cwr) +{ + if (!cwr.getTarget()) + return true; + + bool success = true; + + if (navMeshProps[0].getBool("export", false)) + success = success && buildAndWriteSingleNavMesh(cwr, 0); // exporting main nav mesh separately + + unsigned int exportMask = 0; + int exportedCount = 0; + + for (int idx = 1; idx < MAX_NAVMESHES; ++idx) // -V1008 + { + if (!navMeshProps[idx].getBool("export", false)) + continue; + exportMask |= (1 << idx); + ++exportedCount; + } + + if (exportedCount == 0) + return success; + + cwr.beginTaggedBlock(_MAKE4C('Lnvs')); + const int fmt = 1; + cwr.writeInt32e(fmt); + cwr.writeInt32e(exportMask); + + for (int idx = 1; idx < MAX_NAVMESHES; ++idx) // -V1008 + { + if (exportMask & (1 << idx)) + { + cwr.writeDwString(navMeshProps[idx].getStr("kind", "")); + if (!buildAndWriteSingleNavMesh(cwr, idx)) + { + cwr.beginTaggedBlock(0); + cwr.endBlock(); + } + } + } + + cwr.endBlock(); + + return success; +} + +void HmapLandPlugin::clearNavMesh() +{ + dtFreeNavMesh(navMesh); + navMesh = NULL; + dtFreeTileCache(tileCache); + tileCache = NULL; + pathfinder::clear(); + + clear_and_shrink(coversDebugList); + clear_and_shrink(edgesDebugList); + clear_and_shrink(obstaclesDebugList); + + exportedEdgesDebugListDone = false; + exportedCoversDebugListDone = false; + exportedNavMeshLoadDone = false; + exportedObstaclesLoadDone = false; + + dagRender->invalidateDebugPrimitivesVbuffer(*navMeshBuf); + dagRender->invalidateDebugPrimitivesVbuffer(*coversBuf); + dagRender->invalidateDebugPrimitivesVbuffer(*contoursBuf); + dagRender->invalidateDebugPrimitivesVbuffer(*obstaclesBuf); +} + + +static DebugPrimitivesVbuffer *active_debug_lines_vbuf = nullptr; + + +static void beginDebugPrimitivesVbufferCache(DebugPrimitivesVbuffer *vbuf) +{ + dagRender->beginDebugLinesCacheToVbuffer(*vbuf); + active_debug_lines_vbuf = vbuf; +} + + +static void endDebugPrimitivesVbufferCache(DebugPrimitivesVbuffer *vbuf) +{ + dagRender->endDebugLinesCacheToVbuffer(*vbuf); + active_debug_lines_vbuf = nullptr; +} + + +void HmapLandPlugin::renderNavMeshDebug() +{ + const bool showCovers = shownExportedNavMeshIdx == 0 && showExportedCovers; + const bool showContours = shownExportedNavMeshIdx == 0 && showExportedNavMeshContours; + + setupRecastDetourAllocators(); + auto renderDebugPrimitives = [disableZtest = disableZtestForDebugNavMesh](DebugPrimitivesVbuffer *vbuf) { + // We anyway perform ztest, but with CMPF_LESS function to draw hidden geometry with different color + if (disableZtest) + dagRender->renderLinesFromVbuffer(*vbuf, /*z_test*/ true, /*z_write*/ false, + /*z_func_less*/ true, Color4(0.5, 0.5, 0.5, 1.0)); + dagRender->renderLinesFromVbuffer(*vbuf); + }; + + if (pathfinder::isLoaded() || coversDebugList.size() || edgesDebugList.size()) + { + if (pathfinder::isLoaded() && showExportedNavMesh) + { + if (dagRender->isLinesVbufferValid(*navMeshBuf)) + { + renderDebugPrimitives(navMeshBuf); + } + else + { + beginDebugPrimitivesVbufferCache(navMeshBuf); + pathfinder::renderDebug(); + endDebugPrimitivesVbufferCache(navMeshBuf); + } + } + + if (showCovers && coversDebugList.size() && showExportedCovers) + { + if (dagRender->isLinesVbufferValid(*coversBuf)) + { + renderDebugPrimitives(coversBuf); + } + else + { + beginDebugPrimitivesVbufferCache(coversBuf); + covers::draw_debug(coversDebugList); + covers::draw_debug(coversDebugScene); + endDebugPrimitivesVbufferCache(coversBuf); + } + } + + if (showContours && edgesDebugList.size() && showExportedNavMeshContours) + { + if (dagRender->isLinesVbufferValid(*contoursBuf)) + { + renderDebugPrimitives(contoursBuf); + } + else + { + beginDebugPrimitivesVbufferCache(contoursBuf); + for (const auto &edge : edgesDebugList) + { + if (edge.first.y == -1024.5f) + { + const float ph = edge.first.x; + const float sz = edge.first.z; + const Point3 pt1 = edge.second; + const Point3 pt2 = edge.second + Point3(sz, 0.0f, 0.0f); + const Point3 pt3 = edge.second + Point3(sz, 0.0f, sz); + const Point3 pt4 = edge.second + Point3(0.0f, 0.0f, sz); + const Point3 ofs = Point3(0.0f, ph, 0.0f); + + dagRender->addLineToVbuffer(*contoursBuf, pt1, pt2, E3DCOLOR(200, 0, 0, 255)); + dagRender->addLineToVbuffer(*contoursBuf, pt2, pt3, E3DCOLOR(200, 0, 0, 255)); + dagRender->addLineToVbuffer(*contoursBuf, pt3, pt4, E3DCOLOR(200, 0, 0, 255)); + dagRender->addLineToVbuffer(*contoursBuf, pt4, pt1, E3DCOLOR(200, 0, 0, 255)); + + dagRender->addLineToVbuffer(*contoursBuf, pt1 + ofs, pt2 + ofs, E3DCOLOR(200, 0, 0, 255)); + dagRender->addLineToVbuffer(*contoursBuf, pt2 + ofs, pt3 + ofs, E3DCOLOR(200, 0, 0, 255)); + dagRender->addLineToVbuffer(*contoursBuf, pt3 + ofs, pt4 + ofs, E3DCOLOR(200, 0, 0, 255)); + dagRender->addLineToVbuffer(*contoursBuf, pt4 + ofs, pt1 + ofs, E3DCOLOR(200, 0, 0, 255)); + + dagRender->addLineToVbuffer(*contoursBuf, pt1, pt1 + ofs, E3DCOLOR(200, 0, 0, 255)); + dagRender->addLineToVbuffer(*contoursBuf, pt2, pt2 + ofs, E3DCOLOR(200, 0, 0, 255)); + dagRender->addLineToVbuffer(*contoursBuf, pt3, pt3 + ofs, E3DCOLOR(200, 0, 0, 255)); + dagRender->addLineToVbuffer(*contoursBuf, pt4, pt4 + ofs, E3DCOLOR(200, 0, 0, 255)); + + continue; + } + dagRender->addLineToVbuffer(*contoursBuf, edge.first, edge.second, E3DCOLOR(200, 200, 0, 255)); + } + endDebugPrimitivesVbufferCache(contoursBuf); + } + } + } + + if (showExpotedObstacles && obstaclesDebugList.size()) + { + if (dagRender->isLinesVbufferValid(*obstaclesBuf)) + { + renderDebugPrimitives(obstaclesBuf); + } + else + { + beginDebugPrimitivesVbufferCache(obstaclesBuf); + for (const NavMeshObstacle &obstacle : obstaclesDebugList) + { + Point3 boxWidth = obstacle.box.width(); + // Beware that yAngle is incorrect here, it's mirrored, because matrix to euler function does it in that way + // (non-mathemathical) + TMatrix boxBasis; + Point3 ax = Point3(cosf(obstacle.yAngle), 0, -sinf(obstacle.yAngle)) * boxWidth.x; + Point3 ay = Point3(0, boxWidth.y, 0); + Point3 az = Point3(sinf(obstacle.yAngle), 0, cosf(obstacle.yAngle)) * boxWidth.z; + Point3 pos = obstacle.box.center() - 0.5f * (ax + ay + az); + dagRender->addSolidBoxToVbuffer(*obstaclesBuf, pos, ax, ay, az, E3DCOLOR_MAKE(255, 0, 255, 50)); + dagRender->addBoxToVbuffer(*obstaclesBuf, pos, ax, ay, az, E3DCOLOR_MAKE(255, 0, 255, 255)); + } + endDebugPrimitivesVbufferCache(obstaclesBuf); + } + } + + if (!exportedNavMeshLoadDone && !pathfinder::isLoaded()) + { + load_pathfinder(this, shownExportedNavMeshIdx, navMeshProps[shownExportedNavMeshIdx]); + exportedNavMeshLoadDone = true; + } + + if (!exportedCoversDebugListDone && !coversDebugList.size()) + { + FullFileLoadCB fcrd(DAGORED2->getPluginFilePath(this, "covers.PC.bin")); + if (fcrd.fileHandle) + { + fcrd.beginBlock(); + if (!covers::load(fcrd, coversDebugList)) + DAEDITOR3.conError("failed to load covers from %s", fcrd.getTargetName()); + else + covers::build(128, 8, coversDebugList, coversDebugScene); + fcrd.endBlock(); + } + exportedCoversDebugListDone = true; + } + + const String filePostfix = + (shownExportedNavMeshIdx == 0 ? String(".PC.bin") : String(50, "_%d.PC.bin", shownExportedNavMeshIdx + 1)); + if (!exportedEdgesDebugListDone && !edgesDebugList.size()) + { + FullFileLoadCB fcrd(DAGORED2->getPluginFilePath(this, String("debug_edges") + filePostfix)); + if (fcrd.fileHandle) + { + fcrd.beginBlock(); + load_debug_edges(fcrd, edgesDebugList); + fcrd.endBlock(); + } + exportedEdgesDebugListDone = true; + } + + if (!exportedObstaclesLoadDone && obstaclesDebugList.empty()) + { + FullFileLoadCB fcrd(DAGORED2->getPluginFilePath(this, String("debug_obstacles") + filePostfix)); + if (fcrd.fileHandle) + { + fcrd.beginBlock(); + load_debug_obstacles(fcrd, obstaclesDebugList); + fcrd.endBlock(); + } + exportedObstaclesLoadDone = true; + } +} + +// wrapper for functions used in gameLibs/pathFinder +void draw_cached_debug_line(const Point3 &p0, const Point3 &p1, E3DCOLOR c) +{ + dagRender->addLineToVbuffer(*active_debug_lines_vbuf, p0, p1, c); +} + + +void set_cached_debug_lines_wtm(const TMatrix &tm) { dagRender->setVbufferTm(*active_debug_lines_vbuf, tm); } + +void draw_cached_debug_box(const Point3 &p, const Point3 &ax, const Point3 &ay, const Point3 &az, E3DCOLOR color) +{ + dagRender->addBoxToVbuffer(*active_debug_lines_vbuf, p, ax, ay, az, color); +} + +void draw_cached_debug_box(const BBox3 &box, E3DCOLOR color) { dagRender->addBoxToVbuffer(*active_debug_lines_vbuf, box, color); } + +void draw_cached_debug_solid_triangle(const Point3 p[3], E3DCOLOR color) +{ + dagRender->addTriangleToVbuffer(*active_debug_lines_vbuf, p, color); +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/recastNavMesh.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/recastNavMesh.h new file mode 100644 index 000000000..8ccc324ea --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/recastNavMesh.h @@ -0,0 +1,15 @@ +#pragma once + +enum class NavmeshExportType : uint8_t +{ + WATER = 0, + SPLINES, + HEIGHT_FROM_ABOVE, + GEOMETRY, + WATER_AND_GEOMETRY, + INVALID, + COUNT +}; + +NavmeshExportType navmesh_export_type_name_to_enum(const char *name); +const char *navmesh_export_type_to_string(NavmeshExportType type); diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/renderLandNormals.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/renderLandNormals.cpp new file mode 100644 index 000000000..91412432b --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/renderLandNormals.cpp @@ -0,0 +1,175 @@ +#include +#include +#include +#include "hmlPlugin.h" +#include "landMeshMap.h" +#include "libTools/math/gouraud.h" +#include "renderLandNormals.h" +#include +#include + +float *NormalFrameBuffer::start_ht = 0; + + +static uint16_t isLandMesh = 0; +class OpaqueShader +{ +public: + static inline void shade(const NormalFrameBuffer &pixel, const Point3 &val) + { + if (*pixel.ht > val.x) + return; + *pixel.ht = val.x; + if (isLandMesh) + { // do not calculate normal, save only height - we'll use heightmap normal instead + // ugly hack: do not even save invalid normal - we render landmesh first, + // so we don't need to write invalid value + //*pixel.normal = 0xFFFF; + return; + } + Point3 nrm(val.y, sqrtf(1 - val.y * val.y - val.z * val.z), val.z); + float lg = length(nrm); + float scale = 0.5f / lg; + pixel.normal[pixel.ht - pixel.start_ht] = real2uchar(nrm.x * scale + 0.5) | (real2uchar(nrm.z * scale + 0.5) << 8); + // makes unparallelable!!! + } +}; + + +static void render_mesh(Gouraud &shading, Mesh &m, float sx, float sy, float scale, + Bitarray *used_mats = NULL) +{ + for (int i = 0; i < m.face.size(); ++i) + { + Face &face = m.face[i]; + if (used_mats) + { + int mat = face.mat; + if (mat >= used_mats->size()) + mat = used_mats->size() - 1; + if (mat < 0 || !used_mats->get(mat)) + continue; + } + Point2 scr[3]; + Point3 interp[3]; + for (int vi = 0; vi < 3; vi++) + { + Point3 v = m.vert[face.v[vi]]; + scr[vi] = Point2(v.x - sx, v.z - sy) * scale; + if (!isLandMesh) + { + Point3 vn = -m.vertnorm[m.facengr[i][vi]]; + if (vn.y < 0) + vn = -vn; + interp[vi] = Point3(v.y, vn.x, vn.z); + } + } + shading.draw_triangle(scr, interp); + } +} + +bool create_lmesh_normal_map(LandMeshMap &land, NormalFrameBuffer map, float sx, float sy, float scale, int wd, int ht) +{ + CoolConsole &con = DAGORED2->getConsole(); + + con.setActionDesc("gather static visual..."); + con.setTotal(DAGORED2->getPluginCount()); + StaticGeometryContainer *geoCont = dagGeom->newStaticGeometryContainer(); + for (int i = 0; i < DAGORED2->getPluginCount(); ++i) + { + con.setDone(i); + IGenEditorPlugin *plugin = DAGORED2->getPlugin(i); + + IGatherStaticGeometry *geom = plugin->queryInterface(); + if (!geom) + continue; + + geom->gatherStaticVisualGeometry(*geoCont); + } + con.endProgress(); + if (!geoCont->nodes.size()) + { + con.addMessage(ILogWriter::NOTE, "No other meshes - not rendering anything"); + return false; + } + + + con.setActionDesc("rendering lmesh geom..."); + Gouraud shading; + shading.init(map, wd, ht); + int faces = 0; + isLandMesh = 1; + for (int y = 0; y < land.getNumCellsY(); ++y) + for (int x = 0; x < land.getNumCellsX(); ++x) + { + Mesh *m = land.getCellLandMesh(x, y); + if (!m) + continue; + faces += m->face.size(); + render_mesh(shading, *m, sx, sy, scale); + } + con.setActionDesc("rendering static geom..."); + con.setTotal(geoCont->nodes.size() / 32); + + isLandMesh = 0; + Bitarray used_mats; + for (int i = 0; i < geoCont->nodes.size(); ++i) + { + if (!(i & 31)) + con.setDone(i / 32); + + StaticGeometryNode *node = geoCont->nodes[i]; + + if (!node) + continue; + + used_mats.resize(node->mesh->mats.size()); + int any_landmesh = 0; + for (int mi = 0; mi < node->mesh->mats.size(); ++mi) + { + //==fixme: name could be moved to application.blk + bool iscombined = false; + if (strstr(node->mesh->mats[mi]->className.str(), "land_mesh") && !strstr(node->mesh->mats[mi]->className.str(), "decal")) + { + CfgReader c; + c.getdiv_text(String(128, "[q]\r\n%s\r\n", node->mesh->mats[mi]->scriptText.str()), "q"); + if (c.getbool("render_landmesh_combined", 1)) + iscombined = true; + } + + if (iscombined) + { + used_mats.set(mi, 1); + any_landmesh++; + } + else + used_mats.set(mi, 0); + } + if (!any_landmesh) + continue; + Mesh m = node->mesh->mesh; + if (m.vertnorm.empty()) + { + // Generate normals for cliffs, castles and road ends. + m.calc_ngr(); + m.calc_vertnorms(); + }; + m.transform(node->wtm); + faces += m.face.size(); + if (m.vertnorm.empty()) + ; // no-op + else + { + // fixme: - should not be needed any more, since we use mesh.transform() + // Invert road normals. + // for (unsigned int normNo = 0; normNo < m.vertnorm.size(); normNo++) + // m.vertnorm[normNo] = -m.vertnorm[normNo]; + } + render_mesh(shading, m, sx, sy, scale, &used_mats); + } + dagGeom->deleteStaticGeometryContainer(geoCont); + con.endProgress(); + con.endLog(); + con.addMessage(ILogWriter::REMARK, "%d total faces rendered", faces); + return true; +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/renderLandNormals.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/renderLandNormals.h new file mode 100644 index 000000000..35bb391ed --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/renderLandNormals.h @@ -0,0 +1,16 @@ +#pragma once + +struct NormalFrameBuffer +{ + static float *start_ht; + float *ht; + uint16_t *normal; // if normal is 0xFFFF - it is landMesh + inline void operator+=(int ofs) + { + ht += ofs; + // normal += ofs; + } +}; + +extern bool create_lmesh_normal_map(LandMeshMap &land, NormalFrameBuffer map, float ox, float oy, float scale, int wd, + int ht); // returns true if rendered any pixel diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/roadBuilderIface.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/roadBuilderIface.h new file mode 100644 index 000000000..16d3498c8 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/roadBuilderIface.h @@ -0,0 +1,302 @@ +// Copyright 2023 by Gaijin Games KFT, All rights reserved. +#ifndef _DE2_PLUGIN_ROADS_ROADBUILDERIFACE_H_ +#define _DE2_PLUGIN_ROADS_ROADBUILDERIFACE_H_ +#pragma once + + +namespace roadbuildertool +{ +enum ErrorValues +{ + ERROR_Undefined = 0x0001, + ERROR_OutputDataMismatch = 0x0002, + ERROR_BadLoftShape = 0x0004, + ERROR_NoPointBetweenCrosses = 0x0008, + ERROR_CannotEvaluateCrosslinks = 0x0010, +}; + +static const int MAX_LINES_NUMBER = 24; +enum +{ + ROADSEP_None = 0, // no separation line (may be + ROADSEP_Solid, // single solid line + ROADSEP_Dashed, // single dashed line + ROADSEP_SolidSolid, // double solid line + ROADSEP_DashedSolid, // solid(left) and dashed(right) lines + ROADSEP_SolidDashed, // dashed(left) and solid(right) lines +}; + +struct PointProperties +{ + //! number of lines: from 1 to MAX_LINES_NUMBERS + int linesNumber; + //! turn radius on crossroads at this point + float angleRadius; + //! bezier spline data (all three in world space) + Point3 pos, inHandle, outHandle; + //! up direction for road in point (interpolated between points) + Point3 updir; + //! one line width (interpolated between points) + float lineWidth; + //! material to be used on crossroad in point + int crossRoadMatId; + float crossRoadVScale, crossRoadUScale; + bool roadFlipUV; +}; + +enum +{ + SHAPE_BORDER = 0, + SHAPE_SIDE, + SHAPE_ROAD, + SHAPE_SIDE_HAMMER, + SHAPE_CENTER_HAMMER, + SHAPE_CENTER_BORDER, + SHAPE_WALL, + SHAPE_BRIDGE +}; + +struct RoadShape +{ + struct ShapePoint + { + Point2 pos; + bool soft; + }; + + bool isClosed; + float uScale, vScale; + + ShapePoint *points; + int pointsCount; +}; + +struct LampProperties +{ + enum + { + PLACE_Center, + PLACE_Left, + PLACE_Right, + PLACE_BothSides + }; + + //! offset from road side (can be negative) + float roadOffset; + //! step between lamps (in meters); for any step lamps MUST NOT be on road + float eachSize; + //! lamp type id + int typeId; + //! specifies whether lamps rotate with spline (to always show to road) + bool rotateToRoad; + //! additional vertical offset, MUST BE always added to target pos + float additionalHeightOffset; + + //! lamp placement positions type (PLACE_ enum) + int placementType; +}; + +struct SideSplineProperties +{ + // [0] - at start point, [1] - on normalZone, [2] - at end point + float scale[3]; // 1.0f ~ 100% +}; + +class SimpleLink +{ +public: + int pointId1, pointId2; +}; + +class LinkProperties : public SimpleLink +{ +public: + enum Attributes + { + LSIDE = 0x0001, + LVERTICAL_WALL = 0x0002, + LSIDE_BORDERS = 0x0004, + CENTER_BORDER = 0x0008, + HAMMER_SIDES = 0x0010, + BRIDGE = 0x0020, + HAMMER_CENTER = 0x0040, + GENERATE_LAMPS = 0x0080, + PAINTINGS = 0x0100, + CUSTOM_BRIDGE = 0x0200, + STOP_LINE = 0x0400, + RSIDE_BORDERS = 0x0800, + RSIDE = 0x1000, + RVERTICAL_WALL = 0x2000, + FLIP_ROAD_TEX = 0x4000, + BRIDGE_SUPPORT = 0x8000, + }; + + int types[MAX_LINES_NUMBER]; + + //! road segment attributes + unsigned flags; + //! material id for road + int roadMatId; + //! material id for side + int sideMatId; + int verticalWallsMatId; + int centerBorderMatId; + int hammerSidesMatId; + int hammerCenterMatId; + //! material id for paintings + int paintingsMatId; + + SideSplineProperties sideSplineProperties; + SideSplineProperties wallSplineProperties; + + //! array of lamp properties + const LampProperties *lamps; + //! lamp properties count + int lampsCount; + + //! ids for 2 point connected by this link (connection is directed: 1->2) + // int pointId1, pointId2; + + int addLoftCaps; + + //! first and last point on both sides of read, in terms of spline interpolant t (0..1) + //! for now can be ignored (it is sent as 0.0, 1.0, 0.0, 1.0), but in future should + //! produce ending points on splines to prevent road segment overlap + float leftMint, leftMaxt; + float rightMint, rightMaxt; + + // tesselation precision + float curvatureStrength, minStep, maxStep; + + float leftWallHeight, rightWallHeight; + float centerBorderHeight, leftBorderHeight, rightBorderHeight; + float rightHammerYOffs, rightHammerHeight, leftHammerYOffs, leftHammerHeight; + float centerHammerYOffs, centerHammerHeight; + float bridgeRoadThickness, bridgeStandHeight; + + float walkablePartVScale, walkablePartUScale; +}; + + +//! Decals (additional paintings). Decals must be projected to road, but MUST NOT go outside +struct DecalProperties +{ + //! material id + int materialId; + //! decal center point + Point3 point; + //! decal size + float width, height; + //! whether texcoords should be flipped + bool uFlip, vFlip; + //! rotate angle around world Y, in radians + float angle; +}; + +struct Roads +{ + LinkProperties *links; + int linksCount; + const PointProperties *points; + int pointsCount; + const DecalProperties *decals; + int decalsCount; + + const SimpleLink *boundLinks; + int boundLinksCount; + + // % of side length, value from 0.0f to 0.5f + float transitionPart; +}; + +struct GeometryFaceDetails +{ + enum + { + TYPE_UNDEFINED, + TYPE_LOFTCAP, + TYPE_LOFTSIDE, + TYPE_WALKABLEPART, + TYPE_CROSSWALKABLECENTER_SIDE, + TYPE_CROSSWALKABLECENTER_TRIANGLE, + TYPE_WHITELINES, + TYPE_GROUND, + TYPE_OTHER, + }; + + //! max like smoothing group + unsigned smoothingGroup; + int materialId; + //! face type, used to classify faces + int type; +}; + +struct FaceIndices +{ + int v[3]; //< vertex indices +}; + +struct Lamp +{ + //! position of lamp + Point3 position; + //! euler angles (x=pitch, y=yaw, z=row) + Point3 pitchYawRow; + //! lamp type + int typeId; +}; + +// Geometry structure, returned by road builder tool +struct Geometry +{ + //! face_count indices in vertiecs + FaceIndices *geomFaces; + //! face_count indices in textureCoordinates + FaceIndices *textureFaces; + //! face_count indices in normals + FaceIndices *normalIndices; + //! face_count + GeometryFaceDetails *details; + int faceCount; + Point3 *vertices; + int vertCount; + Point2 *textureCoordinates; + int tcCount; + Point3 *normals; + int normalCount; + Lamp *lamps; + int lampsCount; +}; + +// Road builder tool interface +class RoadBuilder +{ + int version; + +public: + static const int VERSION = 0x102; + + inline RoadBuilder() : version(VERSION) {} + inline int getVersion() const { return version; } + inline bool checkVersion() const { return (version == VERSION); } + + //! should allocate only common memory (used for any build) + virtual void __stdcall init() = 0; + //! all memory allocated in 'init' memory should be cleaned here + virtual void __stdcall release() = 0; + + //! builds roads, can allocate memory specific for current build + virtual bool __stdcall build(const Roads &roads, Geometry &geometry) = 0; + virtual bool __stdcall buildGround(const Roads &roads, int grassMatId, Geometry &geometry, Point2 helperPt) = 0; + + //! all memory allocated in 'build' memory should be cleaned here + virtual void __stdcall endBuild(Geometry &geometry) = 0; + + virtual void __stdcall setRoadShape(int shapeId, RoadShape *shape) = 0; + + //! returns error messages + virtual int __stdcall getErrorMessages() = 0; +}; +} // namespace roadbuildertool + +#endif diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/roadUtil.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/roadUtil.h new file mode 100644 index 000000000..c3521d7e9 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/roadUtil.h @@ -0,0 +1,18 @@ +#pragma once + +#include "hmlSplinePoint.h" +#include + + +inline splineclass::RoadData *getRoad(SplinePointObject *p, bool for_geom = true) +{ + if (!p->getSplineClass() || !p->getSplineClass()->road) + return NULL; + + splineclass::RoadData *r = p->getSplineClass()->road; + + if (for_geom) + return r->buildGeom ? r : NULL; + + return r->buildRoadMap ? r : NULL; +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/roadsSnapshot.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/roadsSnapshot.cpp new file mode 100644 index 000000000..1556158d9 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/roadsSnapshot.cpp @@ -0,0 +1,129 @@ +#include "roadsSnapshot.h" +#include "hmlObjectsEditor.h" +#include "hmlSplineObject.h" +#include "hmlSplinePoint.h" +#include "crossRoad.h" +#include "roadUtil.h" +#include + + +static bool isRoadSpline(SplineObject &o) +{ + if (o.isPoly()) + return false; + + for (int i = o.points.size() - 1; i >= 0; i--) + if (getRoad(o.points[i], false)) + return true; + return false; +} + +static IRoadsProvider::RoadSpline *findRoad(dag::Span rspl, SplineObject *o, + dag::ConstSpan used_o) +{ + for (int i = 0; i < used_o.size(); i++) + if (used_o[i] == o) + return &rspl[i]; + return NULL; +} + + +RoadsSnapshot::RoadsSnapshot(HmapLandObjectEditor &objEd) : rspl(midmem), rc(midmem), rcr(midmem), rpt(midmem) +{ + Tab usedSpl(tmpmem); + int rs_num = 0, rc_num = 0, rcr_num = 0, rpt_num = 0; + + // calculate required size + for (int i = 0; i < objEd.objectCount(); i++) + { + SplineObject *p = RTTI_cast(objEd.getObject(i)); + if (!p || !isRoadSpline(*p)) + continue; + rs_num++; + rpt_num += p->points.size(); + } + for (int i = 0; i < objEd.crossRoads.size(); i++) + { + rcr_num += objEd.crossRoads[i]->points.size(); + rc_num++; + } + + // allocate storage + rspl.reserve(rs_num); + rc.reserve(rc_num); + rcr.reserve(rcr_num); + rpt.reserve(rpt_num); + + // build snapshot + for (int i = 0; i < objEd.objectCount(); i++) + { + SplineObject *p = RTTI_cast(objEd.getObject(i)); + if (!p || !isRoadSpline(*p)) + continue; + + p->getSpline(); + usedSpl.push_back(p); + + IRoadsProvider::RoadSpline &rs = rspl.push_back(); + int ptidx = append_items(rpt, p->points.size()); + + rs.closed = p->isClosed(); + rs.pt.set(&rpt[ptidx], p->points.size()); + rs.curve = p->getBezierSpline(); + + const splineclass::AssetData *asset = NULL; + for (int j = 0; j < rs.pt.size(); j++) + { + asset = getRoad(p->points[j], false) ? p->points[j]->getSplineClass() : NULL; + + rpt[ptidx + j].pt = p->points[j]->getPt(); + rpt[ptidx + j].relIn = p->points[j]->getPtEffRelBezierIn(); + rpt[ptidx + j].relOut = p->points[j]->getPtEffRelBezierOut(); + // rpt[ptidx+j].upDir = p->points[j]->getUpDir(); + rpt[ptidx + j].asset = asset; + } + } + for (int i = 0; i < objEd.crossRoads.size(); i++) + { + IRoadsProvider::RoadCross &c = rc.push_back(); + int ptidx = append_items(rcr, objEd.crossRoads[i]->points.size()); + c.roads.set(&rcr[ptidx], objEd.crossRoads[i]->points.size()); + for (int j = 0; j < c.roads.size(); j++) + { + rcr[ptidx + j].road = findRoad(make_span(rspl), objEd.crossRoads[i]->points[j]->spline, usedSpl); + rcr[ptidx + j].ptIdx = objEd.crossRoads[i]->points[j]->arrId; + } + } + + G_ASSERT(rspl.size() <= rs_num); + G_ASSERT(rc.size() <= rc_num); + G_ASSERT(rcr.size() <= rcr_num); + G_ASSERT(rpt.size() <= rpt_num); + + roads = rspl; + cross = rc; +} + + +#include + +void RoadsSnapshot::debugDump() +{ + debug("=== %d roads:", roads.size()); + for (int i = 0; i < roads.size(); i++) + { + debug(" roads %d: %p, %d pts", i, &roads[i], roads[i].pt.size()); + for (int j = 0; j < roads[i].pt.size(); j++) + debug(" pt %d: pos=" FMT_P3 " in=" FMT_P3 " out=" FMT_P3 " asset=%p", j, P3D(roads[i].pt[j].pt), P3D(roads[i].pt[j].relIn), + P3D(roads[i].pt[j].relOut), roads[i].pt[j].asset); + } + + debug("=== %d crossroads:", cross.size()); + for (int i = 0; i < cross.size(); i++) + { + debug(" cross %d: %d roads", i, cross[i].roads.size()); + for (int j = 0; j < cross[i].roads.size(); j++) + debug(" road %d: road %p ptIdx=%d", j, cross[i].roads[j].road, cross[i].roads[j].ptIdx); + } + debug("---"); +} diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/roadsSnapshot.h b/prog/tools/sceneTools/daEditorX/HeightmapLand/roadsSnapshot.h new file mode 100644 index 000000000..436c75bfe --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/roadsSnapshot.h @@ -0,0 +1,24 @@ +#pragma once + + +#include +#include +#include + + +class HmapLandObjectEditor; + + +class RoadsSnapshot : public IRoadsProvider::Roads, public DObject +{ +public: + RoadsSnapshot(HmapLandObjectEditor &objEd); + virtual void release() { delRef(); } + virtual void debugDump(); + +protected: + Tab rspl; + Tab rc; + Tab rcr; + Tab rpt; +}; diff --git a/prog/tools/sceneTools/daEditorX/HeightmapLand/waterSurfGen.cpp b/prog/tools/sceneTools/daEditorX/HeightmapLand/waterSurfGen.cpp new file mode 100644 index 000000000..37ec28b21 --- /dev/null +++ b/prog/tools/sceneTools/daEditorX/HeightmapLand/waterSurfGen.cpp @@ -0,0 +1,1215 @@ +#include "hmlPlugin.h" +#include "hmlSplineObject.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +extern bool allow_debug_bitmap_dump; + +class Point3Deref : public Point3 +{ +public: + Point3 getPt() const { return *this; } +}; + +#if 1 +static void draw_poly(objgenerator::HugeBitmask &m, dag::ConstSpan pts, float ofs_x, float ofs_y, float scale) +{ + for (int i = 0; i < pts.size(); i++) + { + Point2 p0 = pts[i]; + Point2 d = pts[(i + 1) % pts.size()] - p0; + float len = length(d); + if (len < 1e-36) + continue; + for (float t = 0.0, dt = 1.f / (len * scale * 4); t <= 1; t += dt) + m.set((p0.x + d.x * t - ofs_x) * scale, (p0.y + d.y * t - ofs_y) * scale); + } +} +static void write_tif(objgenerator::HugeBitmask &m, const char *fname) +{ + IBitMaskImageMgr::BitmapMask img; + int w = m.getW(), h = m.getH(); + HmapLandPlugin::bitMaskImgMgr->createBitMask(img, w, h, 1); + + for (int y = 0; y < h; y++) + for (int x = 0; x < w; x++) + img.setMaskPixel1(x, y, m.get(x, y) ? 128 : 0); + + HmapLandPlugin::bitMaskImgMgr->saveImage(img, ".", fname); + HmapLandPlugin::bitMaskImgMgr->destroyImage(img); +} +static void draw_solution(objgenerator::HugeBitmask &m, const ClipperLib::ExPolygons &sol, float ox, float oz, float scl) +{ + Tab pts_2(tmpmem); + Tab pts_3(tmpmem); + Tab pts(tmpmem); + + // debug("sol=%d", sol.size()); + for (int i = 0; i < sol.size(); i++) + { + // debug_(" %d: outer sz=%d ", i, sol[i].outer.size()); + pts_2.resize(sol[i].outer.size()); + for (int j = 0; j < sol[i].outer.size(); j++) + { + pts_2[j].set(sol[i].outer[j].X * 0.001f, sol[i].outer[j].Y * 0.001f); + // debug_(" %.3f,%.3f ", sol[i].outer[j].X*0.001f, sol[i].outer[j].Y*0.001f); + } + // debug(""); + draw_poly(m, pts_2, ox, oz, scl); + + for (int k = 0; k < sol[i].holes.size(); k++) + { + // debug_(" holes[%d]: sz=%d ", k, sol[i].holes[k].size()); + pts_3.resize(sol[i].holes[k].size()); + pts.resize(pts_3.size()); + for (int j = 0; j < sol[i].holes[k].size(); j++) + { + pts_3[j].set(sol[i].holes[k][j].X * 0.001f, 0, sol[i].holes[k][j].Y * 0.001f); + pts[j] = static_cast(&pts_3[j]); + // debug_(" %.3f,%.3f ", sol[i].holes[k][j].X*0.001f, sol[i].holes[k][j].Y*0.001f); + } + // debug(""); + rasterize_poly_2_nz(m, pts, ox, oz, scl); + } + } +} + +static void draw_solution(const char *svg_fn, const ClipperLib::ExPolygons &sol, float ox, float oz, float scl, int w = 512, + int h = 512, float over_scl = 1.0) +{ + FILE *fp = fp = svg_open(svg_fn, w * over_scl, h * over_scl); + ox *= over_scl; + oz *= over_scl; + scl /= over_scl; + + // debug("sol=%d", sol.size()); + for (int i = 0; i < sol.size(); i++) + { + svg_begin_group(fp, "stroke-width=\"0.005\" stroke=\"black\" opacity=\"0.8\" fill=\"red\""); + svg_start_poly(fp, Point2(sol[i].outer[0].X * 0.001 - ox, sol[i].outer[0].Y * 0.001 - oz) * scl); + for (int k = 1; k < sol[i].outer.size(); k++) + svg_add_poly_point(fp, Point2(sol[i].outer[k].X * 0.001 - ox, sol[i].outer[k].Y * 0.001 - oz) * scl); + svg_end_poly(fp); + svg_end_group(fp); + + // debug_(" %d: outer(%d) sz=%d ", i, ClipperLib::Orientation(sol[i].outer), sol[i].outer.size()); + // for (int j = 0; j < sol[i].outer.size(); j++) + // debug_(" %.3f,%.3f ", sol[i].outer[j].X*0.001f, sol[i].outer[j].Y*0.001f); + // debug(""); + + for (int k = 0; k < sol[i].holes.size(); k++) + { + svg_begin_group(fp, "stroke-width=\"0.005\" stroke=\"blue\" opacity=\"0.5\" fill=\"green\""); + svg_start_poly(fp, Point2(sol[i].holes[k][0].X * 0.001 - ox, sol[i].holes[k][0].Y * 0.001 - oz) * scl); + for (int j = 1; j < sol[i].holes[k].size(); j++) + svg_add_poly_point(fp, Point2(sol[i].holes[k][j].X * 0.001 - ox, sol[i].holes[k][j].Y * 0.001 - oz) * scl); + svg_end_poly(fp); + svg_end_group(fp); + // debug_(" holes[%d]: (%d) sz=%d ", + // k, ClipperLib::Orientation(sol[i].holes[k]), sol[i].holes[k].size()); + // for (int j = 0; j < sol[i].holes[k].size(); j++) + // debug_(" %.3f,%.3f ", sol[i].holes[k][j].X*0.001f, sol[i].holes[k][j].Y*0.001f); + // debug(""); + } + } + svg_close(fp); +} +#endif + +static void optimize_polygon(ClipperLib::Polygon &poly, float tolerance = 0.01) +{ + Tab pt(tmpmem); + Tab ptmark(tmpmem); + int n = (int)poly.size(), original_n = n; + pt.resize(n * 2); + ptmark.resize(n); + mem_set_0(ptmark); + + for (int i = 0; i < n; i++) + { + pt[i] = poly[i].X; + pt[i + n] = poly[i].Y; + } + ReducePoints(pt.data(), pt.data() + n, n, ptmark.data(), tolerance * 1000); + if (poly[0].X == poly[n - 1].X && poly[0].Y == poly[n - 1].Y) + n--; + poly.resize(1); + for (int i = 1; i < n; i++) + if (ptmark[i]) + poly.push_back(ClipperLib::IntPoint(pt[i], pt[i + n])); + if (original_n > poly.size()) + debug("optimized poly %d->%d", original_n, poly.size()); +} + +// rasterize polygon on pre-created bitmap, non-zero filling rule +static void rasterize_poly_2_nz(objgenerator::HugeBitmask &bm, ClipperLib::ExPolygons &ep, float ofs_x, float ofs_z, float scale) +{ + TabSortedInline pos(tmpmem); + SmallTab seg; + SmallTab seg_dy; + Point2 p0, p1; + int w = bm.getW(), h = bm.getH(); + float cell = 1.0f / scale; + + // compute bounds + int seg_cnt = 0; + for (int k = 0; k < ep.size(); k++) + { + seg_cnt += (int)ep[k].outer.size(); + for (int j = 0; j < ep[k].holes.size(); j++) + seg_cnt += (int)ep[k].holes[j].size(); + } + + clear_and_resize(seg, seg_cnt); + clear_and_resize(seg_dy, seg_cnt); + seg_cnt = 0; + for (int k = 0; k < ep.size(); k++) + { + ClipperLib::Polygon &p = ep[k].outer; + p1.set(p[0].X * 0.001, p[0].Y * 0.001); + for (int i = p.size() - 1; i >= 0; i--, p1 = p0, seg_cnt++) + { + Point4 &s = seg[seg_cnt]; + p0.set(p[i].X * 0.001, p[i].Y * 0.001); + int cx = (p0.x - ofs_x) / cell, cy = (p0.y - ofs_z) / cell; + if (cx >= 0 && cy >= 0 && cx < bm.getW() && cy < bm.getH()) + bm.set(cx, cy); + + if (fabsf(p1.y - p0.y) < 1e-12) + { + float fc = (p0.y - ofs_z) / cell; + if (fc - floor(fc) >= 0.5) + p0.y -= cell * 0.001; + else + p0.y += cell * 0.001; + } + s.x = p0.x; + s.y = p0.y; + s[2] = p1.y; + s[3] = (p1.y - p0.y); + seg_dy[seg_cnt] = s[3] > 0 ? 2 : 0; + s[3] = (p1.x - p0.x) / s[3]; + } + for (int i = 0, b = seg_cnt - p.size(); i < p.size(); i++) + seg_dy[b + i] = (seg_dy[b + i] & 0xF) | ((seg_dy[b + (i + p.size() - 1) % p.size()] & 0xF) << 4); + + for (int j = 0; j < ep[k].holes.size(); j++) + { + ClipperLib::Polygon &p = ep[k].holes[j]; + p1.set(p[0].X * 0.001, p[0].Y * 0.001); + for (int i = p.size() - 1; i >= 0; i--, p1 = p0, seg_cnt++) + { + Point4 &s = seg[seg_cnt]; + p0.set(p[i].X * 0.001, p[i].Y * 0.001); + int cx = (p0.x - ofs_x) / cell, cy = (p0.y - ofs_z) / cell; + if (cx >= 0 && cy >= 0 && cx < bm.getW() && cy < bm.getH()) + bm.set(cx, cy); + + if (fabsf(p1.y - p0.y) < 1e-12) + { + float fc = (p0.y - ofs_z) / cell; + if (fc - floor(fc) >= 0.5) + p0.y -= cell * 0.001; + else + p0.y += cell * 0.001; + } + s.x = p0.x; + s.y = p0.y; + s[2] = p1.y; + s[3] = (p1.y - p0.y); + seg_dy[seg_cnt] = s[3] > 0 ? 2 : 0; + s[3] = (p1.x - p0.x) / s[3]; + } + for (int i = 0, b = seg_cnt - (int)p.size(); i < p.size(); i++) + seg_dy[b + i] = (seg_dy[b + i] & 0xF) | ((seg_dy[b + (i + p.size() - 1) % p.size()] & 0xF) << 4); + } + } + + pos.reserve(seg.size()); + for (int y = h - 1; y >= 0; y--) + { + float fy = y * cell + ofs_z, fx; + + // gather sorted intersections + pos.clear(); + for (int j = 0; j < seg.size(); j++) + { + Point4 p = seg[j]; + if ((p.y - fy) * (p[2] - fy) > 0) + continue; + + int c_dy = (seg_dy[j] & 0xF) - 1; + int n_dy = ((seg_dy[j] >> 4) & 0xF) - 1; + if (c_dy == n_dy && fabsf(p[2] - fy) < 1e-6) + continue; + + if (float_nonzero(p.y - fy)) + fx = p.x + (fy - p.y) * p[3] - ofs_x; + else + fx = p.x - ofs_x; + + pos.insert(IPoint2(fx * scale * 1000, c_dy)); + } + + // rasterize bitmap using intersection points (nonZero filling rule) + int v0 = 0, x0 = -2000000000; + + for (int j = 0; j < pos.size(); j++) + { + int x1 = pos[j].x / 1000, v1 = v0 + pos[j].y; + if (!v0 && v1) + x0 = x1; + else if (v0 && !v1 && x1 >= 0) + { + if (x0 < 0) + x0 = 0; + if (x1 > w - 1) + x1 = w - 1; + for (; x0 <= x1; x0++) + bm.set(x0, y); + if (x1 == w - 1) + break; + } + v0 = v1; + if (x1 >= w - 1) + break; + } + if (v0) + { + if (x0 < 0) + x0 = 0; + for (; x0 < w; x0++) + bm.set(x0, y); + } + } +} + +static inline int cmp_ip4_x(const IPoint4 *a, const IPoint4 *b) { return a->x - b->x; } +static inline int cmp_ptr_ip4_z(IPoint4 *const *a, IPoint4 *const *b) +{ + if (a[0]->z == b[0]->z) + return a[0] - b[0]; + return a[0]->z - b[0]->z; +} + +struct IPoint4CmpX : public IPoint4 +{ + static bool cmpGt(const IPoint4CmpX *e, int key) { return e->x > key; } + static bool cmpEq(const IPoint4CmpX *e, int key) { return e->x == key; } +}; + +struct IPoint4PtrCmpZ +{ + IPoint4 *p; + static bool cmpGt(const IPoint4PtrCmpZ *e, int key) { return e->p->z > key; } + static bool cmpEq(const IPoint4PtrCmpZ *e, int key) { return e->p->z == key; } +}; + +static void add_border_segments(Tab &water_border_polys, const ClipperLib::Polygon &poly, const BBox3 &hmap_bb, + float waterSurfaceLevel) +{ + int st_id = -1, num; + bool whole = true; + + for (int k = 0; k < poly.size(); k++) + { + Point3 bp(poly[k].X * 0.001f, waterSurfaceLevel, poly[k].Y * 0.001f); + + if (hmap_bb & bp) + { + if (st_id < 0) + { + water_border_polys.push_back().set(1.1e12f, 0, 0); + st_id = water_border_polys.size(); + } + water_border_polys.push_back(bp); + } + else if (st_id >= 0) + { + whole = false; + num = water_border_polys.size() - st_id; + if (num > 1) + { + water_border_polys[st_id - 1].y = num; + water_border_polys[st_id - 1].z = 1; + } + else + { + if (num > 0) + water_border_polys.pop_back(); + water_border_polys.pop_back(); + } + st_id = -1; + } + else + whole = false; + } + if (!whole && st_id >= 0) + { + Point3 bp(poly[0].X * 0.001f, waterSurfaceLevel, poly[0].Y * 0.001f); + if (hmap_bb & bp) + water_border_polys.push_back(bp); + } + + if (st_id < 0) + return; + + num = water_border_polys.size() - st_id; + if (num > (whole ? 0 : 1)) + { + water_border_polys[st_id - 1].y = num; + water_border_polys[st_id - 1].z = whole ? 0 : 1; + } + else + { + if (num > 0) + water_border_polys.pop_back(); + water_border_polys.pop_back(); + } +} +static int cmp_area(const uint64_t *a, const uint64_t *b) { return *a < *b ? -1 : (*a > *b ? 1 : 0); } + +void HmapLandPlugin::rebuildWaterSurface(Tab *p_loft_pt, Tab *p_water_border, Tab *p_hmap_sweep) +{ + if (hasWorldOcean) + heightmapChanged(true); + applyHmModifiers(); + if (detDivisor > 1) + { + for (int y = detRectC[0].y - detDivisor / 2; y < detRectC[1].y + detDivisor / 2; y += detDivisor) + for (int x = detRectC[0].x - detDivisor / 2; x < detRectC[1].x + detDivisor / 2; x += detDivisor) + { + double sum = 0; + int sum_n = 0; + for (int k = 0; k <= detDivisor; k++) + for (int m = 0; m <= detDivisor; m++) + if (insideDetRectC(x + m, y + k)) + sum += heightMapDet.getFinalData(x + m, y + k), sum_n++; + if (sum_n) + { + heightMap.setInitialData(x / detDivisor + 1, y / detDivisor + 1, sum / sum_n); + heightMap.setFinalData(x / detDivisor + 1, y / detDivisor + 1, sum / sum_n); + } + } + } + else if (detDivisor == 1) + for (int y = detRectC[0].y; y < detRectC[1].y; y++) + for (int x = detRectC[0].x; x < detRectC[1].x; x++) + { + heightMap.setInitialData(x, y, heightMapDet.getFinalData(x, y)); + heightMap.setFinalData(x, y, heightMapDet.getFinalData(x, y)); + } + + Tab l_loft_pt(tmpmem); + Tab l_water_border(tmpmem); + Tab l_hmap_sweep(tmpmem); + + Tab &loft_pt_cloud = p_loft_pt ? *p_loft_pt : l_loft_pt; + Tab &water_border_polys = p_water_border ? *p_water_border : l_water_border; + Tab &hmap_sweep_polys = p_hmap_sweep ? *p_hmap_sweep : l_hmap_sweep; + + waterMaskScale = gridCellSize / 2; + if (waterMaskScale < 4) + waterMaskScale = 4; + else if (waterMaskScale > 16) + waterMaskScale = 16; + + + objEd.gatherLoftLandPts(loft_pt_cloud, water_border_polys, hmap_sweep_polys); + /* + for (int i = 0; i < water_border_polys.size(); i++) + debug("w[%3d] " FMT_P3 "", i, P3D(water_border_polys[i])); + for (int i = 0; i < hmap_sweep_polys.size(); i++) + debug("h[%3d] " FMT_P2 "", i, P2D(hmap_sweep_polys[i])); + for (int i = 0; i < loft_pt_cloud.size(); i++) + debug("p[%3d] " FMT_P3 "", i, P3D(loft_pt_cloud[i])); + */ + + BBox3 hmap_bb; + hmap_bb.lim[0].set(heightMapOffset.x, waterSurfaceLevel - 4000, heightMapOffset.y); + hmap_bb.lim[1] = hmap_bb.lim[0] + Point3(getHeightmapSizeX() * gridCellSize, 16000, getHeightmapSizeY() * gridCellSize); + ClipperLib::ExPolygons waterPoly; + ClipperLib::ExPolygons waterPoly_non_ocean; + Ptr sm = NULL; + IAssetService *assetSrv = DAGORED2->queryEditorInterface(); + + objEd.getClearedWaterGeom(); + if (!hasWaterSurface) + { + if (waterMask.getW()) + heightmapChanged(true); + waterMask.reset(); + if (p_water_border) + clear_and_shrink(*p_water_border); + goto process_loft_pt; + } + + waterMask.resize(0, 0); + if (hasWorldOcean) + { + int time0l = dagTools->getTimeMsec(); + ClipperLib::Clipper clpr; + ClipperLib::Polygon ocean_poly; + + if (worldOceanExpand > 0) + { + ocean_poly.resize(8); + ocean_poly[0].X = heightMapOffset.x * 1000; + ocean_poly[0].Y = (heightMapOffset.y - worldOceanExpand) * 1000; + ocean_poly[1].X = (heightMapOffset.x - worldOceanExpand) * 1000; + ocean_poly[1].Y = heightMapOffset.y * 1000; + + ocean_poly[4].X = (heightMapOffset.x + getHeightmapSizeX() * gridCellSize) * 1000; + ocean_poly[4].Y = (heightMapOffset.y + getHeightmapSizeY() * gridCellSize + worldOceanExpand) * 1000; + ocean_poly[5].X = (heightMapOffset.x + getHeightmapSizeX() * gridCellSize + worldOceanExpand) * 1000; + ocean_poly[5].Y = (heightMapOffset.y + getHeightmapSizeY() * gridCellSize) * 1000; + + ocean_poly[2].X = ocean_poly[1].X; + ocean_poly[2].Y = ocean_poly[5].Y; + ocean_poly[3].X = ocean_poly[0].X; + ocean_poly[3].Y = ocean_poly[4].Y; + ocean_poly[6].X = ocean_poly[5].X; + ocean_poly[6].Y = ocean_poly[1].Y; + ocean_poly[7].X = ocean_poly[4].X; + ocean_poly[7].Y = ocean_poly[0].Y; + } + else + { + ocean_poly.resize(4); + ocean_poly[0].X = heightMapOffset.x * 1000; + ocean_poly[0].Y = heightMapOffset.y * 1000; + ocean_poly[2].X = (heightMapOffset.x + getHeightmapSizeX() * gridCellSize) * 1000; + ocean_poly[2].Y = (heightMapOffset.y + getHeightmapSizeY() * gridCellSize) * 1000; + ocean_poly[1].X = ocean_poly[0].X; + ocean_poly[1].Y = ocean_poly[2].Y; + ocean_poly[3].X = ocean_poly[2].X; + ocean_poly[3].Y = ocean_poly[0].Y; + } + if (!ClipperLib::Orientation(ocean_poly)) + reverse(ocean_poly.begin(), ocean_poly.end()); + + clpr.AddPolygon(ocean_poly, ClipperLib::ptSubject); + + Tab pt(tmpmem); + Tab edges(tmpmem); + Tab edges_rev(tmpmem); + int edge_w = getHeightmapSizeX() + 2; + + int edge_idx_remap[13] = {0, 8, edge_w * 8, edge_w * 8 + 8, 2, 3, 3 + 8, 2 + edge_w * 8, 1, 4, 5, 6, 7}; + int pair_tbl[13][6] = { + /* 0*/ {5, 1, 2, 8, 10, 11}, + /* 1*/ {4, 3, 8, 9, 12}, + /* 2*/ {4, 3, 8, 9, 12}, + /* 3*/ {3, 8, 10, 11}, + + /* 4*/ {3, 8, 9, 10}, + /* 5*/ {3, 8, 9, 11}, + /* 6*/ {3, 8, 10, 12}, + /* 7*/ {3, 8, 11, 12}, + + /* 8*/ {0}, + /* 9*/ {2, 10, 11}, + /*10*/ {1, 12}, + /*11*/ {1, 12}, + /*12*/ {0}, + }; + + waterMask.resize(getHeightmapSizeX() * waterMaskScale, getHeightmapSizeY() * waterMaskScale); + + float minx = heightMapOffset[0], maxx = minx + (getHeightmapSizeX() - 1) * gridCellSize; + float miny = heightMapOffset[1], maxy = miny + (getHeightmapSizeY() - 1) * gridCellSize; + + for (int z = -1, ze = getHeightmapSizeY(); z < ze; z++) + for (int x = -1, xe = getHeightmapSizeX(); x < xe; x++) + { + float h0 = -0.1f, hx = -0.1f, hz = -0.1f, hxz = -0.1f; + + if (x >= 0 && z >= 0) + { + h0 = heightMap.getFinalData(x, z) - waterSurfaceLevel; + // if (h0 <= 0) + // waterMask.set(x*waterMaskScale, z*waterMaskScale); + if (x + 1 < xe) + hx = heightMap.getFinalData(x + 1, z) - waterSurfaceLevel; + if (z + 1 < ze) + hz = heightMap.getFinalData(x, z + 1) - waterSurfaceLevel; + if (x + 1 < xe && z + 1 < ze) + hxz = heightMap.getFinalData(x + 1, z + 1) - waterSurfaceLevel; + } + else if (x >= 0) + { + hz = heightMap.getFinalData(x, z + 1) - waterSurfaceLevel; + if (x + 1 < xe) + hxz = heightMap.getFinalData(x + 1, z + 1) - waterSurfaceLevel; + } + else if (z >= 0) + { + hx = heightMap.getFinalData(x + 1, z) - waterSurfaceLevel; + if (z + 1 < ze) + hxz = heightMap.getFinalData(x + 1, z + 1) - waterSurfaceLevel; + } + else + hxz = heightMap.getFinalData(x + 1, z + 1) - waterSurfaceLevel; + + if (h0 <= 0 && hx <= 0 && hz <= 0 && hxz <= 0) + continue; + if (h0 > 0 && hx > 0 && hz > 0 && hxz > 0) + continue; + + float hm = (h0 + hx + hz + hxz) * 0.25f; + unsigned edge_cross_m = 0; + int pt_ofs[13]; + float cx0 = x * gridCellSize + heightMapOffset[0]; + float cz0 = z * gridCellSize + heightMapOffset[1]; + +#define CHECK_PT(y0, x0, z0, idx) \ + if (fabs(y0) < 1e-6) \ + { \ + edge_cross_m |= 1 << idx; \ + pt_ofs[idx] = pt.size(); \ + pt.push_back().set(cx0 + x0 * gridCellSize, cz0 + z0 * gridCellSize); \ + } + +#define CHECK_SEG(y0, y1, x0, z0, x1, z1, idx, vi0, vi1) \ + if (!(edge_cross_m & ((1 << vi0) | (1 << vi1))) && y0 * y1 < 0) \ + { \ + edge_cross_m |= 1 << idx; \ + float t = (0.0f - y0) / (y1 - y0); \ + pt_ofs[idx] = pt.size(); \ + pt.push_back().set(cx0 + (x1 * t + x0 * (1 - t)) * gridCellSize, cz0 + (z1 * t + z0 * (1 - t)) * gridCellSize); \ + } + + CHECK_PT(h0, 0, 0, 0); + CHECK_PT(hx, 1, 0, 1); + CHECK_PT(hz, 0, 1, 2); + CHECK_PT(hxz, 1, 1, 3); + + CHECK_SEG(h0, hx, 0, 0, 1, 0, 4, 0, 1); + CHECK_SEG(h0, hz, 0, 0, 0, 1, 5, 0, 2); + CHECK_SEG(hx, hxz, 1, 0, 1, 1, 6, 1, 3); + CHECK_SEG(hz, hxz, 0, 1, 1, 1, 7, 2, 3); + + CHECK_PT(hm, 0.5, 0.5, 8); + CHECK_SEG(hm, h0, 0.5, 0.5, 0, 0, 9, 8, 0); + CHECK_SEG(hm, hx, 0.5, 0.5, 1, 0, 10, 8, 1); + CHECK_SEG(hm, hz, 0.5, 0.5, 0, 1, 11, 8, 2); + CHECK_SEG(hm, hxz, 0.5, 0.5, 1, 1, 12, 8, 3); + + if (!edge_cross_m) + continue; + + int edge_base = ((z + 1) * edge_w + (x + 1)) * 8; + // debug("%d,%d: %p, mask=%p", x, z, edge_base, edge_cross_m); + for (int i = 0; i < 13; i++) + if (edge_cross_m & (1 << i)) + { + Point2 &pc = pt[pt_ofs[i]]; + if (pc.x <= minx) + pc.x -= worldOceanExpand * 2 + 1; + else if (pc.x >= maxx) + pc.x += worldOceanExpand * 2 + 1; + if (pc.y <= miny) + pc.y -= worldOceanExpand * 2 + 1; + else if (pc.y >= maxy) + pc.y += worldOceanExpand * 2 + 1; + + for (int *j = &pair_tbl[i][1], *je = j + pair_tbl[i][0]; j < je; j++) + if (edge_cross_m & (1 << *j)) + { + // debug(" %p-%p (%d-%d)", + // edge_base+edge_idx_remap[i], edge_base+edge_idx_remap[*j], i, *j); + edges.push_back().set(edge_base + edge_idx_remap[i], pt_ofs[i], edge_base + edge_idx_remap[*j], pt_ofs[*j]); + } + } + } + + sort(edges, &cmp_ip4_x); + edges_rev.resize(edges.size()); + for (int i = 0; i < edges_rev.size(); i++) + edges_rev[i] = &edges[i]; + sort(edges_rev, &cmp_ptr_ip4_z); + + HierBitArray> edge_mark; + int edges_left = edges.size(), edges_count = edges_left, poly_count = 0; + edge_mark.resize(edges_left); + + /* + for (int i = 0; i < edges.size(); i ++) + debug("%d: %p(%d) - %p(%d)", i, edges[i].x, edges[i].y, edges[i].z, edges[i].w); + for (int i = 0; i < edges_rev.size(); i ++) + debug("%d: %d(%d) - %d(%d)", edges_rev[i]-edges.data(), + edges_rev[i]->x, edges_rev[i]->y, edges_rev[i]->z, edges_rev[i]->w); + */ + + int start_edge_idx = 0; + ClipperLib::Polygon island_poly; + ClipperLib::Polygons islands; + Tab eid(tmpmem); + Tab island_area_idx(tmpmem); + int sum_t = 0; + + while (edges_left) + { + int start_id = -1; + int first_id = -1; + int next_id = -1; + bool closed = false; + + eid.resize(0); + island_poly.resize(0); + + for (int i = start_edge_idx, ie = edge_mark.getSz(); i < ie; i++) + if (!edge_mark.get(i)) + { + edges_left--; + edge_mark.set(i); + start_edge_idx = i + 1; + island_poly.push_back(ClipperLib::IntPoint(pt[edges[i].y].x * 1000, pt[edges[i].y].y * 1000)); + island_poly.push_back(ClipperLib::IntPoint(pt[edges[i].w].x * 1000, pt[edges[i].w].y * 1000)); + start_id = first_id = edges[i].x; + next_id = edges[i].z; + eid.clear(); + break; + } + + // debug("start: %p,%p", first_id, next_id); + while (edges_left) + { + bool back = true; + int idx = bfind_rep_idx(make_span_const(static_cast(edges.data()), edges.size()), next_id); + if (idx > 0) + { + for (; idx < edges.size(); idx++) + if (edges[idx].x != next_id) + { + idx = edges.size(); + break; + } + else if (!edge_mark.get(idx)) + break; + } + if (idx < 0 || idx == edges.size()) + { + idx = bfind_rep_idx(make_span_const(reinterpret_cast(edges_rev.data()), edges_rev.size()), next_id); + if (idx >= 0) + { + for (; idx < edges.size(); idx++) + if (edges_rev[idx]->z != next_id) + { + idx = edges.size(); + break; + } + else if (!edge_mark.get(edges_rev[idx] - edges.data())) + break; + } + + if (idx < 0 || idx == edges.size()) + { + if (!eid.size()) + break; + debug(" not found %p (sz=%d, edges_left=%d) reverting to %p", next_id, island_poly.size(), edges_left, eid.back()); + next_id = eid.back(); + eid.pop_back(); + island_poly.pop_back(); + continue; + } + idx = edges_rev[idx] - edges.data(); + back = false; + } + + eid.push_back(next_id); + edges_left--; + edge_mark.set(idx); + if (back) + { + island_poly.push_back(ClipperLib::IntPoint(pt[edges[idx].w].x * 1000, pt[edges[idx].w].y * 1000)); + next_id = edges[idx].z; + } + else + { + island_poly.push_back(ClipperLib::IntPoint(pt[edges[idx].y].x * 1000, pt[edges[idx].y].y * 1000)); + next_id = edges[idx].x; + } + // debug(" add %d: next=%p", back, next_id); + if (next_id == start_id) + { + // debug("loop closed: %d", island_poly.size()); + closed = true; + break; + } + } + + if (!closed) + { + // debug("drop unclosed %d segments", island_poly.size()); + continue; + } + + // for (int i = 0; i < island_poly.size(); i ++) + // debug("%d: %d %d,%d", i, (i>0 && i-1= 0; i--) + if (!ueid.addInt(eid[i])) + for (int j = i + 1; j < eid.size(); j++) + if (eid[j] == eid[i]) + { + if (j > i + 16) + { + debug("skip removing large loop %d..%d", i + 1, j + 1 - 1); + break; + } + debug("remove loop %d..%d (%d,%d - %d,%d)", i + 1, j + 1 - 1, int(island_poly[i + 1].X), int(island_poly[i + 1].Y), + int(island_poly[j + 1].X), int(island_poly[j + 1].Y)); + erase_items(eid, i, j - i); + island_poly.erase(island_poly.begin() + i + 1, island_poly.begin() + j + 1); + break; + } + + optimize_polygon(island_poly, worldOceanShorelineTolerance); + if (!ClipperLib::Orientation(island_poly)) + reverse(island_poly.begin(), island_poly.end()); + + islands.push_back(island_poly); + island_area_idx.push_back((uint64_t(fabs(ClipperLib::Area(island_poly)) * 1e-6) << 16) + island_area_idx.size()); + } + + sort(island_area_idx, &cmp_area); + for (int i = 0; i < island_area_idx.size(); i++) + { + if (clpr.AddPolygon(islands[island_area_idx[i] & 0xFFFF], ClipperLib::ptClip)) + { + poly_count++; + clpr.Execute(ClipperLib::ctXor, waterPoly, ClipperLib::pftNonZero, ClipperLib::pftNonZero); + clpr.Clear(); + for (int k = 0; k < waterPoly.size(); k++) + { + clpr.AddPolygon(waterPoly[k].outer, ClipperLib::ptSubject); + clpr.AddPolygons(waterPoly[k].holes, ClipperLib::ptSubject); + } + } + } + + // compress ocean poly for 1mm inward to avoid precision bugs during intersection + int opcx = (heightMapOffset.x + getHeightmapSizeX() * gridCellSize / 2) * 1000; + int opcy = (heightMapOffset.y + getHeightmapSizeY() * gridCellSize / 2) * 1000; + for (int k = 0; k < ocean_poly.size(); k++) + { + ocean_poly[k].X += ocean_poly[k].X < opcx ? 1 : -1; + ocean_poly[k].Y += ocean_poly[k].Y < opcy ? 1 : -1; + } + clpr.AddPolygon(ocean_poly, ClipperLib::ptClip); + clpr.Execute(ClipperLib::ctIntersection, waterPoly, ClipperLib::pftNonZero, ClipperLib::pftNonZero); + clpr.Clear(); + + debug("optimize final solution"); + int final_pts = 0, final_polys = 0; + for (int k = 0; k < waterPoly.size(); k++) + { + final_polys += 1 + (int)waterPoly[k].holes.size(); + optimize_polygon(waterPoly[k].outer, 0.05); + final_pts += (int)waterPoly[k].outer.size(); + for (int l = 0; l < waterPoly[k].holes.size(); l++) + { + optimize_polygon(waterPoly[k].holes[l], 0.05); + final_pts += (int)waterPoly[k].holes[l].size(); + } + } + + DAEDITOR3.conNote("contoured islands (%d edges, %d points, %d polys ->" + " %d points, %d polys) for %.1f sec", + edges_count, pt.size(), poly_count, final_pts, final_polys, (dagTools->getTimeMsec() - time0l) / 1000.f); + + if (allow_debug_bitmap_dump) + draw_solution(DAGORED2->getPluginFilePath(this, "../../../islandMask.svg"), waterPoly, heightMapOffset.x, heightMapOffset.y, + 1.0f / gridCellSize, getHeightmapSizeX(), getHeightmapSizeY(), 1.2); + } + + bool has_water_exclude = false; + if (water_border_polys.size()) + { + ClipperLib::Clipper clpr, clpr_sep; + ClipperLib::Polygon poly; + for (int k = 0; k < waterPoly.size(); k++) + { + clpr.AddPolygon(waterPoly[k].outer, ClipperLib::ptSubject); + clpr.AddPolygons(waterPoly[k].holes, ClipperLib::ptSubject); + } + + for (int i = 0; i < water_border_polys.size(); i++) + if (water_border_polys[i].x > 1e12f) + { + if (water_border_polys[i].z > 0) + { + i += water_border_polys[i].y; + has_water_exclude = true; + continue; + } + + ClipperLib::PolyType type = ClipperLib::ptSubject; + poly.resize(water_border_polys[i].y); + i++; + for (int j = 0; j < poly.size(); j++, i++) + { + poly[j].X = ClipperLib::long64(water_border_polys[i].x * 1000); + poly[j].Y = ClipperLib::long64(water_border_polys[i].z * 1000); + } + if (!ClipperLib::Orientation(poly)) + { + debug_cp(); + reverse(poly.begin(), poly.end()); + } + clpr.AddPolygon(poly, type); + if (hasWorldOcean) + clpr_sep.AddPolygon(poly, type); + i--; + } + + waterPoly.resize(0); + clpr.Execute(ClipperLib::ctUnion, waterPoly, ClipperLib::pftNonZero, ClipperLib::pftNonZero); + if (hasWorldOcean) + clpr_sep.Execute(ClipperLib::ctUnion, waterPoly_non_ocean, ClipperLib::pftNonZero, ClipperLib::pftNonZero); + } + + if (has_water_exclude && water_border_polys.size()) + { + ClipperLib::Clipper clpr, clpr_sep; + ClipperLib::Polygon poly; + for (int k = 0; k < waterPoly.size(); k++) + { + clpr.AddPolygon(waterPoly[k].outer, ClipperLib::ptSubject); + clpr.AddPolygons(waterPoly[k].holes, ClipperLib::ptSubject); + } + + for (int i = 0; i < water_border_polys.size(); i++) + if (water_border_polys[i].x > 1e12f) + { + if (water_border_polys[i].z <= 0) + { + i += water_border_polys[i].y; + continue; + } + + ClipperLib::PolyType type = ClipperLib::ptClip; + poly.resize(water_border_polys[i].y); + i++; + for (int j = 0; j < poly.size(); j++, i++) + { + poly[j].X = ClipperLib::long64(water_border_polys[i].x * 1000); + poly[j].Y = ClipperLib::long64(water_border_polys[i].z * 1000); + } + if (!ClipperLib::Orientation(poly)) + reverse(poly.begin(), poly.end()); + clpr.AddPolygon(poly, type); + if (hasWorldOcean) + clpr_sep.AddPolygon(poly, type); + i--; + } + + waterPoly.resize(0); + clpr.Execute(ClipperLib::ctDifference, waterPoly, ClipperLib::pftNonZero, ClipperLib::pftNonZero); + + if (hasWorldOcean) + clpr_sep.Execute(ClipperLib::ctDifference, waterPoly_non_ocean, ClipperLib::pftNonZero, ClipperLib::pftNonZero); + } + + if (waterPoly.size() > 0) + { + if (allow_debug_bitmap_dump) + draw_solution(DAGORED2->getPluginFilePath(this, "../../../waterMask.svg"), waterPoly, heightMapOffset.x, heightMapOffset.y, + 1.0f / gridCellSize, getHeightmapSizeX(), getHeightmapSizeY(), 1.2); + + waterMask.resize(getHeightmapSizeX() * waterMaskScale, getHeightmapSizeY() * waterMaskScale); + rasterize_poly_2_nz(waterMask, waterPoly, heightMapOffset.x, heightMapOffset.y, waterMaskScale / gridCellSize); + if (allow_debug_bitmap_dump) + write_tif(waterMask, "../../waterMask.tif"); + } + + if (assetSrv) + sm = assetSrv->getMaterialData(waterMatAsset); + + if (sm && waterPoly.size() > 0) + { + // build water surface mesh + debug_flush(false); + Mesh *pm_water = new Mesh; + Mesh &m_water = *pm_water; + + BBox2 bb; + for (const auto &wpoly : waterPoly) + for (const auto &p : wpoly.outer) + bb += Point2(p.X * 0.001f, p.Y * 0.001f); + bb[0] -= Point2(1, 1); + bb[1] += Point2(1, 1); + + ctl::PointList boundary; + boundary.push_back({bb[0].x, bb[0].y}); + boundary.push_back({bb[1].x, bb[0].y}); + boundary.push_back({bb[1].x, bb[1].y}); + boundary.push_back({bb[0].x, bb[1].y}); + + ctl::DelaunayTriangulation dt{boundary, 16 << 10}; + + dag::Vector> all_wpolys; + all_wpolys.reserve(waterPoly.size()); + for (const auto &wpoly : waterPoly) + { + auto &wpoly1 = all_wpolys.push_back(); + wpoly1.reserve(wpoly.holes.size() + 1); + auto &outer_pts = wpoly1.push_back(); + outer_pts.reserve(wpoly.outer.size()); + for (const auto &p : wpoly.outer) + outer_pts.push_back({p.X * 0.001f, p.Y * 0.001f, waterSurfaceLevel}); + outer_pts.push_back({outer_pts[0]}); + dt.InsertConstrainedLineString(outer_pts); + + for (const auto &hole : wpoly.holes) + { + auto &hole_pts = wpoly1.push_back(); + hole_pts.reserve(hole.size()); + for (const auto &p : hole) + hole_pts.push_back({p.X * 0.001f, p.Y * 0.001f, waterSurfaceLevel}); + hole_pts.push_back({hole_pts[0]}); + dt.InsertConstrainedLineString(hole_pts); + } + } + + debug_flush(true); + + ctl::TIN tin(&dt); + + Tab vert_remap; + vert_remap.resize(tin.verts.size()); + mem_set_ff(vert_remap); + + m_water.vert.reserve(tin.verts.size()); + m_water.face.reserve(tin.triangles.size() / 3); + debug_cp(); + for (int i = 0; i < tin.triangles.size(); i += 3) + { + ctl::Point centroid( + (tin.verts[tin.triangles[i + 0]].x + tin.verts[tin.triangles[i + 1]].x + tin.verts[tin.triangles[i + 2]].x) / 3, + (tin.verts[tin.triangles[i + 0]].y + tin.verts[tin.triangles[i + 1]].y + tin.verts[tin.triangles[i + 2]].y) / 3, + (tin.verts[tin.triangles[i + 0]].z + tin.verts[tin.triangles[i + 1]].z + tin.verts[tin.triangles[i + 2]].z) / 3); + + bool keepTriangle = false; + for (const auto &wpoly1 : all_wpolys) + { + for (const auto &p : wpoly1) + if (ctl::PointInPolygon(centroid, p)) + { + if (&p == wpoly1.begin()) // in outer + keepTriangle = true; + else + { + keepTriangle = false; // in hole + break; + } + } + else if (&p == wpoly1.begin()) // not in outer + break; + if (keepTriangle) + break; + } + if (keepTriangle) + { + Face &f = m_water.face.push_back(); + f.v[0] = tin.triangles[i + 0]; + f.v[2] = tin.triangles[i + 1]; + f.v[1] = tin.triangles[i + 2]; + for (unsigned &vi : f.v) + if (vert_remap[vi] >= 0) + vi = vert_remap[vi]; + else + { + m_water.vert.push_back().set_xzy(tin.verts[vi]); + vi = vert_remap[vi] = m_water.vert.size() - 1; + } + f.mat = 0; + f.smgr = 1; + } + } + m_water.vert.shrink_to_fit(); + m_water.face.shrink_to_fit(); + debug("water mesh: %d verts, %d faces (before holes removal: %d verts, %d faces)", m_water.vert.size(), m_water.face.size(), + tin.verts.size(), tin.triangles.size() / 3); + clear_and_shrink(all_wpolys); + clear_and_shrink(vert_remap); + + m_water.calc_ngr(); + m_water.calc_vertnorms(); + + GeomObject &waterGeom = objEd.getClearedWaterGeom(); + + MaterialDataList *mdl = new MaterialDataList; + mdl->addSubMat(sm); + + StaticGeometryContainer *g = dagGeom->newStaticGeometryContainer(); + dagGeom->objCreator3dAddNode("global_water_surface", pm_water, mdl, *g); + + StaticGeometryContainer *geom = waterGeom.getGeometryContainer(); + for (int i = 0; i < g->nodes.size(); ++i) + { + StaticGeometryNode *node = g->nodes[i]; + + dagGeom->staticGeometryNodeCalcBoundBox(*node); + dagGeom->staticGeometryNodeCalcBoundSphere(*node); + + node->flags |= StaticGeometryNode::FLG_RENDERABLE | StaticGeometryNode::FLG_COLLIDABLE; + geom->addNode(dagGeom->newStaticGeometryNode(*node, tmpmem)); + } + dagGeom->deleteStaticGeometryContainer(g); + + waterGeom.setTm(TMatrix::IDENT); + SplineObject::PolyGeom::recalcLighting(&waterGeom); + + waterGeom.notChangeVertexColors(true); + dagGeom->geomObjectRecompile(waterGeom); + waterGeom.notChangeVertexColors(false); + } + else if (!sm && waterPoly.size() > 0 && assetSrv && !waterMatAsset.empty()) + DAEDITOR3.conError("bad water surface mat: %s", waterMatAsset); + + water_border_polys.clear(); + for (int i = 0; i < waterPoly.size(); i++) + { + ClipperLib::ExPolygon &p = waterPoly[i]; + // optimize_polygon(p.outer); + add_border_segments(water_border_polys, p.outer, hmap_bb, waterSurfaceLevel); + + for (int j = 0; j < p.holes.size(); j++) + { + // optimize_polygon(p.holes[j]); + add_border_segments(water_border_polys, p.holes[j], hmap_bb, waterSurfaceLevel); + } + } + + heightmapChanged(true); + +process_loft_pt: + for (int i = 0; i < loft_pt_cloud.size(); i++) + if (loft_pt_cloud[i].x > 1e12f) + { + i++; + + int st_id = -1, num; + for (int j = 0, je = loft_pt_cloud[i - 1].y; j < je; j++, i++) + { + int x = (loft_pt_cloud[i].x - heightMapOffset.x) * waterMaskScale / gridCellSize; + int z = (loft_pt_cloud[i].z - heightMapOffset.y) * waterMaskScale / gridCellSize; + bool expel = false; + + if (x >= 0 && z >= 0 && x < waterMask.getW() && z < waterMask.getH()) + if (waterMask.get(x, z)) + if (loft_pt_cloud[i].y >= waterSurfaceLevel - 0.01) + expel = true; + + if (!expel && (hmap_bb & loft_pt_cloud[i])) + { + if (st_id < 0) + { + water_border_polys.push_back().set(1.1e12f, 0, 1); + st_id = water_border_polys.size(); + } + water_border_polys.push_back(loft_pt_cloud[i]); + } + else if (st_id >= 0) + { + num = water_border_polys.size() - st_id; + if (num > 1) + water_border_polys[st_id - 1].y = num; + else + { + if (num > 0) + water_border_polys.pop_back(); + water_border_polys.pop_back(); + } + st_id = -1; + } + } + + if (st_id >= 0) + { + num = water_border_polys.size() - st_id; + if (num > 1) + water_border_polys[st_id - 1].y = num; + else + { + if (num > 0) + water_border_polys.pop_back(); + water_border_polys.pop_back(); + } + } + + i--; + } + loft_pt_cloud.clear(); + + if (allow_debug_bitmap_dump) + { + float ox = heightMapOffset.x; + float oz = heightMapOffset.y; + float scl = 1.0f / gridCellSize; + int w = getHeightmapSizeX(); + int h = getHeightmapSizeY(); + float over_scl = 1.2; + + FILE *fp = fp = svg_open(DAGORED2->getPluginFilePath(this, "../../../border.svg"), w * over_scl, h * over_scl); + ox *= over_scl; + oz *= over_scl; + scl /= over_scl; + + svg_begin_group(fp, "stroke-width=\"2\" stroke=\"black\" style=\"fill:none\""); + for (int i = 0; i < water_border_polys.size(); i++) + { + if (water_border_polys[i].x > 1e12f) + { + bool closed = water_border_polys[i].z < 0.5f; + i++; + Point2 p0 = Point2(water_border_polys[i].x - ox, water_border_polys[i].z - oz) * scl; + i++; + svg_start_poly(fp, p0); + for (int ie = i + water_border_polys[i - 2].y - 1; i < ie; i++) + svg_add_poly_point(fp, Point2(water_border_polys[i].x - ox, water_border_polys[i].z - oz) * scl); + i--; + if (closed) + svg_add_poly_point(fp, p0); + svg_end_poly(fp); + } + } + svg_end_group(fp); + svg_close(fp); + } +} +bool HmapLandPlugin::isPointUnderWaterSurf(float fx, float fz) +{ + int x = (fx - heightMapOffset.x) * waterMaskScale / gridCellSize; + int z = (fz - heightMapOffset.y) * waterMaskScale / gridCellSize; + if (x >= 0 && z >= 0 && x < waterMask.getW() && z < waterMask.getH()) + if (waterMask.get(x, z)) + return true; + return false; +} diff --git a/prog/tools/sceneTools/daEditorX/IvyGen/jamfile b/prog/tools/sceneTools/daEditorX/IvyGen/jamfile index 180789b68..c174f028c 100644 --- a/prog/tools/sceneTools/daEditorX/IvyGen/jamfile +++ b/prog/tools/sceneTools/daEditorX/IvyGen/jamfile @@ -3,8 +3,6 @@ Location = prog/tools/sceneTools/daEditorX/IvyGen ; DriverLinkage = dynamic ; include $(Root)/prog/tools/tools_setup.jam ; -UseWTL = yes ; - TargetType = dll ; Target = tools/sceneTools/daEditorX/ivyGen.dll ; OutDir = $(Root)/tools/dagor3_cdk/bin/plugins/de3x ; diff --git a/prog/tools/sceneTools/daEditorX/Occluders/jamfile b/prog/tools/sceneTools/daEditorX/Occluders/jamfile index ee47ff9b3..fd69ab252 100644 --- a/prog/tools/sceneTools/daEditorX/Occluders/jamfile +++ b/prog/tools/sceneTools/daEditorX/Occluders/jamfile @@ -3,8 +3,6 @@ Location = prog/tools/sceneTools/daEditorX/Occluders ; DriverLinkage = dynamic ; include $(Root)/prog/tools/tools_setup.jam ; -UseWTL = yes ; - TargetType = dll ; Target = tools/sceneTools/daEditorX/occluders.dll ; OutDir = $(Root)/tools/dagor3_cdk/bin/plugins/de3x ; diff --git a/prog/tools/sceneTools/daEditorX/ScnExport/jamfile b/prog/tools/sceneTools/daEditorX/ScnExport/jamfile index f2cbbc4a4..356db08d8 100644 --- a/prog/tools/sceneTools/daEditorX/ScnExport/jamfile +++ b/prog/tools/sceneTools/daEditorX/ScnExport/jamfile @@ -1,8 +1,6 @@ Root ?= ../../../../.. ; Location = prog/tools/sceneTools/daEditorX/ScnExport ; -UseWTL = yes ; - TargetType = lib ; Target = tools/sceneTools/daEditorX/scnexport.lib ; diff --git a/prog/tools/sceneTools/daEditorX/StaticGeom/jamfile b/prog/tools/sceneTools/daEditorX/StaticGeom/jamfile index 02c6c2aee..5d4887c7b 100644 --- a/prog/tools/sceneTools/daEditorX/StaticGeom/jamfile +++ b/prog/tools/sceneTools/daEditorX/StaticGeom/jamfile @@ -3,8 +3,6 @@ Location = prog/tools/sceneTools/daEditorX/StaticGeom ; DriverLinkage = dynamic ; include $(Root)/prog/tools/tools_setup.jam ; -UseWTL = yes ; - TargetType = dll ; Target = tools/sceneTools/daEditorX/staticGeom.dll ; OutDir = $(Root)/tools/dagor3_cdk/bin/plugins/de3x ; diff --git a/prog/tools/sceneTools/daEditorX/binSceneView/jamfile b/prog/tools/sceneTools/daEditorX/binSceneView/jamfile index c0b83e08a..7cda4914b 100644 --- a/prog/tools/sceneTools/daEditorX/binSceneView/jamfile +++ b/prog/tools/sceneTools/daEditorX/binSceneView/jamfile @@ -1,8 +1,6 @@ Root ?= ../../../../.. ; Location = prog/tools/sceneTools/daEditorX/binSceneView ; -UseWTL = yes ; - TargetType = lib ; Target = tools/sceneTools/daEditorX/binSceneView.lib ; diff --git a/prog/tools/sceneTools/daEditorX/csg/jamfile b/prog/tools/sceneTools/daEditorX/csg/jamfile index 4a8408cf9..1760d7a3d 100644 --- a/prog/tools/sceneTools/daEditorX/csg/jamfile +++ b/prog/tools/sceneTools/daEditorX/csg/jamfile @@ -3,8 +3,6 @@ Location = prog/tools/sceneTools/daEditorX/csg ; DriverLinkage = dynamic ; include $(Root)/prog/tools/tools_setup.jam ; -UseWTL = no ; - TargetType = dll ; Target = tools/sceneTools/daEditorX/csg.dll ; OutDir = $(Root)/tools/dagor3_cdk/bin/plugins/de3x ; diff --git a/prog/tools/sceneTools/daEditorX/jamfile b/prog/tools/sceneTools/daEditorX/jamfile index 67bd50eb1..fd740f883 100644 --- a/prog/tools/sceneTools/daEditorX/jamfile +++ b/prog/tools/sceneTools/daEditorX/jamfile @@ -9,6 +9,7 @@ TargetType = util ; Target = DaEditor3_all ; Dependencies = + $(Root)/$(Location)/HeightmapLand/jamfile $(Root)/$(Location)/StaticGeom/jamfile $(Root)/$(Location)/IvyGen/jamfile $(Root)/$(Location)/Occluders/jamfile diff --git a/prog/tools/sceneTools/daEditorX/services/dynRenderSrv/dynRender.cpp b/prog/tools/sceneTools/daEditorX/services/dynRenderSrv/dynRender.cpp index 27f1a8b72..7b5ff430c 100644 --- a/prog/tools/sceneTools/daEditorX/services/dynRenderSrv/dynRender.cpp +++ b/prog/tools/sceneTools/daEditorX/services/dynRenderSrv/dynRender.cpp @@ -296,7 +296,7 @@ class DaEditor3DynamicScene : public DagorGameScene, public ICascadeShadowsClien shaders::RenderState rs; rs.cull = CULL_NONE; rs.colorWr = WRITEMASK_ALPHA; - rs.zFunc = CMPF_LESS; + rs.zFunc = CMPF_GREATEREQUAL; rs.zwrite = 0; depthMaskRenderStateId = shaders::render_states::create(rs); effects_depth_texVarId = ::get_shader_variable_id("effects_depth_tex", true); @@ -698,6 +698,15 @@ class DaEditor3DynamicScene : public DagorGameScene, public ICascadeShadowsClien Texture *finalRt = resolvePostProcessing(use_postfx); + if (rtype == RTYPE_DYNAMIC_DEFERRED && dbgShowType != -1) + { + if (::grs_draw_wire) + d3d::setwire(0); + d3d::set_render_target(finalRt, 0); + deferredTarget->debugRender(dbgShowType); + goto skip_non_geom_render; + } + IEditorCoreEngine::get()->renderObjects(); IEditorCoreEngine::get()->renderTransObjects(); ec_camera_elem::freeCameraElem->render(); @@ -706,6 +715,7 @@ class DaEditor3DynamicScene : public DagorGameScene, public ICascadeShadowsClien ec_camera_elem::tpsCameraElem->render(); ec_camera_elem::carCameraElem->render(); + skip_non_geom_render: RectInt r; r.left = viewportX; r.top = viewportY; @@ -736,13 +746,13 @@ class DaEditor3DynamicScene : public DagorGameScene, public ICascadeShadowsClien }; static Vertex v[4]; v[0].p.set(-1, -1, 0); - v[0].c = 0xFFFFFFFF; + v[0].c = 0x00FFFFFF; v[1].p.set(+1, -1, 0); - v[1].c = 0xFFFFFFFF; + v[1].c = 0x00FFFFFF; v[2].p.set(-1, +1, 0); - v[2].c = 0xFFFFFFFF; + v[2].c = 0x00FFFFFF; v[3].p.set(+1, +1, 0); - v[3].c = 0xFFFFFFFF; + v[3].c = 0x00FFFFFF; d3d::draw_up(PRIM_TRISTRIP, 2, v, sizeof(v[0])); d3d::set_program(BAD_PROGRAM); shaders::overrides::reset(); diff --git a/prog/tools/sceneTools/daEditorX/services/fxMgr/fxMgrService.cpp b/prog/tools/sceneTools/daEditorX/services/fxMgr/fxMgrService.cpp index 37a994c02..cc097dcee 100644 --- a/prog/tools/sceneTools/daEditorX/services/fxMgr/fxMgrService.cpp +++ b/prog/tools/sceneTools/daEditorX/services/fxMgr/fxMgrService.cpp @@ -78,9 +78,6 @@ class VirtualFxEntity : public IObjEntity if (fx) fx->setParam(HUID_RAYTRACER, fxRayTracer); ::release_game_resource(res); - - if (dafx_enabled) - set_up_dafx_effect(g_dafx_ctx, fx, false); } } @@ -104,11 +101,22 @@ class FxEntity : public VirtualFxEntity, public IObjEntityUserDataHolder if (!fx) return; - TMatrix ident = TMatrix::IDENT; - fx->setParam(HUID_EMITTER_TM, &ident); - fx->setParam(HUID_TM, &tm); - Point4 p4 = Point4::xyz0(tm.getcol(3)); - fx->setParam(_MAKE4C('PFXP'), &p4); + if (setupDone) + { + TMatrix ident = TMatrix::IDENT; + fx->setParam(HUID_EMITTER_TM, &ident); + fx->setParam(HUID_TM, &tm); + Point4 p4 = Point4::xyz0(tm.getcol(3)); + fx->setParam(_MAKE4C('PFXP'), &p4); + } + else + { + setupDone = true; + + fx->setParam(HUID_RAYTRACER, fxRayTracer); + if (dafx_enabled) + set_up_dafx_effect(g_dafx_ctx, fx, false, true, &tm); + } /*== this code is designed for emitter-editing mode TMatrix fm, em; @@ -152,14 +160,10 @@ class FxEntity : public VirtualFxEntity, public IObjEntityUserDataHolder { nameId = e.nameId; fx = e.fx ? (BaseEffectObject *)e.fx->clone() : NULL; - if (fx) - { - fx->setParam(HUID_RAYTRACER, fxRayTracer); - set_up_dafx_effect(g_dafx_ctx, fx, false); - } } void clear() { + setupDone = false; del_it(fx); del_it(userDataBlk); } @@ -171,6 +175,7 @@ class FxEntity : public VirtualFxEntity, public IObjEntityUserDataHolder MAX_ENTITIES = 0x7FFFFFFF }; + bool setupDone = false; unsigned idx; TMatrix tm; DataBlock *userDataBlk; diff --git a/prog/tools/sharedInclude/dafxToolsHelper/dafxToolsHelper.h b/prog/tools/sharedInclude/dafxToolsHelper/dafxToolsHelper.h index 09f181bba..e8439870f 100644 --- a/prog/tools/sharedInclude/dafxToolsHelper/dafxToolsHelper.h +++ b/prog/tools/sharedInclude/dafxToolsHelper/dafxToolsHelper.h @@ -33,17 +33,25 @@ inline void set_up_dafx_context(dafx::ContextId &dafx_ctx, dafx::CullingId &dafx } } -inline void set_up_dafx_effect(dafx::ContextId dafx_ctx, BaseEffectObject *fx, bool force_recreate) +inline void set_up_dafx_effect(dafx::ContextId dafx_ctx, BaseEffectObject *fx, bool force_recreate, bool enabled = true, + const TMatrix *tm = nullptr) { if (!fx || !dafx_ctx) return; - bool v = true; TMatrix ident = TMatrix::IDENT; dafx::flush_command_queue(dafx_ctx); fx->setParam(_MAKE4C('PFXR'), &force_recreate); - fx->setParam(_MAKE4C('PFXE'), &v); + fx->setParam(_MAKE4C('PFXE'), &enabled); fx->setParam(HUID_EMITTER_TM, &ident); + + if (tm) + { + fx->setParam(HUID_TM, const_cast(tm)); + Point4 p4 = Point4::xyz0(tm->getcol(3)); + fx->setParam(_MAKE4C('PFXP'), &p4); + } + dafx::flush_command_queue(dafx_ctx); } diff --git a/samples/skiesSample/prog/jamfile b/samples/skiesSample/prog/jamfile index 0f4f2103e..3b5cf3b60 100644 --- a/samples/skiesSample/prog/jamfile +++ b/samples/skiesSample/prog/jamfile @@ -106,14 +106,8 @@ if $(Platform) in win32 win64 { engine/drv/drv3d_ps4 engine/drv/hid_nulldrv ; - AddLibs = - -lScePerf_stub_weak - ; - BundleCopy = - @$(_DEVTOOL)/ps4.sdk.$(PS4SdkVer)/target/sce_module/libc.prx sce_module/libc.prx - @$(_DEVTOOL)/ps4.sdk.$(PS4SdkVer)/target/sce_module/libSceFios2.prx sce_module/libSceFios2.prx - ; + include $(Root)/prog/_jBuild/$(Platform)/bundle_prx.jam ; } else if $(Platform) = ps5 { Sources += @@ -125,13 +119,8 @@ if $(Platform) in win32 win64 { engine/drv/drv3d_ps5 ; - AddLibs = - -lSceShare_stub_weak - ; + include $(Root)/prog/_jBuild/$(Platform)/bundle_prx.jam ; - BundleCopy = - @$(_DEVTOOL)/ps5.sdk.$(PS5SdkVer)/target/sce_module/libc.prx sce_module/libc.prx - ; } else if $(Platform) in xboxOne scarlett { UseProgLibs += engine/drv/drv3d_DX12 ; UseProgLibs += engine/drv/hid_gamepad_xinput engine/drv/hid_keyboard engine/drv/hid_nulldrv ; @@ -290,7 +279,7 @@ if $(Platform) in win32 win64 { engine/drv/hid_nswitch engine/drv/hid_nulldrv gameLibs/jsonUtils - gameLibs/nswitch + gameLibs/nswitch/kit gameLibs/nswitch/assets gameLibs/nswitch/account gameLibs/nswitch/journalizedMount diff --git a/samples/testGI/prog/jamfile b/samples/testGI/prog/jamfile index a18b8648b..108e94c5b 100644 --- a/samples/testGI/prog/jamfile +++ b/samples/testGI/prog/jamfile @@ -97,9 +97,6 @@ if $(Platform) in win32 win64 { engine/drv/hid_sony engine/drv/drv3d_ps4 ; - AddLibs = - -lScePerf_stub_weak - ; } else if $(Platform) = android { UseProgLibs += engine/drv/drv3d_vulkan diff --git a/samples/testGI/prog/test_app.cpp b/samples/testGI/prog/test_app.cpp index 9c5acf6b2..5ab5681ec 100644 --- a/samples/testGI/prog/test_app.cpp +++ b/samples/testGI/prog/test_app.cpp @@ -1519,8 +1519,8 @@ class DemoGameScene : public DagorGameScene, public IRenderDynamicCubeFace2, pub { if (gi_panel.update_scene && gi_panel.gi_mode == SSGI) { - set_inv_globtm_to_shader(false); - set_viewvecs_to_shader(); + set_inv_globtm_to_shader(view, projTm, false); + set_viewvecs_to_shader(view, projTm); target->setVar(); updateSSGISceneVoxels(); }