diff --git a/.github/generate_changelog.py b/.github/generate_changelog.py index 5e921fd6e..b07100115 100644 --- a/.github/generate_changelog.py +++ b/.github/generate_changelog.py @@ -8,7 +8,8 @@ import re import sys import json import argparse -from typing import List, Tuple, Optional +import os +from typing import List, Tuple, Optional, Dict, Any def run_git_command(args: List[str]) -> str: @@ -30,14 +31,14 @@ def get_last_two_tags() -> Tuple[str, str]: """Get the latest two git tags.""" tags = run_git_command(["tag", "--sort=-version:refname"]) tag_list = [t for t in tags.split("\n") if t] - + # Filter out old tags that start with 'v' (old versioning scheme) tag_list = [t for t in tag_list if not t.startswith('v')] if len(tag_list) < 2: print("Error: Need at least 2 tags in the repository", file=sys.stderr) sys.exit(1) - + return tag_list[0], tag_list[1] @@ -55,58 +56,144 @@ def get_submodule_commit(submodule_path: str, tag: str) -> Optional[str]: return None -def get_commits_between_tags(tag1: str, tag2: str) -> List[Tuple[str, str]]: - """Get commits between two tags. Returns list of (message, author) tuples.""" +def get_repo_info() -> Tuple[str, str]: + """Get repository owner and name from git remote.""" + try: + remote_url = run_git_command(["config", "--get", "remote.origin.url"]) + + # Handle both HTTPS and SSH URLs + # SSH: git@github.com:owner/repo.git + # HTTPS: https://github.com/owner/repo.git + match = re.search(r'github\.com[:/](.+?)/(.+?)(?:\.git)?$', remote_url) + if match: + owner = match.group(1) + repo = match.group(2) + return owner, repo + else: + print("Error: Could not parse GitHub repository from remote URL", file=sys.stderr) + sys.exit(1) + except: + print("Error: Could not get git remote URL", file=sys.stderr) + sys.exit(1) + + +def get_commits_between_tags(tag1: str, tag2: str) -> List[str]: + """Get commit SHAs between two tags.""" log_output = run_git_command([ "log", f"{tag2}..{tag1}", - "--format=%s|%an|%h" + "--format=%H" ]) - - commits = [] - for line in log_output.split("\n"): - if "|" in line: - message, author, sha = line.split("|", 2) - commits.append((message.strip(), author.strip(), sha.strip())) - + + commits = [sha.strip() for sha in log_output.split("\n") if sha.strip()] return commits -def filter_commits(commits: List[Tuple[str, str]], ignore_patterns: List[str]) -> List[Tuple[str, str]]: - """Filter out commits matching any of the ignore patterns.""" +def get_pr_for_commit(commit_sha: str, owner: str, repo: str, token: str) -> Optional[Dict[str, Any]]: + """Get PR information for a commit using GitHub API.""" + try: + import requests + except ImportError: + print("Error: requests library is required. Install it with: pip install requests", file=sys.stderr) + sys.exit(1) + + headers = { + "Accept": "application/vnd.github+json", + "X-GitHub-Api-Version": "2022-11-28" + } + + if token: + headers["Authorization"] = f"Bearer {token}" + + url = f"https://api.github.com/repos/{owner}/{repo}/commits/{commit_sha}/pulls" + + try: + response = requests.get(url, headers=headers) + response.raise_for_status() + prs = response.json() + + if prs and len(prs) > 0: + # Return the first PR (most relevant one) + pr = prs[0] + return { + "number": pr["number"], + "title": pr["title"], + "author": pr["user"]["login"], + "url": pr["html_url"] + } + except requests.exceptions.HTTPError as e: + if e.response.status_code == 404: + # Commit might not be associated with a PR + return None + elif e.response.status_code == 403: + print("Warning: GitHub API rate limit exceeded. Consider providing a token.", file=sys.stderr) + return None + else: + print(f"Warning: Failed to fetch PR for commit {commit_sha[:7]}: {e}", file=sys.stderr) + return None + except Exception as e: + print(f"Warning: Error fetching PR for commit {commit_sha[:7]}: {e}", file=sys.stderr) + return None + + return None + + +def get_prs_between_tags(tag1: str, tag2: str, owner: str, repo: str, token: str) -> List[Dict[str, Any]]: + """Get PRs between two tags using GitHub API.""" + commits = get_commits_between_tags(tag1, tag2) + print(f"Found {len(commits)} commits, fetching PR information...") + + prs = [] + seen_pr_numbers = set() + + for i, commit_sha in enumerate(commits, 1): + if i % 10 == 0: + print(f"Progress: {i}/{len(commits)} commits processed...") + + pr_info = get_pr_for_commit(commit_sha, owner, repo, token) + if pr_info and pr_info["number"] not in seen_pr_numbers: + seen_pr_numbers.add(pr_info["number"]) + prs.append(pr_info) + + return prs + + +def filter_prs(prs: List[Dict[str, Any]], ignore_patterns: List[str]) -> List[Dict[str, Any]]: + """Filter out PRs matching any of the ignore patterns.""" compiled_patterns = [re.compile(pattern) for pattern in ignore_patterns] - + filtered = [] - for message, author, sha in commits: - if not any(pattern.search(message) for pattern in compiled_patterns): - filtered.append((message, author, sha)) - + for pr in prs: + if not any(pattern.search(pr["title"]) for pattern in compiled_patterns): + filtered.append(pr) + return filtered -def generate_changelog(version: str, prev_version: str, commits: List[Tuple[str, str]], - cs_commit_new: Optional[str], cs_commit_old: Optional[str]) -> str: +def generate_changelog(version: str, prev_version: str, prs: List[Dict[str, Any]], + cs_commit_new: Optional[str], cs_commit_old: Optional[str], + owner: str, repo: str) -> str: """Generate markdown changelog.""" # Calculate statistics - commit_count = len(commits) - unique_authors = len(set(author for _, author, _ in commits)) - + pr_count = len(prs) + unique_authors = len(set(pr["author"] for pr in prs)) + changelog = f"# Dalamud Release v{version}\n\n" changelog += f"We just released Dalamud v{version}, which should be available to users within a few minutes. " - changelog += f"This release includes **{commit_count} commit{'s' if commit_count != 1 else ''} from {unique_authors} contributor{'s' if unique_authors != 1 else ''}**.\n" - changelog += f"[Click here]() to see all Dalamud changes.\n\n" - + changelog += f"This release includes **{pr_count} PR{'s' if pr_count != 1 else ''} from {unique_authors} contributor{'s' if unique_authors != 1 else ''}**.\n" + changelog += f"[Click here]() to see all Dalamud changes.\n\n" + if cs_commit_new and cs_commit_old and cs_commit_new != cs_commit_old: changelog += f"It ships with an updated **FFXIVClientStructs [`{cs_commit_new[:7]}`]()**.\n" changelog += f"[Click here]() to see all CS changes.\n" elif cs_commit_new: changelog += f"It ships with **FFXIVClientStructs [`{cs_commit_new[:7]}`]()**.\n" - + changelog += "## Dalamud Changes\n\n" - - for message, author, sha in commits: - changelog += f"* {message} (by **{author}** as [`{sha}`]())\n" - + + for pr in prs: + changelog += f"* {pr['title']} ([#**{pr['number']}**](<{pr['url']}>) by **{pr['author']}**)\n" + return changelog @@ -117,9 +204,9 @@ def post_to_discord(webhook_url: str, content: str, version: str) -> None: except ImportError: print("Error: requests library is required. Install it with: pip install requests", file=sys.stderr) sys.exit(1) - + filename = f"changelog-v{version}.md" - + # Prepare the payload data = { "content": f"Dalamud v{version} has been released!", @@ -130,13 +217,13 @@ def post_to_discord(webhook_url: str, content: str, version: str) -> None: } ] } - + # Prepare the files files = { "payload_json": (None, json.dumps(data)), "files[0]": (filename, content.encode('utf-8'), 'text/markdown') } - + try: result = requests.post(webhook_url, files=files) result.raise_for_status() @@ -158,54 +245,64 @@ def main(): required=True, help="Discord webhook URL" ) + parser.add_argument( + "--github-token", + default=os.environ.get("GITHUB_TOKEN"), + help="GitHub API token (or set GITHUB_TOKEN env var). Increases rate limit." + ) parser.add_argument( "--ignore", action="append", default=[], - help="Regex patterns to ignore commits (can be specified multiple times)" + help="Regex patterns to ignore PRs (can be specified multiple times)" ) parser.add_argument( "--submodule-path", default="lib/FFXIVClientStructs", help="Path to the FFXIVClientStructs submodule (default: lib/FFXIVClientStructs)" ) - + args = parser.parse_args() - + + # Get repository info + owner, repo = get_repo_info() + print(f"Repository: {owner}/{repo}") + # Get the last two tags latest_tag, previous_tag = get_last_two_tags() print(f"Generating changelog between {previous_tag} and {latest_tag}") - + # Get submodule commits at both tags cs_commit_new = get_submodule_commit(args.submodule_path, latest_tag) cs_commit_old = get_submodule_commit(args.submodule_path, previous_tag) - + if cs_commit_new: print(f"FFXIVClientStructs commit (new): {cs_commit_new[:7]}") if cs_commit_old: print(f"FFXIVClientStructs commit (old): {cs_commit_old[:7]}") - - # Get commits between tags - commits = get_commits_between_tags(latest_tag, previous_tag) - print(f"Found {len(commits)} commits") - - # Filter commits - filtered_commits = filter_commits(commits, args.ignore) - print(f"After filtering: {len(filtered_commits)} commits") - + + # Get PRs between tags + prs = get_prs_between_tags(latest_tag, previous_tag, owner, repo, args.github_token) + prs.reverse() + print(f"Found {len(prs)} PRs") + + # Filter PRs + filtered_prs = filter_prs(prs, args.ignore) + print(f"After filtering: {len(filtered_prs)} PRs") + # Generate changelog - changelog = generate_changelog(latest_tag, previous_tag, filtered_commits, - cs_commit_new, cs_commit_old) - + changelog = generate_changelog(latest_tag, previous_tag, filtered_prs, + cs_commit_new, cs_commit_old, owner, repo) + print("\n" + "="*50) print("Generated Changelog:") print("="*50) print(changelog) print("="*50 + "\n") - + # Post to Discord post_to_discord(args.webhook_url, changelog, latest_tag) if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/.github/workflows/generate-changelog.yml b/.github/workflows/generate-changelog.yml index 5fed3b1eb..e62d5f37c 100644 --- a/.github/workflows/generate-changelog.yml +++ b/.github/workflows/generate-changelog.yml @@ -6,41 +6,43 @@ on: tags: - '*' +permissions: read-all + jobs: generate-changelog: runs-on: ubuntu-latest - + steps: - name: Checkout repository uses: actions/checkout@v4 with: fetch-depth: 0 # Fetch all history and tags submodules: true # Fetch submodules - + - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.14' - + - name: Install dependencies run: | python -m pip install --upgrade pip pip install requests - + - name: Generate and post changelog + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GIT_TERMINAL_PROMPT: 0 run: | python .github/generate_changelog.py \ --webhook-url "${{ secrets.DISCORD_CHANGELOG_WEBHOOK_URL }}" \ - --ignore "^Merge" \ - --ignore "^build:" \ - --ignore "^docs:" - env: - GIT_TERMINAL_PROMPT: 0 - + --ignore "Update ClientStructs" \ + --ignore "^build:" + - name: Upload changelog as artifact if: always() uses: actions/upload-artifact@v4 with: name: changelog path: changelog-*.md - if-no-files-found: ignore \ No newline at end of file + if-no-files-found: ignore diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 299d71e95..9466cb083 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,9 +1,10 @@ name: Build Dalamud on: [push, pull_request, workflow_dispatch] +# Globally blocking because of git pushes in deploy step concurrency: - group: build_dalamud_${{ github.ref_name }} - cancel-in-progress: true + group: build_dalamud_${{ github.repository_owner }} + cancel-in-progress: false jobs: build: diff --git a/.nuke/build.schema.json b/.nuke/build.schema.json index 03211ce8f..6ffb3bb01 100644 --- a/.nuke/build.schema.json +++ b/.nuke/build.schema.json @@ -1,19 +1,57 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "title": "Build Schema", - "$ref": "#/definitions/build", "definitions": { - "build": { - "type": "object", + "Host": { + "type": "string", + "enum": [ + "AppVeyor", + "AzurePipelines", + "Bamboo", + "Bitbucket", + "Bitrise", + "GitHubActions", + "GitLab", + "Jenkins", + "Rider", + "SpaceAutomation", + "TeamCity", + "Terminal", + "TravisCI", + "VisualStudio", + "VSCode" + ] + }, + "ExecutableTarget": { + "type": "string", + "enum": [ + "CI", + "Clean", + "Compile", + "CompileCImGui", + "CompileCImGuizmo", + "CompileCImPlot", + "CompileDalamud", + "CompileDalamudBoot", + "CompileDalamudCrashHandler", + "CompileImGuiNatives", + "CompileInjector", + "Restore", + "SetCILogging", + "Test" + ] + }, + "Verbosity": { + "type": "string", + "description": "", + "enum": [ + "Verbose", + "Normal", + "Minimal", + "Quiet" + ] + }, + "NukeBuild": { "properties": { - "Configuration": { - "type": "string", - "description": "Configuration to build - Default is 'Debug' (local) or 'Release' (server)", - "enum": [ - "Debug", - "Release" - ] - }, "Continue": { "type": "boolean", "description": "Indicates to continue a previously failed build attempt" @@ -23,29 +61,8 @@ "description": "Shows the help text for this build assembly" }, "Host": { - "type": "string", "description": "Host for execution. Default is 'automatic'", - "enum": [ - "AppVeyor", - "AzurePipelines", - "Bamboo", - "Bitbucket", - "Bitrise", - "GitHubActions", - "GitLab", - "Jenkins", - "Rider", - "SpaceAutomation", - "TeamCity", - "Terminal", - "TravisCI", - "VisualStudio", - "VSCode" - ] - }, - "IsDocsBuild": { - "type": "boolean", - "description": "Whether we are building for documentation - emits generated files" + "$ref": "#/definitions/Host" }, "NoLogo": { "type": "boolean", @@ -74,63 +91,46 @@ "type": "array", "description": "List of targets to be skipped. Empty list skips all dependencies", "items": { - "type": "string", - "enum": [ - "CI", - "Clean", - "Compile", - "CompileCImGui", - "CompileCImGuizmo", - "CompileCImPlot", - "CompileDalamud", - "CompileDalamudBoot", - "CompileDalamudCrashHandler", - "CompileImGuiNatives", - "CompileInjector", - "Restore", - "SetCILogging", - "Test" - ] + "$ref": "#/definitions/ExecutableTarget" } }, - "Solution": { - "type": "string", - "description": "Path to a solution file that is automatically loaded" - }, "Target": { "type": "array", "description": "List of targets to be invoked. Default is '{default_target}'", "items": { - "type": "string", - "enum": [ - "CI", - "Clean", - "Compile", - "CompileCImGui", - "CompileCImGuizmo", - "CompileCImPlot", - "CompileDalamud", - "CompileDalamudBoot", - "CompileDalamudCrashHandler", - "CompileImGuiNatives", - "CompileInjector", - "Restore", - "SetCILogging", - "Test" - ] + "$ref": "#/definitions/ExecutableTarget" } }, "Verbosity": { - "type": "string", "description": "Logging verbosity during build execution. Default is 'Normal'", - "enum": [ - "Minimal", - "Normal", - "Quiet", - "Verbose" - ] + "$ref": "#/definitions/Verbosity" } } } - } -} \ No newline at end of file + }, + "allOf": [ + { + "properties": { + "Configuration": { + "type": "string", + "description": "Configuration to build - Default is 'Debug' (local) or 'Release' (server)", + "enum": [ + "Debug", + "Release" + ] + }, + "IsDocsBuild": { + "type": "boolean", + "description": "Whether we are building for documentation - emits generated files" + }, + "Solution": { + "type": "string", + "description": "Path to a solution file that is automatically loaded" + } + } + }, + { + "$ref": "#/definitions/NukeBuild" + } + ] +} diff --git a/Dalamud.Boot/crashhandler_shared.h b/Dalamud.Boot/crashhandler_shared.h index 8d93e4460..0308306ce 100644 --- a/Dalamud.Boot/crashhandler_shared.h +++ b/Dalamud.Boot/crashhandler_shared.h @@ -6,6 +6,8 @@ #define WIN32_LEAN_AND_MEAN #include +#define CUSTOM_EXCEPTION_EXTERNAL_EVENT 0x12345679 + struct exception_info { LPEXCEPTION_POINTERS pExceptionPointers; diff --git a/Dalamud.Boot/dllmain.cpp b/Dalamud.Boot/dllmain.cpp index 80a16f89a..687089f82 100644 --- a/Dalamud.Boot/dllmain.cpp +++ b/Dalamud.Boot/dllmain.cpp @@ -331,6 +331,51 @@ HRESULT WINAPI InitializeImpl(LPVOID lpParam, HANDLE hMainThreadContinue) { logging::I("VEH was disabled manually"); } + // ============================== CLR Reporting =================================== // + + // This is pretty horrible - CLR just doesn't provide a way for us to handle these events, and the API for it + // was pushed back to .NET 11, so we have to hook ReportEventW and catch them ourselves for now. + // Ideally all of this will go away once they get to it. + static std::shared_ptr> s_report_event_hook; + s_report_event_hook = std::make_shared>( + "advapi32.dll!ReportEventW (global import, hook_clr_report_event)", L"advapi32.dll", "ReportEventW"); + s_report_event_hook->set_detour([hook = s_report_event_hook.get()]( + HANDLE hEventLog, + WORD wType, + WORD wCategory, + DWORD dwEventID, + PSID lpUserSid, + WORD wNumStrings, + DWORD dwDataSize, + LPCWSTR* lpStrings, + LPVOID lpRawData)-> BOOL { + + // Check for CLR Error Event IDs + // https://github.com/dotnet/runtime/blob/v10.0.0/src/coreclr/vm/eventreporter.cpp#L370 + if (dwEventID != 1026 && // ERT_UnhandledException: The process was terminated due to an unhandled exception + dwEventID != 1025 && // ERT_ManagedFailFast: The application requested process termination through System.Environment.FailFast + dwEventID != 1023 && // ERT_UnmanagedFailFast: The process was terminated due to an internal error in the .NET Runtime + dwEventID != 1027 && // ERT_StackOverflow: The process was terminated due to a stack overflow + dwEventID != 1028) // ERT_CodeContractFailed: The application encountered a bug. A managed code contract (precondition, postcondition, object invariant, or assert) failed + { + return hook->call_original(hEventLog, wType, wCategory, dwEventID, lpUserSid, wNumStrings, dwDataSize, lpStrings, lpRawData); + } + + if (wNumStrings == 0 || lpStrings == nullptr) { + logging::W("ReportEventW called with no strings."); + return hook->call_original(hEventLog, wType, wCategory, dwEventID, lpUserSid, wNumStrings, dwDataSize, lpStrings, lpRawData); + } + + // In most cases, DalamudCrashHandler will kill us now, so call original here to make sure we still write to the event log. + const BOOL original_ret = hook->call_original(hEventLog, wType, wCategory, dwEventID, lpUserSid, wNumStrings, dwDataSize, lpStrings, lpRawData); + + const std::wstring error_details(lpStrings[0]); + veh::raise_external_event(error_details); + + return original_ret; + }); + logging::I("ReportEventW hook installed."); + // ============================== Dalamud ==================================== // if (static_cast(g_startInfo.BootWaitMessageBox) & static_cast(DalamudStartInfo::WaitMessageboxFlags::BeforeDalamudEntrypoint)) diff --git a/Dalamud.Boot/veh.cpp b/Dalamud.Boot/veh.cpp index b75256af8..c0a0b034a 100644 --- a/Dalamud.Boot/veh.cpp +++ b/Dalamud.Boot/veh.cpp @@ -31,6 +31,8 @@ HANDLE g_crashhandler_process = nullptr; HANDLE g_crashhandler_event = nullptr; HANDLE g_crashhandler_pipe_write = nullptr; +wchar_t g_external_event_info[16384] = L""; + std::recursive_mutex g_exception_handler_mutex; std::chrono::time_point g_time_start; @@ -191,7 +193,11 @@ LONG exception_handler(EXCEPTION_POINTERS* ex) DuplicateHandle(GetCurrentProcess(), g_crashhandler_event, g_crashhandler_process, &exinfo.hEventHandle, 0, TRUE, DUPLICATE_SAME_ACCESS); std::wstring stackTrace; - if (!g_clr) + if (ex->ExceptionRecord->ExceptionCode == CUSTOM_EXCEPTION_EXTERNAL_EVENT) + { + stackTrace = std::wstring(g_external_event_info); + } + else if (!g_clr) { stackTrace = L"(no CLR stack trace available)"; } @@ -252,6 +258,12 @@ LONG WINAPI structured_exception_handler(EXCEPTION_POINTERS* ex) LONG WINAPI vectored_exception_handler(EXCEPTION_POINTERS* ex) { + // special case for CLR exceptions, always trigger crash handler + if (ex->ExceptionRecord->ExceptionCode == CUSTOM_EXCEPTION_EXTERNAL_EVENT) + { + return exception_handler(ex); + } + if (ex->ExceptionRecord->ExceptionCode == 0x12345678) { // pass @@ -435,3 +447,16 @@ bool veh::remove_handler() } return false; } + +void veh::raise_external_event(const std::wstring& info) +{ + const auto info_size = std::min(info.size(), std::size(g_external_event_info) - 1); + wcsncpy_s(g_external_event_info, info.c_str(), info_size); + RaiseException(CUSTOM_EXCEPTION_EXTERNAL_EVENT, 0, 0, nullptr); +} + +extern "C" __declspec(dllexport) void BootVehRaiseExternalEventW(LPCWSTR info) +{ + const std::wstring info_wstr(info); + veh::raise_external_event(info_wstr); +} diff --git a/Dalamud.Boot/veh.h b/Dalamud.Boot/veh.h index 1905272ea..2a02c374e 100644 --- a/Dalamud.Boot/veh.h +++ b/Dalamud.Boot/veh.h @@ -4,4 +4,5 @@ namespace veh { bool add_handler(bool doFullDump, const std::string& workingDirectory); bool remove_handler(); + void raise_external_event(const std::wstring& info); } diff --git a/Dalamud/Configuration/Internal/DalamudConfiguration.cs b/Dalamud/Configuration/Internal/DalamudConfiguration.cs index 9404b5b10..d546dc517 100644 --- a/Dalamud/Configuration/Internal/DalamudConfiguration.cs +++ b/Dalamud/Configuration/Internal/DalamudConfiguration.cs @@ -487,6 +487,14 @@ internal sealed class DalamudConfiguration : IInternalDisposableService /// public Vector2 NotificationAnchorPosition { get; set; } = new(1f, 1f); +#pragma warning disable SA1600 +#pragma warning disable SA1516 + // XLCore/XoM compatibility until they move it out + public string? DalamudBetaKey { get; set; } = null; + public string? DalamudBetaKind { get; set; } +#pragma warning restore SA1516 +#pragma warning restore SA1600 + /// /// Load a configuration from the provided path. /// diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index b9b453f89..7ea4f2caa 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -6,7 +6,7 @@ XIV Launcher addon framework - 13.0.0.11 + 13.0.0.13 $(DalamudVersion) $(DalamudVersion) $(DalamudVersion) @@ -73,8 +73,6 @@ all - - @@ -123,6 +121,8 @@ PreserveNewest + + @@ -227,9 +227,4 @@ - - - - - diff --git a/Dalamud/DalamudAsset.cs b/Dalamud/DalamudAsset.cs index 27771116e..e234fbb4c 100644 --- a/Dalamud/DalamudAsset.cs +++ b/Dalamud/DalamudAsset.cs @@ -151,7 +151,7 @@ public enum DalamudAsset /// : FontAwesome Free Solid. /// [DalamudAsset(DalamudAssetPurpose.Font)] - [DalamudAssetPath("UIRes", "FontAwesomeFreeSolid.otf")] + [DalamudAssetPath("UIRes", "FontAwesome710FreeSolid.otf")] FontAwesomeFreeSolid = 2003, /// diff --git a/Dalamud/Data/DataManager.cs b/Dalamud/Data/DataManager.cs index ed0aa6c4d..559bd84dc 100644 --- a/Dalamud/Data/DataManager.cs +++ b/Dalamud/Data/DataManager.cs @@ -82,8 +82,10 @@ internal sealed class DataManager : IInternalDisposableService, IDataManager var tsInfo = JsonConvert.DeserializeObject( dalamud.StartInfo.TroubleshootingPackData); + + // Don't fail for IndexIntegrityResult.Exception, since the check during launch has a very small timeout this.HasModifiedGameDataFiles = - tsInfo?.IndexIntegrity is LauncherTroubleshootingInfo.IndexIntegrityResult.Failed or LauncherTroubleshootingInfo.IndexIntegrityResult.Exception; + tsInfo?.IndexIntegrity is LauncherTroubleshootingInfo.IndexIntegrityResult.Failed; if (this.HasModifiedGameDataFiles) Log.Verbose("Game data integrity check failed!\n{TsData}", dalamud.StartInfo.TroubleshootingPackData); diff --git a/Dalamud/EntryPoint.cs b/Dalamud/EntryPoint.cs index 15077f3d8..54e25b6f2 100644 --- a/Dalamud/EntryPoint.cs +++ b/Dalamud/EntryPoint.cs @@ -263,7 +263,7 @@ public sealed class EntryPoint var symbolPath = Path.Combine(info.AssetDirectory, "UIRes", "pdb"); var searchPath = $".;{symbolPath}"; - var currentProcess = Windows.Win32.PInvoke.GetCurrentProcess_SafeHandle(); + var currentProcess = Windows.Win32.PInvoke.GetCurrentProcess(); // Remove any existing Symbol Handler and Init a new one with our search path added Windows.Win32.PInvoke.SymCleanup(currentProcess); @@ -292,7 +292,6 @@ public sealed class EntryPoint } var pluginInfo = string.Empty; - var supportText = ", please visit us on Discord for more help"; try { var pm = Service.GetNullable(); @@ -300,9 +299,6 @@ public sealed class EntryPoint if (plugin != null) { pluginInfo = $"Plugin that caused this:\n{plugin.Name}\n\nClick \"Yes\" and remove it.\n\n"; - - if (plugin.IsThirdParty) - supportText = string.Empty; } } catch @@ -310,31 +306,18 @@ public sealed class EntryPoint // ignored } - const MESSAGEBOX_STYLE flags = MESSAGEBOX_STYLE.MB_YESNO | MESSAGEBOX_STYLE.MB_ICONERROR | MESSAGEBOX_STYLE.MB_SYSTEMMODAL; - var result = Windows.Win32.PInvoke.MessageBox( - new HWND(Process.GetCurrentProcess().MainWindowHandle), - $"An internal error in a Dalamud plugin occurred.\nThe game must close.\n\n{ex.GetType().Name}\n{info}\n\n{pluginInfo}More information has been recorded separately{supportText}.\n\nDo you want to disable all plugins the next time you start the game?", - "Dalamud", - flags); - - if (result == MESSAGEBOX_RESULT.IDYES) - { - Log.Information("User chose to disable plugins on next launch..."); - var config = Service.Get(); - config.PluginSafeMode = true; - config.ForceSave(); - } - Log.CloseAndFlush(); - Environment.Exit(-1); + + ErrorHandling.CrashWithContext($"{ex}\n\n{info}\n\n{pluginInfo}"); break; default: Log.Fatal("Unhandled SEH object on AppDomain: {Object}", args.ExceptionObject); Log.CloseAndFlush(); - Environment.Exit(-1); break; } + + Environment.Exit(-1); } private static void OnUnhandledExceptionStallDebug(object sender, UnhandledExceptionEventArgs args) diff --git a/Dalamud/Game/Addon/Events/AddonEventManager.cs b/Dalamud/Game/Addon/Events/AddonEventManager.cs index 945197e2b..980404940 100644 --- a/Dalamud/Game/Addon/Events/AddonEventManager.cs +++ b/Dalamud/Game/Addon/Events/AddonEventManager.cs @@ -9,7 +9,6 @@ using Dalamud.Logging.Internal; using Dalamud.Plugin.Internal.Types; using Dalamud.Plugin.Services; -using FFXIVClientStructs.FFXIV.Client.UI; using FFXIVClientStructs.FFXIV.Component.GUI; namespace Dalamud.Game.Addon.Events; @@ -32,25 +31,21 @@ internal unsafe class AddonEventManager : IInternalDisposableService private readonly AddonLifecycleEventListener finalizeEventListener; - private readonly AddonEventManagerAddressResolver address; - private readonly Hook onUpdateCursor; + private readonly Hook onUpdateCursor; private readonly ConcurrentDictionary pluginEventControllers; - private AddonCursorType? cursorOverride; + private AtkCursor.CursorType? cursorOverride; [ServiceManager.ServiceConstructor] - private AddonEventManager(TargetSigScanner sigScanner) + private AddonEventManager() { - this.address = new AddonEventManagerAddressResolver(); - this.address.Setup(sigScanner); - this.pluginEventControllers = new ConcurrentDictionary(); this.pluginEventControllers.TryAdd(DalamudInternalKey, new PluginEventController()); this.cursorOverride = null; - this.onUpdateCursor = Hook.FromAddress(this.address.UpdateCursor, this.UpdateCursorDetour); + this.onUpdateCursor = Hook.FromAddress(AtkUnitManager.Addresses.UpdateCursor.Value, this.UpdateCursorDetour); this.finalizeEventListener = new AddonLifecycleEventListener(AddonEvent.PreFinalize, string.Empty, this.OnAddonFinalize); this.addonLifecycle.RegisterListener(this.finalizeEventListener); @@ -58,8 +53,6 @@ internal unsafe class AddonEventManager : IInternalDisposableService this.onUpdateCursor.Enable(); } - private delegate nint UpdateCursorDelegate(RaptureAtkModule* module); - /// void IInternalDisposableService.DisposeService() { @@ -117,7 +110,7 @@ internal unsafe class AddonEventManager : IInternalDisposableService /// Force the game cursor to be the specified cursor. /// /// Which cursor to use. - internal void SetCursor(AddonCursorType cursor) => this.cursorOverride = cursor; + internal void SetCursor(AddonCursorType cursor) => this.cursorOverride = (AtkCursor.CursorType)cursor; /// /// Un-forces the game cursor. @@ -168,7 +161,7 @@ internal unsafe class AddonEventManager : IInternalDisposableService } } - private nint UpdateCursorDetour(RaptureAtkModule* module) + private void UpdateCursorDetour(AtkUnitManager* thisPtr) { try { @@ -176,13 +169,14 @@ internal unsafe class AddonEventManager : IInternalDisposableService if (this.cursorOverride is not null && atkStage is not null) { - var cursor = (AddonCursorType)atkStage->AtkCursor.Type; - if (cursor != this.cursorOverride) + ref var atkCursor = ref atkStage->AtkCursor; + + if (atkCursor.Type != this.cursorOverride) { - AtkStage.Instance()->AtkCursor.SetCursorType((AtkCursor.CursorType)this.cursorOverride, 1); + atkCursor.SetCursorType((AtkCursor.CursorType)this.cursorOverride, 1); } - return nint.Zero; + return; } } catch (Exception e) @@ -190,7 +184,7 @@ internal unsafe class AddonEventManager : IInternalDisposableService Log.Error(e, "Exception in UpdateCursorDetour."); } - return this.onUpdateCursor!.Original(module); + this.onUpdateCursor!.Original(thisPtr); } } diff --git a/Dalamud/Game/Addon/Events/AddonEventManagerAddressResolver.cs b/Dalamud/Game/Addon/Events/AddonEventManagerAddressResolver.cs deleted file mode 100644 index ec1c51a12..000000000 --- a/Dalamud/Game/Addon/Events/AddonEventManagerAddressResolver.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Dalamud.Plugin.Services; - -namespace Dalamud.Game.Addon.Events; - -/// -/// AddonEventManager memory address resolver. -/// -internal class AddonEventManagerAddressResolver : BaseAddressResolver -{ - /// - /// Gets the address of the AtkModule UpdateCursor method. - /// - public nint UpdateCursor { get; private set; } - - /// - /// Scan for and setup any configured address pointers. - /// - /// The signature scanner to facilitate setup. - protected override void Setup64Bit(ISigScanner scanner) - { - this.UpdateCursor = scanner.ScanText("48 89 74 24 ?? 48 89 7C 24 ?? 41 56 48 83 EC 20 4C 8B F1 E8 ?? ?? ?? ?? 49 8B CE"); // unnamed in CS - } -} diff --git a/Dalamud/Game/Player/PlayerState.cs b/Dalamud/Game/Player/PlayerState.cs index 917c946db..bd19b5bfb 100644 --- a/Dalamud/Game/Player/PlayerState.cs +++ b/Dalamud/Game/Player/PlayerState.cs @@ -77,7 +77,7 @@ internal unsafe class PlayerState : IServiceType, IPlayerState public RowRef ClassJob => this.IsLoaded ? LuminaUtils.CreateRef(CSPlayerState.Instance()->CurrentClassJobId) : default; /// - public short Level => this.IsLoaded ? CSPlayerState.Instance()->CurrentLevel : default; + public short Level => this.IsLoaded && this.ClassJob.IsValid ? this.GetClassJobLevel(this.ClassJob.Value) : this.EffectiveLevel; /// public bool IsLevelSynced => this.IsLoaded && CSPlayerState.Instance()->IsLevelSynced; diff --git a/Dalamud/Game/Text/Evaluator/SeStringParameter.cs b/Dalamud/Game/Text/Evaluator/SeStringParameter.cs index 1c6dd96cb..036d1c921 100644 --- a/Dalamud/Game/Text/Evaluator/SeStringParameter.cs +++ b/Dalamud/Game/Text/Evaluator/SeStringParameter.cs @@ -3,7 +3,6 @@ using System.Globalization; using Lumina.Text.ReadOnly; using DSeString = Dalamud.Game.Text.SeStringHandling.SeString; -using LSeString = Lumina.Text.SeString; namespace Dalamud.Game.Text.Evaluator; @@ -71,9 +70,6 @@ public readonly struct SeStringParameter public static implicit operator SeStringParameter(ReadOnlySeStringSpan value) => new(new ReadOnlySeString(value)); - [Obsolete("Switch to using ReadOnlySeString instead of Lumina's SeString.", true)] - public static implicit operator SeStringParameter(LSeString value) => new(new ReadOnlySeString(value.RawData)); - public static implicit operator SeStringParameter(DSeString value) => new(new ReadOnlySeString(value.Encode())); public static implicit operator SeStringParameter(string value) => new(value); diff --git a/Dalamud/Game/Text/Noun/NounParams.cs b/Dalamud/Game/Text/Noun/NounParams.cs index 3d5c424be..ab7a732d2 100644 --- a/Dalamud/Game/Text/Noun/NounParams.cs +++ b/Dalamud/Game/Text/Noun/NounParams.cs @@ -60,8 +60,8 @@ internal record struct NounParams() /// public readonly int ColumnOffset => this.SheetName switch { - // See "E8 ?? ?? ?? ?? 44 8B 6B 08" - nameof(LSheets.BeastTribe) => 10, + // See "E8 ?? ?? ?? ?? 44 8B 66 ?? 8B E8" + nameof(LSheets.BeastTribe) => 11, nameof(LSheets.DeepDungeonItem) => 1, nameof(LSheets.DeepDungeonEquipment) => 1, nameof(LSheets.DeepDungeonMagicStone) => 1, diff --git a/Dalamud/Game/Text/SeStringHandling/SeString.cs b/Dalamud/Game/Text/SeStringHandling/SeString.cs index 8805c2177..a1ef5e936 100644 --- a/Dalamud/Game/Text/SeStringHandling/SeString.cs +++ b/Dalamud/Game/Text/SeStringHandling/SeString.cs @@ -113,14 +113,6 @@ public class SeString /// Equivalent SeString. public static implicit operator SeString(string str) => new(new TextPayload(str)); - /// - /// Implicitly convert a string into a SeString containing a . - /// - /// string to convert. - /// Equivalent SeString. - [Obsolete("Switch to using ReadOnlySeString instead of Lumina's SeString.", true)] - public static explicit operator SeString(Lumina.Text.SeString str) => str.ToDalamudString(); - /// /// Parse a binary game message into an SeString. /// diff --git a/Dalamud/Hooking/Hook.cs b/Dalamud/Hooking/Hook.cs index faf4658a5..1cd3ef91d 100644 --- a/Dalamud/Hooking/Hook.cs +++ b/Dalamud/Hooking/Hook.cs @@ -201,19 +201,19 @@ public abstract class Hook : IDalamudHook where T : Delegate if (EnvironmentConfiguration.DalamudForceMinHook) useMinHook = true; - using var moduleHandle = Windows.Win32.PInvoke.GetModuleHandle(moduleName); - if (moduleHandle.IsInvalid) + var moduleHandle = Windows.Win32.PInvoke.GetModuleHandle(moduleName); + if (moduleHandle.IsNull) throw new Exception($"Could not get a handle to module {moduleName}"); - var procAddress = (nint)Windows.Win32.PInvoke.GetProcAddress(moduleHandle, exportName); - if (procAddress == IntPtr.Zero) + var procAddress = Windows.Win32.PInvoke.GetProcAddress(moduleHandle, exportName); + if (procAddress.IsNull) throw new Exception($"Could not get the address of {moduleName}::{exportName}"); - procAddress = HookManager.FollowJmp(procAddress); + var address = HookManager.FollowJmp(procAddress.Value); if (useMinHook) - return new MinHookHook(procAddress, detour, Assembly.GetCallingAssembly()); + return new MinHookHook(address, detour, Assembly.GetCallingAssembly()); else - return new ReloadedHook(procAddress, detour, Assembly.GetCallingAssembly()); + return new ReloadedHook(address, detour, Assembly.GetCallingAssembly()); } /// diff --git a/Dalamud/Interface/FontAwesome/FontAwesomeIcon.cs b/Dalamud/Interface/FontAwesome/FontAwesomeIcon.cs index f88d7f8f0..35df9cfbc 100644 --- a/Dalamud/Interface/FontAwesome/FontAwesomeIcon.cs +++ b/Dalamud/Interface/FontAwesome/FontAwesomeIcon.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // Generated by Dalamud.FASharpGen - don't modify this file directly. -// Font-Awesome Version: 6.4.2 +// Font-Awesome Version: 7.1.0 // //------------------------------------------------------------------------------ @@ -29,14 +29,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "address-book" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "address book", "contact", "directory", "index", "little black book", "rolodex" })] + [FontAwesomeSearchTerms(new[] { "address book", "contact", "directory", "employee", "index", "little black book", "portfolio", "rolodex", "uer", "username" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Communication", "Users + People" })] AddressBook = 0xF2B9, /// /// The Font Awesome "address-card" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "address card", "about", "contact", "id", "identification", "postcard", "profile", "registration" })] + [FontAwesomeSearchTerms(new[] { "address card", "about", "contact", "employee", "id", "identification", "portfolio", "postcard", "profile", "registration", "uer", "username" })] [FontAwesomeCategoriesAttribute(new[] { "Accessibility", "Alphabet", "Business", "Communication", "Users + People" })] AddressCard = 0xF2BB, @@ -54,6 +54,13 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Automotive" })] AirFreshener = 0xF5D0, + /// + /// The Font Awesome "alarm-clock" icon unicode character. + /// + [FontAwesomeSearchTerms(new[] { "alarm clock", "alarm", "alarm clock", "clock", "date", "late", "pending", "reminder", "sleep", "snooze", "timer", "timestamp", "watch" })] + [FontAwesomeCategoriesAttribute(new[] { "Alert", "Time", "Travel + Hotel" })] + AlarmClock = 0xF34E, + /// /// The Font Awesome "align-center" icon unicode character. /// @@ -113,28 +120,28 @@ public enum FontAwesomeIcon /// /// The Font Awesome "anchor-circle-check" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "anchor circle check", "marina", "not affected", "ok", "okay", "port" })] + [FontAwesomeSearchTerms(new[] { "anchor circle check", "enable", "marina", "not affected", "ok", "okay", "port", "validate", "working" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Logistics", "Maritime" })] AnchorCircleCheck = 0xE4AA, /// /// The Font Awesome "anchor-circle-exclamation" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "anchor circle exclamation", "affected", "marina", "port" })] + [FontAwesomeSearchTerms(new[] { "anchor circle exclamation", "affected", "failed", "marina", "port" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Logistics", "Maritime" })] AnchorCircleExclamation = 0xE4AB, /// /// The Font Awesome "anchor-circle-xmark" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "anchor circle xmark", "destroy", "marina", "port" })] + [FontAwesomeSearchTerms(new[] { "anchor circle xmark", "destroy", "marina", "port", "uncheck" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Logistics", "Maritime" })] AnchorCircleXmark = 0xE4AC, /// /// The Font Awesome "anchor-lock" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "anchor lock", "closed", "lockdown", "marina", "port", "quarantine" })] + [FontAwesomeSearchTerms(new[] { "anchor lock", "closed", "lockdown", "marina", "padlock", "port", "privacy", "quarantine" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Logistics", "Maritime" })] AnchorLock = 0xE4AD, @@ -169,7 +176,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "angle-down" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "angle down", "down arrowhead", "arrow", "caret", "download", "expand" })] + [FontAwesomeSearchTerms(new[] { "angle down", "down arrowhead", "arrow", "caret", "download", "expand", "insert" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows" })] AngleDown = 0xF107, @@ -190,7 +197,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "angle-up" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "angle up", "up arrowhead", "arrow", "caret", "collapse", "upload" })] + [FontAwesomeSearchTerms(new[] { "angle up", "up arrowhead", "arrow", "caret", "collapse", "upgrade", "upload" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows" })] AngleUp = 0xF106, @@ -253,7 +260,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "circle-up" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "circle up", "arrow-circle-o-up" })] + [FontAwesomeSearchTerms(new[] { "circle up", "arrow-circle-o-up", "upgrade" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows" })] ArrowAltCircleUp = 0xF35B, @@ -281,7 +288,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "circle-arrow-up" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "circle arrow up", "upload" })] + [FontAwesomeSearchTerms(new[] { "circle arrow up", "upgrade", "upload" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows" })] ArrowCircleUp = 0xF0AA, @@ -309,7 +316,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "arrow-down-up-lock" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "arrow down up lock", "border", "closed", "crossing", "lockdown", "quarantine", "transfer" })] + [FontAwesomeSearchTerms(new[] { "arrow down up lock", "border", "closed", "crossing", "lockdown", "padlock", "privacy", "quarantine", "transfer" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Humanitarian" })] ArrowDownUpLock = 0xE4B0, @@ -337,7 +344,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "arrow-right-arrow-left" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "arrow right arrow left", "rightwards arrow over leftwards arrow", "arrow", "arrows", "reciprocate", "return", "swap", "transfer" })] + [FontAwesomeSearchTerms(new[] { "arrow right arrow left", "arrow", "arrows", "reciprocate", "return", "swap", "transfer" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows" })] ArrowRightArrowLeft = 0xF0EC, @@ -358,14 +365,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "arrow-right-to-bracket" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "arrow right to bracket", "arrow", "enter", "join", "log in", "login", "sign in", "sign up", "sign-in", "signin", "signup" })] + [FontAwesomeSearchTerms(new[] { "arrow right to bracket", "arrow", "enter", "insert", "join", "log in", "login", "sign in", "sign up", "sign-in", "signin", "signup" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows" })] ArrowRightToBracket = 0xF090, /// /// The Font Awesome "arrow-right-to-city" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "arrow right to city", "building", "city", "exodus", "rural", "urban" })] + [FontAwesomeSearchTerms(new[] { "arrow right to city", "building", "city", "exodus", "insert", "rural", "urban" })] [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Humanitarian" })] ArrowRightToCity = 0xE4B3, @@ -393,14 +400,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "arrows-down-to-line" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "arrows down to line", "scale down", "sink" })] + [FontAwesomeSearchTerms(new[] { "arrows down to line", "insert", "scale down", "sink" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Humanitarian" })] ArrowsDownToLine = 0xE4B8, /// /// The Font Awesome "arrows-down-to-people" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "arrows down to people", "affected", "focus", "targeted" })] + [FontAwesomeSearchTerms(new[] { "arrows down to people", "affected", "focus", "insert", "targeted", "together", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Users + People" })] ArrowsDownToPeople = 0xE4B9, @@ -435,14 +442,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "arrows-to-circle" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "arrows to circle", "center", "concentrate", "coordinate", "coordination", "focal point", "focus" })] + [FontAwesomeSearchTerms(new[] { "arrows to circle", "center", "concentrate", "coordinate", "coordination", "focal point", "focus", "insert" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Humanitarian" })] ArrowsToCircle = 0xE4BD, /// /// The Font Awesome "arrows-to-dot" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "arrows to dot", "assembly point", "center", "condense", "focus", "minimize" })] + [FontAwesomeSearchTerms(new[] { "arrows to dot", "assembly point", "center", "condense", "focus", "insert", "minimize" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Business", "Humanitarian", "Marketing" })] ArrowsToDot = 0xE4BE, @@ -463,7 +470,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "arrows-turn-to-dots" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "arrows turn to dots", "destination", "nexus" })] + [FontAwesomeSearchTerms(new[] { "arrows turn to dots", "destination", "insert", "nexus" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Humanitarian" })] ArrowsTurnToDots = 0xE4C1, @@ -484,7 +491,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "arrows-up-to-line" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "arrows up to line", "rise", "scale up" })] + [FontAwesomeSearchTerms(new[] { "arrows up to line", "rise", "scale up", "upgrade" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Humanitarian" })] ArrowsUpToLine = 0xE4C2, @@ -519,28 +526,28 @@ public enum FontAwesomeIcon /// /// The Font Awesome "arrow-up" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "arrow up", "upwards arrow", "forward", "upload" })] + [FontAwesomeSearchTerms(new[] { "arrow up", "upwards arrow", "forward", "upgrade", "upload" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows" })] ArrowUp = 0xF062, /// /// The Font Awesome "arrow-up-from-bracket" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "arrow up from bracket", "share", "transfer", "upload" })] + [FontAwesomeSearchTerms(new[] { "arrow up from bracket", "share", "transfer", "upgrade", "upload" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows" })] ArrowUpFromBracket = 0xE09A, /// /// The Font Awesome "arrow-up-from-ground-water" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "arrow up from ground water", "groundwater", "spring", "water supply", "water table" })] + [FontAwesomeSearchTerms(new[] { "arrow up from ground water", "groundwater", "spring", "upgrade", "water supply", "water table" })] [FontAwesomeCategoriesAttribute(new[] { "Construction", "Energy", "Humanitarian" })] ArrowUpFromGroundWater = 0xE4B5, /// /// The Font Awesome "arrow-up-from-water-pump" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "arrow up from water pump", "flood", "groundwater", "pump", "submersible", "sump pump" })] + [FontAwesomeSearchTerms(new[] { "arrow up from water pump", "flood", "groundwater", "pump", "submersible", "sump pump", "upgrade" })] [FontAwesomeCategoriesAttribute(new[] { "Household", "Humanitarian" })] ArrowUpFromWaterPump = 0xE4B6, @@ -554,14 +561,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "arrow-up-right-dots" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "arrow up right dots", "growth", "increase", "population" })] + [FontAwesomeSearchTerms(new[] { "arrow up right dots", "growth", "increase", "population", "upgrade" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Humanitarian" })] ArrowUpRightDots = 0xE4B7, /// /// The Font Awesome "arrow-up-right-from-square" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "arrow up right from square", "new", "open", "send", "share" })] + [FontAwesomeSearchTerms(new[] { "arrow up right from square", "new", "open", "send", "share", "upgrade" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Humanitarian" })] ArrowUpRightFromSquare = 0xF08E, @@ -576,7 +583,7 @@ public enum FontAwesomeIcon /// The Font Awesome "asterisk" icon unicode character. /// Uses a legacy unicode value for backwards compatability. The current unicode value is 0x2A. /// - [FontAwesomeSearchTerms(new[] { "asterisk", "asterisk", "heavy asterisk", "annotation", "details", "reference", "star" })] + [FontAwesomeSearchTerms(new[] { "asterisk", "asterisk", "heavy asterisk", "annotation", "details", "reference", "required", "star" })] [FontAwesomeCategoriesAttribute(new[] { "Punctuation + Symbols", "Spinners" })] Asterisk = 0xF069, @@ -591,14 +598,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "book-atlas" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "book atlas", "book", "directions", "geography", "globe", "library", "map", "research", "travel", "wayfinding" })] + [FontAwesomeSearchTerms(new[] { "book atlas", "book", "directions", "geography", "globe", "knowledge", "library", "map", "research", "travel", "wayfinding" })] [FontAwesomeCategoriesAttribute(new[] { "Maps", "Travel + Hotel" })] Atlas = 0xF558, /// /// The Font Awesome "atom" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "atheism", "atheist", "atom", "atom symbol", "chemistry", "electron", "ion", "isotope", "neutron", "nuclear", "proton", "science" })] + [FontAwesomeSearchTerms(new[] { "atheism", "atheist", "atom", "atom symbol", "chemistry", "electron", "ion", "isotope", "knowledge", "neutron", "nuclear", "proton", "science" })] [FontAwesomeCategoriesAttribute(new[] { "Education", "Energy", "Religion", "Science", "Science Fiction", "Spinners" })] Atom = 0xF5D2, @@ -619,14 +626,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "award" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "award", "honor", "praise", "prize", "recognition", "ribbon", "trophy" })] + [FontAwesomeSearchTerms(new[] { "award", "guarantee", "honor", "praise", "prize", "recognition", "ribbon", "trophy", "warranty" })] [FontAwesomeCategoriesAttribute(new[] { "Education", "Political" })] Award = 0xF559, /// /// The Font Awesome "baby" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "baby", "users-people" })] + [FontAwesomeSearchTerms(new[] { "baby", "uer", "users-people" })] [FontAwesomeCategoriesAttribute(new[] { "Childhood", "Humanitarian", "Users + People" })] Baby = 0xF77C, @@ -668,7 +675,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "bacterium" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "bacterium", "antibiotic", "antibody", "covid-19", "health", "organism", "sick" })] + [FontAwesomeSearchTerms(new[] { "bacterium", "antibiotic", "antibody", "covid-19", "germ", "health", "organism", "sick" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Medical + Health" })] Bacterium = 0xE05A, @@ -710,14 +717,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "ban" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "abort", "ban", "block", "cancel", "delete", "entry", "forbidden", "hide", "no", "not", "prohibit", "prohibited", "remove", "stop", "trash" })] + [FontAwesomeSearchTerms(new[] { "404", "abort", "ban", "block", "cancel", "circle", "delete", "deny", "disabled", "entry", "failed", "forbidden", "hide", "no", "not", "not found", "prohibit", "prohibited", "remove", "slash", "stop", "trash" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Security" })] Ban = 0xF05E, /// /// The Font Awesome "bandage" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "adhesive bandage", "bandage", "boo boo", "first aid", "ouch" })] + [FontAwesomeSearchTerms(new[] { "adhesive bandage", "bandage", "boo boo", "first aid", "modify", "ouch" })] [FontAwesomeCategoriesAttribute(new[] { "Editing", "Medical + Health" })] BandAid = 0xF462, @@ -815,7 +822,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "bed" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "bed", "hospital", "hotel", "lodging", "mattress", "patient", "person in bed", "rest", "sleep", "travel" })] + [FontAwesomeSearchTerms(new[] { "bed", "hospital", "hotel", "lodging", "mattress", "patient", "person in bed", "rest", "sleep", "travel", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Household", "Humanitarian", "Maps", "Travel + Hotel", "Users + People" })] Bed = 0xF236, @@ -829,7 +836,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "bell" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "alarm", "alert", "bel", "bell", "chime", "notification", "reminder" })] + [FontAwesomeSearchTerms(new[] { "alarm", "alert", "bel", "bell", "chime", "notification", "reminder", "request" })] [FontAwesomeCategoriesAttribute(new[] { "Alert", "Education", "Household", "Maps", "Shopping", "Social", "Time" })] Bell = 0xF0F3, @@ -864,14 +871,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "person-biking" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person biking", "bicycle", "bike", "biking", "cyclist", "pedal", "person biking", "summer", "wheel" })] + [FontAwesomeSearchTerms(new[] { "person biking", "bicycle", "bike", "biking", "cyclist", "pedal", "person biking", "summer", "uer", "wheel" })] [FontAwesomeCategoriesAttribute(new[] { "Childhood", "Sports + Fitness", "Users + People" })] Biking = 0xF84A, /// /// The Font Awesome "binoculars" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "binoculars", "glasses", "magnify", "scenic", "spyglass", "view" })] + [FontAwesomeSearchTerms(new[] { "binoculars", "glasses", "inspection", "magnifier", "magnify", "scenic", "spyglass", "view" })] [FontAwesomeCategoriesAttribute(new[] { "Astronomy", "Camping", "Maps", "Nature" })] Binoculars = 0xF1E5, @@ -913,7 +920,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "person-walking-with-cane" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person walking with cane", "blind", "cane" })] + [FontAwesomeSearchTerms(new[] { "person walking with cane", "blind", "cane", "follow", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Accessibility", "Maps", "Users + People" })] Blind = 0xF29D, @@ -969,14 +976,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "book" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "book", "cover", "decorated", "diary", "documentation", "journal", "library", "notebook", "notebook with decorative cover", "read", "research" })] + [FontAwesomeSearchTerms(new[] { "book", "cover", "decorated", "diary", "documentation", "journal", "knowledge", "library", "notebook", "notebook with decorative cover", "read", "research", "scholar" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Maps", "Writing" })] Book = 0xF02D, /// /// The Font Awesome "book-bookmark" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "book bookmark", "library", "research" })] + [FontAwesomeSearchTerms(new[] { "book bookmark", "knowledge", "library", "research" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Writing" })] BookBookmark = 0xE0BB, @@ -1004,7 +1011,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "book-open" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "book open", "book", "book", "flyer", "library", "notebook", "open", "open book", "pamphlet", "reading", "research" })] + [FontAwesomeSearchTerms(new[] { "book open", "book", "book", "flyer", "knowledge", "library", "notebook", "open", "open book", "pamphlet", "reading", "research" })] [FontAwesomeCategoriesAttribute(new[] { "Education" })] BookOpen = 0xF518, @@ -1130,7 +1137,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "brain" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "brain", "cerebellum", "gray matter", "intellect", "intelligent", "medulla oblongata", "mind", "noodle", "wit" })] + [FontAwesomeSearchTerms(new[] { "brain", "cerebellum", "gray matter", "intellect", "intelligent", "knowledge", "medulla oblongata", "mind", "noodle", "scholar", "wit" })] [FontAwesomeCategoriesAttribute(new[] { "Medical + Health", "Science" })] Brain = 0xF5DC, @@ -1158,28 +1165,28 @@ public enum FontAwesomeIcon /// /// The Font Awesome "bridge-circle-check" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "bridge circle check", "bridge", "not affected", "ok", "okay", "road" })] + [FontAwesomeSearchTerms(new[] { "bridge circle check", "bridge", "enable", "not affected", "ok", "okay", "road", "validate", "working" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Logistics" })] BridgeCircleCheck = 0xE4C9, /// /// The Font Awesome "bridge-circle-exclamation" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "bridge circle exclamation", "affected", "bridge", "road" })] + [FontAwesomeSearchTerms(new[] { "bridge circle exclamation", "affected", "bridge", "failed", "road" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Logistics" })] BridgeCircleExclamation = 0xE4CA, /// /// The Font Awesome "bridge-circle-xmark" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "bridge circle xmark", "bridge", "destroy", "road" })] + [FontAwesomeSearchTerms(new[] { "bridge circle xmark", "bridge", "destroy", "road", "uncheck" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Logistics" })] BridgeCircleXmark = 0xE4CB, /// /// The Font Awesome "bridge-lock" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "bridge lock", "bridge", "closed", "lockdown", "quarantine", "road" })] + [FontAwesomeSearchTerms(new[] { "bridge lock", "bridge", "closed", "lockdown", "padlock", "privacy", "quarantine", "road" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Logistics" })] BridgeLock = 0xE4CC, @@ -1193,7 +1200,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "briefcase" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "bag", "briefcas", "briefcase", "business", "luggage", "office", "work" })] + [FontAwesomeSearchTerms(new[] { "bag", "briefcas", "briefcase", "business", "luggage", "offer", "office", "portfolio", "work" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Maps", "Travel + Hotel" })] Briefcase = 0xF0B1, @@ -1207,7 +1214,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "tower-broadcast" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "tower broadcast", "airwaves", "antenna", "communication", "emergency", "radio", "reception", "waves" })] + [FontAwesomeSearchTerms(new[] { "tower broadcast", "airwaves", "antenna", "communication", "emergency", "radio", "reception", "signal", "waves" })] [FontAwesomeCategoriesAttribute(new[] { "Connectivity", "Energy", "Film + Video", "Humanitarian" })] BroadcastTower = 0xF519, @@ -1221,7 +1228,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "brush" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "brush", "art", "bristles", "color", "handle", "paint" })] + [FontAwesomeSearchTerms(new[] { "brush", "art", "bristles", "color", "handle", "maintenance", "modify", "paint" })] [FontAwesomeCategoriesAttribute(new[] { "Construction", "Design", "Editing" })] Brush = 0xF55D, @@ -1249,7 +1256,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "bug-slash" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "bug slash", "beetle", "fix", "glitch", "insect", "optimize", "repair", "report", "warning" })] + [FontAwesomeSearchTerms(new[] { "bug slash", "beetle", "disabled", "fix", "glitch", "insect", "optimize", "repair", "report", "warning" })] [FontAwesomeCategoriesAttribute(new[] { "Coding", "Security" })] BugSlash = 0xE490, @@ -1270,42 +1277,42 @@ public enum FontAwesomeIcon /// /// The Font Awesome "building-circle-check" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "building circle check", "building", "city", "not affected", "office", "ok", "okay" })] + [FontAwesomeSearchTerms(new[] { "building circle check", "building", "city", "enable", "not affected", "office", "ok", "okay", "validate", "working" })] [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Humanitarian" })] BuildingCircleCheck = 0xE4D2, /// /// The Font Awesome "building-circle-exclamation" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "building circle exclamation", "affected", "building", "city", "office" })] + [FontAwesomeSearchTerms(new[] { "building circle exclamation", "affected", "building", "city", "failed", "office" })] [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Humanitarian" })] BuildingCircleExclamation = 0xE4D3, /// /// The Font Awesome "building-circle-xmark" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "building circle xmark", "building", "city", "destroy", "office" })] + [FontAwesomeSearchTerms(new[] { "building circle xmark", "building", "city", "destroy", "office", "uncheck" })] [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Humanitarian" })] BuildingCircleXmark = 0xE4D4, /// /// The Font Awesome "building-flag" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "building flag", " city", "building", "diplomat", "embassy", "flag", "headquarters", "united nations" })] + [FontAwesomeSearchTerms(new[] { "building flag", "building", "city", "diplomat", "embassy", "flag", "headquarters", "united nations" })] [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Humanitarian", "Political" })] BuildingFlag = 0xE4D5, /// /// The Font Awesome "building-lock" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "building lock", "building", "city", "closed", "lock", "lockdown", "quarantine", "secure" })] + [FontAwesomeSearchTerms(new[] { "building lock", "building", "city", "closed", "lock", "lockdown", "padlock", "privacy", "quarantine", "secure" })] [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Humanitarian", "Security" })] BuildingLock = 0xE4D6, /// /// The Font Awesome "building-ngo" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "building ngo", " city", "building", "non governmental organization", "office" })] + [FontAwesomeSearchTerms(new[] { "building ngo", "building", "city", "non governmental organization", "office" })] [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Humanitarian" })] BuildingNgo = 0xE4D7, @@ -1326,7 +1333,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "building-user" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "building user", "apartment", "building", "city" })] + [FontAwesomeSearchTerms(new[] { "building user", "apartment", "building", "city", "employee", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Humanitarian" })] BuildingUser = 0xE4DA, @@ -1340,7 +1347,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "bullhorn" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "bullhorn", "bullhorn", "announcement", "broadcast", "loud", "louder", "loudspeaker", "megaphone", "public address", "share" })] + [FontAwesomeSearchTerms(new[] { "bullhorn", "bullhorn", "announcement", "broadcast", "loud", "louder", "loudspeaker", "megaphone", "public address", "request", "share" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Communication", "Marketing", "Political", "Shopping" })] Bullhorn = 0xF0A1, @@ -1382,10 +1389,17 @@ public enum FontAwesomeIcon /// /// The Font Awesome "business-time" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "business time", "alarm", "briefcase", "business socks", "clock", "flight of the conchords", "reminder", "wednesday" })] + [FontAwesomeSearchTerms(new[] { "business time", "alarm", "briefcase", "business socks", "clock", "flight of the conchords", "portfolio", "reminder", "wednesday" })] [FontAwesomeCategoriesAttribute(new[] { "Business" })] BusinessTime = 0xF64A, + /// + /// The Font Awesome "bus-side" icon unicode character. + /// + [FontAwesomeSearchTerms(new[] { "bus side", "bus", "public transportation", "transportation", "travel", "vehicle" })] + [FontAwesomeCategoriesAttribute(new[] { "Automotive", "Humanitarian", "Logistics", "Transportation", "Travel + Hotel" })] + BusSide = 0xE81D, + /// /// The Font Awesome "calculator" icon unicode character. /// @@ -1410,7 +1424,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "calendar-check" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "calendar check", "accept", "agree", "appointment", "confirm", "correct", "date", "day", "done", "event", "month", "ok", "schedule", "select", "success", "tick", "time", "todo", "when", "year" })] + [FontAwesomeSearchTerms(new[] { "calendar check", "accept", "agree", "appointment", "confirm", "correct", "date", "day", "done", "enable", "event", "month", "ok", "schedule", "select", "success", "tick", "time", "todo", "validate", "warranty", "when", "working", "year" })] [FontAwesomeCategoriesAttribute(new[] { "Time" })] CalendarCheck = 0xF274, @@ -1438,7 +1452,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "calendar-xmark" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "calendar xmark", "archive", "calendar", "date", "day", "delete", "event", "month", "remove", "schedule", "time", "when", "x", "year" })] + [FontAwesomeSearchTerms(new[] { "calendar xmark", "archive", "calendar", "date", "day", "delete", "event", "month", "remove", "schedule", "time", "uncheck", "when", "x", "year" })] [FontAwesomeCategoriesAttribute(new[] { "Time" })] CalendarTimes = 0xF273, @@ -1452,21 +1466,21 @@ public enum FontAwesomeIcon /// /// The Font Awesome "camera" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "camera", "image", "lens", "photo", "picture", "record", "shutter", "video" })] + [FontAwesomeSearchTerms(new[] { "camera", "image", "img", "lens", "photo", "picture", "record", "shutter", "video" })] [FontAwesomeCategoriesAttribute(new[] { "Devices + Hardware", "Photos + Images", "Shopping", "Social" })] Camera = 0xF030, /// /// The Font Awesome "camera-retro" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "camera retro", "camera", "image", "lens", "photo", "picture", "record", "shutter", "video" })] + [FontAwesomeSearchTerms(new[] { "camera retro", "camera", "image", "img", "lens", "photo", "picture", "record", "shutter", "video" })] [FontAwesomeCategoriesAttribute(new[] { "Devices + Hardware", "Photos + Images", "Shopping" })] CameraRetro = 0xF083, /// /// The Font Awesome "camera-rotate" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "camera rotate", "flip", "front-facing", "photo", "selfie" })] + [FontAwesomeSearchTerms(new[] { "camera rotate", "flip", "front-facing", "img", "photo", "selfie" })] [FontAwesomeCategoriesAttribute(new[] { "Photos + Images" })] CameraRotate = 0xE0D8, @@ -1557,7 +1571,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "square-caret-down" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "square caret down", "arrow", "caret-square-o-down", "dropdown", "expand", "menu", "more", "triangle" })] + [FontAwesomeSearchTerms(new[] { "square caret down", "arrow", "caret-square-o-down", "dropdown", "expand", "insert", "menu", "more", "triangle" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows" })] CaretSquareDown = 0xF150, @@ -1578,14 +1592,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "square-caret-up" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "square caret up", "arrow", "caret-square-o-up", "collapse", "triangle", "upload" })] + [FontAwesomeSearchTerms(new[] { "square caret up", "arrow", "caret-square-o-up", "collapse", "triangle", "upgrade", "upload" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows" })] CaretSquareUp = 0xF151, /// /// The Font Awesome "caret-up" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "caret up", "arrow", "collapse", "triangle" })] + [FontAwesomeSearchTerms(new[] { "caret up", "arrow", "collapse", "triangle", "upgrade" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows" })] CaretUp = 0xF0D8, @@ -1613,7 +1627,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "cart-arrow-down" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "cart arrow down", "download", "save", "shopping" })] + [FontAwesomeSearchTerms(new[] { "cart arrow down", "download", "insert", "save", "shopping" })] [FontAwesomeCategoriesAttribute(new[] { "Shopping" })] CartArrowDown = 0xF218, @@ -1662,7 +1676,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "certificate" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "certificate", "badge", "star", "verified" })] + [FontAwesomeSearchTerms(new[] { "certificate", "badge", "guarantee", "star", "verified" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Shapes", "Shopping", "Spinners" })] Certificate = 0xF0A3, @@ -1683,91 +1697,98 @@ public enum FontAwesomeIcon /// /// The Font Awesome "chalkboard-user" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "chalkboard user", "blackboard", "instructor", "learning", "professor", "school", "whiteboard", "writing" })] + [FontAwesomeSearchTerms(new[] { "chalkboard user", "blackboard", "instructor", "learning", "professor", "school", "uer", "whiteboard", "writing" })] [FontAwesomeCategoriesAttribute(new[] { "Education", "Users + People" })] ChalkboardTeacher = 0xF51C, /// /// The Font Awesome "charging-station" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "charging station", "electric", "ev", "tesla", "vehicle" })] + [FontAwesomeSearchTerms(new[] { "charging station", "car charger", "charge", "charging", "electric", "ev", "tesla", "vehicle" })] [FontAwesomeCategoriesAttribute(new[] { "Automotive", "Energy" })] ChargingStation = 0xF5E7, /// /// The Font Awesome "chart-area" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "chart area", "analytics", "area", "chart", "graph" })] + [FontAwesomeSearchTerms(new[] { "chart area", "analytics", "area", "chart", "graph", "performance", "revenue", "statistics" })] [FontAwesomeCategoriesAttribute(new[] { "Charts + Diagrams" })] ChartArea = 0xF1FE, /// /// The Font Awesome "chart-bar" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "chart bar", "analytics", "bar", "chart", "graph" })] + [FontAwesomeSearchTerms(new[] { "chart bar", "analytics", "bar", "chart", "graph", "performance", "statistics" })] [FontAwesomeCategoriesAttribute(new[] { "Charts + Diagrams" })] ChartBar = 0xF080, /// /// The Font Awesome "chart-column" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "chart column", "bar", "bar chart", "chart", "graph", "track", "trend" })] + [FontAwesomeSearchTerms(new[] { "chart column", "bar", "bar chart", "chart", "graph", "performance", "revenue", "statistics", "track", "trend" })] [FontAwesomeCategoriesAttribute(new[] { "Charts + Diagrams" })] ChartColumn = 0xE0E3, + /// + /// The Font Awesome "chart-diagram" icon unicode character. + /// + [FontAwesomeSearchTerms(new[] { "chart diagram", "algorithm", "analytics", "flow", "graph" })] + [FontAwesomeCategoriesAttribute(new[] { "Charts + Diagrams", "Coding" })] + ChartDiagram = 0xE695, + /// /// The Font Awesome "chart-gantt" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "chart gantt", "chart", "graph", "track", "trend" })] + [FontAwesomeSearchTerms(new[] { "chart gantt", "chart", "graph", "performance", "statistics", "track", "trend" })] [FontAwesomeCategoriesAttribute(new[] { "Charts + Diagrams" })] ChartGantt = 0xE0E4, /// /// The Font Awesome "chart-line" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "chart line", "activity", "analytics", "chart", "dashboard", "gain", "graph", "increase", "line" })] + [FontAwesomeSearchTerms(new[] { "chart line", "activity", "analytics", "chart", "dashboard", "gain", "graph", "increase", "line", "performance", "revenue", "statistics" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Charts + Diagrams", "Money" })] ChartLine = 0xF201, /// /// The Font Awesome "chart-pie" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "chart pie", "analytics", "chart", "diagram", "graph", "pie" })] + [FontAwesomeSearchTerms(new[] { "chart pie", "analytics", "chart", "diagram", "graph", "performance", "pie", "revenue", "statistics" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Charts + Diagrams", "Money" })] ChartPie = 0xF200, /// /// The Font Awesome "chart-simple" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "chart simple", "analytics", "bar", "chart", "column", "graph", "row", "trend" })] + [FontAwesomeSearchTerms(new[] { "chart simple", "analytics", "bar", "chart", "column", "graph", "performance", "revenue", "row", "statistics", "trend" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Charts + Diagrams", "Editing", "Logistics", "Marketing" })] ChartSimple = 0xE473, /// /// The Font Awesome "check" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "check mark", "accept", "agree", "check", "check mark", "checkmark", "confirm", "correct", "done", "mark", "notice", "notification", "notify", "ok", "select", "success", "tick", "todo", "yes", "✓" })] + [FontAwesomeSearchTerms(new[] { "check mark", "accept", "agree", "check", "check mark", "checkmark", "confirm", "correct", "coupon", "done", "enable", "mark", "notice", "notification", "notify", "ok", "select", "success", "tick", "todo", "true", "validate", "working", "yes", "✓" })] [FontAwesomeCategoriesAttribute(new[] { "Editing", "Punctuation + Symbols", "Text Formatting" })] Check = 0xF00C, /// /// The Font Awesome "circle-check" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "circle check", "accept", "affected", "agree", "clear", "confirm", "correct", "done", "ok", "select", "success", "tick", "todo", "yes" })] + [FontAwesomeSearchTerms(new[] { "circle check", "accept", "affected", "agree", "clear", "confirm", "correct", "coupon", "done", "enable", "ok", "select", "success", "tick", "todo", "validate", "working", "yes" })] [FontAwesomeCategoriesAttribute(new[] { "Editing", "Text Formatting", "Toggle" })] CheckCircle = 0xF058, /// /// The Font Awesome "check-double" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "check double", "accept", "agree", "checkmark", "confirm", "correct", "done", "notice", "notification", "notify", "ok", "select", "success", "tick", "todo" })] + [FontAwesomeSearchTerms(new[] { "check double", "accept", "agree", "checkmark", "confirm", "correct", "coupon", "done", "enable", "notice", "notification", "notify", "ok", "select", "select all", "success", "tick", "todo", "validate", "working" })] [FontAwesomeCategoriesAttribute(new[] { "Editing", "Political", "Punctuation + Symbols", "Text Formatting" })] CheckDouble = 0xF560, /// /// The Font Awesome "square-check" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "square check", "accept", "agree", "box", "button", "check", "check box with check", "check mark button", "checkmark", "confirm", "correct", "done", "mark", "ok", "select", "success", "tick", "todo", "yes", "✓" })] + [FontAwesomeSearchTerms(new[] { "square check", "accept", "agree", "box", "button", "check", "check box with check", "check mark button", "checkmark", "confirm", "correct", "coupon", "done", "enable", "mark", "ok", "select", "success", "tick", "todo", "validate", "working", "yes", "✓" })] [FontAwesomeCategoriesAttribute(new[] { "Editing", "Text Formatting" })] CheckSquare = 0xF14A, @@ -1858,14 +1879,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "circle-chevron-up" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "circle chevron up", "arrow", "collapse", "upload" })] + [FontAwesomeSearchTerms(new[] { "circle chevron up", "arrow", "collapse", "upgrade", "upload" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows" })] ChevronCircleUp = 0xF139, /// /// The Font Awesome "chevron-down" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "chevron down", "arrow", "download", "expand" })] + [FontAwesomeSearchTerms(new[] { "chevron down", "arrow", "download", "expand", "insert" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows" })] ChevronDown = 0xF078, @@ -1886,14 +1907,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "chevron-up" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "chevron up", "arrow", "collapse", "upload" })] + [FontAwesomeSearchTerms(new[] { "chevron up", "arrow", "collapse", "upgrade", "upload" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows" })] ChevronUp = 0xF077, /// /// The Font Awesome "child" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "child", "boy", "girl", "kid", "toddler", "young", "youth" })] + [FontAwesomeSearchTerms(new[] { "child", "boy", "girl", "kid", "toddler", "uer", "young", "youth" })] [FontAwesomeCategoriesAttribute(new[] { "Childhood", "Users + People" })] Child = 0xF1AE, @@ -1907,21 +1928,21 @@ public enum FontAwesomeIcon /// /// The Font Awesome "child-dress" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "child dress", "boy", "girl", "kid", "toddler", "young", "youth" })] + [FontAwesomeSearchTerms(new[] { "child dress", "boy", "girl", "kid", "toddler", "uer", "young", "youth" })] [FontAwesomeCategoriesAttribute(new[] { "Childhood", "Users + People" })] ChildDress = 0xE59C, /// /// The Font Awesome "child-reaching" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "child reaching", "boy", "girl", "kid", "toddler", "young", "youth" })] + [FontAwesomeSearchTerms(new[] { "child reaching", "boy", "girl", "kid", "toddler", "uer", "young", "youth" })] [FontAwesomeCategoriesAttribute(new[] { "Childhood", "Users + People" })] ChildReaching = 0xE59D, /// /// The Font Awesome "children" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "children", "boy", "child", "girl", "kid", "kids", "young", "youth" })] + [FontAwesomeSearchTerms(new[] { "children", "boy", "child", "girl", "kid", "kids", "together", "uer", "young", "youth" })] [FontAwesomeCategoriesAttribute(new[] { "Childhood", "Humanitarian", "Users + People" })] Children = 0xE4E1, @@ -1977,49 +1998,49 @@ public enum FontAwesomeIcon /// /// The Font Awesome "clipboard" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "clipboar", "clipboard", "copy", "notes", "paste", "record" })] + [FontAwesomeSearchTerms(new[] { "clipboard", "copy", "notepad", "notes", "paste", "record" })] [FontAwesomeCategoriesAttribute(new[] { "Business" })] Clipboard = 0xF328, /// /// The Font Awesome "clipboard-check" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "clipboard check", "accept", "agree", "confirm", "done", "ok", "select", "success", "tick", "todo", "yes" })] - [FontAwesomeCategoriesAttribute(new[] { "Logistics", "Science" })] + [FontAwesomeSearchTerms(new[] { "clipboard check", "accept", "agree", "confirm", "coupon", "done", "enable", "ok", "select", "success", "tick", "todo", "validate", "working", "yes" })] + [FontAwesomeCategoriesAttribute(new[] { "Business", "Logistics", "Science" })] ClipboardCheck = 0xF46C, /// /// The Font Awesome "clipboard-list" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "clipboard list", "checklist", "completed", "done", "finished", "intinerary", "ol", "schedule", "tick", "todo", "ul" })] + [FontAwesomeSearchTerms(new[] { "clipboard list", "cheatsheet", "checklist", "completed", "done", "finished", "intinerary", "ol", "schedule", "summary", "survey", "tick", "todo", "ul", "wishlist" })] [FontAwesomeCategoriesAttribute(new[] { "Logistics" })] ClipboardList = 0xF46D, /// /// The Font Awesome "clipboard-question" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "clipboard question", "assistance", "interview", "query", "question" })] + [FontAwesomeSearchTerms(new[] { "clipboard question", "assistance", "faq", "interview", "query", "question" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Humanitarian", "Logistics" })] ClipboardQuestion = 0xE4E3, /// /// The Font Awesome "clipboard-user" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "clipboard user", "attendance", "record", "roster", "staff" })] - [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Medical + Health", "Users + People" })] + [FontAwesomeSearchTerms(new[] { "clipboard user", "attendance", "employee", "record", "roster", "staff", "uer" })] + [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Logistics", "Medical + Health", "Users + People" })] ClipboardUser = 0xF7F3, /// /// The Font Awesome "clock" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "00", "4", "4:00", "clock", "date", "four", "four o’clock", "hour", "late", "minute", "o'clock", "o’clock", "schedule", "ticking", "time", "timer", "timestamp", "watch" })] + [FontAwesomeSearchTerms(new[] { "00", "4", "4:00", "clock", "date", "four", "four o’clock", "hour", "late", "minute", "o'clock", "o’clock", "pending", "schedule", "ticking", "time", "timer", "timestamp", "watch" })] [FontAwesomeCategoriesAttribute(new[] { "Time" })] Clock = 0xF017, /// /// The Font Awesome "clone" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "clone", "arrange", "copy", "duplicate", "paste" })] + [FontAwesomeSearchTerms(new[] { "clone", "add", "arrange", "copy", "duplicate", "new", "paste" })] [FontAwesomeCategoriesAttribute(new[] { "Design", "Files", "Photos + Images" })] Clone = 0xF24D, @@ -2112,7 +2133,7 @@ public enum FontAwesomeIcon /// The Font Awesome "cloud-arrow-up" icon unicode character. /// Uses a legacy unicode value for backwards compatability. The current unicode value is 0xF0EE. /// - [FontAwesomeSearchTerms(new[] { "cloud arrow up", "import", "save", "upload" })] + [FontAwesomeSearchTerms(new[] { "cloud arrow up", "import", "save", "upgrade", "upload" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Connectivity" })] CloudUploadAlt = 0xF382, @@ -2133,14 +2154,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "code" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "brackets", "code", "development", "html" })] + [FontAwesomeSearchTerms(new[] { "brackets", "code", "development", "html", "mysql", "sql" })] [FontAwesomeCategoriesAttribute(new[] { "Coding" })] Code = 0xF121, /// /// The Font Awesome "code-branch" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "code branch", "branch", "git", "github", "rebase", "svn", "vcs", "version" })] + [FontAwesomeSearchTerms(new[] { "code branch", "branch", "git", "github", "mysql", "rebase", "sql", "svn", "vcs", "version" })] [FontAwesomeCategoriesAttribute(new[] { "Coding" })] CodeBranch = 0xF126, @@ -2189,21 +2210,21 @@ public enum FontAwesomeIcon /// /// The Font Awesome "gear" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "cog", "cogwheel", "gear", "mechanical", "settings", "sprocket", "tool", "wheel" })] + [FontAwesomeSearchTerms(new[] { "cog", "cogwheel", "configuration", "gear", "mechanical", "modify", "settings", "sprocket", "tool", "wheel" })] [FontAwesomeCategoriesAttribute(new[] { "Coding", "Editing", "Spinners" })] Cog = 0xF013, /// /// The Font Awesome "gears" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "gears", "mechanical", "settings", "sprocket", "wheel" })] + [FontAwesomeSearchTerms(new[] { "configuration", "gears", "mechanical", "modify", "settings", "sprocket", "wheel" })] [FontAwesomeCategoriesAttribute(new[] { "Coding", "Logistics" })] Cogs = 0xF085, /// /// The Font Awesome "coins" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "coins", "currency", "dime", "financial", "gold", "money", "penny" })] + [FontAwesomeSearchTerms(new[] { "coins", "currency", "dime", "financial", "gold", "money", "penny", "premium" })] [FontAwesomeCategoriesAttribute(new[] { "Money" })] Coins = 0xF51E, @@ -2217,63 +2238,70 @@ public enum FontAwesomeIcon /// /// The Font Awesome "table-columns" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "table columns", "browser", "dashboard", "organize", "panes", "split" })] + [FontAwesomeSearchTerms(new[] { "table columns", "browser", "category", "dashboard", "organize", "panes", "split" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Text Formatting" })] Columns = 0xF0DB, /// /// The Font Awesome "comment" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "comment", "right speech bubble", "bubble", "chat", "commenting", "conversation", "feedback", "message", "note", "notification", "sms", "speech", "texting" })] + [FontAwesomeSearchTerms(new[] { "comment", "right speech bubble", "answer", "bubble", "chat", "commenting", "conversation", "conversation", "discussion", "feedback", "message", "note", "notification", "sms", "speech", "talk", "talking", "texting" })] [FontAwesomeCategoriesAttribute(new[] { "Communication", "Shapes", "Social" })] Comment = 0xF075, /// /// The Font Awesome "message" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "bubble", "chat", "commenting", "conversation", "feedback", "message", "note", "notification", "sms", "speech", "texting" })] + [FontAwesomeSearchTerms(new[] { "answer", "bubble", "chat", "commenting", "conversation", "conversation", "discussion", "feedback", "message", "note", "notification", "sms", "speech", "talk", "talking", "texting" })] [FontAwesomeCategoriesAttribute(new[] { "Communication", "Social" })] CommentAlt = 0xF27A, /// /// The Font Awesome "comment-dollar" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "comment dollar", "bubble", "chat", "commenting", "conversation", "feedback", "message", "money", "note", "notification", "pay", "sms", "speech", "spend", "texting", "transfer" })] + [FontAwesomeSearchTerms(new[] { "comment dollar", "answer", "bubble", "chat", "commenting", "conversation", "feedback", "message", "money", "note", "notification", "pay", "salary", "sms", "speech", "spend", "texting", "transfer" })] [FontAwesomeCategoriesAttribute(new[] { "Marketing", "Money" })] CommentDollar = 0xF651, /// /// The Font Awesome "comment-dots" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "comment dots", "balloon", "bubble", "chat", "comic", "commenting", "conversation", "dialog", "feedback", "message", "more", "note", "notification", "reply", "sms", "speech", "speech balloon", "texting" })] + [FontAwesomeSearchTerms(new[] { "comment dots", "answer", "balloon", "bubble", "chat", "comic", "commenting", "conversation", "dialog", "feedback", "message", "more", "note", "notification", "reply", "request", "sms", "speech", "speech balloon", "texting" })] [FontAwesomeCategoriesAttribute(new[] { "Communication" })] CommentDots = 0xF4AD, /// /// The Font Awesome "comment-medical" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "comment medical", "advice", "bubble", "chat", "commenting", "conversation", "diagnose", "feedback", "message", "note", "notification", "prescription", "sms", "speech", "texting" })] + [FontAwesomeSearchTerms(new[] { "comment medical", "advice", "answer", "bubble", "chat", "commenting", "conversation", "diagnose", "feedback", "message", "note", "notification", "prescription", "sms", "speech", "texting" })] [FontAwesomeCategoriesAttribute(new[] { "Communication", "Medical + Health" })] CommentMedical = 0xF7F5, + /// + /// The Font Awesome "comment-nodes" icon unicode character. + /// + [FontAwesomeSearchTerms(new[] { "comment nodes", "ai", "artificial intelligence", "cluster", "language", "model", "network", "neuronal" })] + [FontAwesomeCategoriesAttribute(new[] { "Coding", "Communication" })] + CommentNodes = 0xE696, + /// /// The Font Awesome "comments" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "comments", "two speech bubbles", "bubble", "chat", "commenting", "conversation", "feedback", "message", "note", "notification", "sms", "speech", "texting" })] + [FontAwesomeSearchTerms(new[] { "comments", "two speech bubbles", "answer", "bubble", "chat", "commenting", "conversation", "conversation", "discussion", "feedback", "message", "note", "notification", "sms", "speech", "talk", "talking", "texting" })] [FontAwesomeCategoriesAttribute(new[] { "Communication" })] Comments = 0xF086, /// /// The Font Awesome "comments-dollar" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "comments dollar", "bubble", "chat", "commenting", "conversation", "feedback", "message", "money", "note", "notification", "pay", "sms", "speech", "spend", "texting", "transfer" })] + [FontAwesomeSearchTerms(new[] { "comments dollar", "answer", "bubble", "chat", "commenting", "conversation", "feedback", "message", "money", "note", "notification", "pay", "salary", "sms", "speech", "spend", "texting", "transfer" })] [FontAwesomeCategoriesAttribute(new[] { "Marketing", "Money" })] CommentsDollar = 0xF653, /// /// The Font Awesome "comment-slash" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "comment slash", "bubble", "cancel", "chat", "commenting", "conversation", "feedback", "message", "mute", "note", "notification", "quiet", "sms", "speech", "texting" })] + [FontAwesomeSearchTerms(new[] { "comment slash", "answer", "bubble", "cancel", "chat", "commenting", "conversation", "disabled", "feedback", "message", "mute", "note", "notification", "quiet", "sms", "speech", "texting" })] [FontAwesomeCategoriesAttribute(new[] { "Communication" })] CommentSlash = 0xF4B3, @@ -2301,7 +2329,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "down-left-and-up-right-to-center" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "down left and up right to center", "collapse", "fullscreen", "minimize", "move", "resize", "shrink", "smaller" })] + [FontAwesomeSearchTerms(new[] { "down left and up right to center", "collapse", "fullscreen", "minimize", "move", "resize", "scale", "shrink", "size", "smaller" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Media Playback" })] CompressAlt = 0xF422, @@ -2322,7 +2350,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "bell-concierge" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "bell concierge", "attention", "bell", "bellhop", "bellhop bell", "hotel", "receptionist", "service", "support" })] + [FontAwesomeSearchTerms(new[] { "bell concierge", "attention", "bell", "bellhop", "bellhop bell", "hotel", "receptionist", "request", "service", "support" })] [FontAwesomeCategoriesAttribute(new[] { "Travel + Hotel" })] ConciergeBell = 0xF562, @@ -2378,14 +2406,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "crop" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "crop", "design", "frame", "mask", "resize", "shrink" })] + [FontAwesomeSearchTerms(new[] { "crop", "design", "frame", "mask", "modify", "resize", "shrink" })] [FontAwesomeCategoriesAttribute(new[] { "Design", "Editing" })] Crop = 0xF125, /// /// The Font Awesome "crop-simple" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "crop simple", "design", "frame", "mask", "resize", "shrink" })] + [FontAwesomeSearchTerms(new[] { "crop simple", "design", "frame", "mask", "modify", "resize", "shrink" })] [FontAwesomeCategoriesAttribute(new[] { "Design", "Editing" })] CropAlt = 0xF565, @@ -2413,7 +2441,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "crown" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "award", "clothing", "crown", "favorite", "king", "queen", "royal", "tiara" })] + [FontAwesomeSearchTerms(new[] { "award", "clothing", "crown", "favorite", "king", "queen", "royal", "tiara", "vip" })] [FontAwesomeCategoriesAttribute(new[] { "Shapes" })] Crown = 0xF521, @@ -2455,14 +2483,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "scissors" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "black safety scissors", "white scissors", "clip", "cutting", "scissors", "snip", "tool" })] + [FontAwesomeSearchTerms(new[] { "black safety scissors", "white scissors", "clip", "cutting", "equipment", "modify", "scissors", "snip", "tool" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Design", "Editing", "Files" })] Cut = 0xF0C4, /// /// The Font Awesome "database" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "database", "computer", "development", "directory", "memory", "storage" })] + [FontAwesomeSearchTerms(new[] { "database", "computer", "development", "directory", "memory", "mysql", "sql", "storage" })] [FontAwesomeCategoriesAttribute(new[] { "Devices + Hardware" })] Database = 0xF1C0, @@ -2470,7 +2498,7 @@ public enum FontAwesomeIcon /// The Font Awesome "ear-deaf" icon unicode character. /// [FontAwesomeSearchTerms(new[] { "ear deaf", "ear", "hearing", "sign language" })] - [FontAwesomeCategoriesAttribute(new[] { "Accessibility" })] + [FontAwesomeCategoriesAttribute(new[] { "Accessibility", "Communication" })] Deaf = 0xF2A4, /// @@ -2498,7 +2526,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "person-dots-from-line" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person dots from line", "allergy", "diagnosis" })] + [FontAwesomeSearchTerms(new[] { "person dots from line", "allergy", "diagnosis", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Medical + Health", "Users + People" })] Diagnoses = 0xF470, @@ -2526,7 +2554,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "diamond" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "diamond", "card", "cards", "diamond suit", "game", "gem", "gemstone", "poker", "suit" })] + [FontAwesomeSearchTerms(new[] { "diamond", "ace", "card", "cards", "diamond suit", "game", "gem", "gemstone", "poker", "suit" })] [FontAwesomeCategoriesAttribute(new[] { "Gaming", "Shapes" })] Diamond = 0xF219, @@ -2653,7 +2681,7 @@ public enum FontAwesomeIcon /// The Font Awesome "dollar-sign" icon unicode character. /// Uses a legacy unicode value for backwards compatability. The current unicode value is 0x24. /// - [FontAwesomeSearchTerms(new[] { "dollar sign", "dollar sign", "currency", "dollar", "heavy dollar sign", "money" })] + [FontAwesomeSearchTerms(new[] { "dollar sign", "dollar sign", "coupon", "currency", "dollar", "heavy dollar sign", "investment", "money", "premium", "revenue", "salary" })] [FontAwesomeCategoriesAttribute(new[] { "Charity", "Maps", "Money" })] DollarSign = 0xF155, @@ -2674,7 +2702,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "circle-dollar-to-slot" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "circle dollar to slot", "contribute", "generosity", "gift", "give" })] + [FontAwesomeSearchTerms(new[] { "circle dollar to slot", "contribute", "generosity", "gift", "give", "premium" })] [FontAwesomeCategoriesAttribute(new[] { "Charity", "Money", "Political" })] Donate = 0xF4B9, @@ -2688,7 +2716,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "door-closed" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "door closed", "doo", "door", "enter", "exit", "locked" })] + [FontAwesomeSearchTerms(new[] { "door closed", "doo", "door", "enter", "exit", "locked", "privacy" })] [FontAwesomeCategoriesAttribute(new[] { "Household", "Security", "Travel + Hotel" })] DoorClosed = 0xF52A, @@ -2716,7 +2744,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "download" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "download", "export", "hard drive", "save", "transfer" })] + [FontAwesomeSearchTerms(new[] { "download", "export", "hard drive", "insert", "save", "transfer" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Devices + Hardware" })] Download = 0xF019, @@ -2765,7 +2793,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "dumbbell" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "dumbbell", "exercise", "gym", "strength", "weight", "weight-lifting" })] + [FontAwesomeSearchTerms(new[] { "dumbbell", "exercise", "gym", "strength", "weight", "weight-lifting", "workout" })] [FontAwesomeCategoriesAttribute(new[] { "Sports + Fitness", "Travel + Hotel" })] Dumbbell = 0xF44B, @@ -2800,7 +2828,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "pen-to-square" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "pen to square", "edit", "pen", "pencil", "update", "write" })] + [FontAwesomeSearchTerms(new[] { "pen to square", "edit", "modify", "pen", "pencil", "update", "write" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Design", "Editing", "Writing" })] Edit = 0xF044, @@ -2821,56 +2849,56 @@ public enum FontAwesomeIcon /// /// The Font Awesome "elevator" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "accessibility", "elevator", "hoist", "lift", "users-people" })] + [FontAwesomeSearchTerms(new[] { "accessibility", "elevator", "hoist", "lift", "uer", "users-people" })] [FontAwesomeCategoriesAttribute(new[] { "Travel + Hotel", "Users + People" })] Elevator = 0xE16D, /// /// The Font Awesome "ellipsis" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "ellipsis", "dots", "drag", "kebab", "list", "menu", "nav", "navigation", "ol", "pacman", "reorder", "settings", "ul" })] + [FontAwesomeSearchTerms(new[] { "ellipsis", "dots", "drag", "kebab", "list", "menu", "nav", "navigation", "ol", "pacman", "reorder", "settings", "three dots", "ul" })] [FontAwesomeCategoriesAttribute(new[] { "Editing" })] EllipsisH = 0xF141, /// /// The Font Awesome "ellipsis-vertical" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "ellipsis vertical", "dots", "drag", "kebab", "list", "menu", "nav", "navigation", "ol", "reorder", "settings", "ul" })] + [FontAwesomeSearchTerms(new[] { "ellipsis vertical", "bullet", "dots", "drag", "kebab", "list", "menu", "nav", "navigation", "ol", "reorder", "settings", "three dots", "ul" })] [FontAwesomeCategoriesAttribute(new[] { "Editing" })] EllipsisV = 0xF142, /// /// The Font Awesome "envelope" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "back of envelope", "e-mail", "email", "envelope", "letter", "mail", "message", "notification", "support" })] + [FontAwesomeSearchTerms(new[] { "back of envelope", "e-mail", "email", "envelope", "letter", "mail", "message", "newsletter", "notification", "offer", "support" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Communication", "Humanitarian", "Social", "Writing" })] Envelope = 0xF0E0, /// /// The Font Awesome "envelope-circle-check" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "envelope circle check", "check", "email", "envelope", "mail", "not affected", "ok", "okay", "read", "sent" })] + [FontAwesomeSearchTerms(new[] { "envelope circle check", "check", "email", "enable", "envelope", "mail", "not affected", "ok", "okay", "read", "sent", "validate", "working" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Communication", "Humanitarian" })] EnvelopeCircleCheck = 0xE4E8, /// /// The Font Awesome "envelope-open" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "envelope open", "e-mail", "email", "letter", "mail", "message", "notification", "support" })] + [FontAwesomeSearchTerms(new[] { "envelope open", "e-mail", "email", "letter", "mail", "message", "newsletter", "notification", "offer", "support" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Communication", "Writing" })] EnvelopeOpen = 0xF2B6, /// /// The Font Awesome "envelope-open-text" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "envelope open text", "e-mail", "email", "letter", "mail", "message", "notification", "support" })] + [FontAwesomeSearchTerms(new[] { "envelope open text", "e-mail", "email", "letter", "mail", "message", "newsletter", "notification", "offer", "support" })] [FontAwesomeCategoriesAttribute(new[] { "Marketing" })] EnvelopeOpenText = 0xF658, /// /// The Font Awesome "square-envelope" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "square envelope", "e-mail", "email", "letter", "mail", "message", "notification", "support" })] + [FontAwesomeSearchTerms(new[] { "square envelope", "e-mail", "email", "letter", "mail", "message", "notification", "offer", "support" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Communication" })] EnvelopeSquare = 0xF199, @@ -2914,42 +2942,42 @@ public enum FontAwesomeIcon /// The Font Awesome "exclamation" icon unicode character. /// Uses a legacy unicode value for backwards compatability. The current unicode value is 0x21. /// - [FontAwesomeSearchTerms(new[] { "!", "exclamation mark", "alert", "danger", "error", "exclamation", "important", "mark", "notice", "notification", "notify", "outlined", "problem", "punctuation", "red exclamation mark", "warning", "white exclamation mark" })] + [FontAwesomeSearchTerms(new[] { "!", "exclamation mark", "alert", "attention", "danger", "error", "exclamation", "failed", "important", "mark", "notice", "notification", "notify", "outlined", "problem", "punctuation", "red exclamation mark", "required", "warning", "white exclamation mark" })] [FontAwesomeCategoriesAttribute(new[] { "Alert", "Punctuation + Symbols" })] Exclamation = 0xF12A, /// /// The Font Awesome "circle-exclamation" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "circle exclamation", "affect", "alert", "damage", "danger", "error", "important", "notice", "notification", "notify", "problem", "warning" })] + [FontAwesomeSearchTerms(new[] { "circle exclamation", "affect", "alert", "attention", "damage", "danger", "error", "failed", "important", "notice", "notification", "notify", "problem", "required", "warning" })] [FontAwesomeCategoriesAttribute(new[] { "Alert", "Punctuation + Symbols" })] ExclamationCircle = 0xF06A, /// /// The Font Awesome "triangle-exclamation" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "triangle exclamation", "alert", "danger", "error", "important", "notice", "notification", "notify", "problem", "warnin", "warning" })] + [FontAwesomeSearchTerms(new[] { "triangle exclamation", "alert", "attention", "danger", "error", "failed", "important", "notice", "notification", "notify", "problem", "required", "warnin", "warning" })] [FontAwesomeCategoriesAttribute(new[] { "Alert" })] ExclamationTriangle = 0xF071, /// /// The Font Awesome "expand" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "expand", "bigger", "crop", "enlarge", "focus", "fullscreen", "resize", "viewfinder" })] + [FontAwesomeSearchTerms(new[] { "arrows", "bigger", "enlarge", "expand", "fullscreen", "maximize", "resize", "resize", "scale", "size", "viewfinder" })] [FontAwesomeCategoriesAttribute(new[] { "Media Playback" })] Expand = 0xF065, /// /// The Font Awesome "up-right-and-down-left-from-center" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "up right and down left from center", "arrows", "bigger", "enlarge", "fullscreen", "resize" })] + [FontAwesomeSearchTerms(new[] { "up right and down left from center", "arrows", "bigger", "enlarge", "expand", "fullscreen", "maximize", "resize", "resize", "scale", "size" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Media Playback" })] ExpandAlt = 0xF424, /// /// The Font Awesome "maximize" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "maximize", "bigger", "enlarge", "fullscreen", "move", "resize" })] + [FontAwesomeSearchTerms(new[] { "arrows", "bigger", "enlarge", "expand", "fullscreen", "maximize", "resize", "resize", "scale", "size" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Media Playback" })] ExpandArrowsAlt = 0xF31E, @@ -2963,7 +2991,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "up-right-from-square" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "up right from square", "external-link", "new", "open", "share" })] + [FontAwesomeSearchTerms(new[] { "up right from square", "external-link", "new", "open", "share", "upgrade" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows" })] ExternalLinkAlt = 0xF35D, @@ -2991,7 +3019,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "eye-slash" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "eye slash", "blind", "hide", "show", "toggle", "unseen", "views", "visible", "visiblity" })] + [FontAwesomeSearchTerms(new[] { "eye slash", "blind", "disabled", "hide", "show", "toggle", "unseen", "views", "visible", "visiblity" })] [FontAwesomeCategoriesAttribute(new[] { "Design", "Editing", "Maps", "Photos + Images", "Security" })] EyeSlash = 0xF070, @@ -3005,14 +3033,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "backward-fast" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "backward fast", "arrow", "beginning", "first", "last track button", "previous", "previous scene", "previous track", "rewind", "start", "triangle" })] + [FontAwesomeSearchTerms(new[] { "backward fast", "arrow", "beginning", "first", "last track button", "previous", "previous scene", "previous track", "quick", "rewind", "start", "triangle" })] [FontAwesomeCategoriesAttribute(new[] { "Media Playback" })] FastBackward = 0xF049, /// /// The Font Awesome "forward-fast" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "forward fast", "arrow", "end", "last", "next", "next scene", "next track", "next track button", "triangle" })] + [FontAwesomeSearchTerms(new[] { "forward fast", "arrow", "end", "last", "next", "next scene", "next track", "next track button", "quick", "triangle" })] [FontAwesomeCategoriesAttribute(new[] { "Media Playback" })] FastForward = 0xF050, @@ -3054,7 +3082,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "person-dress" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person dress", "man", "skirt", "woman" })] + [FontAwesomeSearchTerms(new[] { "person dress", "man", "skirt", "uer", "woman" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Users + People" })] Female = 0xF182, @@ -3075,7 +3103,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "file" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "file", "empty document", "document", "new", "page", "page facing up", "pdf", "resume" })] + [FontAwesomeSearchTerms(new[] { "file", "empty document", "cv", "document", "new", "page", "page facing up", "pdf", "resume" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Coding", "Files", "Humanitarian", "Shapes", "Writing" })] File = 0xF15B, @@ -3103,14 +3131,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "file-circle-check" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "file circle check", "document", "file", "not affected", "ok", "okay", "paper" })] + [FontAwesomeSearchTerms(new[] { "file circle check", "document", "enable", "file", "not affected", "ok", "okay", "paper", "validate", "working" })] [FontAwesomeCategoriesAttribute(new[] { "Files", "Humanitarian" })] FileCircleCheck = 0xE5A0, /// /// The Font Awesome "file-circle-exclamation" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "file circle exclamation", "document", "file", "paper" })] + [FontAwesomeSearchTerms(new[] { "file circle exclamation", "document", "failed", "file", "paper" })] [FontAwesomeCategoriesAttribute(new[] { "Files", "Humanitarian" })] FileCircleExclamation = 0xE4EB, @@ -3138,21 +3166,21 @@ public enum FontAwesomeIcon /// /// The Font Awesome "file-circle-xmark" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "file circle xmark", "document", "file", "paper" })] + [FontAwesomeSearchTerms(new[] { "file circle xmark", "document", "file", "paper", "uncheck" })] [FontAwesomeCategoriesAttribute(new[] { "Files", "Humanitarian" })] FileCircleXmark = 0xE5A1, /// /// The Font Awesome "file-code" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "file code", "css", "development", "document", "html" })] + [FontAwesomeSearchTerms(new[] { "file code", "css", "development", "document", "html", "mysql", "sql" })] [FontAwesomeCategoriesAttribute(new[] { "Coding", "Files" })] FileCode = 0xF1C9, /// /// The Font Awesome "file-contract" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "file contract", "agreement", "binding", "document", "legal", "signature" })] + [FontAwesomeSearchTerms(new[] { "file contract", "agreement", "binding", "document", "legal", "signature", "username" })] [FontAwesomeCategoriesAttribute(new[] { "Security" })] FileContract = 0xF56C, @@ -3166,7 +3194,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "file-arrow-down" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "file arrow down", "document", "export", "save" })] + [FontAwesomeSearchTerms(new[] { "file arrow down", "archive", "document", "export", "insert", "save" })] [FontAwesomeCategoriesAttribute(new[] { "Files" })] FileDownload = 0xF56D, @@ -3184,17 +3212,31 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Files" })] FileExport = 0xF56E, + /// + /// The Font Awesome "file-fragment" icon unicode character. + /// + [FontAwesomeSearchTerms(new[] { "file fragment", "block", "data", "partial", "piece" })] + [FontAwesomeCategoriesAttribute(new[] { "Files" })] + FileFragment = 0xE697, + + /// + /// The Font Awesome "file-half-dashed" icon unicode character. + /// + [FontAwesomeSearchTerms(new[] { "file half dashed", "data", "fragment", "partial", "piece" })] + [FontAwesomeCategoriesAttribute(new[] { "Files" })] + FileHalfDashed = 0xE698, + /// /// The Font Awesome "file-image" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "file image", "document with picture", "document", "image", "jpg", "photo", "png" })] + [FontAwesomeSearchTerms(new[] { "file image", "document with picture", "document", "image", "img", "jpg", "photo", "png" })] [FontAwesomeCategoriesAttribute(new[] { "Files", "Photos + Images" })] FileImage = 0xF1C5, /// /// The Font Awesome "file-import" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "file import", "copy", "document", "send", "upload" })] + [FontAwesomeSearchTerms(new[] { "file import", "copy", "document", "insert", "send", "upload" })] [FontAwesomeCategoriesAttribute(new[] { "Files" })] FileImport = 0xF56F, @@ -3208,7 +3250,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "file-invoice-dollar" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "file invoice dollar", "$", "account", "bill", "charge", "document", "dollar-sign", "money", "payment", "receipt", "usd" })] + [FontAwesomeSearchTerms(new[] { "file invoice dollar", "$", "account", "bill", "charge", "document", "dollar-sign", "money", "payment", "receipt", "revenue", "salary", "usd" })] [FontAwesomeCategoriesAttribute(new[] { "Money" })] FileInvoiceDollar = 0xF571, @@ -3236,7 +3278,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "file-pen" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "file pen", "edit", "memo", "pen", "pencil", "update", "write" })] + [FontAwesomeSearchTerms(new[] { "file pen", "edit", "memo", "modify", "pen", "pencil", "update", "write" })] [FontAwesomeCategoriesAttribute(new[] { "Files", "Humanitarian" })] FilePen = 0xF31C, @@ -3264,14 +3306,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "file-signature" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "file signature", "john hancock", "contract", "document", "name" })] + [FontAwesomeSearchTerms(new[] { "file signature", "john hancock", "contract", "document", "name", "username" })] [FontAwesomeCategoriesAttribute(new[] { "Security" })] FileSignature = 0xF573, /// /// The Font Awesome "file-arrow-up" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "file arrow up", "document", "import", "page", "save" })] + [FontAwesomeSearchTerms(new[] { "file arrow up", "document", "import", "page", "save", "upgrade" })] [FontAwesomeCategoriesAttribute(new[] { "Files" })] FileUpload = 0xF574, @@ -3320,14 +3362,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "filter-circle-xmark" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "filter circle xmark", "cancel", "funnel", "options", "remove", "separate", "sort" })] + [FontAwesomeSearchTerms(new[] { "filter circle xmark", "cancel", "funnel", "options", "remove", "separate", "sort", "uncheck" })] [FontAwesomeCategoriesAttribute(new[] { "Text Formatting" })] FilterCircleXmark = 0xE17B, /// /// The Font Awesome "fingerprint" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "fingerprint", "human", "id", "identification", "lock", "smudge", "touch", "unique", "unlock" })] + [FontAwesomeSearchTerms(new[] { "fingerprint", "human", "id", "identification", "lock", "privacy", "smudge", "touch", "unique", "unlock" })] [FontAwesomeCategoriesAttribute(new[] { "Accessibility", "Security" })] Fingerprint = 0xF577, @@ -3411,14 +3453,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "flask" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "flask", "beaker", "chemicals", "experiment", "experimental", "labs", "liquid", "potion", "science", "vial" })] + [FontAwesomeSearchTerms(new[] { "flask", "beaker", "chemicals", "experiment", "experimental", "knowledge", "labs", "liquid", "potion", "science", "vial" })] [FontAwesomeCategoriesAttribute(new[] { "Food + Beverage", "Maps", "Medical + Health", "Science" })] Flask = 0xF0C3, /// /// The Font Awesome "flask-vial" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "flask vial", " beaker", " chemicals", " experiment", " experimental", " labs", " liquid", " science", " vial", "ampule", "chemistry", "lab", "laboratory", "potion", "test", "test tube" })] + [FontAwesomeSearchTerms(new[] { "flask vial", "ampule", "beaker", "chemicals", "chemistry", "experiment", "experimental", "lab", "laboratory", "labs", "liquid", "potion", "science", "test", "test tube", "vial" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Medical + Health", "Science" })] FlaskVial = 0xE4F3, @@ -3539,7 +3581,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "face-frown" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "face frown", "disapprove", "emoticon", "face", "frown", "frowning face", "rating", "sad" })] + [FontAwesomeSearchTerms(new[] { "face frown", "disapprove", "emoticon", "face", "frown", "frowning face", "rating", "sad", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Communication", "Emoji", "Users + People" })] Frown = 0xF119, @@ -3553,7 +3595,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "filter-circle-dollar" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "filter circle dollar", "filter", "money", "options", "separate", "sort" })] + [FontAwesomeSearchTerms(new[] { "filter circle dollar", "filter", "money", "options", "premium", "separate", "sort" })] [FontAwesomeCategoriesAttribute(new[] { "Marketing" })] FunnelDollar = 0xF662, @@ -3567,7 +3609,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "gamepad" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "gamepad", "arcade", "controller", "d-pad", "joystick", "video", "video game" })] + [FontAwesomeSearchTerms(new[] { "gamepad", "arcade", "controller", "d-pad", "joystick", "playstore", "video", "video game" })] [FontAwesomeCategoriesAttribute(new[] { "Childhood", "Devices + Hardware", "Gaming", "Maps" })] Gamepad = 0xF11B, @@ -3595,7 +3637,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "gauge-simple-high" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "gauge simple high", "dashboard", "fast", "odometer", "speed", "speedometer" })] + [FontAwesomeSearchTerms(new[] { "gauge simple high", "dashboard", "fast", "odometer", "quick", "speed", "speedometer" })] [FontAwesomeCategoriesAttribute(new[] { "Automotive" })] GaugeSimpleHigh = 0xF62A, @@ -3693,7 +3735,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "globe" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "all", "coordinates", "country", "earth", "global", "globe", "globe with meridians", "gps", "internet", "language", "localize", "location", "map", "meridians", "network", "online", "place", "planet", "translate", "travel", "world" })] + [FontAwesomeSearchTerms(new[] { "all", "coordinates", "country", "earth", "global", "globe", "globe with meridians", "gps", "internet", "language", "localize", "location", "map", "meridians", "network", "online", "place", "planet", "translate", "travel", "world", "www" })] [FontAwesomeCategoriesAttribute(new[] { "Astronomy", "Business", "Charity", "Connectivity", "Maps" })] Globe = 0xF0AC, @@ -3820,7 +3862,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "face-grin-stars" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "face grin stars", "emoticon", "eyes", "face", "grinning", "star", "star-struck", "starry-eyed" })] + [FontAwesomeSearchTerms(new[] { "face grin stars", "emoticon", "eyes", "face", "grinning", "quality", "star", "star-struck", "starry-eyed", "vip" })] [FontAwesomeCategoriesAttribute(new[] { "Emoji" })] GrinStars = 0xF587, @@ -3862,7 +3904,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "grip" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "grip", "affordance", "drag", "drop", "grab", "handle" })] + [FontAwesomeSearchTerms(new[] { "grip", "affordance", "app", "collection", "dashboard", "drag", "drop", "grab", "grid", "handle", "launcher", "square" })] [FontAwesomeCategoriesAttribute(new[] { "Editing" })] GripHorizontal = 0xF58D, @@ -3925,7 +3967,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "hammer" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "admin", "fix", "hammer", "recovery", "repair", "settings", "tool" })] + [FontAwesomeSearchTerms(new[] { "admin", "configuration", "equipment", "fix", "hammer", "maintenance", "modify", "recovery", "repair", "settings", "tool" })] [FontAwesomeCategoriesAttribute(new[] { "Construction", "Humanitarian" })] Hammer = 0xF6E3, @@ -3953,8 +3995,8 @@ public enum FontAwesomeIcon /// /// The Font Awesome "hand-holding-droplet" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "hand holding droplet", "carry", "covid-19", "drought", "grow", "lift", "sanitation" })] - [FontAwesomeCategoriesAttribute(new[] { "Charity", "Hands" })] + [FontAwesomeSearchTerms(new[] { "hand holding droplet", "blood", "carry", "covid-19", "drought", "grow", "lift", "sanitation" })] + [FontAwesomeCategoriesAttribute(new[] { "Charity", "Hands", "Medical + Health" })] HandHoldingDroplet = 0xF4C1, /// @@ -3967,7 +4009,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "hand-holding-heart" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "hand holding heart", "carry", "charity", "gift", "lift", "package" })] + [FontAwesomeSearchTerms(new[] { "hand holding heart", "carry", "charity", "gift", "lift", "package", "wishlist" })] [FontAwesomeCategoriesAttribute(new[] { "Charity", "Hands" })] HandHoldingHeart = 0xF4BE, @@ -3981,7 +4023,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "hand-holding-dollar" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "hand holding dollar", "$", "carry", "dollar sign", "donation", "giving", "lift", "money", "price" })] + [FontAwesomeSearchTerms(new[] { "hand holding dollar", "$", "carry", "coupon", "dollar sign", "donate", "donation", "giving", "investment", "lift", "money", "premium", "price", "revenue", "salary" })] [FontAwesomeCategoriesAttribute(new[] { "Charity", "Hands", "Money" })] HandHoldingUsd = 0xF4C0, @@ -4002,7 +4044,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "hand" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "hand", "raised hand", "backhand", "game", "halt", "palm", "raised", "raised back of hand", "roshambo", "stop" })] + [FontAwesomeSearchTerms(new[] { "hand", "raised hand", "backhand", "game", "halt", "palm", "raised", "raised back of hand", "request", "roshambo", "stop" })] [FontAwesomeCategoriesAttribute(new[] { "Hands", "Media Playback" })] HandPaper = 0xF256, @@ -4044,7 +4086,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "hand-point-up" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "hand point up", "finger", "hand", "hand-o-up", "index", "index pointing up", "point", "up" })] + [FontAwesomeSearchTerms(new[] { "hand point up", "finger", "hand", "hand-o-up", "index", "index pointing up", "point", "request", "up", "upgrade" })] [FontAwesomeCategoriesAttribute(new[] { "Hands" })] HandPointUp = 0xF0A6, @@ -4094,27 +4136,29 @@ public enum FontAwesomeIcon /// The Font Awesome "handshake" icon unicode character. /// [FontAwesomeSearchTerms(new[] { "handshake", "agreement", "greeting", "meeting", "partnership" })] - [FontAwesomeCategoriesAttribute(new[] { "Charity", "Hands", "Political", "Shopping" })] + [FontAwesomeCategoriesAttribute(new[] { "Charity", "Hands", "Humanitarian", "Political", "Shopping" })] Handshake = 0xF2B5, /// - /// The Font Awesome "handshake-simple" icon unicode character. + /// The Font Awesome "handshake" icon unicode character. + /// Uses a legacy unicode value for backwards compatability. The current unicode value is 0xF2B5. /// - [FontAwesomeSearchTerms(new[] { "handshake simple", "agreement", "greeting", "hand", "handshake", "meeting", "partnership", "shake" })] - [FontAwesomeCategoriesAttribute(new[] { "Charity", "Hands", "Humanitarian" })] + [FontAwesomeSearchTerms(new[] { "handshake", "agreement", "greeting", "meeting", "partnership" })] + [FontAwesomeCategoriesAttribute(new[] { "Charity", "Hands", "Humanitarian", "Political", "Shopping" })] HandshakeSimple = 0xF4C6, /// - /// The Font Awesome "handshake-simple-slash" icon unicode character. + /// The Font Awesome "handshake-slash" icon unicode character. + /// Uses a legacy unicode value for backwards compatability. The current unicode value is 0xE060. /// - [FontAwesomeSearchTerms(new[] { "handshake simple slash", "broken", "covid-19", "social distance" })] + [FontAwesomeSearchTerms(new[] { "handshake slash", "broken", "covid-19", "disabled", "social distance" })] [FontAwesomeCategoriesAttribute(new[] { "Hands" })] HandshakeSimpleSlash = 0xE05F, /// /// The Font Awesome "handshake-slash" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "handshake slash", "broken", "covid-19", "social distance" })] + [FontAwesomeSearchTerms(new[] { "handshake slash", "broken", "covid-19", "disabled", "social distance" })] [FontAwesomeCategoriesAttribute(new[] { "Hands" })] HandshakeSlash = 0xE060, @@ -4128,7 +4172,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "hands-holding-child" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "hands holding child", "care", "give", "help", "hold", "protect" })] + [FontAwesomeSearchTerms(new[] { "hands holding child", "care", "give", "help", "hold", "parent", "protect" })] [FontAwesomeCategoriesAttribute(new[] { "Charity", "Childhood", "Hands", "Humanitarian", "Security" })] HandsHoldingChild = 0xE4FA, @@ -4163,7 +4207,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "helmet-safety" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "helmet safety", "construction", "hardhat", "helmet", "safety" })] + [FontAwesomeSearchTerms(new[] { "helmet safety", "construction", "hardhat", "helmet", "maintenance", "safety" })] [FontAwesomeCategoriesAttribute(new[] { "Construction", "Logistics" })] HardHat = 0xF807, @@ -4218,10 +4262,11 @@ public enum FontAwesomeIcon Headphones = 0xF025, /// - /// The Font Awesome "headphones-simple" icon unicode character. + /// The Font Awesome "headphones" icon unicode character. + /// Uses a legacy unicode value for backwards compatability. The current unicode value is 0xF025. /// - [FontAwesomeSearchTerms(new[] { "headphones simple", "audio", "listen", "music", "sound", "speaker" })] - [FontAwesomeCategoriesAttribute(new[] { "Music + Audio" })] + [FontAwesomeSearchTerms(new[] { "headphones", "audio", "earbud", "headphone", "listen", "music", "sound", "speaker" })] + [FontAwesomeCategoriesAttribute(new[] { "Devices + Hardware", "Film + Video", "Music + Audio" })] HeadphonesAlt = 0xF58F, /// @@ -4234,35 +4279,35 @@ public enum FontAwesomeIcon /// /// The Font Awesome "head-side-cough" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "head side cough", "cough", "covid-19", "germs", "lungs", "respiratory", "sick" })] + [FontAwesomeSearchTerms(new[] { "head side cough", "cough", "covid-19", "germs", "lungs", "respiratory", "sick", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Medical + Health", "Users + People" })] HeadSideCough = 0xE061, /// /// The Font Awesome "head-side-cough-slash" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "head side cough slash", "cough", "covid-19", "germs", "lungs", "respiratory", "sick" })] + [FontAwesomeSearchTerms(new[] { "head side cough slash", "cough", "covid-19", "disabled", "germs", "lungs", "respiratory", "sick", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Medical + Health", "Users + People" })] HeadSideCoughSlash = 0xE062, /// /// The Font Awesome "head-side-mask" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "head side mask", "breath", "coronavirus", "covid-19", "filter", "flu", "infection", "pandemic", "respirator", "virus" })] + [FontAwesomeSearchTerms(new[] { "head side mask", "breath", "coronavirus", "covid-19", "filter", "flu", "infection", "pandemic", "respirator", "uer", "virus" })] [FontAwesomeCategoriesAttribute(new[] { "Medical + Health", "Users + People" })] HeadSideMask = 0xE063, /// /// The Font Awesome "head-side-virus" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "head side virus", "cold", "coronavirus", "covid-19", "flu", "infection", "pandemic", "sick" })] + [FontAwesomeSearchTerms(new[] { "head side virus", "cold", "coronavirus", "covid-19", "flu", "infection", "pandemic", "sick", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Medical + Health", "Users + People" })] HeadSideVirus = 0xE064, /// /// The Font Awesome "heart" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "black", "black heart", "blue", "blue heart", "brown", "brown heart", "card", "evil", "favorite", "game", "green", "green heart", "heart", "heart suit", "like", "love", "orange", "orange heart", "purple", "purple heart", "red heart", "relationship", "valentine", "white", "white heart", "wicked", "yellow", "yellow heart" })] + [FontAwesomeSearchTerms(new[] { "ace", "card", "favorite", "game", "heart", "heart suit", "like", "love", "relationship", "valentine", "wishlist" })] [FontAwesomeCategoriesAttribute(new[] { "Charity", "Gaming", "Holidays", "Maps", "Medical + Health", "Shapes", "Shopping", "Social", "Sports + Fitness" })] Heart = 0xF004, @@ -4290,14 +4335,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "heart-circle-check" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "heart circle check", "favorite", "heart", "love", "not affected", "ok", "okay" })] + [FontAwesomeSearchTerms(new[] { "heart circle check", "enable", "favorite", "heart", "love", "not affected", "ok", "okay", "validate", "working" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Medical + Health" })] HeartCircleCheck = 0xE4FD, /// /// The Font Awesome "heart-circle-exclamation" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "heart circle exclamation", "favorite", "heart", "love" })] + [FontAwesomeSearchTerms(new[] { "heart circle exclamation", "failed", "favorite", "heart", "love" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Medical + Health" })] HeartCircleExclamation = 0xE4FE, @@ -4318,7 +4363,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "heart-circle-xmark" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "heart circle xmark", "favorite", "heart", "love" })] + [FontAwesomeSearchTerms(new[] { "heart circle xmark", "favorite", "heart", "love", "uncheck" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Medical + Health" })] HeartCircleXmark = 0xE501, @@ -4343,17 +4388,38 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Disaster + Crisis", "Humanitarian" })] HelmetUn = 0xE503, + /// + /// The Font Awesome "hexagon" icon unicode character. + /// + [FontAwesomeSearchTerms(new[] { "hexagon", "horizontal black hexagon", "geometry", "honeycomb", "polygon", "shape" })] + [FontAwesomeCategoriesAttribute(new[] { "Shapes" })] + Hexagon = 0xF312, + + /// + /// The Font Awesome "hexagon-nodes" icon unicode character. + /// + [FontAwesomeSearchTerms(new[] { "hexagon nodes", "action", "ai", "artificial intelligence", "cluster", "graph", "language", "llm", "model", "network", "neuronal" })] + [FontAwesomeCategoriesAttribute(new[] { "Charts + Diagrams", "Coding" })] + HexagonNodes = 0xE699, + + /// + /// The Font Awesome "hexagon-nodes-bolt" icon unicode character. + /// + [FontAwesomeSearchTerms(new[] { "hexagon nodes bolt", "llm", "action", "ai", "artificial intelligence", "cluster", "graph", "language", "llm", "model", "network", "neuronal" })] + [FontAwesomeCategoriesAttribute(new[] { "Charts + Diagrams", "Coding" })] + HexagonNodesBolt = 0xE69A, + /// /// The Font Awesome "highlighter" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "highlighter", "edit", "marker", "sharpie", "update", "write" })] + [FontAwesomeSearchTerms(new[] { "highlighter", "edit", "marker", "modify", "sharpie", "update", "write" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Design", "Text Formatting" })] Highlighter = 0xF591, /// /// The Font Awesome "person-hiking" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person hiking", "autumn", "fall", "hike", "mountain", "outdoors", "summer", "walk" })] + [FontAwesomeSearchTerms(new[] { "person hiking", "autumn", "fall", "follow", "hike", "mountain", "outdoors", "summer", "uer", "walk" })] [FontAwesomeCategoriesAttribute(new[] { "Camping", "Nature", "Sports + Fitness", "Users + People" })] Hiking = 0xF6EC, @@ -4381,7 +4447,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "clock-rotate-left" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "clock rotate left", "rewind", "clock", "reverse", "time", "time machine", "time travel" })] + [FontAwesomeSearchTerms(new[] { "clock rotate left", "rewind", "clock", "pending", "reverse", "time", "time machine", "time travel", "waiting" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Medical + Health" })] History = 0xF1DA, @@ -4445,7 +4511,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "hospital-user" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "hospital user", "covid-19", "doctor", "network", "patient", "primary care" })] + [FontAwesomeSearchTerms(new[] { "hospital user", "covid-19", "doctor", "network", "patient", "primary care", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Medical + Health", "Users + People" })] HospitalUser = 0xF80D, @@ -4466,7 +4532,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "hot-tub-person" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "hot tub person", "jacuzzi", "spa" })] + [FontAwesomeSearchTerms(new[] { "hot tub person", "jacuzzi", "spa", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Travel + Hotel", "Users + People" })] HotTub = 0xF593, @@ -4480,21 +4546,21 @@ public enum FontAwesomeIcon /// /// The Font Awesome "hourglass-end" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "hourglass end", "hour", "hourglass done", "minute", "sand", "stopwatch", "time", "timer" })] + [FontAwesomeSearchTerms(new[] { "hourglass end", "hour", "hourglass done", "minute", "pending", "sand", "stopwatch", "time", "timer", "waiting" })] [FontAwesomeCategoriesAttribute(new[] { "Time" })] HourglassEnd = 0xF253, /// /// The Font Awesome "hourglass-half" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "hourglass half", "hour", "minute", "sand", "stopwatch", "time" })] + [FontAwesomeSearchTerms(new[] { "hourglass half", "hour", "minute", "pending", "sand", "stopwatch", "time", "waiting" })] [FontAwesomeCategoriesAttribute(new[] { "Time" })] HourglassHalf = 0xF252, /// /// The Font Awesome "hourglass-start" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "hourglass start", "hour", "minute", "sand", "stopwatch", "time" })] + [FontAwesomeSearchTerms(new[] { "hourglass start", "hour", "minute", "sand", "stopwatch", "time", "waiting" })] [FontAwesomeCategoriesAttribute(new[] { "Time" })] HourglassStart = 0xF251, @@ -4508,7 +4574,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "house-chimney-user" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "house chimney user", "covid-19", "home", "isolation", "quarantine" })] + [FontAwesomeSearchTerms(new[] { "house chimney user", "covid-19", "home", "isolation", "quarantine", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Household", "Users + People" })] HouseChimneyUser = 0xE065, @@ -4522,21 +4588,21 @@ public enum FontAwesomeIcon /// /// The Font Awesome "house-circle-check" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "house circle check", "abode", "home", "house", "not affected", "ok", "okay" })] + [FontAwesomeSearchTerms(new[] { "house circle check", "abode", "enable", "home", "house", "not affected", "ok", "okay", "validate", "working" })] [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Humanitarian" })] HouseCircleCheck = 0xE509, /// /// The Font Awesome "house-circle-exclamation" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "house circle exclamation", "abode", "affected", "home", "house" })] + [FontAwesomeSearchTerms(new[] { "house circle exclamation", "abode", "affected", "failed", "home", "house" })] [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Humanitarian" })] HouseCircleExclamation = 0xE50A, /// /// The Font Awesome "house-circle-xmark" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "house circle xmark", "abode", "destroy", "home", "house" })] + [FontAwesomeSearchTerms(new[] { "house circle xmark", "abode", "destroy", "home", "house", "uncheck" })] [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Humanitarian" })] HouseCircleXmark = 0xE50B, @@ -4592,7 +4658,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "house-lock" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "house lock", "closed", "home", "house", "lockdown", "quarantine" })] + [FontAwesomeSearchTerms(new[] { "house lock", "closed", "home", "house", "lockdown", "padlock", "privacy", "quarantine" })] [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Household", "Humanitarian", "Security" })] HouseLock = 0xE510, @@ -4606,21 +4672,21 @@ public enum FontAwesomeIcon /// /// The Font Awesome "house-medical-circle-check" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "house medical circle check", "clinic", "hospital", "not affected", "ok", "okay" })] + [FontAwesomeSearchTerms(new[] { "house medical circle check", "clinic", "enable", "hospital", "not affected", "ok", "okay", "validate", "working" })] [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Humanitarian", "Medical + Health" })] HouseMedicalCircleCheck = 0xE511, /// /// The Font Awesome "house-medical-circle-exclamation" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "house medical circle exclamation", "affected", "clinic", "hospital" })] + [FontAwesomeSearchTerms(new[] { "house medical circle exclamation", "affected", "clinic", "failed", "hospital" })] [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Humanitarian", "Medical + Health" })] HouseMedicalCircleExclamation = 0xE512, /// /// The Font Awesome "house-medical-circle-xmark" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "house medical circle xmark", "clinic", "destroy", "hospital" })] + [FontAwesomeSearchTerms(new[] { "house medical circle xmark", "clinic", "destroy", "hospital", "uncheck" })] [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Humanitarian", "Medical + Health" })] HouseMedicalCircleXmark = 0xE513, @@ -4634,7 +4700,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "house-signal" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "house signal", "abode", "building", "connect", "family", "home", "residence", "smart home", "wifi" })] + [FontAwesomeSearchTerms(new[] { "house signal", "abode", "building", "connect", "family", "home", "residence", "smart home", "wifi", "www" })] [FontAwesomeCategoriesAttribute(new[] { "Connectivity", "Household", "Humanitarian" })] HouseSignal = 0xE012, @@ -4648,7 +4714,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "house-user" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "house user", "house" })] + [FontAwesomeSearchTerms(new[] { "house user", "house", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Household", "Users + People" })] HouseUser = 0xE1B0, @@ -4690,7 +4756,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "icons" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "icons", "bolt", "emoji", "heart", "image", "music", "photo", "symbols" })] + [FontAwesomeSearchTerms(new[] { "icons", "bolt", "category", "emoji", "heart", "image", "music", "photo", "symbols" })] [FontAwesomeCategoriesAttribute(new[] { "Communication", "Design", "Social", "Text Formatting" })] Icons = 0xF86D, @@ -4704,21 +4770,21 @@ public enum FontAwesomeIcon /// /// The Font Awesome "id-badge" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "id badge", "address", "contact", "identification", "license", "profile" })] + [FontAwesomeSearchTerms(new[] { "id badge", "address", "contact", "identification", "license", "profile", "uer", "username" })] [FontAwesomeCategoriesAttribute(new[] { "Photos + Images", "Security", "Users + People" })] IdBadge = 0xF2C1, /// /// The Font Awesome "id-card" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "id card", "contact", "demographics", "document", "identification", "issued", "profile", "registration" })] + [FontAwesomeSearchTerms(new[] { "id card", "contact", "demographics", "document", "identification", "issued", "profile", "registration", "uer", "username" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Photos + Images", "Security", "Users + People" })] IdCard = 0xF2C2, /// /// The Font Awesome "id-card-clip" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "id card clip", "contact", "demographics", "document", "identification", "issued", "profile" })] + [FontAwesomeSearchTerms(new[] { "id card clip", "contact", "demographics", "document", "identification", "issued", "profile", "uer", "username" })] [FontAwesomeCategoriesAttribute(new[] { "Medical + Health", "Security", "Users + People" })] IdCardAlt = 0xF47F, @@ -4732,14 +4798,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "image" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "image", "album", "landscape", "photo", "picture" })] + [FontAwesomeSearchTerms(new[] { "image", "album", "img", "landscape", "photo", "picture" })] [FontAwesomeCategoriesAttribute(new[] { "Maps", "Photos + Images", "Social" })] Image = 0xF03E, /// /// The Font Awesome "images" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "images", "album", "landscape", "photo", "picture" })] + [FontAwesomeSearchTerms(new[] { "images", "album", "img", "landscape", "photo", "picture" })] [FontAwesomeCategoriesAttribute(new[] { "Maps", "Photos + Images", "Social" })] Images = 0xF302, @@ -4792,6 +4858,12 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Accessibility", "Maps" })] InfoCircle = 0xF05A, + /// + /// The Font Awesome "instagramsquare" icon unicode character. + /// + [Obsolete] + InstagramSquare = 0xF955, + /// /// The Font Awesome "italic" icon unicode character. /// @@ -4921,7 +4993,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "landmark" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "landmark", "building", "classical", "historic", "memorable", "monument", "museum", "politics" })] + [FontAwesomeSearchTerms(new[] { "landmark", "building", "classical", "historic", "memorable", "monument", "museum", "politics", "society" })] [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Business", "Humanitarian", "Maps", "Money" })] Landmark = 0xF66F, @@ -4956,14 +5028,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "laptop" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "computer", "cpu", "dell", "demo", "device", "laptop", "mac", "macbook", "machine", "pc", "personal" })] + [FontAwesomeSearchTerms(new[] { "computer", "cpu", "dell", "demo", "device", "fabook", "fb", "laptop", "mac", "macbook", "machine", "pc", "personal" })] [FontAwesomeCategoriesAttribute(new[] { "Devices + Hardware", "Humanitarian" })] Laptop = 0xF109, /// /// The Font Awesome "laptop-code" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "laptop code", "computer", "cpu", "dell", "demo", "develop", "device", "mac", "macbook", "machine", "pc" })] + [FontAwesomeSearchTerms(new[] { "laptop code", "computer", "cpu", "dell", "demo", "develop", "device", "fabook", "fb", "mac", "macbook", "machine", "mysql", "pc", "sql" })] [FontAwesomeCategoriesAttribute(new[] { "Coding", "Education" })] LaptopCode = 0xF5FC, @@ -5019,7 +5091,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "layer-group" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "layer group", "arrange", "develop", "layers", "map", "stack" })] + [FontAwesomeSearchTerms(new[] { "layer group", "arrange", "category", "develop", "layers", "map", "platform", "stack" })] [FontAwesomeCategoriesAttribute(new[] { "Design", "Maps" })] LayerGroup = 0xF5FD, @@ -5076,7 +5148,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "lightbulb" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "lightbulb", " comic", " electric", " idea", " innovation", " inspiration", " light", " light bulb", " bulb", "bulb", "comic", "electric", "energy", "idea", "inspiration", "mechanical" })] + [FontAwesomeSearchTerms(new[] { "lightbulb", "bulb", "bulb", "comic", "comic", "electric", "electric", "energy", "idea", "idea", "innovation", "inspiration", "inspiration", "light", "light bulb", "mechanical" })] [FontAwesomeCategoriesAttribute(new[] { "Energy", "Household", "Maps", "Marketing" })] Lightbulb = 0xF0EB, @@ -5104,28 +5176,28 @@ public enum FontAwesomeIcon /// /// The Font Awesome "list" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "list", "checklist", "completed", "done", "finished", "ol", "todo", "ul" })] + [FontAwesomeSearchTerms(new[] { "list", "bullet", "category", "cheatsheet", "checklist", "completed", "done", "finished", "ol", "summary", "todo", "ul" })] [FontAwesomeCategoriesAttribute(new[] { "Text Formatting" })] List = 0xF03A, /// /// The Font Awesome "rectangle-list" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "rectangle list", "checklist", "completed", "done", "finished", "ol", "todo", "ul" })] + [FontAwesomeSearchTerms(new[] { "rectangle list", "cheatsheet", "checklist", "completed", "done", "finished", "ol", "summary", "todo", "ul" })] [FontAwesomeCategoriesAttribute(new[] { "Text Formatting" })] ListAlt = 0xF022, /// /// The Font Awesome "list-ol" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "list ol", "checklist", "completed", "done", "finished", "numbers", "ol", "todo", "ul" })] + [FontAwesomeSearchTerms(new[] { "list ol", "cheatsheet", "checklist", "completed", "done", "finished", "numbers", "ol", "summary", "todo", "ul" })] [FontAwesomeCategoriesAttribute(new[] { "Text Formatting" })] ListOl = 0xF0CB, /// /// The Font Awesome "list-ul" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "list ul", "checklist", "completed", "done", "finished", "ol", "todo", "ul" })] + [FontAwesomeSearchTerms(new[] { "list ul", "bullet", "cheatsheet", "checklist", "completed", "done", "finished", "ol", "summary", "survey", "todo", "ul" })] [FontAwesomeCategoriesAttribute(new[] { "Text Formatting" })] ListUl = 0xF0CA, @@ -5153,21 +5225,21 @@ public enum FontAwesomeIcon /// /// The Font Awesome "location-pin-lock" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "location pin lock", "closed", "lockdown", "map", "quarantine" })] + [FontAwesomeSearchTerms(new[] { "location pin lock", "closed", "lockdown", "map", "padlock", "privacy", "quarantine" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Maps" })] LocationPinLock = 0xE51F, /// /// The Font Awesome "lock" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "admin", "closed", "lock", "locked", "open", "password", "private", "protect", "security" })] + [FontAwesomeSearchTerms(new[] { "admin", "closed", "lock", "locked", "open", "padlock", "password", "privacy", "private", "protect", "security" })] [FontAwesomeCategoriesAttribute(new[] { "Security" })] Lock = 0xF023, /// /// The Font Awesome "lock-open" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "lock open", "admin", "lock", "open", "password", "private", "protect", "security", "unlock" })] + [FontAwesomeSearchTerms(new[] { "lock open", "admin", "lock", "open", "padlock", "password", "privacy", "private", "protect", "security", "unlock" })] [FontAwesomeCategoriesAttribute(new[] { "Security" })] LockOpen = 0xF3C1, @@ -5202,7 +5274,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "up-long" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "up long", "long-arrow-up", "upload" })] + [FontAwesomeSearchTerms(new[] { "up long", "long-arrow-up", "upgrade", "upload" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows" })] LongArrowAltUp = 0xF30C, @@ -5251,28 +5323,28 @@ public enum FontAwesomeIcon /// /// The Font Awesome "magnifying-glass-arrow-right" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "magnifying glass arrow right", "find", "next", "search" })] + [FontAwesomeSearchTerms(new[] { "magnifying glass arrow right", "find", "magnifier", "next", "search" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Humanitarian", "Marketing" })] MagnifyingGlassArrowRight = 0xE521, /// /// The Font Awesome "magnifying-glass-chart" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "magnifying glass chart", " data", " graph", " intelligence", "analysis", "chart", "market" })] + [FontAwesomeSearchTerms(new[] { "magnifying glass chart", "analysis", "chart", "data", "graph", "intelligence", "magnifier", "market", "revenue" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Humanitarian", "Marketing" })] MagnifyingGlassChart = 0xE522, /// /// The Font Awesome "envelopes-bulk" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "envelopes bulk", "archive", "envelope", "letter", "post office", "postal", "postcard", "send", "stamp", "usps" })] + [FontAwesomeSearchTerms(new[] { "envelopes bulk", "archive", "envelope", "letter", "newsletter", "offer", "post office", "postal", "postcard", "send", "stamp", "usps" })] [FontAwesomeCategoriesAttribute(new[] { "Marketing" })] MailBulk = 0xF674, /// /// The Font Awesome "person" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person", "man", "person standing", "stand", "standing", "woman" })] + [FontAwesomeSearchTerms(new[] { "person", "default", "man", "person standing", "stand", "standing", "uer", "woman" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Maps", "Users + People" })] Male = 0xF183, @@ -5335,7 +5407,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "marker" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "marker", "design", "edit", "sharpie", "update", "write" })] + [FontAwesomeSearchTerms(new[] { "marker", "design", "edit", "modify", "sharpie", "update", "write" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Design" })] Marker = 0xF5A1, @@ -5349,7 +5421,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "mars-and-venus-burst" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "mars and venus burst", "gender", "violence" })] + [FontAwesomeSearchTerms(new[] { "mars and venus burst", "gender", "uer", "violence" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Security", "Users + People" })] MarsAndVenusBurst = 0xE523, @@ -5412,7 +5484,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "medal" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "award", "medal", "ribbon", "sports medal", "star", "trophy" })] + [FontAwesomeSearchTerms(new[] { "award", "guarantee", "medal", "quality", "ribbon", "sports medal", "star", "trophy", "warranty" })] [FontAwesomeCategoriesAttribute(new[] { "Sports + Fitness" })] Medal = 0xF5A2, @@ -5426,7 +5498,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "face-meh" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "face meh", "deadpan", "emoticon", "face", "meh", "neutral", "neutral face", "rating" })] + [FontAwesomeSearchTerms(new[] { "face meh", "deadpan", "default", "emoticon", "face", "meh", "neutral", "neutral face", "rating", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Communication", "Emoji", "Users + People" })] Meh = 0xF11A, @@ -5482,35 +5554,35 @@ public enum FontAwesomeIcon /// /// The Font Awesome "microphone" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "microphone", "address", "audio", "information", "podcast", "public", "record", "sing", "sound", "voice" })] + [FontAwesomeSearchTerms(new[] { "microphone", "address", "audio", "information", "podcast", "public", "record", "sing", "sound", "talking", "voice" })] [FontAwesomeCategoriesAttribute(new[] { "Communication", "Film + Video", "Music + Audio", "Toggle" })] Microphone = 0xF130, /// /// The Font Awesome "microphone-lines" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "microphone lines", "audio", "mic", "microphone", "music", "podcast", "record", "sing", "sound", "studio", "studio microphone", "voice" })] + [FontAwesomeSearchTerms(new[] { "microphone lines", "audio", "mic", "microphone", "music", "podcast", "record", "sing", "sound", "studio", "studio microphone", "talking", "voice" })] [FontAwesomeCategoriesAttribute(new[] { "Communication", "Film + Video", "Music + Audio" })] MicrophoneAlt = 0xF3C9, /// /// The Font Awesome "microphone-lines-slash" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "microphone lines slash", "audio", "disable", "mute", "podcast", "record", "sing", "sound", "voice" })] + [FontAwesomeSearchTerms(new[] { "microphone lines slash", "audio", "disable", "disabled", "disconnect", "disconnect", "mute", "podcast", "record", "sing", "sound", "voice" })] [FontAwesomeCategoriesAttribute(new[] { "Communication", "Film + Video", "Music + Audio" })] MicrophoneAltSlash = 0xF539, /// /// The Font Awesome "microphone-slash" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "microphone slash", "audio", "disable", "mute", "podcast", "record", "sing", "sound", "voice" })] + [FontAwesomeSearchTerms(new[] { "microphone slash", "audio", "disable", "disabled", "mute", "podcast", "record", "sing", "sound", "voice" })] [FontAwesomeCategoriesAttribute(new[] { "Communication", "Film + Video", "Music + Audio", "Toggle" })] MicrophoneSlash = 0xF131, /// /// The Font Awesome "microscope" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "covid-19", "electron", "lens", "microscope", "optics", "science", "shrink", "testing", "tool" })] + [FontAwesomeSearchTerms(new[] { "covid-19", "electron", "knowledge", "lens", "microscope", "optics", "science", "shrink", "testing", "tool" })] [FontAwesomeCategoriesAttribute(new[] { "Education", "Humanitarian", "Medical + Health", "Science" })] Microscope = 0xF610, @@ -5584,73 +5656,80 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Communication", "Devices + Hardware", "Humanitarian" })] MobileScreen = 0xF3CF, + /// + /// The Font Awesome "mobile-vibrate" icon unicode character. + /// + [FontAwesomeSearchTerms(new[] { "mobile vibrate", "android", "call", "cell", "cell phone", "device", "haptic", "mobile", "mobile phone", "notification", "number", "phone", "screen", "telephone", "text" })] + [FontAwesomeCategoriesAttribute(new[] { "Communication", "Devices + Hardware" })] + MobileVibrate = 0xE816, + /// /// The Font Awesome "money-bill" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "money bill", "buy", "cash", "checkout", "money", "payment", "price", "purchase" })] + [FontAwesomeSearchTerms(new[] { "money bill", "buy", "cash", "checkout", "coupon", "investment", "money", "payment", "premium", "price", "purchase", "revenue", "salary" })] [FontAwesomeCategoriesAttribute(new[] { "Maps", "Money" })] MoneyBill = 0xF0D6, /// /// The Font Awesome "money-bill-1" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "money bill 1", "buy", "cash", "checkout", "money", "payment", "price", "purchase" })] + [FontAwesomeSearchTerms(new[] { "money bill 1", "buy", "cash", "checkout", "money", "payment", "premium", "price", "purchase", "salary" })] [FontAwesomeCategoriesAttribute(new[] { "Maps", "Money" })] MoneyBillAlt = 0xF3D1, /// /// The Font Awesome "money-bills" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "money bills", "atm", "cash", "money", "moolah" })] + [FontAwesomeSearchTerms(new[] { "money bills", "atm", "cash", "investment", "money", "moolah", "premium", "revenue", "salary" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Money" })] MoneyBills = 0xE1F3, /// /// The Font Awesome "money-bill-transfer" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "money bill transfer", "bank", "conversion", "deposit", "money", "transfer", "withdrawal" })] + [FontAwesomeSearchTerms(new[] { "money bill transfer", "bank", "conversion", "deposit", "investment", "money", "salary", "transfer", "withdrawal" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Money" })] MoneyBillTransfer = 0xE528, /// /// The Font Awesome "money-bill-trend-up" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "money bill trend up", "bank", "bonds", "inflation", "market", "stocks", "trade" })] + [FontAwesomeSearchTerms(new[] { "money bill trend up", "bank", "bonds", "inflation", "investment", "market", "revenue", "salary", "stocks", "trade" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Money" })] MoneyBillTrendUp = 0xE529, /// /// The Font Awesome "money-bill-wave" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "money bill wave", "buy", "cash", "checkout", "money", "payment", "price", "purchase" })] + [FontAwesomeSearchTerms(new[] { "money bill wave", "buy", "cash", "checkout", "money", "payment", "premium", "price", "purchase", "salary" })] [FontAwesomeCategoriesAttribute(new[] { "Money" })] MoneyBillWave = 0xF53A, /// /// The Font Awesome "money-bill-1-wave" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "money bill 1 wave", "buy", "cash", "checkout", "money", "payment", "price", "purchase" })] + [FontAwesomeSearchTerms(new[] { "money bill 1 wave", "buy", "cash", "checkout", "money", "payment", "premium", "price", "purchase", "salary" })] [FontAwesomeCategoriesAttribute(new[] { "Money" })] MoneyBillWaveAlt = 0xF53B, /// /// The Font Awesome "money-bill-wheat" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "money bill wheat", "agribusiness", "agriculture", "farming", "food", "livelihood", "subsidy" })] + [FontAwesomeSearchTerms(new[] { "money bill wheat", "agribusiness", "agriculture", "farming", "food", "investment", "livelihood", "subsidy" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Money" })] MoneyBillWheat = 0xE52A, /// /// The Font Awesome "money-check" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "money check", "bank check", "buy", "checkout", "cheque", "money", "payment", "price", "purchase" })] + [FontAwesomeSearchTerms(new[] { "money check", "bank check", "buy", "checkout", "cheque", "money", "payment", "price", "purchase", "salary" })] [FontAwesomeCategoriesAttribute(new[] { "Money", "Shopping" })] MoneyCheck = 0xF53C, /// /// The Font Awesome "money-check-dollar" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "money check dollar", "bank check", "buy", "checkout", "cheque", "money", "payment", "price", "purchase" })] + [FontAwesomeSearchTerms(new[] { "money check dollar", "bank check", "buy", "checkout", "cheque", "money", "payment", "price", "purchase", "salary" })] [FontAwesomeCategoriesAttribute(new[] { "Money", "Shopping" })] MoneyCheckAlt = 0xF53D, @@ -5783,14 +5862,21 @@ public enum FontAwesomeIcon /// /// The Font Awesome "newspaper" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "article", "editorial", "headline", "journal", "journalism", "news", "newspaper", "paper", "press" })] + [FontAwesomeSearchTerms(new[] { "article", "editorial", "headline", "journal", "journalism", "news", "newsletter", "newspaper", "paper", "press" })] [FontAwesomeCategoriesAttribute(new[] { "Maps", "Writing" })] Newspaper = 0xF1EA, + /// + /// The Font Awesome "non-binary" icon unicode character. + /// + [FontAwesomeSearchTerms(new[] { "non binary", "female", "gender", "male", "nb", "queer" })] + [FontAwesomeCategoriesAttribute(new[] { "Genders" })] + NonBinary = 0xE807, + /// /// The Font Awesome "notdef" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "notdef", "close", "missing" })] + [FontAwesomeSearchTerms(new[] { "notdef", "404", "close", "missing", "not found" })] [FontAwesomeCategoriesAttribute(new[] { "Coding", "Writing" })] Notdef = 0xE1FE, @@ -5822,6 +5908,13 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Design" })] ObjectUngroup = 0xF248, + /// + /// The Font Awesome "octagon" icon unicode character. + /// + [FontAwesomeSearchTerms(new[] { "octagon", "octagonal", "shape", "sign", "stop", "stop sign" })] + [FontAwesomeCategoriesAttribute(new[] { "Shapes" })] + Octagon = 0xF306, + /// /// The Font Awesome "oil-can" icon unicode character. /// @@ -5867,14 +5960,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "paintbrush" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "acrylic", "art", "brush", "color", "fill", "paint", "paintbrush", "painting", "pigment", "watercolor" })] + [FontAwesomeSearchTerms(new[] { "acrylic", "art", "brush", "color", "fill", "modify", "paint", "paintbrush", "painting", "pigment", "watercolor" })] [FontAwesomeCategoriesAttribute(new[] { "Design", "Editing" })] PaintBrush = 0xF1FC, /// /// The Font Awesome "paint-roller" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "paint roller", "acrylic", "art", "brush", "color", "fill", "paint", "pigment", "watercolor" })] + [FontAwesomeSearchTerms(new[] { "paint roller", "acrylic", "art", "brush", "color", "fill", "maintenance", "paint", "pigment", "watercolor" })] [FontAwesomeCategoriesAttribute(new[] { "Construction", "Design" })] PaintRoller = 0xF5AA, @@ -5895,7 +5988,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "panorama" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "panorama", "image", "landscape", "photo", "wide" })] + [FontAwesomeSearchTerms(new[] { "panorama", "image", "img", "landscape", "photo", "wide" })] [FontAwesomeCategoriesAttribute(new[] { "Photos + Images" })] Panorama = 0xE209, @@ -5986,98 +6079,105 @@ public enum FontAwesomeIcon /// /// The Font Awesome "pen" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "ballpoint", "design", "edit", "pen", "update", "write" })] + [FontAwesomeSearchTerms(new[] { "ballpoint", "design", "edit", "modify", "pen", "update", "write" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Design", "Editing", "Writing" })] Pen = 0xF304, /// /// The Font Awesome "pen-clip" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "pen clip", "design", "edit", "update", "write" })] + [FontAwesomeSearchTerms(new[] { "pen clip", "design", "edit", "modify", "update", "write" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Design", "Editing", "Writing" })] PenAlt = 0xF305, /// /// The Font Awesome "pencil" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "lower left pencil", "design", "draw", "edit", "lead", "pencil", "update", "write" })] + [FontAwesomeSearchTerms(new[] { "lower left pencil", "design", "draw", "edit", "lead", "maintenance", "modify", "pencil", "update", "write" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Construction", "Design", "Editing", "Writing" })] PencilAlt = 0xF303, /// /// The Font Awesome "pen-ruler" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "pen ruler", "design", "draft", "draw", "pencil" })] + [FontAwesomeSearchTerms(new[] { "pen ruler", "design", "draft", "draw", "maintenance", "modify", "pencil" })] [FontAwesomeCategoriesAttribute(new[] { "Construction", "Design", "Editing" })] PencilRuler = 0xF5AE, /// /// The Font Awesome "pen-fancy" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "pen fancy", "black nib", "design", "edit", "fountain", "fountain pen", "nib", "pen", "update", "write" })] + [FontAwesomeSearchTerms(new[] { "pen fancy", "black nib", "design", "edit", "fountain", "fountain pen", "modify", "nib", "pen", "update", "write" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Design", "Editing" })] PenFancy = 0xF5AC, /// /// The Font Awesome "pen-nib" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "pen nib", "design", "edit", "fountain pen", "update", "write" })] + [FontAwesomeSearchTerms(new[] { "pen nib", "design", "edit", "fountain pen", "modify", "update", "write" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Design", "Editing" })] PenNib = 0xF5AD, /// /// The Font Awesome "square-pen" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "square pen", "edit", "pencil-square", "update", "write" })] + [FontAwesomeSearchTerms(new[] { "square pen", "edit", "modify", "pencil-square", "update", "write" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Editing", "Writing" })] PenSquare = 0xF14B, + /// + /// The Font Awesome "pentagon" icon unicode character. + /// + [FontAwesomeSearchTerms(new[] { "5", "five", "pentagon", "shape" })] + [FontAwesomeCategoriesAttribute(new[] { "Shapes" })] + Pentagon = 0xE790, + /// /// The Font Awesome "people-arrows" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "people arrows", "distance", "isolation", "separate", "social distancing", "users-people" })] + [FontAwesomeSearchTerms(new[] { "people arrows", "conversation", "discussion", "distance", "insert", "isolation", "separate", "social distancing", "talk", "talking", "together", "uer", "users-people" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Users + People" })] PeopleArrows = 0xE068, /// /// The Font Awesome "people-carry-box" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "people carry box", "users-people" })] + [FontAwesomeSearchTerms(new[] { "people carry box", "together", "uer", "users-people" })] [FontAwesomeCategoriesAttribute(new[] { "Moving", "Users + People" })] PeopleCarry = 0xF4CE, /// /// The Font Awesome "people-group" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "people group", "family", "group", "team" })] + [FontAwesomeSearchTerms(new[] { "people group", "crowd", "family", "group", "team", "together", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Marketing", "Users + People" })] PeopleGroup = 0xE533, /// /// The Font Awesome "people-line" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "people line", "group", "need" })] + [FontAwesomeSearchTerms(new[] { "people line", "crowd", "group", "need", "together", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Users + People" })] PeopleLine = 0xE534, /// /// The Font Awesome "people-pulling" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "people pulling", "forced return", "yanking" })] + [FontAwesomeSearchTerms(new[] { "people pulling", "forced return", "together", "uer", "yanking" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Security", "Users + People" })] PeoplePulling = 0xE535, /// /// The Font Awesome "people-robbery" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "people robbery", "criminal", "hands up", "looting", "robbery", "steal" })] + [FontAwesomeSearchTerms(new[] { "people robbery", "criminal", "hands up", "looting", "robbery", "steal", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Security", "Users + People" })] PeopleRobbery = 0xE536, /// /// The Font Awesome "people-roof" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "people roof", "family", "group", "manage", "people", "safe", "shelter" })] + [FontAwesomeSearchTerms(new[] { "people roof", "crowd", "family", "group", "manage", "people", "safe", "shelter", "together", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Camping", "Household", "Humanitarian", "Users + People" })] PeopleRoof = 0xE537, @@ -6107,105 +6207,105 @@ public enum FontAwesomeIcon /// /// The Font Awesome "person-arrow-down-to-line" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person arrow down to line", "ground", "indigenous", "native" })] + [FontAwesomeSearchTerms(new[] { "person arrow down to line", "ground", "indigenous", "insert", "native", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Users + People" })] PersonArrowDownToLine = 0xE538, /// /// The Font Awesome "person-arrow-up-from-line" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person arrow up from line", "population", "rise" })] + [FontAwesomeSearchTerms(new[] { "person arrow up from line", "population", "rise", "uer", "upgrade" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Users + People" })] PersonArrowUpFromLine = 0xE539, /// /// The Font Awesome "person-booth" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person booth", "changing room", "curtain", "vote", "voting" })] + [FontAwesomeSearchTerms(new[] { "person booth", "changing room", "curtain", "uer", "vote", "voting" })] [FontAwesomeCategoriesAttribute(new[] { "Political", "Shopping", "Users + People" })] PersonBooth = 0xF756, /// /// The Font Awesome "person-breastfeeding" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person breastfeeding", "baby", "child", "infant", "mother", "nutrition", "sustenance" })] + [FontAwesomeSearchTerms(new[] { "person breastfeeding", "baby", "child", "infant", "mother", "nutrition", "parent", "sustenance", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Childhood", "Humanitarian", "Medical + Health", "Users + People" })] PersonBreastfeeding = 0xE53A, /// /// The Font Awesome "person-burst" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person burst", "abuse", "accident", "crash", "explode", "violence" })] + [FontAwesomeSearchTerms(new[] { "person burst", "abuse", "accident", "crash", "explode", "uer", "violence" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Security", "Users + People" })] PersonBurst = 0xE53B, /// /// The Font Awesome "person-cane" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person cane", "aging", "cane", "elderly", "old", "staff" })] + [FontAwesomeSearchTerms(new[] { "person cane", "aging", "cane", "elderly", "old", "staff", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Accessibility", "Humanitarian", "Medical + Health", "Users + People" })] PersonCane = 0xE53C, /// /// The Font Awesome "person-chalkboard" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person chalkboard", "blackboard", "instructor", "keynote", "lesson", "presentation", "teacher" })] + [FontAwesomeSearchTerms(new[] { "person chalkboard", "blackboard", "instructor", "keynote", "lesson", "presentation", "teacher", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Education", "Humanitarian", "Users + People" })] PersonChalkboard = 0xE53D, /// /// The Font Awesome "person-circle-check" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person circle check", "approved", "not affected", "ok", "okay" })] + [FontAwesomeSearchTerms(new[] { "person circle check", "approved", "enable", "not affected", "ok", "okay", "uer", "validate", "working" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Users + People" })] PersonCircleCheck = 0xE53E, /// /// The Font Awesome "person-circle-exclamation" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person circle exclamation", "affected", "alert", "lost", "missing" })] + [FontAwesomeSearchTerms(new[] { "person circle exclamation", "affected", "alert", "failed", "lost", "missing", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Users + People" })] PersonCircleExclamation = 0xE53F, /// /// The Font Awesome "person-circle-minus" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person circle minus", "delete", "remove" })] + [FontAwesomeSearchTerms(new[] { "person circle minus", "delete", "remove", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Users + People" })] PersonCircleMinus = 0xE540, /// /// The Font Awesome "person-circle-plus" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person circle plus", "add", "found" })] + [FontAwesomeSearchTerms(new[] { "person circle plus", "add", "follow", "found", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Users + People" })] PersonCirclePlus = 0xE541, /// /// The Font Awesome "person-circle-question" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person circle question", "lost", "missing" })] + [FontAwesomeSearchTerms(new[] { "person circle question", "faq", "lost", "missing", "request", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Users + People" })] PersonCircleQuestion = 0xE542, /// /// The Font Awesome "person-circle-xmark" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person circle xmark", "dead", "removed" })] + [FontAwesomeSearchTerms(new[] { "person circle xmark", "dead", "removed", "uer", "uncheck" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Users + People" })] PersonCircleXmark = 0xE543, /// /// The Font Awesome "person-digging" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person digging", "bury", "construction", "debris", "dig", "men at work" })] + [FontAwesomeSearchTerms(new[] { "person digging", "bury", "construction", "debris", "dig", "maintenance", "men at work", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Construction", "Humanitarian", "Users + People" })] PersonDigging = 0xF85E, /// /// The Font Awesome "person-dress-burst" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person dress burst", "abuse", "accident", "crash", "explode", "violence" })] + [FontAwesomeSearchTerms(new[] { "person dress burst", "abuse", "accident", "crash", "explode", "uer", "violence" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Security", "Users + People" })] PersonDressBurst = 0xE544, @@ -6219,112 +6319,112 @@ public enum FontAwesomeIcon /// /// The Font Awesome "person-falling" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person falling", "accident", "fall", "trip" })] + [FontAwesomeSearchTerms(new[] { "person falling", "accident", "fall", "trip", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Users + People" })] PersonFalling = 0xE546, /// /// The Font Awesome "person-falling-burst" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person falling burst", "accident", "crash", "death", "fall", "homicide", "murder" })] + [FontAwesomeSearchTerms(new[] { "person falling burst", "accident", "crash", "death", "fall", "homicide", "murder", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Security", "Users + People" })] PersonFallingBurst = 0xE547, /// /// The Font Awesome "person-half-dress" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person half dress", "gender", "man", "restroom", "transgender", "woman" })] + [FontAwesomeSearchTerms(new[] { "person half dress", "gender", "man", "restroom", "transgender", "uer", "woman" })] [FontAwesomeCategoriesAttribute(new[] { "Genders", "Humanitarian", "Medical + Health", "Users + People" })] PersonHalfDress = 0xE548, /// /// The Font Awesome "person-harassing" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person harassing", "abuse", "scream", "shame", "shout", "yell" })] + [FontAwesomeSearchTerms(new[] { "person harassing", "abuse", "scream", "shame", "shout", "uer", "yell" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Security", "Users + People" })] PersonHarassing = 0xE549, /// /// The Font Awesome "person-military-pointing" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person military pointing", "army", "customs", "guard" })] + [FontAwesomeSearchTerms(new[] { "person military pointing", "army", "customs", "guard", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Security", "Users + People" })] PersonMilitaryPointing = 0xE54A, /// /// The Font Awesome "person-military-rifle" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person military rifle", "armed forces", "army", "military", "rifle", "war" })] + [FontAwesomeSearchTerms(new[] { "person military rifle", "armed forces", "army", "military", "rifle", "uer", "war" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Security", "Users + People" })] PersonMilitaryRifle = 0xE54B, /// /// The Font Awesome "person-military-to-person" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person military to person", "civilian", "coordination", "military" })] + [FontAwesomeSearchTerms(new[] { "person military to person", "civilian", "coordination", "military", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Security", "Users + People" })] PersonMilitaryToPerson = 0xE54C, /// /// The Font Awesome "person-pregnant" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person pregnant", "baby", "birth", "child", "pregnant", "pregnant woman", "woman" })] + [FontAwesomeSearchTerms(new[] { "person pregnant", "baby", "birth", "child", "parent", "pregnant", "pregnant woman", "uer", "woman" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Users + People" })] PersonPregnant = 0xE31E, /// /// The Font Awesome "person-rays" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person rays", "affected", "focus", "shine" })] + [FontAwesomeSearchTerms(new[] { "person rays", "affected", "focus", "shine", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Marketing", "Users + People" })] PersonRays = 0xE54D, /// /// The Font Awesome "person-rifle" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person rifle", "army", "combatant", "gun", "military", "rifle", "war" })] + [FontAwesomeSearchTerms(new[] { "person rifle", "army", "combatant", "gun", "military", "rifle", "uer", "war" })] [FontAwesomeCategoriesAttribute(new[] { "Disaster + Crisis", "Humanitarian", "Security", "Users + People" })] PersonRifle = 0xE54E, /// /// The Font Awesome "person-shelter" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person shelter", "house", "inside", "roof", "safe", "safety", "shelter" })] + [FontAwesomeSearchTerms(new[] { "person shelter", "house", "inside", "roof", "safe", "safety", "shelter", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Camping", "Humanitarian", "Security", "Users + People" })] PersonShelter = 0xE54F, /// /// The Font Awesome "person-through-window" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person through window", "door", "exit", "forced entry", "leave", "robbery", "steal", "window" })] + [FontAwesomeSearchTerms(new[] { "person through window", "door", "exit", "forced entry", "leave", "robbery", "steal", "uer", "window" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Security", "Users + People" })] PersonThroughWindow = 0xE5A9, /// /// The Font Awesome "person-walking-arrow-loop-left" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person walking arrow loop left", "population return", "return" })] + [FontAwesomeSearchTerms(new[] { "person walking arrow loop left", "follow", "population return", "return", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Disaster + Crisis", "Humanitarian", "Users + People" })] PersonWalkingArrowLoopLeft = 0xE551, /// /// The Font Awesome "person-walking-arrow-right" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person walking arrow right", "exit", "internally displaced", "leave", "refugee" })] + [FontAwesomeSearchTerms(new[] { "person walking arrow right", "exit", "follow", "internally displaced", "leave", "refugee", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Disaster + Crisis", "Humanitarian", "Users + People" })] PersonWalkingArrowRight = 0xE552, /// /// The Font Awesome "person-walking-dashed-line-arrow-right" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person walking dashed line arrow right", "exit", "refugee" })] + [FontAwesomeSearchTerms(new[] { "person walking dashed line arrow right", "exit", "follow", "refugee", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Disaster + Crisis", "Humanitarian", "Users + People" })] PersonWalkingDashedLineArrowRight = 0xE553, /// /// The Font Awesome "person-walking-luggage" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person walking luggage", "bag", "baggage", "briefcase", "carry-on", "deployment", "rolling" })] + [FontAwesomeSearchTerms(new[] { "person walking luggage", "bag", "baggage", "briefcase", "carry-on", "deployment", "follow", "rolling", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Travel + Hotel", "Users + People" })] PersonWalkingLuggage = 0xE554, @@ -6345,7 +6445,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "phone" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "left hand telephone receiver", "call", "earphone", "number", "phone", "receiver", "support", "telephone", "telephone receiver", "voice" })] + [FontAwesomeSearchTerms(new[] { "left hand telephone receiver", "call", "earphone", "number", "phone", "receiver", "support", "talking", "telephone", "telephone receiver", "voice" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Communication", "Maps" })] Phone = 0xF095, @@ -6359,7 +6459,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "phone-slash" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "phone slash", "call", "cancel", "earphone", "mute", "number", "support", "telephone", "voice" })] + [FontAwesomeSearchTerms(new[] { "phone slash", "call", "cancel", "disabled", "disconnect", "earphone", "mute", "number", "support", "telephone", "voice" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Communication" })] PhoneSlash = 0xF3DD, @@ -6380,7 +6480,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "phone-volume" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "phone volume", "call", "earphone", "number", "sound", "support", "telephone", "voice", "volume-control-phone" })] + [FontAwesomeSearchTerms(new[] { "phone volume", "call", "earphone", "number", "ring", "ringing", "sound", "support", "talking", "telephone", "voice", "volume-control-phone" })] [FontAwesomeCategoriesAttribute(new[] { "Accessibility", "Business", "Communication", "Maps", "Media Playback" })] PhoneVolume = 0xF2A0, @@ -6394,7 +6494,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "piggy-bank" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "piggy bank", "bank", "save", "savings" })] + [FontAwesomeSearchTerms(new[] { "piggy bank", "bank", "salary", "save", "savings" })] [FontAwesomeCategoriesAttribute(new[] { "Charity", "Money", "Political" })] PiggyBank = 0xF4D3, @@ -6430,27 +6530,27 @@ public enum FontAwesomeIcon /// The Font Awesome "plane-arrival" icon unicode character. /// [FontAwesomeSearchTerms(new[] { "plane arrival", "aeroplane", "airplane", "airplane arrival", "airport", "arrivals", "arriving", "destination", "fly", "land", "landing", "location", "mode", "travel", "trip" })] - [FontAwesomeCategoriesAttribute(new[] { "Travel + Hotel" })] + [FontAwesomeCategoriesAttribute(new[] { "Transportation", "Travel + Hotel" })] PlaneArrival = 0xF5AF, /// /// The Font Awesome "plane-circle-check" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "plane circle check", "airplane", "airport", "flight", "fly", "not affected", "ok", "okay", "travel" })] + [FontAwesomeSearchTerms(new[] { "plane circle check", "airplane", "airport", "enable", "flight", "fly", "not affected", "ok", "okay", "travel", "validate", "working" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Logistics", "Travel + Hotel" })] PlaneCircleCheck = 0xE555, /// /// The Font Awesome "plane-circle-exclamation" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "plane circle exclamation", "affected", "airplane", "airport", "flight", "fly", "travel" })] + [FontAwesomeSearchTerms(new[] { "plane circle exclamation", "affected", "airplane", "airport", "failed", "flight", "fly", "travel" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Logistics", "Travel + Hotel" })] PlaneCircleExclamation = 0xE556, /// /// The Font Awesome "plane-circle-xmark" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "plane circle xmark", "airplane", "airport", "destroy", "flight", "fly", "travel" })] + [FontAwesomeSearchTerms(new[] { "plane circle xmark", "airplane", "airport", "destroy", "flight", "fly", "travel", "uncheck" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Logistics", "Travel + Hotel" })] PlaneCircleXmark = 0xE557, @@ -6464,14 +6564,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "plane-lock" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "plane lock", "airplane", "airport", "closed", "flight", "fly", "lockdown", "quarantine", "travel" })] + [FontAwesomeSearchTerms(new[] { "plane lock", "airplane", "airport", "closed", "flight", "fly", "lockdown", "padlock", "privacy", "quarantine", "travel" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Logistics", "Travel + Hotel" })] PlaneLock = 0xE558, /// /// The Font Awesome "plane-slash" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "plane slash", "airplane mode", "airport", "canceled", "covid-19", "delayed", "grounded", "travel" })] + [FontAwesomeSearchTerms(new[] { "plane slash", "airplane mode", "airport", "canceled", "covid-19", "delayed", "disabled", "grounded", "travel" })] [FontAwesomeCategoriesAttribute(new[] { "Transportation", "Travel + Hotel" })] PlaneSlash = 0xE069, @@ -6527,21 +6627,21 @@ public enum FontAwesomeIcon /// /// The Font Awesome "plug-circle-check" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "plug circle check", "electric", "electricity", "not affected", "ok", "okay", "plug", "power" })] + [FontAwesomeSearchTerms(new[] { "plug circle check", "electric", "electricity", "enable", "not affected", "ok", "okay", "plug", "power", "validate", "working" })] [FontAwesomeCategoriesAttribute(new[] { "Energy", "Humanitarian" })] PlugCircleCheck = 0xE55C, /// /// The Font Awesome "plug-circle-exclamation" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "plug circle exclamation", "affected", "electric", "electricity", "plug", "power" })] + [FontAwesomeSearchTerms(new[] { "plug circle exclamation", "affected", "electric", "electricity", "failed", "plug", "power" })] [FontAwesomeCategoriesAttribute(new[] { "Energy", "Humanitarian" })] PlugCircleExclamation = 0xE55D, /// /// The Font Awesome "plug-circle-minus" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "plug circle minus", "electric", "electricity", "plug", "power" })] + [FontAwesomeSearchTerms(new[] { "plug circle minus", "disconnect", "electric", "electricity", "plug", "power" })] [FontAwesomeCategoriesAttribute(new[] { "Energy", "Humanitarian" })] PlugCircleMinus = 0xE55E, @@ -6555,7 +6655,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "plug-circle-xmark" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "plug circle xmark", "destroy", "electric", "electricity", "outage", "plug", "power" })] + [FontAwesomeSearchTerms(new[] { "plug circle xmark", "destroy", "disconnect", "electric", "electricity", "outage", "plug", "power", "uncheck" })] [FontAwesomeCategoriesAttribute(new[] { "Energy", "Humanitarian" })] PlugCircleXmark = 0xE560, @@ -6563,7 +6663,7 @@ public enum FontAwesomeIcon /// The Font Awesome "plus" icon unicode character. /// Uses a legacy unicode value for backwards compatability. The current unicode value is 0x2B. /// - [FontAwesomeSearchTerms(new[] { "+", "plus sign", "add", "create", "expand", "math", "new", "plus", "positive", "shape", "sign" })] + [FontAwesomeSearchTerms(new[] { "+", "plus sign", "add", "create", "expand", "follow", "math", "modify", "new", "plus", "positive", "shape", "sign" })] [FontAwesomeCategoriesAttribute(new[] { "Editing", "Maps", "Mathematics", "Medical + Health", "Punctuation + Symbols" })] Plus = 0xF067, @@ -6598,21 +6698,21 @@ public enum FontAwesomeIcon /// /// The Font Awesome "square-poll-vertical" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "square poll vertical", "chart", "graph", "results", "survey", "trend", "vote", "voting" })] + [FontAwesomeSearchTerms(new[] { "square poll vertical", "chart", "graph", "results", "revenue", "statistics", "survey", "trend", "vote", "voting" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Charts + Diagrams", "Marketing", "Social" })] Poll = 0xF681, /// /// The Font Awesome "square-poll-horizontal" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "square poll horizontal", "chart", "graph", "results", "survey", "trend", "vote", "voting" })] + [FontAwesomeSearchTerms(new[] { "square poll horizontal", "chart", "graph", "results", "statistics", "survey", "trend", "vote", "voting" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Charts + Diagrams", "Marketing", "Social" })] PollH = 0xF682, /// /// The Font Awesome "poo" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "crap", "dung", "face", "monster", "pile of poo", "poo", "poop", "shit", "smile", "turd" })] + [FontAwesomeSearchTerms(new[] { "crap", "dung", "face", "monster", "pile of poo", "poo", "poop", "shit", "smile", "turd", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Communication", "Users + People" })] Poo = 0xF2FE, @@ -6633,7 +6733,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "image-portrait" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "image portrait", "id", "image", "photo", "picture", "selfie" })] + [FontAwesomeSearchTerms(new[] { "image portrait", "id", "image", "img", "photo", "picture", "selfie", "uer", "username" })] [FontAwesomeCategoriesAttribute(new[] { "Photos + Images", "Users + People" })] Portrait = 0xF3E0, @@ -6654,7 +6754,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "person-praying" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person praying", "kneel", "place of worship", "religion", "thank", "worship" })] + [FontAwesomeSearchTerms(new[] { "person praying", "kneel", "place of worship", "religion", "thank", "uer", "worship" })] [FontAwesomeCategoriesAttribute(new[] { "Religion", "Users + People" })] Pray = 0xF683, @@ -6703,7 +6803,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "diagram-project" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "diagram project", "chart", "graph", "network", "pert" })] + [FontAwesomeSearchTerms(new[] { "diagram project", "chart", "graph", "network", "pert", "statistics" })] [FontAwesomeCategoriesAttribute(new[] { "Charts + Diagrams", "Coding" })] ProjectDiagram = 0xF542, @@ -6731,22 +6831,22 @@ public enum FontAwesomeIcon /// /// The Font Awesome "qrcode" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "qrcode", "barcode", "info", "information", "scan" })] - [FontAwesomeCategoriesAttribute(new[] { "Coding" })] + [FontAwesomeSearchTerms(new[] { "qrcode", "barcode", "info", "information", "qr", "qr-code", "scan" })] + [FontAwesomeCategoriesAttribute(new[] { "Coding", "Shopping" })] Qrcode = 0xF029, /// /// The Font Awesome "question" icon unicode character. /// Uses a legacy unicode value for backwards compatability. The current unicode value is 0x3F. /// - [FontAwesomeSearchTerms(new[] { "?", "question mark", "help", "information", "mark", "outlined", "punctuation", "question", "red question mark", "support", "unknown", "white question mark" })] + [FontAwesomeSearchTerms(new[] { "?", "question mark", "faq", "help", "information", "mark", "outlined", "punctuation", "question", "red question mark", "request", "support", "unknown", "white question mark" })] [FontAwesomeCategoriesAttribute(new[] { "Accessibility", "Alert", "Punctuation + Symbols" })] Question = 0xF128, /// /// The Font Awesome "circle-question" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "circle question", "help", "information", "support", "unknown" })] + [FontAwesomeSearchTerms(new[] { "circle question", "faq", "help", "information", "support", "unknown" })] [FontAwesomeCategoriesAttribute(new[] { "Accessibility", "Punctuation + Symbols" })] QuestionCircle = 0xF059, @@ -6816,14 +6916,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "ranking-star" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "ranking star", "chart", "first place", "podium", "rank", "win" })] + [FontAwesomeSearchTerms(new[] { "ranking star", "chart", "first place", "podium", "quality", "rank", "revenue", "win" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Marketing", "Sports + Fitness" })] RankingStar = 0xE561, /// /// The Font Awesome "receipt" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "accounting", "bookkeeping", "check", "evidence", "invoice", "money", "pay", "proof", "receipt", "table" })] + [FontAwesomeSearchTerms(new[] { "accounting", "bookkeeping", "check", "coupon", "evidence", "invoice", "money", "pay", "proof", "receipt", "table" })] [FontAwesomeCategoriesAttribute(new[] { "Medical + Health", "Money", "Shopping" })] Receipt = 0xF543, @@ -6844,15 +6944,15 @@ public enum FontAwesomeIcon /// /// The Font Awesome "arrow-rotate-right" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "arrow rotate right", "clockwise open circle arrow", "forward", "refresh", "reload", "repeat" })] - [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Media Playback" })] + [FontAwesomeSearchTerms(new[] { "arrow rotate right", "clockwise open circle arrow", "forward", "refresh", "reload", "renew", "repeat", "retry" })] + [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Media Playback", "Spinners" })] Redo = 0xF01E, /// /// The Font Awesome "rotate-right" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "rotate right", "forward", "refresh", "reload", "repeat" })] - [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Media Playback" })] + [FontAwesomeSearchTerms(new[] { "rotate right", "forward", "refresh", "reload", "renew", "repeat", "retry" })] + [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Media Playback", "Spinners" })] RedoAlt = 0xF2F9, /// @@ -6865,14 +6965,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "text-slash" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "text slash", "cancel", "font", "format", "remove", "style", "text" })] + [FontAwesomeSearchTerms(new[] { "text slash", "cancel", "disabled", "font", "format", "remove", "style", "text" })] [FontAwesomeCategoriesAttribute(new[] { "Text Formatting" })] RemoveFormat = 0xF87D, /// /// The Font Awesome "repeat" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "arrow", "clockwise", "flip", "reload", "repeat", "repeat button", "rewind", "switch" })] + [FontAwesomeSearchTerms(new[] { "arrow", "clockwise", "flip", "reload", "renew", "repeat", "repeat button", "retry", "rewind", "switch" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Media Playback" })] Repeat = 0xF363, @@ -6900,14 +7000,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "restroom" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "restroom", "bathroom", "toilet", "water closet", "wc" })] + [FontAwesomeSearchTerms(new[] { "restroom", "bathroom", "toilet", "uer", "water closet", "wc" })] [FontAwesomeCategoriesAttribute(new[] { "Maps", "Users + People" })] Restroom = 0xF7BD, /// /// The Font Awesome "retweet" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "retweet", "refresh", "reload", "share", "swap" })] + [FontAwesomeSearchTerms(new[] { "retweet", "refresh", "reload", "renew", "retry", "share", "swap" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Social" })] Retweet = 0xF079, @@ -6921,7 +7021,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "ring" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "ring", "dungeons & dragons", "gollum", "band", "binding", "d&d", "dnd", "engagement", "fantasy", "gold", "jewelry", "marriage", "precious" })] + [FontAwesomeSearchTerms(new[] { "ring", "dungeons & dragons", "gollum", "band", "binding", "d&d", "dnd", "engagement", "fantasy", "gold", "jewelry", "marriage", "precious", "premium" })] [FontAwesomeCategoriesAttribute(new[] { "Gaming", "Spinners" })] Ring = 0xF70B, @@ -6949,28 +7049,28 @@ public enum FontAwesomeIcon /// /// The Font Awesome "road-circle-check" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "road circle check", "freeway", "highway", "not affected", "ok", "okay", "pavement", "road" })] + [FontAwesomeSearchTerms(new[] { "road circle check", "enable", "freeway", "highway", "not affected", "ok", "okay", "pavement", "road", "validate", "working" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Logistics" })] RoadCircleCheck = 0xE564, /// /// The Font Awesome "road-circle-exclamation" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "road circle exclamation", "affected", "freeway", "highway", "pavement", "road" })] + [FontAwesomeSearchTerms(new[] { "road circle exclamation", "affected", "failed", "freeway", "highway", "pavement", "road" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Logistics" })] RoadCircleExclamation = 0xE565, /// /// The Font Awesome "road-circle-xmark" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "road circle xmark", "destroy", "freeway", "highway", "pavement", "road" })] + [FontAwesomeSearchTerms(new[] { "road circle xmark", "destroy", "freeway", "highway", "pavement", "road", "uncheck" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Logistics" })] RoadCircleXmark = 0xE566, /// /// The Font Awesome "road-lock" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "road lock", "closed", "freeway", "highway", "lockdown", "pavement", "quarantine", "road" })] + [FontAwesomeSearchTerms(new[] { "road lock", "closed", "freeway", "highway", "lockdown", "padlock", "pavement", "privacy", "quarantine", "road" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Logistics" })] RoadLock = 0xE567, @@ -7061,7 +7161,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "person-running" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person running", "exit", "flee", "marathon", "person running", "race", "running" })] + [FontAwesomeSearchTerms(new[] { "person running", "exit", "flee", "follow", "marathon", "person running", "race", "running", "uer", "workout" })] [FontAwesomeCategoriesAttribute(new[] { "Sports + Fitness", "Users + People" })] Running = 0xF70C, @@ -7082,14 +7182,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "sack-dollar" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "sack dollar", "bag", "burlap", "cash", "dollar", "money", "money bag", "moneybag", "robber", "santa", "usd" })] + [FontAwesomeSearchTerms(new[] { "sack dollar", "bag", "burlap", "cash", "dollar", "investment", "money", "money bag", "moneybag", "premium", "robber", "salary", "santa", "usd" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Money" })] SackDollar = 0xF81D, /// /// The Font Awesome "sack-xmark" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "sack xmark", "bag", "burlap", "rations" })] + [FontAwesomeSearchTerms(new[] { "sack xmark", "bag", "burlap", "coupon", "rations", "salary", "uncheck" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Money" })] SackXmark = 0xE56A, @@ -7145,21 +7245,21 @@ public enum FontAwesomeIcon /// /// The Font Awesome "school-circle-check" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "school circle check", "not affected", "ok", "okay", "schoolhouse" })] + [FontAwesomeSearchTerms(new[] { "school circle check", "enable", "not affected", "ok", "okay", "schoolhouse", "validate", "working" })] [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Education", "Humanitarian" })] SchoolCircleCheck = 0xE56B, /// /// The Font Awesome "school-circle-exclamation" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "school circle exclamation", "affected", "schoolhouse" })] + [FontAwesomeSearchTerms(new[] { "school circle exclamation", "affected", "failed", "schoolhouse" })] [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Education", "Humanitarian" })] SchoolCircleExclamation = 0xE56C, /// /// The Font Awesome "school-circle-xmark" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "school circle xmark", "destroy", "schoolhouse" })] + [FontAwesomeSearchTerms(new[] { "school circle xmark", "destroy", "schoolhouse", "uncheck" })] [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Education", "Humanitarian" })] SchoolCircleXmark = 0xE56D, @@ -7173,63 +7273,63 @@ public enum FontAwesomeIcon /// /// The Font Awesome "school-lock" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "school lock", "closed", "lockdown", "quarantine", "schoolhouse" })] + [FontAwesomeSearchTerms(new[] { "school lock", "closed", "lockdown", "padlock", "privacy", "quarantine", "schoolhouse" })] [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Education", "Humanitarian" })] SchoolLock = 0xE56F, /// /// The Font Awesome "screwdriver" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "admin", "fix", "mechanic", "repair", "screw", "screwdriver", "settings", "tool" })] + [FontAwesomeSearchTerms(new[] { "admin", "configuration", "equipment", "fix", "maintenance", "mechanic", "modify", "repair", "screw", "screwdriver", "settings", "tool" })] [FontAwesomeCategoriesAttribute(new[] { "Construction" })] Screwdriver = 0xF54A, /// /// The Font Awesome "scroll" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "dungeons & dragons", "announcement", "d&d", "dnd", "fantasy", "paper", "script", "scroll" })] + [FontAwesomeSearchTerms(new[] { "dungeons & dragons", "announcement", "d&d", "dnd", "fantasy", "paper", "scholar", "script", "scroll" })] [FontAwesomeCategoriesAttribute(new[] { "Gaming" })] Scroll = 0xF70E, /// /// The Font Awesome "sd-card" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "sd card", "image", "memory", "photo", "save" })] + [FontAwesomeSearchTerms(new[] { "sd card", "image", "img", "memory", "photo", "save" })] [FontAwesomeCategoriesAttribute(new[] { "Devices + Hardware" })] SdCard = 0xF7C2, /// /// The Font Awesome "magnifying-glass" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "magnifying glass", "bigger", "enlarge", "find", "glass", "magnify", "magnifying", "magnifying glass tilted left", "preview", "search", "tool", "zoom" })] + [FontAwesomeSearchTerms(new[] { "magnifying glass", "bigger", "enlarge", "equipment", "find", "glass", "inspection", "magnifier", "magnify", "magnifying", "magnifying glass tilted left", "preview", "search", "tool", "zoom" })] [FontAwesomeCategoriesAttribute(new[] { "Maps" })] Search = 0xF002, /// /// The Font Awesome "magnifying-glass-dollar" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "magnifying glass dollar", "bigger", "enlarge", "find", "magnify", "money", "preview", "zoom" })] + [FontAwesomeSearchTerms(new[] { "magnifying glass dollar", "bigger", "enlarge", "find", "magnifier", "magnify", "money", "preview", "zoom" })] [FontAwesomeCategoriesAttribute(new[] { "Marketing" })] SearchDollar = 0xF688, /// /// The Font Awesome "magnifying-glass-location" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "magnifying glass location", "bigger", "enlarge", "find", "magnify", "preview", "zoom" })] - [FontAwesomeCategoriesAttribute(new[] { "Marketing" })] + [FontAwesomeSearchTerms(new[] { "magnifying glass location", "bigger", "enlarge", "find", "magnifier", "magnify", "preview", "zoom" })] + [FontAwesomeCategoriesAttribute(new[] { "Maps", "Marketing" })] SearchLocation = 0xF689, /// /// The Font Awesome "magnifying-glass-minus" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "magnifying glass minus", "minify", "negative", "smaller", "zoom", "zoom out" })] + [FontAwesomeSearchTerms(new[] { "magnifying glass minus", "magnifier", "minify", "negative", "smaller", "zoom", "zoom out" })] [FontAwesomeCategoriesAttribute(new[] { "Maps" })] SearchMinus = 0xF010, /// /// The Font Awesome "magnifying-glass-plus" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "magnifying glass plus", "bigger", "enlarge", "magnify", "positive", "zoom", "zoom in" })] + [FontAwesomeSearchTerms(new[] { "magnifying glass plus", "bigger", "enlarge", "magnifier", "magnify", "positive", "zoom", "zoom in" })] [FontAwesomeCategoriesAttribute(new[] { "Maps" })] SearchPlus = 0xF00E, @@ -7243,14 +7343,21 @@ public enum FontAwesomeIcon /// /// The Font Awesome "seedling" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "environment", "flora", "grow", "plant", "sapling", "seedling", "vegan", "young" })] + [FontAwesomeSearchTerms(new[] { "environment", "flora", "grow", "investment", "plant", "sapling", "seedling", "vegan", "young" })] [FontAwesomeCategoriesAttribute(new[] { "Charity", "Energy", "Food + Beverage", "Fruits + Vegetables", "Humanitarian", "Nature", "Science" })] Seedling = 0xF4D8, + /// + /// The Font Awesome "septagon" icon unicode character. + /// + [FontAwesomeSearchTerms(new[] { "septagon", "7", "heptagon", "seven", "shape" })] + [FontAwesomeCategoriesAttribute(new[] { "Shapes" })] + Septagon = 0xE820, + /// /// The Font Awesome "server" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "server", "computer", "cpu", "database", "hardware", "network" })] + [FontAwesomeSearchTerms(new[] { "server", "computer", "cpu", "database", "hardware", "mysql", "network", "sql" })] [FontAwesomeCategoriesAttribute(new[] { "Devices + Hardware" })] Server = 0xF233, @@ -7313,7 +7420,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "shield-halved" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "shield halved", "achievement", "armor", "award", "block", "cleric", "defend", "defense", "holy", "paladin", "security", "shield", "weapon", "winner" })] + [FontAwesomeSearchTerms(new[] { "shield halved", "achievement", "armor", "award", "block", "cleric", "defend", "defense", "holy", "paladin", "privacy", "security", "shield", "weapon", "winner" })] [FontAwesomeCategoriesAttribute(new[] { "Coding", "Gaming", "Security" })] ShieldAlt = 0xF3ED, @@ -7334,7 +7441,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "shield-heart" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "shield heart", "love", "protect", "safe", "safety", "shield" })] + [FontAwesomeSearchTerms(new[] { "shield heart", "love", "protect", "safe", "safety", "shield", "wishlist" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Security" })] ShieldHeart = 0xE574, @@ -7355,7 +7462,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "truck-fast" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "truck fast", "express", "fedex", "mail", "overnight", "package", "ups" })] + [FontAwesomeSearchTerms(new[] { "truck fast", "express", "fedex", "mail", "overnight", "package", "quick", "ups" })] [FontAwesomeCategoriesAttribute(new[] { "Logistics", "Shopping" })] ShippingFast = 0xF48B, @@ -7369,7 +7476,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "shop-lock" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "shop lock", "bodega", "building", "buy", "closed", "lock", "lockdown", "market", "purchase", "quarantine", "shop", "shopping", "store" })] + [FontAwesomeSearchTerms(new[] { "shop lock", "bodega", "building", "buy", "closed", "lock", "lockdown", "market", "padlock", "privacy", "purchase", "quarantine", "shop", "shopping", "store" })] [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Humanitarian", "Shopping" })] ShopLock = 0xE4A5, @@ -7397,7 +7504,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "shop-slash" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "shop slash", "building", "buy", "closed", "covid-19", "purchase", "shopping" })] + [FontAwesomeSearchTerms(new[] { "shop slash", "building", "buy", "closed", "disabled", "purchase", "shopping" })] [FontAwesomeCategoriesAttribute(new[] { "Shopping" })] ShopSlash = 0xE070, @@ -7418,7 +7525,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "van-shuttle" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "van shuttle", "airport", "bus", "machine", "minibus", "public-transportation", "transportation", "travel", "vehicle" })] + [FontAwesomeSearchTerms(new[] { "van shuttle", "airport", "bus", "minibus", "public-transportation", "transportation", "travel", "vehicle" })] [FontAwesomeCategoriesAttribute(new[] { "Automotive", "Transportation", "Travel + Hotel" })] ShuttleVan = 0xF5B6, @@ -7439,7 +7546,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "signature" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "signature", "john hancock", "cursive", "name", "writing" })] + [FontAwesomeSearchTerms(new[] { "signature", "john hancock", "cursive", "name", "username", "writing" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Editing", "Writing" })] Signature = 0xF5B7, @@ -7471,6 +7578,20 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Devices + Hardware" })] SimCard = 0xF7C4, + /// + /// The Font Awesome "single-quote-left" icon unicode character. + /// + [FontAwesomeSearchTerms(new[] { "single quote left", "left single quotation mark", "mention", "note", "phrase", "text", "type" })] + [FontAwesomeCategoriesAttribute(new[] { "Communication", "Punctuation + Symbols", "Writing" })] + SingleQuoteLeft = 0xE81B, + + /// + /// The Font Awesome "single-quote-right" icon unicode character. + /// + [FontAwesomeSearchTerms(new[] { "single quote right", "mention", "note", "phrase", "right single quotation mark", "text", "type" })] + [FontAwesomeCategoriesAttribute(new[] { "Communication", "Punctuation + Symbols", "Writing" })] + SingleQuoteRight = 0xE81C, + /// /// The Font Awesome "sink" icon unicode character. /// @@ -7488,28 +7609,28 @@ public enum FontAwesomeIcon /// /// The Font Awesome "person-skating" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person skating", "figure skating", "ice", "olympics", "rink", "skate", "winter" })] + [FontAwesomeSearchTerms(new[] { "person skating", "figure skating", "ice", "olympics", "rink", "skate", "uer", "winter" })] [FontAwesomeCategoriesAttribute(new[] { "Sports + Fitness", "Users + People" })] Skating = 0xF7C5, /// /// The Font Awesome "person-skiing" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person skiing", "downhill", "olympics", "ski", "skier", "snow", "winter" })] + [FontAwesomeSearchTerms(new[] { "person skiing", "downhill", "olympics", "ski", "skier", "snow", "uer", "winter" })] [FontAwesomeCategoriesAttribute(new[] { "Sports + Fitness", "Users + People" })] Skiing = 0xF7C9, /// /// The Font Awesome "person-skiing-nordic" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person skiing nordic", "cross country", "olympics", "winter" })] + [FontAwesomeSearchTerms(new[] { "person skiing nordic", "cross country", "olympics", "uer", "winter" })] [FontAwesomeCategoriesAttribute(new[] { "Sports + Fitness", "Users + People" })] SkiingNordic = 0xF7CA, /// /// The Font Awesome "skull" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "bones", "death", "face", "fairy tale", "monster", "skeleton", "skull", "x-ray", "yorick" })] + [FontAwesomeSearchTerms(new[] { "bones", "death", "face", "fairy tale", "monster", "skeleton", "skull", "uer", "x-ray", "yorick" })] [FontAwesomeCategoriesAttribute(new[] { "Halloween", "Medical + Health", "Users + People" })] Skull = 0xF54C, @@ -7537,14 +7658,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "sliders" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "adjust", "settings", "sliders", "toggle" })] - [FontAwesomeCategoriesAttribute(new[] { "Editing", "Media Playback", "Music + Audio", "Photos + Images" })] + [FontAwesomeSearchTerms(new[] { "adjust", "configuration", "modify", "settings", "sliders", "toggle" })] + [FontAwesomeCategoriesAttribute(new[] { "Editing", "Media Playback", "Music + Audio", "Photos + Images", "Toggle" })] SlidersH = 0xF1DE, /// /// The Font Awesome "face-smile" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "face smile", "approve", "emoticon", "face", "happy", "rating", "satisfied", "slightly smiling face", "smile" })] + [FontAwesomeSearchTerms(new[] { "face smile", "approve", "default", "emoticon", "face", "happy", "rating", "satisfied", "slightly smiling face", "smile", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Communication", "Emoji", "Users + People" })] Smile = 0xF118, @@ -7579,21 +7700,21 @@ public enum FontAwesomeIcon /// /// The Font Awesome "ban-smoking" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "ban smoking", "ban", "cancel", "forbidden", "no", "no smoking", "non-smoking", "not", "prohibited", "smoking" })] + [FontAwesomeSearchTerms(new[] { "ban smoking", "ban", "cancel", "circle", "deny", "disabled", "forbidden", "no", "no smoking", "non-smoking", "not", "prohibited", "slash", "smoking" })] [FontAwesomeCategoriesAttribute(new[] { "Medical + Health", "Travel + Hotel" })] SmokingBan = 0xF54D, /// /// The Font Awesome "comment-sms" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "comment sms", "chat", "conversation", "message", "mobile", "notification", "phone", "sms", "texting" })] + [FontAwesomeSearchTerms(new[] { "comment sms", "answer", "chat", "conversation", "message", "mobile", "notification", "phone", "sms", "texting" })] [FontAwesomeCategoriesAttribute(new[] { "Communication" })] Sms = 0xF7CD, /// /// The Font Awesome "person-snowboarding" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person snowboarding", "olympics", "ski", "snow", "snowboard", "snowboarder", "winter" })] + [FontAwesomeSearchTerms(new[] { "person snowboarding", "olympics", "ski", "snow", "snowboard", "snowboarder", "uer", "winter" })] [FontAwesomeCategoriesAttribute(new[] { "Sports + Fitness", "Users + People" })] Snowboarding = 0xF7CE, @@ -7691,7 +7812,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "arrow-up-wide-short" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "arrow up wide short", "arrange", "filter", "order", "sort-amount-desc" })] + [FontAwesomeSearchTerms(new[] { "arrow up wide short", "arrange", "filter", "order", "sort-amount-desc", "upgrade" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows" })] SortAmountUp = 0xF161, @@ -7705,7 +7826,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "sort-down" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "sort down", "arrow", "descending", "filter", "order", "sort-desc" })] + [FontAwesomeSearchTerms(new[] { "sort down", "arrow", "descending", "filter", "insert", "order", "sort-desc" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows" })] SortDown = 0xF0DD, @@ -7740,7 +7861,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "sort-up" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "sort up", "arrow", "ascending", "filter", "order", "sort-asc" })] + [FontAwesomeSearchTerms(new[] { "sort up", "arrow", "ascending", "filter", "order", "sort-asc", "upgrade" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows" })] SortUp = 0xF0DE, @@ -7761,7 +7882,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "spell-check" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "spell check", "dictionary", "edit", "editor", "grammar", "text" })] + [FontAwesomeSearchTerms(new[] { "spell check", "dictionary", "edit", "editor", "enable", "grammar", "text", "validate", "working" })] [FontAwesomeCategoriesAttribute(new[] { "Text Formatting" })] SpellCheck = 0xF891, @@ -7775,10 +7896,17 @@ public enum FontAwesomeIcon /// /// The Font Awesome "spinner" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "spinner", "circle", "loading", "progress" })] + [FontAwesomeSearchTerms(new[] { "spinner", "circle", "loading", "pending", "progress" })] [FontAwesomeCategoriesAttribute(new[] { "Spinners" })] Spinner = 0xF110, + /// + /// The Font Awesome "spiral" icon unicode character. + /// + [FontAwesomeSearchTerms(new[] { "spiral", "design", "dizzy", "rotate", "spin", "swirl", "twist" })] + [FontAwesomeCategoriesAttribute(new[] { "Design", "Shapes" })] + Spiral = 0xE80A, + /// /// The Font Awesome "splotch" icon unicode character. /// @@ -7807,6 +7935,13 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Arrows" })] SquareArrowUpRight = 0xF14C, + /// + /// The Font Awesome "square-binary" icon unicode character. + /// + [FontAwesomeSearchTerms(new[] { "square binary", "ai", "data", "language", "llm", "model", "programming", "token" })] + [FontAwesomeCategoriesAttribute(new[] { "Coding", "Shapes" })] + SquareBinary = 0xE69B, + /// /// The Font Awesome "square-full" icon unicode character. /// @@ -7824,7 +7959,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "square-person-confined" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "square person confined", "captivity", "confined" })] + [FontAwesomeSearchTerms(new[] { "square person confined", "captivity", "confined", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Security", "Users + People" })] SquarePersonConfined = 0xE577, @@ -7845,7 +7980,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "square-xmark" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "square xmark", "close", "cross", "cross mark button", "incorrect", "mark", "notice", "notification", "notify", "problem", "square", "window", "wrong", "x", "×" })] + [FontAwesomeSearchTerms(new[] { "square xmark", "close", "cross", "cross mark button", "incorrect", "mark", "notice", "notification", "notify", "problem", "square", "uncheck", "window", "wrong", "x", "×" })] [FontAwesomeCategoriesAttribute(new[] { "Mathematics" })] SquareXmark = 0xF2D3, @@ -7880,7 +8015,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "star" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "achievement", "award", "favorite", "important", "night", "rating", "score", "star" })] + [FontAwesomeSearchTerms(new[] { "achievement", "award", "favorite", "important", "night", "quality", "rating", "score", "star", "vip" })] [FontAwesomeCategoriesAttribute(new[] { "Shapes", "Shopping", "Social", "Toggle" })] Star = 0xF005, @@ -7964,7 +8099,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "stopwatch" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "clock", "reminder", "stopwatch", "time" })] + [FontAwesomeSearchTerms(new[] { "clock", "reminder", "stopwatch", "time", "waiting" })] [FontAwesomeCategoriesAttribute(new[] { "Time" })] Stopwatch = 0xF2F2, @@ -7992,7 +8127,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "store-slash" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "store slash", "building", "buy", "closed", "covid-19", "purchase", "shopping" })] + [FontAwesomeSearchTerms(new[] { "store slash", "building", "buy", "closed", "disabled", "purchase", "shopping" })] [FontAwesomeCategoriesAttribute(new[] { "Shopping" })] StoreSlash = 0xE071, @@ -8006,14 +8141,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "street-view" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "street view", "directions", "location", "map", "navigation" })] + [FontAwesomeSearchTerms(new[] { "street view", "directions", "location", "map", "navigation", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Maps", "Users + People" })] StreetView = 0xF21D, /// /// The Font Awesome "strikethrough" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "strikethrough", "cancel", "edit", "font", "format", "text", "type" })] + [FontAwesomeSearchTerms(new[] { "strikethrough", "cancel", "edit", "font", "format", "modify", "text", "type" })] [FontAwesomeCategoriesAttribute(new[] { "Text Formatting" })] Strikethrough = 0xF0CC, @@ -8090,7 +8225,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "person-swimming" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person swimming", "ocean", "person swimming", "pool", "sea", "swim", "water" })] + [FontAwesomeSearchTerms(new[] { "person swimming", "ocean", "person swimming", "pool", "sea", "swim", "uer", "water" })] [FontAwesomeCategoriesAttribute(new[] { "Maritime", "Sports + Fitness", "Travel + Hotel", "Users + People" })] Swimmer = 0xF5C4, @@ -8111,14 +8246,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "arrows-rotate" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "arrows rotate", "clockwise right and left semicircle arrows", "exchange", "refresh", "reload", "rotate", "swap" })] - [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Editing", "Media Playback" })] + [FontAwesomeSearchTerms(new[] { "arrows rotate", "clockwise right and left semicircle arrows", "clockwise", "exchange", "modify", "refresh", "reload", "renew", "retry", "rotate", "swap" })] + [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Editing", "Media Playback", "Spinners" })] Sync = 0xF021, /// /// The Font Awesome "rotate" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "anticlockwise", "arrow", "counterclockwise", "counterclockwise arrows button", "exchange", "refresh", "reload", "rotate", "swap", "withershins" })] + [FontAwesomeSearchTerms(new[] { "arrow", "clockwise", "exchange", "modify", "refresh", "reload", "renew", "retry", "rotate", "swap", "withershins" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Editing", "Media Playback", "Spinners" })] SyncAlt = 0xF2F1, @@ -8132,10 +8267,31 @@ public enum FontAwesomeIcon /// /// The Font Awesome "table" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "table", "data", "excel", "spreadsheet" })] + [FontAwesomeSearchTerms(new[] { "table", "category", "data", "excel", "spreadsheet" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Text Formatting" })] Table = 0xF0CE, + /// + /// The Font Awesome "table-cells-column-lock" icon unicode character. + /// + [FontAwesomeSearchTerms(new[] { "table cells column lock", "blocks", "boxes", "category", "column", "excel", "grid", "lock", "spreadsheet", "squares" })] + [FontAwesomeCategoriesAttribute(new[] { "Text Formatting" })] + TableCellsColumnLock = 0xE678, + + /// + /// The Font Awesome "table-cells-row-lock" icon unicode character. + /// + [FontAwesomeSearchTerms(new[] { "table cells row lock", "blocks", "boxes", "category", "column", "column", "excel", "grid", "lock", "lock", "spreadsheet", "squares" })] + [FontAwesomeCategoriesAttribute(new[] { "Text Formatting" })] + TableCellsRowLock = 0xE67A, + + /// + /// The Font Awesome "table-cells-row-unlock" icon unicode character. + /// + [FontAwesomeSearchTerms(new[] { "table cells row unlock", "blocks", "boxes", "category", "column", "column", "excel", "grid", "lock", "lock", "spreadsheet", "squares", "unlock" })] + [FontAwesomeCategoriesAttribute(new[] { "Text Formatting" })] + TableCellsRowUnlock = 0xE691, + /// /// The Font Awesome "tablet" icon unicode character. /// @@ -8175,7 +8331,7 @@ public enum FontAwesomeIcon /// The Font Awesome "gauge-high" icon unicode character. /// Uses a legacy unicode value for backwards compatability. The current unicode value is 0xF625. /// - [FontAwesomeSearchTerms(new[] { "gauge high", "dashboard", "fast", "odometer", "speed", "speedometer" })] + [FontAwesomeSearchTerms(new[] { "gauge high", "dashboard", "fast", "odometer", "quick", "speed", "speedometer" })] [FontAwesomeCategoriesAttribute(new[] { "Automotive" })] TachometerAlt = 0xF3FD, @@ -8217,7 +8373,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "list-check" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "list check", "checklist", "downloading", "downloads", "loading", "progress", "project management", "settings", "to do" })] + [FontAwesomeSearchTerms(new[] { "list check", "bullet", "cheatsheet", "checklist", "downloading", "downloads", "enable", "loading", "progress", "project management", "settings", "summary", "to do", "validate", "working" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Text Formatting" })] Tasks = 0xF0AE, @@ -8280,42 +8436,42 @@ public enum FontAwesomeIcon /// /// The Font Awesome "tent" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "bivouac", "campground", "refugee", "shelter", "tent" })] + [FontAwesomeSearchTerms(new[] { "bivouac", "campground", "campsite", "refugee", "shelter", "tent" })] [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Camping", "Humanitarian" })] Tent = 0xE57D, /// /// The Font Awesome "tent-arrow-down-to-line" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "tent arrow down to line", "permanent", "refugee", "shelter" })] + [FontAwesomeSearchTerms(new[] { "tent arrow down to line", "bivouac", "campground", "campsite", "permanent", "refugee", "refugee", "shelter", "shelter", "tent" })] [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Camping", "Humanitarian" })] TentArrowDownToLine = 0xE57E, /// /// The Font Awesome "tent-arrow-left-right" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "tent arrow left right", "refugee", "shelter", "transition" })] + [FontAwesomeSearchTerms(new[] { "tent arrow left right", "bivouac", "campground", "campsite", "refugee", "refugee", "shelter", "shelter", "tent", "transition" })] [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Camping", "Humanitarian" })] TentArrowLeftRight = 0xE57F, /// /// The Font Awesome "tent-arrows-down" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "tent arrows down", "refugee", "shelter", "spontaneous" })] + [FontAwesomeSearchTerms(new[] { "tent arrows down", "bivouac", "campground", "campsite", "insert", "refugee", "refugee", "shelter", "shelter", "spontaneous", "tent" })] [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Camping", "Humanitarian" })] TentArrowsDown = 0xE581, /// /// The Font Awesome "tent-arrow-turn-left" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "tent arrow turn left", "refugee", "shelter", "temporary" })] + [FontAwesomeSearchTerms(new[] { "tent arrow turn left", "bivouac", "campground", "campsite", "refugee", "refugee", "shelter", "shelter", "temporary", "tent" })] [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Camping", "Humanitarian" })] TentArrowTurnLeft = 0xE580, /// /// The Font Awesome "tents" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "tents", "bivouac", "campground", "refugee", "shelter", "tent" })] + [FontAwesomeSearchTerms(new[] { "tents", "bivouac", "bivouac", "campground", "campground", "campsite", "refugee", "refugee", "shelter", "shelter", "tent", "tent" })] [FontAwesomeCategoriesAttribute(new[] { "Buildings", "Camping", "Humanitarian" })] Tents = 0xE582, @@ -8329,21 +8485,21 @@ public enum FontAwesomeIcon /// /// The Font Awesome "text-height" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "text height", "edit", "font", "format", "text", "type" })] + [FontAwesomeSearchTerms(new[] { "text height", "edit", "font", "format", "modify", "text", "type" })] [FontAwesomeCategoriesAttribute(new[] { "Text Formatting" })] TextHeight = 0xF034, /// /// The Font Awesome "text-width" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "text width", "edit", "font", "format", "text", "type" })] + [FontAwesomeSearchTerms(new[] { "text width", "edit", "font", "format", "modify", "text", "type" })] [FontAwesomeCategoriesAttribute(new[] { "Text Formatting" })] TextWidth = 0xF035, /// /// The Font Awesome "table-cells" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "table cells", "blocks", "boxes", "grid", "squares" })] + [FontAwesomeSearchTerms(new[] { "table cells", "blocks", "boxes", "category", "excel", "grid", "spreadsheet", "squares" })] [FontAwesomeCategoriesAttribute(new[] { "Text Formatting" })] Th = 0xF00A, @@ -8399,14 +8555,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "table-cells-large" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "table cells large", "blocks", "boxes", "grid", "squares" })] + [FontAwesomeSearchTerms(new[] { "table cells large", "blocks", "boxes", "category", "excel", "grid", "spreadsheet", "squares" })] [FontAwesomeCategoriesAttribute(new[] { "Text Formatting" })] ThLarge = 0xF009, /// /// The Font Awesome "table-list" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "table list", "checklist", "completed", "done", "finished", "ol", "todo", "ul" })] + [FontAwesomeSearchTerms(new[] { "table list", "category", "cheatsheet", "checklist", "completed", "done", "finished", "ol", "summary", "todo", "ul" })] [FontAwesomeCategoriesAttribute(new[] { "Text Formatting" })] ThList = 0xF00B, @@ -8431,17 +8587,24 @@ public enum FontAwesomeIcon [FontAwesomeCategoriesAttribute(new[] { "Business", "Maps", "Social", "Writing" })] Thumbtack = 0xF08D, + /// + /// The Font Awesome "thumbtack-slash" icon unicode character. + /// + [FontAwesomeSearchTerms(new[] { "thumbtack slash", "black pushpin", "coordinates", "location", "marker", "pin", "pushpin", "thumb-tack", "unpin" })] + [FontAwesomeCategoriesAttribute(new[] { "Business", "Maps", "Social", "Writing" })] + ThumbtackSlash = 0xE68F, + /// /// The Font Awesome "ticket" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "admission", "admission tickets", "movie", "pass", "support", "ticket" })] + [FontAwesomeSearchTerms(new[] { "admission", "admission tickets", "coupon", "movie", "pass", "support", "ticket", "voucher" })] [FontAwesomeCategoriesAttribute(new[] { "Film + Video", "Maps" })] Ticket = 0xF145, /// /// The Font Awesome "ticket-simple" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "ticket simple", "movie", "pass", "support", "ticket" })] + [FontAwesomeSearchTerms(new[] { "ticket simple", "admission", "coupon", "movie", "pass", "support", "ticket", "voucher" })] [FontAwesomeCategoriesAttribute(new[] { "Maps", "Shapes" })] TicketAlt = 0xF3FF, @@ -8455,29 +8618,29 @@ public enum FontAwesomeIcon /// /// The Font Awesome "xmark" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "xmark", "cancellation x", "multiplication sign", "multiplication x", "cancel", "close", "cross", "cross mark", "error", "exit", "incorrect", "mark", "multiplication", "multiply", "notice", "notification", "notify", "problem", "sign", "wrong", "x", "×" })] + [FontAwesomeSearchTerms(new[] { "xmark", "cancellation x", "multiplication sign", "multiplication x", "cancel", "close", "cross", "cross mark", "error", "exit", "incorrect", "mark", "multiplication", "multiply", "notice", "notification", "notify", "problem", "sign", "uncheck", "wrong", "x", "×" })] [FontAwesomeCategoriesAttribute(new[] { "Editing", "Mathematics" })] Times = 0xF00D, /// /// The Font Awesome "circle-xmark" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "circle xmark", "close", "cross", "destroy", "exit", "incorrect", "notice", "notification", "notify", "problem", "wrong", "x" })] + [FontAwesomeSearchTerms(new[] { "circle xmark", "close", "cross", "destroy", "exit", "incorrect", "notice", "notification", "notify", "problem", "uncheck", "wrong", "x" })] [FontAwesomeCategoriesAttribute(new[] { "Mathematics" })] TimesCircle = 0xF057, /// /// The Font Awesome "droplet" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "cold", "color", "comic", "drop", "droplet", "raindrop", "sweat", "waterdrop" })] - [FontAwesomeCategoriesAttribute(new[] { "Design", "Humanitarian", "Maps", "Photos + Images" })] + [FontAwesomeSearchTerms(new[] { "blood", "cold", "color", "comic", "drop", "droplet", "raindrop", "sweat", "waterdrop" })] + [FontAwesomeCategoriesAttribute(new[] { "Design", "Humanitarian", "Maps", "Medical + Health", "Photos + Images" })] Tint = 0xF043, /// /// The Font Awesome "droplet-slash" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "droplet slash", "color", "drop", "droplet", "raindrop", "waterdrop" })] - [FontAwesomeCategoriesAttribute(new[] { "Design" })] + [FontAwesomeSearchTerms(new[] { "droplet slash", "blood", "color", "disabled", "drop", "droplet", "raindrop", "waterdrop" })] + [FontAwesomeCategoriesAttribute(new[] { "Design", "Medical + Health" })] TintSlash = 0xF5C7, /// @@ -8518,7 +8681,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "toilet-paper-slash" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "toilet paper slash", "bathroom", "covid-19", "halloween", "holiday", "lavatory", "leaves", "prank", "privy", "restroom", "roll", "toilet", "trouble", "ut oh", "wipe" })] + [FontAwesomeSearchTerms(new[] { "toilet paper slash", "bathroom", "covid-19", "disabled", "halloween", "holiday", "lavatory", "leaves", "prank", "privy", "restroom", "roll", "toilet", "trouble", "ut oh", "wipe" })] [FontAwesomeCategoriesAttribute(new[] { "Household" })] ToiletPaperSlash = 0xE072, @@ -8539,14 +8702,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "toolbox" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "admin", "chest", "container", "fix", "mechanic", "repair", "settings", "tool", "toolbox", "tools" })] + [FontAwesomeSearchTerms(new[] { "admin", "chest", "configuration", "container", "equipment", "fix", "maintenance", "mechanic", "modify", "repair", "settings", "tool", "toolbox", "tools" })] [FontAwesomeCategoriesAttribute(new[] { "Construction" })] Toolbox = 0xF552, /// /// The Font Awesome "screwdriver-wrench" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "screwdriver wrench", "admin", "fix", "repair", "screwdriver", "settings", "tools", "wrench" })] + [FontAwesomeSearchTerms(new[] { "screwdriver wrench", "admin", "configuration", "equipment", "fix", "maintenance", "modify", "repair", "screwdriver", "settings", "tools", "wrench" })] [FontAwesomeCategoriesAttribute(new[] { "Construction" })] Tools = 0xF7D9, @@ -8581,7 +8744,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "tower-cell" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "tower cell", "airwaves", "antenna", "communication", "radio", "reception", "waves" })] + [FontAwesomeSearchTerms(new[] { "tower cell", "airwaves", "antenna", "communication", "radio", "reception", "signal", "waves" })] [FontAwesomeCategoriesAttribute(new[] { "Communication", "Connectivity", "Film + Video", "Humanitarian" })] TowerCell = 0xE585, @@ -8609,7 +8772,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "traffic-light" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "traffic light", "direction", "light", "road", "signal", "traffic", "travel", "vertical traffic light" })] + [FontAwesomeSearchTerms(new[] { "traffic light", "direction", "go", "light", "road", "signal", "slow", "stop", "traffic", "travel", "vertical traffic light" })] [FontAwesomeCategoriesAttribute(new[] { "Maps" })] TrafficLight = 0xF637, @@ -8665,21 +8828,21 @@ public enum FontAwesomeIcon /// /// The Font Awesome "trash-arrow-up" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "trash arrow up", "back", "control z", "delete", "garbage", "hide", "oops", "remove", "undo" })] + [FontAwesomeSearchTerms(new[] { "trash arrow up", "back", "control z", "delete", "garbage", "hide", "oops", "remove", "undo", "upgrade" })] [FontAwesomeCategoriesAttribute(new[] { "Editing" })] TrashRestore = 0xF829, /// /// The Font Awesome "trash-can-arrow-up" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "trash can arrow up", "back", "control z", "delete", "garbage", "hide", "oops", "remove", "undo" })] + [FontAwesomeSearchTerms(new[] { "trash can arrow up", "back", "control z", "delete", "garbage", "hide", "oops", "remove", "undo", "upgrade" })] [FontAwesomeCategoriesAttribute(new[] { "Editing" })] TrashRestoreAlt = 0xF82A, /// /// The Font Awesome "tree" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "bark", "evergreen tree", "fall", "flora", "forest", "nature", "plant", "seasonal", "tree" })] + [FontAwesomeSearchTerms(new[] { "bark", "evergreen tree", "fall", "flora", "forest", "investment", "nature", "plant", "seasonal", "tree" })] [FontAwesomeCategoriesAttribute(new[] { "Camping", "Maps", "Nature" })] Tree = 0xF1BB, @@ -8700,14 +8863,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "trowel" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "trowel", "build", "construction", "tool" })] + [FontAwesomeSearchTerms(new[] { "trowel", "build", "construction", "equipment", "maintenance", "tool" })] [FontAwesomeCategoriesAttribute(new[] { "Construction", "Humanitarian" })] Trowel = 0xE589, /// /// The Font Awesome "trowel-bricks" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "trowel bricks", "build", "construction", "reconstruction", "tool" })] + [FontAwesomeSearchTerms(new[] { "trowel bricks", "build", "construction", "maintenance", "reconstruction", "tool" })] [FontAwesomeCategoriesAttribute(new[] { "Construction", "Humanitarian" })] TrowelBricks = 0xE58A, @@ -8728,8 +8891,8 @@ public enum FontAwesomeIcon /// /// The Font Awesome "truck-droplet" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "truck droplet", "thirst", "truck", "water", "water supply" })] - [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Transportation" })] + [FontAwesomeSearchTerms(new[] { "truck droplet", "blood", "thirst", "truck", "water", "water supply" })] + [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Medical + Health", "Transportation" })] TruckDroplet = 0xE58C, /// @@ -8777,7 +8940,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "truck-pickup" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "truck pickup", "cargo", "pick-up", "pickup", "pickup truck", "truck", "vehicle" })] + [FontAwesomeSearchTerms(new[] { "truck pickup", "cargo", "maintenance", "pick-up", "pickup", "pickup truck", "truck", "vehicle" })] [FontAwesomeCategoriesAttribute(new[] { "Automotive", "Construction", "Transportation" })] TruckPickup = 0xF63C, @@ -8833,7 +8996,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "underline" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "underline", "edit", "emphasis", "format", "text", "writing" })] + [FontAwesomeSearchTerms(new[] { "underline", "edit", "emphasis", "format", "modify", "text", "writing" })] [FontAwesomeCategoriesAttribute(new[] { "Text Formatting" })] Underline = 0xF0CD, @@ -8841,20 +9004,20 @@ public enum FontAwesomeIcon /// The Font Awesome "arrow-rotate-left" icon unicode character. /// [FontAwesomeSearchTerms(new[] { "arrow rotate left", "anticlockwise open circle arrow", "back", "control z", "exchange", "oops", "return", "rotate", "swap" })] - [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Media Playback" })] + [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Media Playback", "Spinners" })] Undo = 0xF0E2, /// /// The Font Awesome "rotate-left" icon unicode character. /// [FontAwesomeSearchTerms(new[] { "rotate left", "back", "control z", "exchange", "oops", "return", "swap" })] - [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Media Playback" })] + [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Media Playback", "Spinners" })] UndoAlt = 0xF2EA, /// /// The Font Awesome "universal-access" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "universal access", "users-people" })] + [FontAwesomeSearchTerms(new[] { "universal access", "uer", "users-people" })] [FontAwesomeCategoriesAttribute(new[] { "Accessibility" })] UniversalAccess = 0xF29A, @@ -8868,252 +9031,254 @@ public enum FontAwesomeIcon /// /// The Font Awesome "link-slash" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "link slash", "attachment", "chain", "chain-broken", "remove" })] + [FontAwesomeSearchTerms(new[] { "link slash", "attachment", "chain", "chain-broken", "disabled", "disconnect", "remove" })] [FontAwesomeCategoriesAttribute(new[] { "Editing" })] Unlink = 0xF127, /// /// The Font Awesome "unlock" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "admin", "lock", "open", "password", "private", "protect", "unlock", "unlocked" })] + [FontAwesomeSearchTerms(new[] { "admin", "lock", "open", "padlock", "password", "privacy", "private", "protect", "unlock", "unlocked" })] [FontAwesomeCategoriesAttribute(new[] { "Security" })] Unlock = 0xF09C, /// /// The Font Awesome "unlock-keyhole" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "unlock keyhole", "admin", "lock", "password", "private", "protect" })] + [FontAwesomeSearchTerms(new[] { "unlock keyhole", "admin", "lock", "padlock", "password", "privacy", "private", "protect" })] [FontAwesomeCategoriesAttribute(new[] { "Security" })] UnlockAlt = 0xF13E, /// /// The Font Awesome "upload" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "upload", "hard drive", "import", "publish" })] + [FontAwesomeSearchTerms(new[] { "upload", "hard drive", "import", "publish", "upgrade" })] [FontAwesomeCategoriesAttribute(new[] { "Arrows", "Devices + Hardware" })] Upload = 0xF093, /// /// The Font Awesome "user" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "user", "adult", "bust", "bust in silhouette", "gender-neutral", "person", "profile", "silhouette", "unspecified gender", "users-people" })] + [FontAwesomeSearchTerms(new[] { "user", "adult", "bust", "bust in silhouette", "default", "employee", "gender-neutral", "person", "profile", "silhouette", "uer", "unspecified gender", "username", "users-people" })] [FontAwesomeCategoriesAttribute(new[] { "Social", "Users + People" })] User = 0xF007, /// - /// The Font Awesome "user-large" icon unicode character. + /// The Font Awesome "user" icon unicode character. + /// Uses a legacy unicode value for backwards compatability. The current unicode value is 0xF007. /// - [FontAwesomeSearchTerms(new[] { "user large", "users-people" })] - [FontAwesomeCategoriesAttribute(new[] { "Users + People" })] + [FontAwesomeSearchTerms(new[] { "user", "adult", "bust", "bust in silhouette", "default", "employee", "gender-neutral", "person", "profile", "silhouette", "uer", "unspecified gender", "username", "users-people" })] + [FontAwesomeCategoriesAttribute(new[] { "Social", "Users + People" })] UserAlt = 0xF406, /// - /// The Font Awesome "user-large-slash" icon unicode character. + /// The Font Awesome "user-slash" icon unicode character. + /// Uses a legacy unicode value for backwards compatability. The current unicode value is 0xF506. /// - [FontAwesomeSearchTerms(new[] { "user large slash", "users-people" })] + [FontAwesomeSearchTerms(new[] { "user slash", "ban", "delete", "deny", "disabled", "disconnect", "employee", "remove", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Users + People" })] UserAltSlash = 0xF4FA, /// /// The Font Awesome "user-astronaut" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "user astronaut", "avatar", "clothing", "cosmonaut", "nasa", "space", "suit" })] + [FontAwesomeSearchTerms(new[] { "user astronaut", "avatar", "clothing", "cosmonaut", "nasa", "space", "suit", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Astronomy", "Science Fiction", "Users + People" })] UserAstronaut = 0xF4FB, /// /// The Font Awesome "user-check" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "user check", "users-people" })] + [FontAwesomeSearchTerms(new[] { "user check", "employee", "enable", "uer", "users-people", "validate", "working" })] [FontAwesomeCategoriesAttribute(new[] { "Users + People" })] UserCheck = 0xF4FC, /// /// The Font Awesome "circle-user" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "circle user", "users-people" })] + [FontAwesomeSearchTerms(new[] { "circle user", "employee", "uer", "username", "users-people" })] [FontAwesomeCategoriesAttribute(new[] { "Social", "Users + People" })] UserCircle = 0xF2BD, /// /// The Font Awesome "user-clock" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "user clock", "users-people" })] + [FontAwesomeSearchTerms(new[] { "user clock", "employee", "uer", "users-people" })] [FontAwesomeCategoriesAttribute(new[] { "Users + People" })] UserClock = 0xF4FD, /// /// The Font Awesome "user-gear" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "user gear", "users-people" })] + [FontAwesomeSearchTerms(new[] { "user gear", "employee", "together", "uer", "users-people" })] [FontAwesomeCategoriesAttribute(new[] { "Users + People" })] UserCog = 0xF4FE, /// /// The Font Awesome "user-pen" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "user pen", "users-people" })] + [FontAwesomeSearchTerms(new[] { "user pen", "employee", "modify", "uer", "users-people" })] [FontAwesomeCategoriesAttribute(new[] { "Users + People" })] UserEdit = 0xF4FF, /// /// The Font Awesome "user-group" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "user group", "bust", "busts in silhouette", "silhouette", "users-people" })] + [FontAwesomeSearchTerms(new[] { "user group", "bust", "busts in silhouette", "crowd", "employee", "silhouette", "together", "uer", "users-people" })] [FontAwesomeCategoriesAttribute(new[] { "Social", "Users + People" })] UserFriends = 0xF500, /// /// The Font Awesome "user-graduate" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "user graduate", "users-people" })] + [FontAwesomeSearchTerms(new[] { "user graduate", "uer", "users-people" })] [FontAwesomeCategoriesAttribute(new[] { "Education", "Users + People" })] UserGraduate = 0xF501, /// /// The Font Awesome "user-injured" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "user injured", "users-people" })] + [FontAwesomeSearchTerms(new[] { "user injured", "employee", "uer", "users-people" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Users + People" })] UserInjured = 0xF728, /// /// The Font Awesome "user-lock" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "user lock", "users-people" })] + [FontAwesomeSearchTerms(new[] { "user lock", "employee", "padlock", "privacy", "uer", "users-people" })] [FontAwesomeCategoriesAttribute(new[] { "Security", "Users + People" })] UserLock = 0xF502, /// /// The Font Awesome "user-doctor" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "user doctor", "covid-19", "health", "job", "medical", "nurse", "occupation", "physician", "profile", "surgeon", "worker" })] + [FontAwesomeSearchTerms(new[] { "user doctor", "covid-19", "health", "job", "medical", "nurse", "occupation", "physician", "profile", "surgeon", "uer", "worker" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Medical + Health", "Users + People" })] UserMd = 0xF0F0, /// /// The Font Awesome "user-minus" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "user minus", "delete", "negative", "remove" })] + [FontAwesomeSearchTerms(new[] { "user minus", "delete", "employee", "negative", "remove", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Users + People" })] UserMinus = 0xF503, /// /// The Font Awesome "user-ninja" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "user ninja", "assassin", "avatar", "dangerous", "deadly", "fighter", "hidden", "ninja", "sneaky", "stealth" })] + [FontAwesomeSearchTerms(new[] { "user ninja", "assassin", "avatar", "dangerous", "deadly", "fighter", "hidden", "ninja", "sneaky", "stealth", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Users + People" })] UserNinja = 0xF504, /// /// The Font Awesome "user-nurse" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "user nurse", "covid-19", "doctor", "health", "md", "medical", "midwife", "physician", "practitioner", "surgeon", "worker" })] + [FontAwesomeSearchTerms(new[] { "user nurse", "covid-19", "doctor", "health", "md", "medical", "midwife", "physician", "practitioner", "surgeon", "uer", "worker" })] [FontAwesomeCategoriesAttribute(new[] { "Medical + Health", "Users + People" })] UserNurse = 0xF82F, /// /// The Font Awesome "user-plus" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "user plus", "add", "avatar", "positive", "sign up", "signup", "team" })] + [FontAwesomeSearchTerms(new[] { "user plus", "add", "avatar", "employee", "follow", "positive", "sign up", "signup", "team", "user" })] [FontAwesomeCategoriesAttribute(new[] { "Social", "Users + People" })] UserPlus = 0xF234, /// /// The Font Awesome "users" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "users", "users-people" })] + [FontAwesomeSearchTerms(new[] { "users", "employee", "together", "uer", "users-people" })] [FontAwesomeCategoriesAttribute(new[] { "Social", "Users + People" })] Users = 0xF0C0, /// /// The Font Awesome "users-between-lines" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "users between lines", "covered", "group", "people" })] + [FontAwesomeSearchTerms(new[] { "users between lines", "covered", "crowd", "employee", "group", "people", "together", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Users + People" })] UsersBetweenLines = 0xE591, /// /// The Font Awesome "users-gear" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "users gear", "users-people" })] + [FontAwesomeSearchTerms(new[] { "users gear", "employee", "uer", "users-people" })] [FontAwesomeCategoriesAttribute(new[] { "Users + People" })] UsersCog = 0xF509, /// /// The Font Awesome "user-secret" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "user secret", "detective", "sleuth", "spy", "users-people" })] + [FontAwesomeSearchTerms(new[] { "user secret", "detective", "sleuth", "spy", "uer", "users-people" })] [FontAwesomeCategoriesAttribute(new[] { "Coding", "Security", "Users + People" })] UserSecret = 0xF21B, /// /// The Font Awesome "user-shield" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "user shield", "protect", "safety" })] + [FontAwesomeSearchTerms(new[] { "user shield", "employee", "protect", "safety", "security", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Security", "Users + People" })] UserShield = 0xF505, /// /// The Font Awesome "user-slash" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "user slash", "ban", "delete", "remove" })] + [FontAwesomeSearchTerms(new[] { "user slash", "ban", "delete", "deny", "disabled", "disconnect", "employee", "remove", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Users + People" })] UserSlash = 0xF506, /// /// The Font Awesome "users-line" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "users line", "group", "need", "people" })] + [FontAwesomeSearchTerms(new[] { "users line", "crowd", "employee", "group", "need", "people", "together", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Users + People" })] UsersLine = 0xE592, /// /// The Font Awesome "users-rays" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "users rays", "affected", "focused", "group", "people" })] + [FontAwesomeSearchTerms(new[] { "users rays", "affected", "crowd", "employee", "focused", "group", "people", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Users + People" })] UsersRays = 0xE593, /// /// The Font Awesome "users-rectangle" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "users rectangle", "focus", "group", "people", "reached" })] + [FontAwesomeSearchTerms(new[] { "users rectangle", "crowd", "employee", "focus", "group", "people", "reached", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Users + People" })] UsersRectangle = 0xE594, /// /// The Font Awesome "users-slash" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "users slash", "users-people" })] + [FontAwesomeSearchTerms(new[] { "users slash", "disabled", "disconnect", "employee", "together", "uer", "users-people" })] [FontAwesomeCategoriesAttribute(new[] { "Users + People" })] UsersSlash = 0xE073, /// /// The Font Awesome "users-viewfinder" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "users viewfinder", "focus", "group", "people", "targeted" })] + [FontAwesomeSearchTerms(new[] { "users viewfinder", "crowd", "focus", "group", "people", "targeted", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Users + People" })] UsersViewfinder = 0xE595, /// /// The Font Awesome "user-tag" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "user tag", "users-people" })] + [FontAwesomeSearchTerms(new[] { "user tag", "employee", "uer", "users-people" })] [FontAwesomeCategoriesAttribute(new[] { "Users + People" })] UserTag = 0xF507, /// /// The Font Awesome "user-tie" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "user tie", "avatar", "business", "clothing", "formal", "professional", "suit" })] + [FontAwesomeSearchTerms(new[] { "user tie", "administrator", "avatar", "business", "clothing", "employee", "formal", "offer", "portfolio", "professional", "suit", "uer" })] [FontAwesomeCategoriesAttribute(new[] { "Clothing + Fashion", "Users + People" })] UserTie = 0xF508, /// /// The Font Awesome "user-xmark" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "user xmark", "archive", "delete", "remove", "x" })] + [FontAwesomeSearchTerms(new[] { "user xmark", "archive", "delete", "employee", "remove", "uer", "uncheck", "x" })] [FontAwesomeCategoriesAttribute(new[] { "Users + People" })] UserTimes = 0xF235, @@ -9134,15 +9299,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "vault" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "vault", "bank", "important", "lock", "money", "safe" })] + [FontAwesomeSearchTerms(new[] { "vault", "bank", "important", "investment", "lock", "money", "premium", "privacy", "safe", "salary" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Money", "Security" })] Vault = 0xE2C5, /// - /// The Font Awesome "vector-square" icon unicode character. + /// The Font Awesome "vectorsquare" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "vector square", "anchors", "lines", "object", "render", "shape" })] - [FontAwesomeCategoriesAttribute(new[] { "Design" })] + [Obsolete] VectorSquare = 0xF5CB, /// @@ -9183,21 +9347,21 @@ public enum FontAwesomeIcon /// /// The Font Awesome "vial" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "vial", "ampule", "chemist", "chemistry", "experiment", "lab", "sample", "science", "test", "test tube" })] + [FontAwesomeSearchTerms(new[] { "vial", "ampule", "chemist", "chemistry", "experiment", "knowledge", "lab", "sample", "science", "test", "test tube" })] [FontAwesomeCategoriesAttribute(new[] { "Medical + Health", "Science" })] Vial = 0xF492, /// /// The Font Awesome "vial-circle-check" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "vial circle check", "ampule", "chemist", "chemistry", "not affected", "ok", "okay", "success", "test tube", "tube", "vaccine" })] + [FontAwesomeSearchTerms(new[] { "vial circle check", "ampule", "chemist", "chemistry", "enable", "not affected", "ok", "okay", "success", "test tube", "tube", "vaccine", "validate", "working" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Medical + Health", "Science" })] VialCircleCheck = 0xE596, /// /// The Font Awesome "vials" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "vials", "ampule", "experiment", "lab", "sample", "science", "test", "test tube" })] + [FontAwesomeSearchTerms(new[] { "vials", "ampule", "experiment", "knowledge", "lab", "sample", "science", "test", "test tube" })] [FontAwesomeCategoriesAttribute(new[] { "Medical + Health", "Science" })] Vials = 0xF493, @@ -9218,7 +9382,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "video-slash" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "video slash", "add", "create", "film", "new", "positive", "record", "video" })] + [FontAwesomeSearchTerms(new[] { "video slash", "add", "create", "disabled", "disconnect", "film", "new", "positive", "record", "video" })] [FontAwesomeCategoriesAttribute(new[] { "Communication", "Film + Video" })] VideoSlash = 0xF4E2, @@ -9246,7 +9410,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "virus-covid-slash" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "virus covid slash", "bug", "covid-19", "flu", "health", "infection", "pandemic", "vaccine", "viral", "virus" })] + [FontAwesomeSearchTerms(new[] { "virus covid slash", "bug", "covid-19", "disabled", "flu", "health", "infection", "pandemic", "vaccine", "viral", "virus" })] [FontAwesomeCategoriesAttribute(new[] { "Medical + Health" })] VirusCovidSlash = 0xE4A9, @@ -9260,7 +9424,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "virus-slash" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "virus slash", "bug", "coronavirus", "covid-19", "cure", "eliminate", "flu", "health", "infection", "pandemic", "sick", "vaccine", "viral" })] + [FontAwesomeSearchTerms(new[] { "virus slash", "bug", "coronavirus", "covid-19", "cure", "disabled", "eliminate", "flu", "health", "infection", "pandemic", "sick", "vaccine", "viral" })] [FontAwesomeCategoriesAttribute(new[] { "Medical + Health" })] VirusSlash = 0xE075, @@ -9316,7 +9480,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "check-to-slot" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "check to slot", "accept", "cast", "election", "politics", "positive", "voting", "yes" })] + [FontAwesomeSearchTerms(new[] { "check to slot", "accept", "cast", "election", "enable", "politics", "positive", "validate", "voting", "working", "yes" })] [FontAwesomeCategoriesAttribute(new[] { "Political" })] VoteYea = 0xF772, @@ -9337,14 +9501,14 @@ public enum FontAwesomeIcon /// /// The Font Awesome "person-walking" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "person walking", "crosswalk", "exercise", "hike", "move", "person walking", "walk", "walking" })] + [FontAwesomeSearchTerms(new[] { "person walking", "crosswalk", "exercise", "follow", "hike", "move", "person walking", "uer", "walk", "walking", "workout" })] [FontAwesomeCategoriesAttribute(new[] { "Humanitarian", "Sports + Fitness", "Users + People" })] Walking = 0xF554, /// /// The Font Awesome "wallet" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "wallet", "billfold", "cash", "currency", "money" })] + [FontAwesomeSearchTerms(new[] { "wallet", "billfold", "cash", "currency", "money", "salary" })] [FontAwesomeCategoriesAttribute(new[] { "Business", "Money" })] Wallet = 0xF555, @@ -9380,9 +9544,16 @@ public enum FontAwesomeIcon /// The Font Awesome "wave-square" icon unicode character. /// [FontAwesomeSearchTerms(new[] { "wave square", "frequency", "pulse", "signal" })] - [FontAwesomeCategoriesAttribute(new[] { "Mathematics" })] + [FontAwesomeCategoriesAttribute(new[] { "Mathematics", "Music + Audio" })] WaveSquare = 0xF83E, + /// + /// The Font Awesome "web-awesome" icon unicode character. + /// + [FontAwesomeSearchTerms(new[] { "web awesome", "awesome", "coding", "components", "crown", "web" })] + [FontAwesomeCategoriesAttribute(new[] { "Coding", "Design" })] + WebAwesome = 0xE682, + /// /// The Font Awesome "weight-scale" icon unicode character. /// @@ -9407,28 +9578,28 @@ public enum FontAwesomeIcon /// /// The Font Awesome "wheat-awn-circle-exclamation" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "wheat awn circle exclamation", "affected", "famine", "food", "gluten", "hunger", "starve", "straw" })] + [FontAwesomeSearchTerms(new[] { "wheat awn circle exclamation", "affected", "failed", "famine", "food", "gluten", "hunger", "starve", "straw" })] [FontAwesomeCategoriesAttribute(new[] { "Disaster + Crisis", "Food + Beverage", "Humanitarian" })] WheatAwnCircleExclamation = 0xE598, /// /// The Font Awesome "wheelchair" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "wheelchair", "users-people" })] + [FontAwesomeSearchTerms(new[] { "wheelchair", "disabled", "uer", "users-people" })] [FontAwesomeCategoriesAttribute(new[] { "Accessibility", "Maps", "Medical + Health", "Transportation", "Travel + Hotel", "Users + People" })] Wheelchair = 0xF193, /// /// The Font Awesome "wheelchair-move" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "wheelchair move", "access", "handicap", "impairment", "physical", "wheelchair symbol" })] + [FontAwesomeSearchTerms(new[] { "wheelchair move", "access", "disabled", "handicap", "impairment", "physical", "uer", "wheelchair symbol" })] [FontAwesomeCategoriesAttribute(new[] { "Accessibility", "Humanitarian", "Maps", "Medical + Health", "Transportation", "Travel + Hotel", "Users + People" })] WheelchairMove = 0xE2CE, /// /// The Font Awesome "wifi" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "wifi", "connection", "hotspot", "internet", "network", "wireless" })] + [FontAwesomeSearchTerms(new[] { "wifi", "connection", "hotspot", "internet", "network", "signal", "wireless", "www" })] [FontAwesomeCategoriesAttribute(new[] { "Connectivity", "Humanitarian", "Maps", "Toggle", "Travel + Hotel" })] Wifi = 0xF1EB, @@ -9442,7 +9613,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "rectangle-xmark" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "rectangle xmark", "browser", "cancel", "computer", "development" })] + [FontAwesomeSearchTerms(new[] { "rectangle xmark", "browser", "cancel", "computer", "development", "uncheck" })] [FontAwesomeCategoriesAttribute(new[] { "Coding" })] WindowClose = 0xF410, @@ -9505,7 +9676,7 @@ public enum FontAwesomeIcon /// /// The Font Awesome "wrench" icon unicode character. /// - [FontAwesomeSearchTerms(new[] { "construction", "fix", "mechanic", "plumbing", "settings", "spanner", "tool", "update", "wrench" })] + [FontAwesomeSearchTerms(new[] { "configuration", "construction", "equipment", "fix", "mechanic", "modify", "plumbing", "settings", "spanner", "tool", "update", "wrench" })] [FontAwesomeCategoriesAttribute(new[] { "Construction", "Maps" })] Wrench = 0xF0AD, diff --git a/Dalamud/Interface/FontIdentifier/IObjectWithLocalizableName.cs b/Dalamud/Interface/FontIdentifier/IObjectWithLocalizableName.cs index 2b970a5fd..4b3860431 100644 --- a/Dalamud/Interface/FontIdentifier/IObjectWithLocalizableName.cs +++ b/Dalamud/Interface/FontIdentifier/IObjectWithLocalizableName.cs @@ -64,9 +64,9 @@ public interface IObjectWithLocalizableName var result = new Dictionary((int)count); for (var i = 0u; i < count; i++) { - fn->GetLocaleName(i, (ushort*)buf, maxStrLen).ThrowOnError(); + fn->GetLocaleName(i, buf, maxStrLen).ThrowOnError(); var key = new string(buf); - fn->GetString(i, (ushort*)buf, maxStrLen).ThrowOnError(); + fn->GetString(i, buf, maxStrLen).ThrowOnError(); var value = new string(buf); result[key.ToLowerInvariant()] = value; } diff --git a/Dalamud/Interface/FontIdentifier/SystemFontFamilyId.cs b/Dalamud/Interface/FontIdentifier/SystemFontFamilyId.cs index 420ee77a4..83a5e810d 100644 --- a/Dalamud/Interface/FontIdentifier/SystemFontFamilyId.cs +++ b/Dalamud/Interface/FontIdentifier/SystemFontFamilyId.cs @@ -133,8 +133,8 @@ public sealed class SystemFontFamilyId : IFontFamilyId var familyIndex = 0u; BOOL exists = false; - fixed (void* pName = this.EnglishName) - sfc.Get()->FindFamilyName((ushort*)pName, &familyIndex, &exists).ThrowOnError(); + fixed (char* pName = this.EnglishName) + sfc.Get()->FindFamilyName(pName, &familyIndex, &exists).ThrowOnError(); if (!exists) throw new FileNotFoundException($"Font \"{this.EnglishName}\" not found."); diff --git a/Dalamud/Interface/FontIdentifier/SystemFontId.cs b/Dalamud/Interface/FontIdentifier/SystemFontId.cs index e11759a88..8401f4c79 100644 --- a/Dalamud/Interface/FontIdentifier/SystemFontId.cs +++ b/Dalamud/Interface/FontIdentifier/SystemFontId.cs @@ -113,8 +113,8 @@ public sealed class SystemFontId : IFontId var familyIndex = 0u; BOOL exists = false; - fixed (void* name = this.Family.EnglishName) - sfc.Get()->FindFamilyName((ushort*)name, &familyIndex, &exists).ThrowOnError(); + fixed (char* name = this.Family.EnglishName) + sfc.Get()->FindFamilyName(name, &familyIndex, &exists).ThrowOnError(); if (!exists) throw new FileNotFoundException($"Font \"{this.Family.EnglishName}\" not found."); @@ -151,7 +151,7 @@ public sealed class SystemFontId : IFontId flocal.Get()->GetFilePathLengthFromKey(refKey, refKeySize, &pathSize).ThrowOnError(); var path = stackalloc char[(int)pathSize + 1]; - flocal.Get()->GetFilePathFromKey(refKey, refKeySize, (ushort*)path, pathSize + 1).ThrowOnError(); + flocal.Get()->GetFilePathFromKey(refKey, refKeySize, path, pathSize + 1).ThrowOnError(); return (new(path, 0, (int)pathSize), (int)fface.Get()->GetIndex()); } diff --git a/Dalamud/Interface/ImGuiBackend/Helpers/ReShadePeeler.cs b/Dalamud/Interface/ImGuiBackend/Helpers/ReShadePeeler.cs index 824ba382a..3f3c98c26 100644 --- a/Dalamud/Interface/ImGuiBackend/Helpers/ReShadePeeler.cs +++ b/Dalamud/Interface/ImGuiBackend/Helpers/ReShadePeeler.cs @@ -104,19 +104,19 @@ internal static unsafe class ReShadePeeler fixed (byte* pfn5 = "glBegin"u8) fixed (byte* pfn6 = "vkCreateDevice"u8) { - if (GetProcAddress((HMODULE)dosh, (sbyte*)pfn0) == 0) + if (GetProcAddress((HMODULE)dosh, (sbyte*)pfn0) == null) continue; - if (GetProcAddress((HMODULE)dosh, (sbyte*)pfn1) == 0) + if (GetProcAddress((HMODULE)dosh, (sbyte*)pfn1) == null) continue; - if (GetProcAddress((HMODULE)dosh, (sbyte*)pfn2) == 0) + if (GetProcAddress((HMODULE)dosh, (sbyte*)pfn2) == null) continue; - if (GetProcAddress((HMODULE)dosh, (sbyte*)pfn3) == 0) + if (GetProcAddress((HMODULE)dosh, (sbyte*)pfn3) == null) continue; - if (GetProcAddress((HMODULE)dosh, (sbyte*)pfn4) == 0) + if (GetProcAddress((HMODULE)dosh, (sbyte*)pfn4) == null) continue; - if (GetProcAddress((HMODULE)dosh, (sbyte*)pfn5) == 0) + if (GetProcAddress((HMODULE)dosh, (sbyte*)pfn5) == null) continue; - if (GetProcAddress((HMODULE)dosh, (sbyte*)pfn6) == 0) + if (GetProcAddress((HMODULE)dosh, (sbyte*)pfn6) == null) continue; } diff --git a/Dalamud/Interface/ImGuiBackend/InputHandler/Win32InputHandler.StaticLookupFunctions.cs b/Dalamud/Interface/ImGuiBackend/InputHandler/Win32InputHandler.StaticLookupFunctions.cs index 5710a5991..a7b70ce35 100644 --- a/Dalamud/Interface/ImGuiBackend/InputHandler/Win32InputHandler.StaticLookupFunctions.cs +++ b/Dalamud/Interface/ImGuiBackend/InputHandler/Win32InputHandler.StaticLookupFunctions.cs @@ -299,11 +299,12 @@ internal sealed partial class Win32InputHandler private static void ViewportFlagsToWin32Styles(ImGuiViewportFlags flags, out int style, out int exStyle) { - style = (int)(flags.HasFlag(ImGuiViewportFlags.NoDecoration) ? WS.WS_POPUP : WS.WS_OVERLAPPEDWINDOW); - exStyle = - (int)(flags.HasFlag(ImGuiViewportFlags.NoTaskBarIcon) ? WS.WS_EX_TOOLWINDOW : (uint)WS.WS_EX_APPWINDOW); + style = (flags & ImGuiViewportFlags.NoDecoration) != 0 ? unchecked((int)WS.WS_POPUP) : WS.WS_OVERLAPPEDWINDOW; + exStyle = (flags & ImGuiViewportFlags.NoTaskBarIcon) != 0 ? WS.WS_EX_TOOLWINDOW : WS.WS_EX_APPWINDOW; exStyle |= WS.WS_EX_NOREDIRECTIONBITMAP; - if (flags.HasFlag(ImGuiViewportFlags.TopMost)) + if ((flags & ImGuiViewportFlags.TopMost) != 0) exStyle |= WS.WS_EX_TOPMOST; + if ((flags & ImGuiViewportFlags.NoInputs) != 0) + exStyle |= WS.WS_EX_TRANSPARENT | WS.WS_EX_LAYERED; } } diff --git a/Dalamud/Interface/ImGuiBackend/InputHandler/Win32InputHandler.cs b/Dalamud/Interface/ImGuiBackend/InputHandler/Win32InputHandler.cs index 596df4c67..a9e9b5a0f 100644 --- a/Dalamud/Interface/ImGuiBackend/InputHandler/Win32InputHandler.cs +++ b/Dalamud/Interface/ImGuiBackend/InputHandler/Win32InputHandler.cs @@ -8,6 +8,7 @@ using System.Text; using Dalamud.Bindings.ImGui; using Dalamud.Memory; +using Dalamud.Utility; using Serilog; @@ -34,11 +35,12 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler private readonly HCURSOR[] cursors; private readonly WndProcDelegate wndProcDelegate; - private readonly bool[] imguiMouseIsDown; private readonly nint platformNamePtr; private ViewportHandler viewportHandler; + private int mouseButtonsDown; + private bool mouseTracked; private long lastTime; private nint iniPathPtr; @@ -64,7 +66,8 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler io.BackendFlags |= ImGuiBackendFlags.HasMouseCursors | ImGuiBackendFlags.HasSetMousePos | ImGuiBackendFlags.RendererHasViewports | - ImGuiBackendFlags.PlatformHasViewports; + ImGuiBackendFlags.PlatformHasViewports | + ImGuiBackendFlags.HasMouseHoveredViewport; this.platformNamePtr = Marshal.StringToHGlobalAnsi("imgui_impl_win32_c#"); io.Handle->BackendPlatformName = (byte*)this.platformNamePtr; @@ -74,8 +77,6 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler if (io.ConfigFlags.HasFlag(ImGuiConfigFlags.ViewportsEnable)) this.viewportHandler = new(this); - this.imguiMouseIsDown = new bool[5]; - this.cursors = new HCURSOR[9]; this.cursors[(int)ImGuiMouseCursor.Arrow] = LoadCursorW(default, IDC.IDC_ARROW); this.cursors[(int)ImGuiMouseCursor.TextInput] = LoadCursorW(default, IDC.IDC_IBEAM); @@ -95,8 +96,6 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler private delegate LRESULT WndProcDelegate(HWND hWnd, uint uMsg, WPARAM wparam, LPARAM lparam); - private delegate BOOL MonitorEnumProcDelegate(HMONITOR monitor, HDC hdc, RECT* rect, LPARAM lparam); - /// public bool UpdateCursor { get; set; } = true; @@ -155,6 +154,7 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler public void NewFrame(int targetWidth, int targetHeight) { var io = ImGui.GetIO(); + var focusedWindow = GetForegroundWindow(); io.DisplaySize.X = targetWidth; io.DisplaySize.Y = targetHeight; @@ -168,9 +168,9 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler this.viewportHandler.UpdateMonitors(); - this.UpdateMousePos(); + this.UpdateMouseData(focusedWindow); - this.ProcessKeyEventsWorkarounds(); + this.ProcessKeyEventsWorkarounds(focusedWindow); // TODO: need to figure out some way to unify all this // The bottom case works(?) if the caller hooks SetCursor, but otherwise causes fps issues @@ -224,6 +224,40 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler switch (msg) { + case WM.WM_MOUSEMOVE: + { + if (!this.mouseTracked) + { + var tme = new TRACKMOUSEEVENT + { + cbSize = (uint)sizeof(TRACKMOUSEEVENT), + dwFlags = TME.TME_LEAVE, + hwndTrack = hWndCurrent, + }; + this.mouseTracked = TrackMouseEvent(&tme); + } + + var mousePos = new POINT(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); + if ((io.ConfigFlags & ImGuiConfigFlags.ViewportsEnable) != 0) + ClientToScreen(hWndCurrent, &mousePos); + io.AddMousePosEvent(mousePos.x, mousePos.y); + break; + } + + case WM.WM_MOUSELEAVE: + { + this.mouseTracked = false; + var mouseScreenPos = new POINT(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); + ClientToScreen(hWndCurrent, &mouseScreenPos); + if (this.ViewportFromPoint(mouseScreenPos).IsNull) + { + var fltMax = ImGuiNative.GETFLTMAX(); + io.AddMousePosEvent(-fltMax, -fltMax); + } + + break; + } + case WM.WM_LBUTTONDOWN: case WM.WM_LBUTTONDBLCLK: case WM.WM_RBUTTONDOWN: @@ -236,11 +270,10 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler var button = GetButton(msg, wParam); if (io.WantCaptureMouse) { - if (!ImGui.IsAnyMouseDown() && GetCapture() == nint.Zero) + if (this.mouseButtonsDown == 0 && GetCapture() == nint.Zero) SetCapture(hWndCurrent); - - io.MouseDown[button] = true; - this.imguiMouseIsDown[button] = true; + this.mouseButtonsDown |= 1 << button; + io.AddMouseButtonEvent(button, true); return default(LRESULT); } @@ -256,13 +289,12 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler case WM.WM_XBUTTONUP: { var button = GetButton(msg, wParam); - if (io.WantCaptureMouse && this.imguiMouseIsDown[button]) + if (io.WantCaptureMouse) { - if (!ImGui.IsAnyMouseDown() && GetCapture() == hWndCurrent) + this.mouseButtonsDown &= ~(1 << button); + if (this.mouseButtonsDown == 0 && GetCapture() == hWndCurrent) ReleaseCapture(); - - io.MouseDown[button] = false; - this.imguiMouseIsDown[button] = false; + io.AddMouseButtonEvent(button, false); return default(LRESULT); } @@ -272,7 +304,7 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler case WM.WM_MOUSEWHEEL: if (io.WantCaptureMouse) { - io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA; + io.AddMouseWheelEvent(0, GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA); return default(LRESULT); } @@ -280,7 +312,7 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler case WM.WM_MOUSEHWHEEL: if (io.WantCaptureMouse) { - io.MouseWheelH += GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA; + io.AddMouseWheelEvent(GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA, 0); return default(LRESULT); } @@ -374,68 +406,86 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler this.viewportHandler.UpdateMonitors(); break; - case WM.WM_KILLFOCUS when hWndCurrent == this.hWnd: - if (!ImGui.IsAnyMouseDown() && GetCapture() == hWndCurrent) - ReleaseCapture(); + case WM.WM_SETFOCUS when hWndCurrent == this.hWnd: + io.AddFocusEvent(true); + break; - ImGui.GetIO().WantCaptureMouse = false; - ImGui.ClearWindowFocus(); + case WM.WM_KILLFOCUS when hWndCurrent == this.hWnd: + io.AddFocusEvent(false); + // if (!ImGui.IsAnyMouseDown() && GetCapture() == hWndCurrent) + // ReleaseCapture(); + // + // ImGui.GetIO().WantCaptureMouse = false; + // ImGui.ClearWindowFocus(); break; } return null; } - private void UpdateMousePos() + private void UpdateMouseData(HWND focusedWindow) { var io = ImGui.GetIO(); - var pt = default(POINT); - // Depending on if Viewports are enabled, we have to change how we process - // the cursor position. If viewports are enabled, we pass the absolute cursor - // position to ImGui. Otherwise, we use the old method of passing client-local - // mouse position to ImGui. - if (io.ConfigFlags.HasFlag(ImGuiConfigFlags.ViewportsEnable)) + var mouseScreenPos = default(POINT); + var hasMouseScreenPos = GetCursorPos(&mouseScreenPos) != 0; + + var isAppFocused = + focusedWindow != default + && (focusedWindow == this.hWnd + || IsChild(focusedWindow, this.hWnd) + || !ImGui.FindViewportByPlatformHandle(focusedWindow).IsNull); + + if (isAppFocused) { + // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) + // When multi-viewports are enabled, all Dear ImGui positions are same as OS positions. if (io.WantSetMousePos) { - SetCursorPos((int)io.MousePos.X, (int)io.MousePos.Y); + var pos = new POINT((int)io.MousePos.X, (int)io.MousePos.Y); + if ((io.ConfigFlags & ImGuiConfigFlags.ViewportsEnable) != 0) + ClientToScreen(this.hWnd, &pos); + SetCursorPos(pos.x, pos.y); } + } - if (GetCursorPos(&pt)) - { - io.MousePos.X = pt.x; - io.MousePos.Y = pt.y; - } - else - { - io.MousePos.X = float.MinValue; - io.MousePos.Y = float.MinValue; - } + // (Optional) Fallback to provide mouse position when focused (WM_MOUSEMOVE already provides this when hovered or captured) + if (!io.WantSetMousePos && !this.mouseTracked && hasMouseScreenPos) + { + // Single viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window) + // (This is the position you can get with ::GetCursorPos() + ::ScreenToClient() or WM_MOUSEMOVE.) + // Multi-viewport mode: mouse position in OS absolute coordinates (io.MousePos is (0,0) when the mouse is on the upper-left of the primary monitor) + // (This is the position you can get with ::GetCursorPos() or WM_MOUSEMOVE + ::ClientToScreen(). In theory adding viewport->Pos to a client position would also be the same.) + var mousePos = mouseScreenPos; + if ((io.ConfigFlags & ImGuiConfigFlags.ViewportsEnable) == 0) + ClientToScreen(focusedWindow, &mousePos); + io.AddMousePosEvent(mousePos.x, mousePos.y); + } + + // (Optional) When using multiple viewports: call io.AddMouseViewportEvent() with the viewport the OS mouse cursor is hovering. + // If ImGuiBackendFlags_HasMouseHoveredViewport is not set by the backend, Dear imGui will ignore this field and infer the information using its flawed heuristic. + // - [X] Win32 backend correctly ignore viewports with the _NoInputs flag (here using ::WindowFromPoint with WM_NCHITTEST + HTTRANSPARENT in WndProc does that) + // Some backend are not able to handle that correctly. If a backend report an hovered viewport that has the _NoInputs flag (e.g. when dragging a window + // for docking, the viewport has the _NoInputs flag in order to allow us to find the viewport under), then Dear ImGui is forced to ignore the value reported + // by the backend, and use its flawed heuristic to guess the viewport behind. + // - [X] Win32 backend correctly reports this regardless of another viewport behind focused and dragged from (we need this to find a useful drag and drop target). + if (hasMouseScreenPos) + { + var viewport = this.ViewportFromPoint(mouseScreenPos); + io.AddMouseViewportEvent(!viewport.IsNull ? viewport.ID : 0u); } else { - if (io.WantSetMousePos) - { - pt.x = (int)io.MousePos.X; - pt.y = (int)io.MousePos.Y; - ClientToScreen(this.hWnd, &pt); - SetCursorPos(pt.x, pt.y); - } - - if (GetCursorPos(&pt) && ScreenToClient(this.hWnd, &pt)) - { - io.MousePos.X = pt.x; - io.MousePos.Y = pt.y; - } - else - { - io.MousePos.X = float.MinValue; - io.MousePos.Y = float.MinValue; - } + io.AddMouseViewportEvent(0); } } + private ImGuiViewportPtr ViewportFromPoint(POINT mouseScreenPos) + { + var hoveredHwnd = WindowFromPoint(mouseScreenPos); + return hoveredHwnd != default ? ImGui.FindViewportByPlatformHandle(hoveredHwnd) : default; + } + private bool UpdateMouseCursor() { var io = ImGui.GetIO(); @@ -451,7 +501,7 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler return true; } - private void ProcessKeyEventsWorkarounds() + private void ProcessKeyEventsWorkarounds(HWND focusedWindow) { // Left & right Shift keys: when both are pressed together, Windows tend to not generate the WM_KEYUP event for the first released one. if (ImGui.IsKeyDown(ImGuiKey.LeftShift) && !IsVkDown(VK.VK_LSHIFT)) @@ -480,7 +530,7 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler { // See: https://github.com/goatcorp/ImGuiScene/pull/13 // > GetForegroundWindow from winuser.h is a surprisingly expensive function. - var isForeground = GetForegroundWindow() == this.hWnd; + var isForeground = focusedWindow == this.hWnd; for (var i = (int)ImGuiKey.NamedKeyBegin; i < (int)ImGuiKey.NamedKeyEnd; i++) { // Skip raising modifier keys if the game is focused. @@ -622,7 +672,7 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler hbrBackground = (HBRUSH)(1 + COLOR.COLOR_BACKGROUND), lpfnWndProc = (delegate* unmanaged)Marshal .GetFunctionPointerForDelegate(this.input.wndProcDelegate), - lpszClassName = (ushort*)windowClassNamePtr, + lpszClassName = windowClassNamePtr, }; if (RegisterClassExW(&wcex) == 0) @@ -646,19 +696,12 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler return; var pio = ImGui.GetPlatformIO(); - - if (ImGui.GetPlatformIO().Handle->Monitors.Data != null) - { - // We allocated the platform monitor data in OnUpdateMonitors ourselves, - // so we have to free it ourselves to ImGui doesn't try to, or else it will crash - Marshal.FreeHGlobal(new IntPtr(ImGui.GetPlatformIO().Handle->Monitors.Data)); - ImGui.GetPlatformIO().Handle->Monitors = default; - } + ImGui.GetPlatformIO().Handle->Monitors.Free(); fixed (char* windowClassNamePtr = WindowClassName) { UnregisterClassW( - (ushort*)windowClassNamePtr, + windowClassNamePtr, (HINSTANCE)Marshal.GetHINSTANCE(typeof(ViewportHandler).Module)); } @@ -693,59 +736,50 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler // Here we use a manual ImVector overload, free the existing monitor data, // and allocate our own, as we are responsible for telling ImGui about monitors var pio = ImGui.GetPlatformIO(); - var numMonitors = GetSystemMetrics(SM.SM_CMONITORS); - var data = Marshal.AllocHGlobal(Marshal.SizeOf() * numMonitors); - if (pio.Handle->Monitors.Data != null) - Marshal.FreeHGlobal(new IntPtr(pio.Handle->Monitors.Data)); - pio.Handle->Monitors = new(numMonitors, numMonitors, (ImGuiPlatformMonitor*)data.ToPointer()); + pio.Handle->Monitors.Resize(0); - // ImGuiPlatformIOPtr platformIO = ImGui.GetPlatformIO(); - // Marshal.FreeHGlobal(platformIO.Handle->Monitors.Data); - // int numMonitors = GetSystemMetrics(SystemMetric.SM_CMONITORS); - // nint data = Marshal.AllocHGlobal(Marshal.SizeOf() * numMonitors); - // platformIO.Handle->Monitors = new ImVector(numMonitors, numMonitors, data); - - var monitorIndex = -1; - var enumfn = new MonitorEnumProcDelegate( - (hMonitor, _, _, _) => - { - monitorIndex++; - var info = new MONITORINFO { cbSize = (uint)sizeof(MONITORINFO) }; - if (!GetMonitorInfoW(hMonitor, &info)) - return true; - - var monitorLt = new Vector2(info.rcMonitor.left, info.rcMonitor.top); - var monitorRb = new Vector2(info.rcMonitor.right, info.rcMonitor.bottom); - var workLt = new Vector2(info.rcWork.left, info.rcWork.top); - var workRb = new Vector2(info.rcWork.right, info.rcWork.bottom); - // Give ImGui the info for this display - - ref var imMonitor = ref ImGui.GetPlatformIO().Monitors.Ref(monitorIndex); - imMonitor.MainPos = monitorLt; - imMonitor.MainSize = monitorRb - monitorLt; - imMonitor.WorkPos = workLt; - imMonitor.WorkSize = workRb - workLt; - imMonitor.DpiScale = 1f; - return true; - }); - EnumDisplayMonitors( - default, - null, - (delegate* unmanaged)Marshal.GetFunctionPointerForDelegate(enumfn), - default); + EnumDisplayMonitors(default, null, &EnumDisplayMonitorsCallback, default); Log.Information("Monitors set up!"); - for (var i = 0; i < numMonitors; i++) + foreach (ref var monitor in pio.Handle->Monitors) { - var monitor = pio.Handle->Monitors[i]; Log.Information( - "Monitor {Index}: {MainPos} {MainSize} {WorkPos} {WorkSize}", - i, + "Monitor: {MainPos} {MainSize} {WorkPos} {WorkSize}", monitor.MainPos, monitor.MainSize, monitor.WorkPos, monitor.WorkSize); } + + return; + + [UnmanagedCallersOnly] + static BOOL EnumDisplayMonitorsCallback(HMONITOR hMonitor, HDC hdc, RECT* rect, LPARAM lParam) + { + var info = new MONITORINFO { cbSize = (uint)sizeof(MONITORINFO) }; + if (!GetMonitorInfoW(hMonitor, &info)) + return true; + + var monitorLt = new Vector2(info.rcMonitor.left, info.rcMonitor.top); + var monitorRb = new Vector2(info.rcMonitor.right, info.rcMonitor.bottom); + var workLt = new Vector2(info.rcWork.left, info.rcWork.top); + var workRb = new Vector2(info.rcWork.right, info.rcWork.bottom); + + // Give ImGui the info for this display + var imMonitor = new ImGuiPlatformMonitor + { + MainPos = monitorLt, + MainSize = monitorRb - monitorLt, + WorkPos = workLt, + WorkSize = workRb - workLt, + DpiScale = 1f, + }; + if ((info.dwFlags & MONITORINFOF_PRIMARY) != 0) + ImGui.GetPlatformIO().Monitors.PushFront(imMonitor); + else + ImGui.GetPlatformIO().Monitors.PushBack(imMonitor); + return true; + } } [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])] @@ -781,8 +815,8 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler { data->Hwnd = CreateWindowExW( (uint)data->DwExStyle, - (ushort*)windowClassNamePtr, - (ushort*)windowClassNamePtr, + windowClassNamePtr, + windowClassNamePtr, (uint)data->DwStyle, rect.left, rect.top, @@ -794,6 +828,9 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler null); } + if (data->Hwnd == 0) + Util.Fatal($"CreateWindowExW failed: {GetLastError()}", "ImGui Viewport error"); + data->HwndOwned = true; viewport.PlatformRequestResize = false; viewport.PlatformHandle = viewport.PlatformHandleRaw = data->Hwnd; @@ -993,7 +1030,7 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler { var data = (ImGuiViewportDataWin32*)viewport.PlatformUserData; fixed (char* pwszTitle = MemoryHelper.ReadStringNullTerminated((nint)title)) - SetWindowTextW(data->Hwnd, (ushort*)pwszTitle); + SetWindowTextW(data->Hwnd, pwszTitle); } [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])] diff --git a/Dalamud/Interface/ImGuiSeStringRenderer/Internal/SeStringColorStackSet.cs b/Dalamud/Interface/ImGuiSeStringRenderer/Internal/SeStringColorStackSet.cs index ad60d405e..85ab2e441 100644 --- a/Dalamud/Interface/ImGuiSeStringRenderer/Internal/SeStringColorStackSet.cs +++ b/Dalamud/Interface/ImGuiSeStringRenderer/Internal/SeStringColorStackSet.cs @@ -15,10 +15,6 @@ namespace Dalamud.Interface.ImGuiSeStringRenderer.Internal; /// Color stacks to use while evaluating a SeString. internal sealed class SeStringColorStackSet { - /// Parsed , containing colors to use with and - /// . - private readonly uint[,] colorTypes; - /// Foreground color stack while evaluating a SeString for rendering. /// Touched only from the main thread. private readonly List colorStack = []; @@ -39,30 +35,38 @@ internal sealed class SeStringColorStackSet foreach (var row in uiColor) maxId = (int)Math.Max(row.RowId, maxId); - this.colorTypes = new uint[maxId + 1, 4]; + this.ColorTypes = new uint[maxId + 1, 4]; foreach (var row in uiColor) { // Contains ABGR. - this.colorTypes[row.RowId, 0] = row.Dark; - this.colorTypes[row.RowId, 1] = row.Light; - this.colorTypes[row.RowId, 2] = row.ClassicFF; - this.colorTypes[row.RowId, 3] = row.ClearBlue; + this.ColorTypes[row.RowId, 0] = row.Dark; + this.ColorTypes[row.RowId, 1] = row.Light; + this.ColorTypes[row.RowId, 2] = row.ClassicFF; + this.ColorTypes[row.RowId, 3] = row.ClearBlue; } if (BitConverter.IsLittleEndian) { // ImGui wants RGBA in LE. - fixed (uint* p = this.colorTypes) + fixed (uint* p = this.ColorTypes) { - foreach (ref var r in new Span(p, this.colorTypes.GetLength(0) * this.colorTypes.GetLength(1))) + foreach (ref var r in new Span(p, this.ColorTypes.GetLength(0) * this.ColorTypes.GetLength(1))) r = BinaryPrimitives.ReverseEndianness(r); } } } + /// Initializes a new instance of the class. + /// Color types. + public SeStringColorStackSet(uint[,] colorTypes) => this.ColorTypes = colorTypes; + /// Gets a value indicating whether at least one color has been pushed to the edge color stack. public bool HasAdditionalEdgeColor { get; private set; } + /// Gets the parsed containing colors to use with + /// and . + public uint[,] ColorTypes { get; } + /// Resets the colors in the stack. /// Draw state. internal void Initialize(scoped ref SeStringDrawState drawState) @@ -191,9 +195,9 @@ internal sealed class SeStringColorStackSet } // Opacity component is ignored. - var color = themeIndex >= 0 && themeIndex < this.colorTypes.GetLength(1) && - colorTypeIndex < this.colorTypes.GetLength(0) - ? this.colorTypes[colorTypeIndex, themeIndex] + var color = themeIndex >= 0 && themeIndex < this.ColorTypes.GetLength(1) && + colorTypeIndex < this.ColorTypes.GetLength(0) + ? this.ColorTypes[colorTypeIndex, themeIndex] : 0u; rgbaStack.Add(color | 0xFF000000u); diff --git a/Dalamud/Interface/ImGuiSeStringRenderer/Internal/SeStringRenderer.cs b/Dalamud/Interface/ImGuiSeStringRenderer/Internal/SeStringRenderer.cs index d0c40cd9f..397502b30 100644 --- a/Dalamud/Interface/ImGuiSeStringRenderer/Internal/SeStringRenderer.cs +++ b/Dalamud/Interface/ImGuiSeStringRenderer/Internal/SeStringRenderer.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Numerics; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; @@ -25,7 +26,7 @@ namespace Dalamud.Interface.ImGuiSeStringRenderer.Internal; /// Draws SeString. [ServiceManager.EarlyLoadedService] -internal unsafe class SeStringRenderer : IInternalDisposableService +internal class SeStringRenderer : IServiceType { private const int ImGuiContextCurrentWindowOffset = 0x3FF0; private const int ImGuiWindowDcOffset = 0x118; @@ -47,28 +48,19 @@ internal unsafe class SeStringRenderer : IInternalDisposableService /// Parsed text fragments from a SeString. /// Touched only from the main thread. - private readonly List fragments = []; + private readonly List fragmentsMainThread = []; /// Color stacks to use while evaluating a SeString for rendering. /// Touched only from the main thread. - private readonly SeStringColorStackSet colorStackSet; - - /// Splits a draw list so that different layers of a single glyph can be drawn out of order. - private ImDrawListSplitter* splitter = ImGui.ImDrawListSplitter(); + private readonly SeStringColorStackSet colorStackSetMainThread; [ServiceManager.ServiceConstructor] private SeStringRenderer(DataManager dm, TargetSigScanner sigScanner) { - this.colorStackSet = new(dm.Excel.GetSheet()); + this.colorStackSetMainThread = new(dm.Excel.GetSheet()); this.gfd = dm.GetFile("common/font/gfdata.gfd")!; } - /// Finalizes an instance of the class. - ~SeStringRenderer() => this.ReleaseUnmanagedResources(); - - /// - void IInternalDisposableService.DisposeService() => this.ReleaseUnmanagedResources(); - /// Compiles and caches a SeString from a text macro representation. /// SeString text macro representation. /// Newline characters will be normalized to newline payloads. @@ -80,6 +72,44 @@ internal unsafe class SeStringRenderer : IInternalDisposableService text.ReplaceLineEndings("
"), new() { ExceptionMode = MacroStringParseExceptionMode.EmbedError })); + /// Creates a draw data that will draw the given SeString onto it. + /// SeString to render. + /// Parameters for drawing. + /// A new self-contained draw data. + public unsafe BufferBackedImDrawData CreateDrawData( + ReadOnlySeStringSpan sss, + scoped in SeStringDrawParams drawParams = default) + { + if (drawParams.TargetDrawList is not null) + { + throw new ArgumentException( + $"{nameof(SeStringDrawParams.TargetDrawList)} may not be specified.", + nameof(drawParams)); + } + + var dd = BufferBackedImDrawData.Create(); + + try + { + var size = this.Draw(sss, drawParams with { TargetDrawList = dd.ListPtr }).Size; + + var offset = drawParams.ScreenOffset ?? Vector2.Zero; + foreach (var vtx in new Span(dd.ListPtr.VtxBuffer.Data, dd.ListPtr.VtxBuffer.Size)) + offset = Vector2.Min(offset, vtx.Pos); + + dd.Data.DisplayPos = offset; + dd.Data.DisplaySize = size - offset; + dd.Data.Valid = 1; + dd.UpdateDrawDataStatistics(); + return dd; + } + catch + { + dd.Dispose(); + throw; + } + } + /// Compiles and caches a SeString from a text macro representation, and then draws it. /// SeString text macro representation. /// Newline characters will be normalized to newline payloads. @@ -113,28 +143,44 @@ internal unsafe class SeStringRenderer : IInternalDisposableService /// ImGui ID, if link functionality is desired. /// Button flags to use on link interaction. /// Interaction result of the rendered text. - public SeStringDrawResult Draw( + public unsafe SeStringDrawResult Draw( ReadOnlySeStringSpan sss, scoped in SeStringDrawParams drawParams = default, ImGuiId imGuiId = default, ImGuiButtonFlags buttonFlags = ImGuiButtonFlags.MouseButtonDefault) { - // Drawing is only valid if done from the main thread anyway, especially with interactivity. - ThreadSafety.AssertMainThread(); + // Interactivity is supported only from the main thread. + if (!imGuiId.IsEmpty()) + ThreadSafety.AssertMainThread(); if (drawParams.TargetDrawList is not null && imGuiId) throw new ArgumentException("ImGuiId cannot be set if TargetDrawList is manually set.", nameof(imGuiId)); - // This also does argument validation for drawParams. Do it here. - var state = new SeStringDrawState(sss, drawParams, this.colorStackSet, this.splitter); + using var cleanup = new DisposeSafety.ScopedFinalizer(); - // Reset and initialize the state. - this.fragments.Clear(); - this.colorStackSet.Initialize(ref state); + ImFont* font = null; + if (drawParams.Font.HasValue) + font = drawParams.Font.Value; + + // API14: Remove commented out code + if (ThreadSafety.IsMainThread /* && drawParams.TargetDrawList is null */ && font is null) + font = ImGui.GetFont(); + if (font is null) + throw new ArgumentException("Specified font is empty."); + + // This also does argument validation for drawParams. Do it here. + // `using var` makes a struct read-only, but we do want to modify it. + var stateStorage = new SeStringDrawState( + sss, + drawParams, + ThreadSafety.IsMainThread ? this.colorStackSetMainThread : new(this.colorStackSetMainThread.ColorTypes), + ThreadSafety.IsMainThread ? this.fragmentsMainThread : [], + font); + ref var state = ref Unsafe.AsRef(in stateStorage); // Analyze the provided SeString and break it up to text fragments. this.CreateTextFragments(ref state); - var fragmentSpan = CollectionsMarshal.AsSpan(this.fragments); + var fragmentSpan = CollectionsMarshal.AsSpan(state.Fragments); // Calculate size. var size = Vector2.Zero; @@ -147,24 +193,17 @@ internal unsafe class SeStringRenderer : IInternalDisposableService state.SplitDrawList(); - // Handle cases where ImGui.AlignTextToFramePadding has been called. - var context = ImGui.GetCurrentContext(); - var currLineTextBaseOffset = 0f; - if (!context.IsNull) - { - var currentWindow = context.CurrentWindow; - if (!currentWindow.IsNull) - { - currLineTextBaseOffset = currentWindow.DC.CurrLineTextBaseOffset; - } - } - var itemSize = size; - if (currLineTextBaseOffset != 0f) + if (drawParams.TargetDrawList is null) { - itemSize.Y += 2 * currLineTextBaseOffset; - foreach (ref var f in fragmentSpan) - f.Offset += new Vector2(0, currLineTextBaseOffset); + // Handle cases where ImGui.AlignTextToFramePadding has been called. + var currLineTextBaseOffset = ImGui.GetCurrentContext().CurrentWindow.DC.CurrLineTextBaseOffset; + if (currLineTextBaseOffset != 0f) + { + itemSize.Y += 2 * currLineTextBaseOffset; + foreach (ref var f in fragmentSpan) + f.Offset += new Vector2(0, currLineTextBaseOffset); + } } // Draw all text fragments. @@ -280,15 +319,6 @@ internal unsafe class SeStringRenderer : IInternalDisposableService return displayRune.Value != 0; } - private void ReleaseUnmanagedResources() - { - if (this.splitter is not null) - { - this.splitter->Destroy(); - this.splitter = null; - } - } - /// Creates text fragment, taking line and word breaking into account. /// Draw state. private void CreateTextFragments(ref SeStringDrawState state) @@ -391,7 +421,7 @@ internal unsafe class SeStringRenderer : IInternalDisposableService var overflows = Math.Max(w, xy.X + fragment.VisibleWidth) > state.WrapWidth; // Test if the fragment does not fit into the current line and the current line is not empty. - if (xy.X != 0 && this.fragments.Count > 0 && !this.fragments[^1].BreakAfter && overflows) + if (xy.X != 0 && state.Fragments.Count > 0 && !state.Fragments[^1].BreakAfter && overflows) { // Introduce break if this is the first time testing the current break unit or the current fragment // is an entity. @@ -401,7 +431,7 @@ internal unsafe class SeStringRenderer : IInternalDisposableService xy.X = 0; xy.Y += state.LineHeight; w = 0; - CollectionsMarshal.AsSpan(this.fragments)[^1].BreakAfter = true; + CollectionsMarshal.AsSpan(state.Fragments)[^1].BreakAfter = true; fragment.Offset = xy; // Now that the fragment is given its own line, test if it overflows again. @@ -419,16 +449,16 @@ internal unsafe class SeStringRenderer : IInternalDisposableService fragment = this.CreateFragment(state, prev, curr, true, xy, link, entity, remainingWidth); } } - else if (this.fragments.Count > 0 && xy.X != 0) + else if (state.Fragments.Count > 0 && xy.X != 0) { // New fragment fits into the current line, and it has a previous fragment in the same line. // If the previous fragment ends with a soft hyphen, adjust its width so that the width of its // trailing soft hyphens are not considered. - if (this.fragments[^1].EndsWithSoftHyphen) - xy.X += this.fragments[^1].AdvanceWidthWithoutSoftHyphen - this.fragments[^1].AdvanceWidth; + if (state.Fragments[^1].EndsWithSoftHyphen) + xy.X += state.Fragments[^1].AdvanceWidthWithoutSoftHyphen - state.Fragments[^1].AdvanceWidth; // Adjust this fragment's offset from kerning distance. - xy.X += state.CalculateScaledDistance(this.fragments[^1].LastRune, fragment.FirstRune); + xy.X += state.CalculateScaledDistance(state.Fragments[^1].LastRune, fragment.FirstRune); fragment.Offset = xy; } @@ -439,7 +469,7 @@ internal unsafe class SeStringRenderer : IInternalDisposableService w = Math.Max(w, xy.X + fragment.VisibleWidth); xy.X += fragment.AdvanceWidth; prev = fragment.To; - this.fragments.Add(fragment); + state.Fragments.Add(fragment); if (fragment.BreakAfter) { @@ -491,7 +521,7 @@ internal unsafe class SeStringRenderer : IInternalDisposableService if (gfdTextureSrv != 0) { state.Draw( - new ImTextureID(gfdTextureSrv), + new(gfdTextureSrv), offset + new Vector2(x, MathF.Round((state.LineHeight - size.Y) / 2)), size, useHq ? gfdEntry.HqUv0 : gfdEntry.Uv0, @@ -528,7 +558,7 @@ internal unsafe class SeStringRenderer : IInternalDisposableService return; - static nint GetGfdTextureSrv() + static unsafe nint GetGfdTextureSrv() { var uim = UIModule.Instance(); if (uim is null) @@ -553,7 +583,7 @@ internal unsafe class SeStringRenderer : IInternalDisposableService /// Determines a bitmap icon to display for the given SeString payload. /// Byte span that should include a SeString payload. /// Icon to display, or if it should not be displayed as an icon. - private BitmapFontIcon GetBitmapFontIconFor(ReadOnlySpan sss) + private unsafe BitmapFontIcon GetBitmapFontIconFor(ReadOnlySpan sss) { var e = new ReadOnlySeStringSpan(sss).GetEnumerator(); if (!e.MoveNext() || e.Current.MacroCode is not MacroCode.Icon and not MacroCode.Icon2) @@ -710,38 +740,4 @@ internal unsafe class SeStringRenderer : IInternalDisposableService firstDisplayRune ?? default, lastNonSoftHyphenRune); } - - /// Represents a text fragment in a SeString span. - /// Starting byte offset (inclusive) in a SeString. - /// Ending byte offset (exclusive) in a SeString. - /// Byte offset of the link that decorates this text fragment, or -1 if none. - /// Offset in pixels w.r.t. . - /// Replacement entity, if any. - /// Visible width of this text fragment. This is the width required to draw everything - /// without clipping. - /// Advance width of this text fragment. This is the width required to add to the cursor - /// to position the next fragment correctly. - /// Same with , but trimming all the - /// trailing soft hyphens. - /// Whether to insert a line break after this text fragment. - /// Whether this text fragment ends with one or more soft hyphens. - /// First rune in this text fragment. - /// Last rune in this text fragment, for the purpose of calculating kerning distance with - /// the following text fragment in the same line, if any. - private record struct TextFragment( - int From, - int To, - int Link, - Vector2 Offset, - SeStringReplacementEntity Entity, - float VisibleWidth, - float AdvanceWidth, - float AdvanceWidthWithoutSoftHyphen, - bool BreakAfter, - bool EndsWithSoftHyphen, - Rune FirstRune, - Rune LastRune) - { - public bool IsSoftHyphenVisible => this.EndsWithSoftHyphen && this.BreakAfter; - } } diff --git a/Dalamud/Interface/ImGuiSeStringRenderer/Internal/TextFragment.cs b/Dalamud/Interface/ImGuiSeStringRenderer/Internal/TextFragment.cs new file mode 100644 index 000000000..a64c32109 --- /dev/null +++ b/Dalamud/Interface/ImGuiSeStringRenderer/Internal/TextFragment.cs @@ -0,0 +1,39 @@ +using System.Numerics; +using System.Text; + +namespace Dalamud.Interface.ImGuiSeStringRenderer.Internal; + +/// Represents a text fragment in a SeString span. +/// Starting byte offset (inclusive) in a SeString. +/// Ending byte offset (exclusive) in a SeString. +/// Byte offset of the link that decorates this text fragment, or -1 if none. +/// Offset in pixels w.r.t. . +/// Replacement entity, if any. +/// Visible width of this text fragment. This is the width required to draw everything +/// without clipping. +/// Advance width of this text fragment. This is the width required to add to the cursor +/// to position the next fragment correctly. +/// Same with , but trimming all the +/// trailing soft hyphens. +/// Whether to insert a line break after this text fragment. +/// Whether this text fragment ends with one or more soft hyphens. +/// First rune in this text fragment. +/// Last rune in this text fragment, for the purpose of calculating kerning distance with +/// the following text fragment in the same line, if any. +internal record struct TextFragment( + int From, + int To, + int Link, + Vector2 Offset, + SeStringReplacementEntity Entity, + float VisibleWidth, + float AdvanceWidth, + float AdvanceWidthWithoutSoftHyphen, + bool BreakAfter, + bool EndsWithSoftHyphen, + Rune FirstRune, + Rune LastRune) +{ + /// Gets a value indicating whether the fragment ends with a visible soft hyphen. + public bool IsSoftHyphenVisible => this.EndsWithSoftHyphen && this.BreakAfter; +} diff --git a/Dalamud/Interface/ImGuiSeStringRenderer/SeStringDrawParams.cs b/Dalamud/Interface/ImGuiSeStringRenderer/SeStringDrawParams.cs index f3d4c44e9..09c3e9ed9 100644 --- a/Dalamud/Interface/ImGuiSeStringRenderer/SeStringDrawParams.cs +++ b/Dalamud/Interface/ImGuiSeStringRenderer/SeStringDrawParams.cs @@ -12,7 +12,11 @@ public record struct SeStringDrawParams /// Gets or sets the target draw list. /// Target draw list, default(ImDrawListPtr) to not draw, or null to use /// (the default). - /// If this value is set, will not be called, and ImGui ID will be ignored. + /// + /// If this value is set, will not be called, and ImGui ID will be ignored. + /// You must specify a valid draw list, a valid font via and if you set this value, + /// since the renderer will not be able to retrieve them from ImGui context. + /// Must be set when drawing off the main thread. /// public ImDrawListPtr? TargetDrawList { get; set; } @@ -21,16 +25,20 @@ public record struct SeStringDrawParams public SeStringReplacementEntity.GetEntityDelegate? GetEntity { get; set; } /// Gets or sets the screen offset of the left top corner. - /// Screen offset to draw at, or null to use . + /// Screen offset to draw at, or null to use , if no + /// is specified. Otherwise, you must specify it (for example, by passing when passing the window + /// draw list. public Vector2? ScreenOffset { get; set; } /// Gets or sets the font to use. /// Font to use, or null to use (the default). + /// Must be set when specifying a target draw-list or drawing off the main thread. public ImFontPtr? Font { get; set; } /// Gets or sets the font size. /// Font size in pixels, or 0 to use the current ImGui font size . /// + /// Must be set when specifying a target draw-list or drawing off the main thread. public float? FontSize { get; set; } /// Gets or sets the line height ratio. diff --git a/Dalamud/Interface/ImGuiSeStringRenderer/SeStringDrawState.cs b/Dalamud/Interface/ImGuiSeStringRenderer/SeStringDrawState.cs index 64a7f3db3..c5aba26c1 100644 --- a/Dalamud/Interface/ImGuiSeStringRenderer/SeStringDrawState.cs +++ b/Dalamud/Interface/ImGuiSeStringRenderer/SeStringDrawState.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -6,6 +7,8 @@ using System.Text; using Dalamud.Bindings.ImGui; using Dalamud.Interface.ImGuiSeStringRenderer.Internal; using Dalamud.Interface.Utility; +using Dalamud.Utility; + using FFXIVClientStructs.FFXIV.Component.GUI; using Lumina.Text.Payloads; using Lumina.Text.ReadOnly; @@ -19,46 +22,88 @@ public unsafe ref struct SeStringDrawState private static readonly int ChannelCount = Enum.GetValues().Length; private readonly ImDrawList* drawList; - private readonly SeStringColorStackSet colorStackSet; - private readonly ImDrawListSplitter* splitter; + + private ImDrawListSplitter splitter; /// Initializes a new instance of the struct. /// Raw SeString byte span. /// Instance of to initialize from. /// Instance of to use. - /// Instance of ImGui Splitter to use. + /// Fragments. + /// Font to use. internal SeStringDrawState( ReadOnlySpan span, scoped in SeStringDrawParams ssdp, SeStringColorStackSet colorStackSet, - ImDrawListSplitter* splitter) + List fragments, + ImFont* font) { - this.colorStackSet = colorStackSet; - this.splitter = splitter; - this.drawList = ssdp.TargetDrawList ?? ImGui.GetWindowDrawList(); this.Span = span; + this.ColorStackSet = colorStackSet; + this.Fragments = fragments; + this.Font = font; + + if (ssdp.TargetDrawList is null) + { + if (!ThreadSafety.IsMainThread) + { + throw new ArgumentException( + $"{nameof(ssdp.TargetDrawList)} must be set to render outside the main thread."); + } + + this.drawList = ssdp.TargetDrawList ?? ImGui.GetWindowDrawList(); + this.ScreenOffset = ssdp.ScreenOffset ?? ImGui.GetCursorScreenPos(); + this.FontSize = ssdp.FontSize ?? ImGui.GetFontSize(); + this.WrapWidth = ssdp.WrapWidth ?? ImGui.GetContentRegionAvail().X; + this.Color = ssdp.Color ?? ImGui.GetColorU32(ImGuiCol.Text); + this.LinkHoverBackColor = ssdp.LinkHoverBackColor ?? ImGui.GetColorU32(ImGuiCol.ButtonHovered); + this.LinkActiveBackColor = ssdp.LinkActiveBackColor ?? ImGui.GetColorU32(ImGuiCol.ButtonActive); + this.ThemeIndex = ssdp.ThemeIndex ?? AtkStage.Instance()->AtkUIColorHolder->ActiveColorThemeType; + } + else + { + this.drawList = ssdp.TargetDrawList.Value; + this.ScreenOffset = ssdp.ScreenOffset ?? Vector2.Zero; + + // API14: Remove, always throw + if (ThreadSafety.IsMainThread) + { + this.ScreenOffset = ssdp.ScreenOffset ?? ImGui.GetCursorScreenPos(); + this.FontSize = ssdp.FontSize ?? ImGui.GetFontSize(); + } + else + { + throw new ArgumentException( + $"{nameof(ssdp.FontSize)} must be set when specifying a target draw list, as it cannot be fetched from the ImGui state."); + } + + // this.FontSize = ssdp.FontSize ?? throw new ArgumentException( + // $"{nameof(ssdp.FontSize)} must be set when specifying a target draw list, as it cannot be fetched from the ImGui state."); + this.WrapWidth = ssdp.WrapWidth ?? float.MaxValue; + this.Color = ssdp.Color ?? uint.MaxValue; + this.LinkHoverBackColor = 0; // Interactivity is unused outside the main thread. + this.LinkActiveBackColor = 0; // Interactivity is unused outside the main thread. + this.ThemeIndex = ssdp.ThemeIndex ?? 0; + } + + this.splitter = default; this.GetEntity = ssdp.GetEntity; - this.ScreenOffset = ssdp.ScreenOffset ?? ImGui.GetCursorScreenPos(); this.ScreenOffset = new(MathF.Round(this.ScreenOffset.X), MathF.Round(this.ScreenOffset.Y)); - this.Font = ssdp.EffectiveFont; - this.FontSize = ssdp.FontSize ?? ImGui.GetFontSize(); - this.FontSizeScale = this.FontSize / this.Font->FontSize; + this.FontSizeScale = this.FontSize / this.Font.FontSize; this.LineHeight = MathF.Round(ssdp.EffectiveLineHeight); - this.WrapWidth = ssdp.WrapWidth ?? ImGui.GetContentRegionAvail().X; this.LinkUnderlineThickness = ssdp.LinkUnderlineThickness ?? 0f; this.Opacity = ssdp.EffectiveOpacity; this.EdgeOpacity = (ssdp.EdgeStrength ?? 0.25f) * ssdp.EffectiveOpacity; - this.Color = ssdp.Color ?? ImGui.GetColorU32(ImGuiCol.Text); this.EdgeColor = ssdp.EdgeColor ?? 0xFF000000; this.ShadowColor = ssdp.ShadowColor ?? 0xFF000000; - this.LinkHoverBackColor = ssdp.LinkHoverBackColor ?? ImGui.GetColorU32(ImGuiCol.ButtonHovered); - this.LinkActiveBackColor = ssdp.LinkActiveBackColor ?? ImGui.GetColorU32(ImGuiCol.ButtonActive); this.ForceEdgeColor = ssdp.ForceEdgeColor; - this.ThemeIndex = ssdp.ThemeIndex ?? AtkStage.Instance()->AtkUIColorHolder->ActiveColorThemeType; this.Bold = ssdp.Bold; this.Italic = ssdp.Italic; this.Edge = ssdp.Edge; this.Shadow = ssdp.Shadow; + + this.ColorStackSet.Initialize(ref this); + fragments.Clear(); } /// @@ -74,7 +119,7 @@ public unsafe ref struct SeStringDrawState public Vector2 ScreenOffset { get; } /// - public ImFont* Font { get; } + public ImFontPtr Font { get; } /// public float FontSize { get; } @@ -135,7 +180,7 @@ public unsafe ref struct SeStringDrawState /// Gets a value indicating whether the edge should be drawn. public readonly bool ShouldDrawEdge => - (this.Edge || this.colorStackSet.HasAdditionalEdgeColor) && this.EdgeColor >= 0x1000000; + (this.Edge || this.ColorStackSet.HasAdditionalEdgeColor) && this.EdgeColor >= 0x1000000; /// Gets a value indicating whether the edge should be drawn. public readonly bool ShouldDrawShadow => this is { Shadow: true, ShadowColor: >= 0x1000000 }; @@ -143,11 +188,17 @@ public unsafe ref struct SeStringDrawState /// Gets a value indicating whether the edge should be drawn. public readonly bool ShouldDrawForeground => this is { Color: >= 0x1000000 }; + /// Gets the color stacks. + internal SeStringColorStackSet ColorStackSet { get; } + + /// Gets the text fragments. + internal List Fragments { get; } + /// Sets the current channel in the ImGui draw list splitter. /// Channel to switch to. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly void SetCurrentChannel(SeStringDrawChannel channelIndex) => - this.splitter->SetCurrentChannel(this.drawList, (int)channelIndex); + public void SetCurrentChannel(SeStringDrawChannel channelIndex) => + this.splitter.SetCurrentChannel(this.drawList, (int)channelIndex); /// Draws a single texture. /// ImGui texture ID to draw from. @@ -216,9 +267,9 @@ public unsafe ref struct SeStringDrawState /// Draws a single glyph using current styling configurations. /// Glyph to draw. /// Offset of the glyph in pixels w.r.t. . - internal readonly void DrawGlyph(scoped in ImGuiHelpers.ImFontGlyphReal g, Vector2 offset) + internal void DrawGlyph(scoped in ImGuiHelpers.ImFontGlyphReal g, Vector2 offset) { - var texId = this.Font->ContainerAtlas->Textures.Ref(g.TextureIndex).TexID; + var texId = this.Font.ContainerAtlas.Textures.Ref(g.TextureIndex).TexID; var xy0 = new Vector2( MathF.Round(g.X0 * this.FontSizeScale), MathF.Round(g.Y0 * this.FontSizeScale)); @@ -268,14 +319,14 @@ public unsafe ref struct SeStringDrawState /// Offset of the glyph in pixels w.r.t. /// . /// Advance width of the glyph. - internal readonly void DrawLinkUnderline(Vector2 offset, float advanceWidth) + internal void DrawLinkUnderline(Vector2 offset, float advanceWidth) { if (this.LinkUnderlineThickness < 1f) return; offset += this.ScreenOffset; offset.Y += (this.LinkUnderlineThickness - 1) / 2f; - offset.Y += MathF.Round(((this.LineHeight - this.FontSize) / 2) + (this.Font->Ascent * this.FontSizeScale)); + offset.Y += MathF.Round(((this.LineHeight - this.FontSize) / 2) + (this.Font.Ascent * this.FontSizeScale)); this.SetCurrentChannel(SeStringDrawChannel.Foreground); this.DrawList.AddLine( @@ -302,9 +353,9 @@ public unsafe ref struct SeStringDrawState internal readonly ref ImGuiHelpers.ImFontGlyphReal FindGlyph(Rune rune) { var p = rune.Value is >= ushort.MinValue and < ushort.MaxValue - ? this.Font->FindGlyph((ushort)rune.Value) - : this.Font->FallbackGlyph; - return ref *(ImGuiHelpers.ImFontGlyphReal*)p; + ? (ImFontGlyphPtr)this.Font.FindGlyph((ushort)rune.Value) + : this.Font.FallbackGlyph; + return ref *(ImGuiHelpers.ImFontGlyphReal*)p.Handle; } /// Gets the glyph corresponding to the given codepoint. @@ -337,7 +388,7 @@ public unsafe ref struct SeStringDrawState return 0; return MathF.Round( - this.Font->GetDistanceAdjustmentForPair( + this.Font.GetDistanceAdjustmentForPair( (ushort)left.Value, (ushort)right.Value) * this.FontSizeScale); } @@ -350,15 +401,15 @@ public unsafe ref struct SeStringDrawState switch (payload.MacroCode) { case MacroCode.Color: - this.colorStackSet.HandleColorPayload(ref this, payload); + this.ColorStackSet.HandleColorPayload(ref this, payload); return true; case MacroCode.EdgeColor: - this.colorStackSet.HandleEdgeColorPayload(ref this, payload); + this.ColorStackSet.HandleEdgeColorPayload(ref this, payload); return true; case MacroCode.ShadowColor: - this.colorStackSet.HandleShadowColorPayload(ref this, payload); + this.ColorStackSet.HandleShadowColorPayload(ref this, payload); return true; case MacroCode.Bold when payload.TryGetExpression(out var e) && e.TryGetUInt(out var u): @@ -379,11 +430,11 @@ public unsafe ref struct SeStringDrawState return true; case MacroCode.ColorType: - this.colorStackSet.HandleColorTypePayload(ref this, payload); + this.ColorStackSet.HandleColorTypePayload(ref this, payload); return true; case MacroCode.EdgeColorType: - this.colorStackSet.HandleEdgeColorTypePayload(ref this, payload); + this.ColorStackSet.HandleEdgeColorTypePayload(ref this, payload); return true; default: @@ -393,10 +444,9 @@ public unsafe ref struct SeStringDrawState /// Splits the draw list. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal readonly void SplitDrawList() => - this.splitter->Split(this.drawList, ChannelCount); + internal void SplitDrawList() => this.splitter.Split(this.drawList, ChannelCount); /// Merges the draw list. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal readonly void MergeDrawList() => this.splitter->Merge(this.drawList); + internal void MergeDrawList() => this.splitter.Merge(this.drawList); } diff --git a/Dalamud/Interface/Internal/DalamudInterface.cs b/Dalamud/Interface/Internal/DalamudInterface.cs index 64e1acaa4..bf55a5486 100644 --- a/Dalamud/Interface/Internal/DalamudInterface.cs +++ b/Dalamud/Interface/Internal/DalamudInterface.cs @@ -533,6 +533,13 @@ internal class DalamudInterface : IInternalDisposableService this.creditsDarkeningAnimation.Restart(); } + /// + public T GetDataWindowWidget() where T : IDataWindowWidget => this.dataWindow.GetWidget(); + + /// Sets the data window current widget. + /// Widget to set current. + public void SetDataWindowWidget(IDataWindowWidget widget) => this.dataWindow.CurrentWidget = widget; + private void OnDraw() { this.FrameCount++; @@ -660,6 +667,8 @@ internal class DalamudInterface : IInternalDisposableService { if (this.isImGuiDrawDevMenu) { + using var barColor = ImRaii.PushColor(ImGuiCol.WindowBg, new Vector4(0.060f, 0.060f, 0.060f, 0.773f)); + barColor.Push(ImGuiCol.MenuBarBg, Vector4.Zero); if (ImGui.BeginMainMenuBar()) { var pluginManager = Service.Get(); @@ -832,6 +841,11 @@ internal class DalamudInterface : IInternalDisposableService ImGui.PopStyleVar(); } + if (ImGui.MenuItem("Raise external event through boot")) + { + ErrorHandling.CrashWithContext("Tést"); + } + ImGui.EndMenu(); } diff --git a/Dalamud/Interface/Internal/InterfaceManager.cs b/Dalamud/Interface/Internal/InterfaceManager.cs index 76a1b5172..96fcb7dfd 100644 --- a/Dalamud/Interface/Internal/InterfaceManager.cs +++ b/Dalamud/Interface/Internal/InterfaceManager.cs @@ -256,7 +256,7 @@ internal partial class InterfaceManager : IInternalDisposableService var gwh = default(HWND); fixed (char* pClass = "FFXIVGAME") { - while ((gwh = FindWindowExW(default, gwh, (ushort*)pClass, default)) != default) + while ((gwh = FindWindowExW(default, gwh, pClass, default)) != default) { uint pid; _ = GetWindowThreadProcessId(gwh, &pid); diff --git a/Dalamud/Interface/Internal/ReShadeHandling/ReShadeAddonInterface.Exports.cs b/Dalamud/Interface/Internal/ReShadeHandling/ReShadeAddonInterface.Exports.cs index d8d210076..d7d3b56c3 100644 --- a/Dalamud/Interface/Internal/ReShadeHandling/ReShadeAddonInterface.Exports.cs +++ b/Dalamud/Interface/Internal/ReShadeHandling/ReShadeAddonInterface.Exports.cs @@ -63,11 +63,11 @@ internal sealed unsafe partial class ReShadeAddonInterface return; - bool GetProcAddressInto(ProcessModule m, ReadOnlySpan name, void* res) + static bool GetProcAddressInto(ProcessModule m, ReadOnlySpan name, void* res) { Span name8 = stackalloc byte[Encoding.UTF8.GetByteCount(name) + 1]; name8[Encoding.UTF8.GetBytes(name, name8)] = 0; - *(nint*)res = GetProcAddress((HMODULE)m.BaseAddress, (sbyte*)Unsafe.AsPointer(ref name8[0])); + *(nint*)res = (nint)GetProcAddress((HMODULE)m.BaseAddress, (sbyte*)Unsafe.AsPointer(ref name8[0])); return *(nint*)res != 0; } } @@ -174,7 +174,7 @@ internal sealed unsafe partial class ReShadeAddonInterface CERT.CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT.CERT_NAME_ISSUER_FLAG, null, - (ushort*)Unsafe.AsPointer(ref issuerName[0]), + (char*)Unsafe.AsPointer(ref issuerName[0]), pcb); if (pcb == 0) throw new Win32Exception("CertGetNameStringW(2)"); diff --git a/Dalamud/Interface/Internal/ReShadeHandling/ReShadeUnwrapper.cs b/Dalamud/Interface/Internal/ReShadeHandling/ReShadeUnwrapper.cs index f1210425d..711de6eb2 100644 --- a/Dalamud/Interface/Internal/ReShadeHandling/ReShadeUnwrapper.cs +++ b/Dalamud/Interface/Internal/ReShadeHandling/ReShadeUnwrapper.cs @@ -94,7 +94,7 @@ internal static unsafe class ReShadeUnwrapper static bool HasProcExported(ProcessModule m, ReadOnlySpan name) { fixed (byte* p = name) - return GetProcAddress((HMODULE)m.BaseAddress, (sbyte*)p) != 0; + return GetProcAddress((HMODULE)m.BaseAddress, (sbyte*)p) != null; } } diff --git a/Dalamud/Interface/Internal/StaThreadService.cs b/Dalamud/Interface/Internal/StaThreadService.cs index 87e003288..bb5caa281 100644 --- a/Dalamud/Interface/Internal/StaThreadService.cs +++ b/Dalamud/Interface/Internal/StaThreadService.cs @@ -216,7 +216,7 @@ internal partial class StaThreadService : IInternalDisposableService lpfnWndProc = &MessageReceiverWndProcStatic, hInstance = hInstance, hbrBackground = (HBRUSH)(COLOR.COLOR_BACKGROUND + 1), - lpszClassName = (ushort*)name, + lpszClassName = name, }; wndClassAtom = RegisterClassExW(&wndClass); @@ -226,8 +226,8 @@ internal partial class StaThreadService : IInternalDisposableService this.messageReceiverHwndTask.SetResult( CreateWindowExW( 0, - (ushort*)wndClassAtom, - (ushort*)name, + (char*)wndClassAtom, + name, 0, CW_USEDEFAULT, CW_USEDEFAULT, @@ -275,7 +275,7 @@ internal partial class StaThreadService : IInternalDisposableService _ = OleFlushClipboard(); OleUninitialize(); if (wndClassAtom != 0) - UnregisterClassW((ushort*)wndClassAtom, hInstance); + UnregisterClassW((char*)wndClassAtom, hInstance); this.messageReceiverHwndTask.TrySetException(e); } } diff --git a/Dalamud/Interface/Internal/Windows/Data/DataWindow.cs b/Dalamud/Interface/Internal/Windows/Data/DataWindow.cs index ae86958dd..eb0589d59 100644 --- a/Dalamud/Interface/Internal/Windows/Data/DataWindow.cs +++ b/Dalamud/Interface/Internal/Windows/Data/DataWindow.cs @@ -68,7 +68,7 @@ internal class DataWindow : Window, IDisposable private bool isExcept; private bool selectionCollapsed; - private IDataWindowWidget currentWidget; + private bool isLoaded; /// @@ -82,9 +82,12 @@ internal class DataWindow : Window, IDisposable this.RespectCloseHotkey = false; this.orderedModules = this.modules.OrderBy(module => module.DisplayName); - this.currentWidget = this.orderedModules.First(); + this.CurrentWidget = this.orderedModules.First(); } + /// Gets or sets the current widget. + public IDataWindowWidget CurrentWidget { get; set; } + /// public void Dispose() => this.modules.OfType().AggregateToDisposable().Dispose(); @@ -99,6 +102,20 @@ internal class DataWindow : Window, IDisposable { } + /// Gets the data window widget of the specified type. + /// Type of the data window widget to find. + /// Found widget. + public T GetWidget() where T : IDataWindowWidget + { + foreach (var m in this.modules) + { + if (m is T w) + return w; + } + + throw new ArgumentException($"No widget of type {typeof(T).FullName} found."); + } + /// /// Set the DataKind dropdown menu. /// @@ -110,7 +127,7 @@ internal class DataWindow : Window, IDisposable if (this.modules.FirstOrDefault(module => module.IsWidgetCommand(dataKind)) is { } targetModule) { - this.currentWidget = targetModule; + this.CurrentWidget = targetModule; } else { @@ -153,9 +170,9 @@ internal class DataWindow : Window, IDisposable { foreach (var widget in this.orderedModules) { - if (ImGui.Selectable(widget.DisplayName, this.currentWidget == widget)) + if (ImGui.Selectable(widget.DisplayName, this.CurrentWidget == widget)) { - this.currentWidget = widget; + this.CurrentWidget = widget; } } @@ -206,9 +223,9 @@ internal class DataWindow : Window, IDisposable try { - if (this.currentWidget is { Ready: true }) + if (this.CurrentWidget is { Ready: true }) { - this.currentWidget.Draw(); + this.CurrentWidget.Draw(); } else { diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/FontAwesomeTestWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/FontAwesomeTestWidget.cs index 91f1af98e..4f5540daf 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/FontAwesomeTestWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/FontAwesomeTestWidget.cs @@ -1,9 +1,15 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Numerics; +using System.Threading.Tasks; using Dalamud.Bindings.ImGui; +using Dalamud.Interface.Components; +using Dalamud.Interface.Textures.Internal; using Dalamud.Interface.Utility; +using Dalamud.Interface.Utility.Internal; + +using Lumina.Text.ReadOnly; namespace Dalamud.Interface.Internal.Windows.Data.Widgets; @@ -87,12 +93,30 @@ internal class FontAwesomeTestWidget : IDataWindowWidget ImGuiHelpers.ScaledDummy(10f); for (var i = 0; i < this.icons?.Count; i++) { + if (this.icons[i] == FontAwesomeIcon.None) + continue; + + ImGui.AlignTextToFramePadding(); ImGui.Text($"0x{(int)this.icons[i].ToIconChar():X}"); ImGuiHelpers.ScaledRelativeSameLine(50f); ImGui.Text($"{this.iconNames?[i]}"); ImGuiHelpers.ScaledRelativeSameLine(280f); ImGui.PushFont(this.useFixedWidth ? InterfaceManager.IconFontFixedWidth : InterfaceManager.IconFont); ImGui.Text(this.icons[i].ToIconString()); + ImGuiHelpers.ScaledRelativeSameLine(320f); + if (this.useFixedWidth + ? ImGui.Button($"{(char)this.icons[i]}##FontAwesomeIconButton{i}") + : ImGuiComponents.IconButton($"##FontAwesomeIconButton{i}", this.icons[i])) + { + _ = Service.Get().ShowTextureSaveMenuAsync( + this.DisplayName, + this.icons[i].ToString(), + Task.FromResult( + Service.Get().CreateTextureFromSeString( + ReadOnlySeString.FromText(this.icons[i].ToIconString()), + new() { Font = ImGui.GetFont(), FontSize = ImGui.GetFontSize() }))); + } + ImGui.PopFont(); ImGuiHelpers.ScaledDummy(2f); } diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/SeStringRendererTestWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/SeStringRendererTestWidget.cs index 7ff5a63be..6a07152e5 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/SeStringRendererTestWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/SeStringRendererTestWidget.cs @@ -1,5 +1,6 @@ using System.Numerics; using System.Text; +using System.Threading.Tasks; using Dalamud.Bindings.ImGui; using Dalamud.Data; @@ -9,11 +10,13 @@ using Dalamud.Interface.ImGuiSeStringRenderer; using Dalamud.Interface.ImGuiSeStringRenderer.Internal; using Dalamud.Interface.Textures.Internal; using Dalamud.Interface.Utility; +using Dalamud.Interface.Utility.Internal; using Dalamud.Storage.Assets; using Dalamud.Utility; using FFXIVClientStructs.FFXIV.Component.GUI; using Lumina.Excel.Sheets; using Lumina.Text; +using Lumina.Text.Parse; using Lumina.Text.Payloads; using Lumina.Text.ReadOnly; @@ -56,11 +59,11 @@ internal unsafe class SeStringRendererTestWidget : IDataWindowWidget /// public void Draw() { - var t2 = ImGui.ColorConvertU32ToFloat4(this.style.Color ?? ImGui.GetColorU32(ImGuiCol.Text)); + var t2 = ImGui.ColorConvertU32ToFloat4(this.style.Color ??= ImGui.GetColorU32(ImGuiCol.Text)); if (ImGui.ColorEdit4("Color", ref t2)) this.style.Color = ImGui.ColorConvertFloat4ToU32(t2); - t2 = ImGui.ColorConvertU32ToFloat4(this.style.EdgeColor ?? 0xFF000000u); + t2 = ImGui.ColorConvertU32ToFloat4(this.style.EdgeColor ??= 0xFF000000u); if (ImGui.ColorEdit4("Edge Color", ref t2)) this.style.EdgeColor = ImGui.ColorConvertFloat4ToU32(t2); @@ -69,27 +72,27 @@ internal unsafe class SeStringRendererTestWidget : IDataWindowWidget if (ImGui.Checkbox("Forced"u8, ref t)) this.style.ForceEdgeColor = t; - t2 = ImGui.ColorConvertU32ToFloat4(this.style.ShadowColor ?? 0xFF000000u); - if (ImGui.ColorEdit4("Shadow Color", ref t2)) + t2 = ImGui.ColorConvertU32ToFloat4(this.style.ShadowColor ??= 0xFF000000u); + if (ImGui.ColorEdit4("Shadow Color"u8, ref t2)) this.style.ShadowColor = ImGui.ColorConvertFloat4ToU32(t2); - t2 = ImGui.ColorConvertU32ToFloat4(this.style.LinkHoverBackColor ?? ImGui.GetColorU32(ImGuiCol.ButtonHovered)); - if (ImGui.ColorEdit4("Link Hover Color", ref t2)) + t2 = ImGui.ColorConvertU32ToFloat4(this.style.LinkHoverBackColor ??= ImGui.GetColorU32(ImGuiCol.ButtonHovered)); + if (ImGui.ColorEdit4("Link Hover Color"u8, ref t2)) this.style.LinkHoverBackColor = ImGui.ColorConvertFloat4ToU32(t2); - t2 = ImGui.ColorConvertU32ToFloat4(this.style.LinkActiveBackColor ?? ImGui.GetColorU32(ImGuiCol.ButtonActive)); - if (ImGui.ColorEdit4("Link Active Color", ref t2)) + t2 = ImGui.ColorConvertU32ToFloat4(this.style.LinkActiveBackColor ??= ImGui.GetColorU32(ImGuiCol.ButtonActive)); + if (ImGui.ColorEdit4("Link Active Color"u8, ref t2)) this.style.LinkActiveBackColor = ImGui.ColorConvertFloat4ToU32(t2); - var t3 = this.style.LineHeight ?? 1f; + var t3 = this.style.LineHeight ??= 1f; if (ImGui.DragFloat("Line Height"u8, ref t3, 0.01f, 0.4f, 3f, "%.02f")) this.style.LineHeight = t3; - t3 = this.style.Opacity ?? ImGui.GetStyle().Alpha; + t3 = this.style.Opacity ??= 1f; if (ImGui.DragFloat("Opacity"u8, ref t3, 0.005f, 0f, 1f, "%.02f")) this.style.Opacity = t3; - t3 = this.style.EdgeStrength ?? 0.25f; + t3 = this.style.EdgeStrength ??= 0.25f; if (ImGui.DragFloat("Edge Strength"u8, ref t3, 0.005f, 0f, 1f, "%.02f")) this.style.EdgeStrength = t3; @@ -174,6 +177,24 @@ internal unsafe class SeStringRendererTestWidget : IDataWindowWidget ImGuiHelpers.SeStringWrapped(this.logkind.Value.Data.Span, this.style); } + if (ImGui.CollapsingHeader("Draw into drawlist")) + { + ImGuiHelpers.ScaledDummy(100); + ImGui.SetCursorScreenPos(ImGui.GetItemRectMin() + ImGui.GetStyle().FramePadding); + var clipMin = ImGui.GetItemRectMin() + ImGui.GetStyle().FramePadding; + var clipMax = ImGui.GetItemRectMax() - ImGui.GetStyle().FramePadding; + clipMin.Y = MathF.Max(clipMin.Y, ImGui.GetWindowPos().Y); + clipMax.Y = MathF.Min(clipMax.Y, ImGui.GetWindowPos().Y + ImGui.GetWindowHeight()); + + var dl = ImGui.GetWindowDrawList(); + dl.PushClipRect(clipMin, clipMax); + ImGuiHelpers.CompileSeStringWrapped( + "Test test", + new SeStringDrawParams + { Color = 0xFFFFFFFF, WrapWidth = float.MaxValue, TargetDrawList = dl }); + dl.PopClipRect(); + } + if (ImGui.CollapsingHeader("Addon Table"u8)) { if (ImGui.BeginTable("Addon Sheet"u8, 3)) @@ -240,6 +261,27 @@ internal unsafe class SeStringRendererTestWidget : IDataWindowWidget Service.Get().CompileAndCache(this.testString).Data.Span)); } + ImGui.SameLine(); + + if (ImGui.Button("Copy as Image")) + { + _ = Service.Get().ShowTextureSaveMenuAsync( + this.DisplayName, + $"From {nameof(SeStringRendererTestWidget)}", + Task.FromResult( + Service.Get().CreateTextureFromSeString( + ReadOnlySeString.FromMacroString( + this.testString, + new(ExceptionMode: MacroStringParseExceptionMode.EmbedError)), + this.style with + { + Font = ImGui.GetFont(), + FontSize = ImGui.GetFontSize(), + WrapWidth = ImGui.GetContentRegionAvail().X, + ThemeIndex = AtkStage.Instance()->AtkUIColorHolder->ActiveColorThemeType, + }))); + } + ImGuiHelpers.ScaledDummy(3); ImGuiHelpers.CompileSeStringWrapped( "Optional features implemented for the following test input:
" + diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/TexWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/TexWidget.cs index 52fa0e822..3416a2506 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/TexWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/TexWidget.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Numerics; @@ -306,12 +306,12 @@ internal class TexWidget : IDataWindowWidget pres->Release(); ImGui.Text($"RC: Resource({rcres})/View({rcsrv})"); - ImGui.Text(source.ToString()); + ImGui.Text($"{source.Width} x {source.Height} | {source}"); } else { - ImGui.Text("RC: -"u8); - ImGui.Text(" "u8); + ImGui.Text("RC: -"); + ImGui.Text(string.Empty); } } @@ -342,6 +342,10 @@ internal class TexWidget : IDataWindowWidget runLater?.Invoke(); } + /// Adds a texture wrap for debug display purposes. + /// Task returning a texture. + public void AddTexture(Task textureTask) => this.addedTextures.Add(new(Api10: textureTask)); + private unsafe void DrawBlame(List allBlames) { var im = Service.Get(); diff --git a/Dalamud/Interface/Internal/Windows/SelfTest/Steps/NounProcessorSelfTestStep.cs b/Dalamud/Interface/Internal/Windows/SelfTest/Steps/NounProcessorSelfTestStep.cs index ccb23d395..ccccc691c 100644 --- a/Dalamud/Interface/Internal/Windows/SelfTest/Steps/NounProcessorSelfTestStep.cs +++ b/Dalamud/Interface/Internal/Windows/SelfTest/Steps/NounProcessorSelfTestStep.cs @@ -191,6 +191,29 @@ internal class NounProcessorSelfTestStep : ISelfTestStep new(nameof(LSheets.Item), 44348, ClientLanguage.French, 2, (int)FrenchArticleType.PossessiveFirstPerson, 1, "mes mémoquartz inhabituels fantasmagoriques"), new(nameof(LSheets.Item), 44348, ClientLanguage.French, 2, (int)FrenchArticleType.PossessiveSecondPerson, 1, "tes mémoquartz inhabituels fantasmagoriques"), new(nameof(LSheets.Item), 44348, ClientLanguage.French, 2, (int)FrenchArticleType.PossessiveThirdPerson, 1, "ses mémoquartz inhabituels fantasmagoriques"), + + // ColumnOffset tests + + new(nameof(LSheets.BeastTribe), 1, ClientLanguage.English, 1, (int)EnglishArticleType.Indefinite, 1, "a Amalj'aa"), + new(nameof(LSheets.BeastTribe), 1, ClientLanguage.English, 1, (int)EnglishArticleType.Definite, 1, "the Amalj'aa"), + + new(nameof(LSheets.DeepDungeonEquipment), 1, ClientLanguage.English, 1, (int)EnglishArticleType.Indefinite, 1, "an aetherpool arm"), + new(nameof(LSheets.DeepDungeonEquipment), 1, ClientLanguage.English, 1, (int)EnglishArticleType.Definite, 1, "the aetherpool arm"), + + new(nameof(LSheets.DeepDungeonItem), 1, ClientLanguage.English, 1, (int)EnglishArticleType.Indefinite, 1, "a pomander of safety"), + new(nameof(LSheets.DeepDungeonItem), 1, ClientLanguage.English, 1, (int)EnglishArticleType.Definite, 1, "the pomander of safety"), + + new(nameof(LSheets.DeepDungeonMagicStone), 1, ClientLanguage.English, 1, (int)EnglishArticleType.Indefinite, 1, "a splinter of Inferno magicite"), + new(nameof(LSheets.DeepDungeonMagicStone), 1, ClientLanguage.English, 1, (int)EnglishArticleType.Definite, 1, "the splinter of Inferno magicite"), + + new(nameof(LSheets.DeepDungeonDemiclone), 1, ClientLanguage.English, 1, (int)EnglishArticleType.Indefinite, 1, "an Unei demiclone"), + new(nameof(LSheets.DeepDungeonDemiclone), 1, ClientLanguage.English, 1, (int)EnglishArticleType.Definite, 1, "the Unei demiclone"), + + new(nameof(LSheets.Glasses), 1, ClientLanguage.English, 1, (int)EnglishArticleType.Indefinite, 1, "a pair of oval spectacles"), + new(nameof(LSheets.Glasses), 1, ClientLanguage.English, 1, (int)EnglishArticleType.Definite, 1, "the pair of oval spectacles"), + + new(nameof(LSheets.GlassesStyle), 1, ClientLanguage.English, 1, (int)EnglishArticleType.Indefinite, 1, "a shaded spectacles"), + new(nameof(LSheets.GlassesStyle), 1, ClientLanguage.English, 1, (int)EnglishArticleType.Definite, 1, "the shaded spectacles"), ]; private enum GermanCases diff --git a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs index 62f83f82f..482a00153 100644 --- a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs +++ b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs @@ -86,7 +86,8 @@ internal class TitleScreenMenuWindow : Window, IDisposable : base( "TitleScreenMenuOverlay", ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.AlwaysAutoResize | ImGuiWindowFlags.NoScrollbar | - ImGuiWindowFlags.NoBackground | ImGuiWindowFlags.NoFocusOnAppearing | ImGuiWindowFlags.NoNavFocus) + ImGuiWindowFlags.NoBackground | ImGuiWindowFlags.NoFocusOnAppearing | ImGuiWindowFlags.NoNavFocus | + ImGuiWindowFlags.NoDocking) { this.showTsm = consoleManager.AddVariable("dalamud.show_tsm", "Show the Title Screen Menu", true); diff --git a/Dalamud/Interface/ManagedFontAtlas/IFontHandle.cs b/Dalamud/Interface/ManagedFontAtlas/IFontHandle.cs index 2853aa4d2..be2f5a742 100644 --- a/Dalamud/Interface/ManagedFontAtlas/IFontHandle.cs +++ b/Dalamud/Interface/ManagedFontAtlas/IFontHandle.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Threading; +using System.Threading.Tasks; using Dalamud.Bindings.ImGui; @@ -33,10 +34,22 @@ public interface IFontHandle : IDisposable ///
/// /// Use directly if you want to keep the current ImGui font if the font is not ready.
- /// Alternatively, use to wait for this property to become true. + /// Alternatively, use to wait for this property to become true. ///
bool Available { get; } + /// + /// Attempts to lock the fully constructed instance of corresponding to the this + /// , for use in any thread.
+ /// Modification of the font will exhibit undefined behavior if some other thread also uses the font. + ///
+ /// The error message, if any. + /// + /// An instance of that must be disposed after use on success; + /// null with populated on failure. + /// + ILockedImFont? TryLock(out string? errorMessage); + /// /// Locks the fully constructed instance of corresponding to the this /// , for use in any thread.
@@ -92,4 +105,11 @@ public interface IFontHandle : IDisposable ///
/// A task containing this . Task WaitAsync(); + + /// + /// Waits for to become true. + /// + /// The cancellation token. + /// A task containing this . + Task WaitAsync(CancellationToken cancellationToken); } diff --git a/Dalamud/Interface/ManagedFontAtlas/Internals/FontAtlasFactory.BuildToolkit.cs b/Dalamud/Interface/ManagedFontAtlas/Internals/FontAtlasFactory.BuildToolkit.cs index 2a93cf093..41c87fd39 100644 --- a/Dalamud/Interface/ManagedFontAtlas/Internals/FontAtlasFactory.BuildToolkit.cs +++ b/Dalamud/Interface/ManagedFontAtlas/Internals/FontAtlasFactory.BuildToolkit.cs @@ -15,7 +15,6 @@ using Dalamud.Interface.Textures.TextureWraps; using Dalamud.Interface.Utility; using Dalamud.Storage.Assets; using Dalamud.Utility; -using SharpDX.DXGI; using TerraFX.Interop.DirectX; namespace Dalamud.Interface.ManagedFontAtlas.Internals; @@ -749,7 +748,7 @@ internal sealed partial class FontAtlasFactory new( width, height, - (int)(use4 ? Format.B4G4R4A4_UNorm : Format.B8G8R8A8_UNorm), + (int)(use4 ? DXGI_FORMAT.DXGI_FORMAT_B4G4R4A4_UNORM : DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM), width * bpp), buf, name); diff --git a/Dalamud/Interface/ManagedFontAtlas/Internals/FontHandle.cs b/Dalamud/Interface/ManagedFontAtlas/Internals/FontHandle.cs index 1fdaf4596..98a823deb 100644 --- a/Dalamud/Interface/ManagedFontAtlas/Internals/FontHandle.cs +++ b/Dalamud/Interface/ManagedFontAtlas/Internals/FontHandle.cs @@ -238,12 +238,17 @@ internal abstract class FontHandle : IFontHandle } /// - public Task WaitAsync() + public Task WaitAsync() => this.WaitAsync(CancellationToken.None); + + /// + public Task WaitAsync(CancellationToken cancellationToken) { if (this.Available) return Task.FromResult(this); var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + cancellationToken.Register(() => tcs.TrySetCanceled()); + this.ImFontChanged += OnImFontChanged; this.Disposed += OnDisposed; if (this.Available) diff --git a/Dalamud/Interface/Textures/Internal/BitmapCodecInfo.cs b/Dalamud/Interface/Textures/Internal/BitmapCodecInfo.cs index 3d5456500..ec56caadd 100644 --- a/Dalamud/Interface/Textures/Internal/BitmapCodecInfo.cs +++ b/Dalamud/Interface/Textures/Internal/BitmapCodecInfo.cs @@ -44,12 +44,12 @@ internal sealed class BitmapCodecInfo : IBitmapCodecInfo private static unsafe string ReadStringUsing( IWICBitmapCodecInfo* codecInfo, - delegate* unmanaged readFuncPtr) + delegate* unmanaged[MemberFunction] readFuncPtr) { var cch = 0u; _ = readFuncPtr(codecInfo, 0, null, &cch); var buf = stackalloc char[(int)cch + 1]; - Marshal.ThrowExceptionForHR(readFuncPtr(codecInfo, cch + 1, (ushort*)buf, &cch)); + Marshal.ThrowExceptionForHR(readFuncPtr(codecInfo, cch + 1, buf, &cch)); return new(buf, 0, (int)cch); } } diff --git a/Dalamud/Interface/Textures/Internal/TextureManager.BlameTracker.cs b/Dalamud/Interface/Textures/Internal/TextureManager.BlameTracker.cs index 837b41271..fde40d462 100644 --- a/Dalamud/Interface/Textures/Internal/TextureManager.BlameTracker.cs +++ b/Dalamud/Interface/Textures/Internal/TextureManager.BlameTracker.cs @@ -219,14 +219,14 @@ internal sealed partial class TextureManager return; - [UnmanagedCallersOnly] + [UnmanagedCallersOnly(CallConvs = [typeof(CallConvMemberFunction)])] static int QueryInterfaceStatic(IUnknown* pThis, Guid* riid, void** ppvObject) => ToManagedObject(pThis)?.QueryInterface(riid, ppvObject) ?? E.E_UNEXPECTED; - [UnmanagedCallersOnly] + [UnmanagedCallersOnly(CallConvs = [typeof(CallConvMemberFunction)])] static uint AddRefStatic(IUnknown* pThis) => (uint)(ToManagedObject(pThis)?.AddRef() ?? 0); - [UnmanagedCallersOnly] + [UnmanagedCallersOnly(CallConvs = [typeof(CallConvMemberFunction)])] static uint ReleaseStatic(IUnknown* pThis) => (uint)(ToManagedObject(pThis)?.Release() ?? 0); } diff --git a/Dalamud/Interface/Textures/Internal/TextureManager.Clipboard.cs b/Dalamud/Interface/Textures/Internal/TextureManager.Clipboard.cs index 8a510e967..75f7ab975 100644 --- a/Dalamud/Interface/Textures/Internal/TextureManager.Clipboard.cs +++ b/Dalamud/Interface/Textures/Internal/TextureManager.Clipboard.cs @@ -133,7 +133,7 @@ internal sealed partial class TextureManager }, }, }; - namea.AsSpan().CopyTo(new(fgda.fgd.e0.cFileName, 260)); + namea.AsSpan().CopyTo(new(Unsafe.AsPointer(ref fgda.fgd.e0.cFileName[0]), 260)); AddToDataObject( pdo, @@ -157,7 +157,7 @@ internal sealed partial class TextureManager }, }, }; - preferredFileNameWithoutExtension.AsSpan().CopyTo(new(fgdw.fgd.e0.cFileName, 260)); + preferredFileNameWithoutExtension.AsSpan().CopyTo(new(Unsafe.AsPointer(ref fgdw.fgd.e0.cFileName[0]), 260)); AddToDataObject( pdo, @@ -450,7 +450,7 @@ internal sealed partial class TextureManager try { IStream* pfs; - SHCreateStreamOnFileW((ushort*)pPath, sharedRead, &pfs).ThrowOnError(); + SHCreateStreamOnFileW((char*)pPath, sharedRead, &pfs).ThrowOnError(); var stgm2 = new STGMEDIUM { diff --git a/Dalamud/Interface/Textures/Internal/TextureManager.FromSeString.cs b/Dalamud/Interface/Textures/Internal/TextureManager.FromSeString.cs new file mode 100644 index 000000000..3e90ae3ea --- /dev/null +++ b/Dalamud/Interface/Textures/Internal/TextureManager.FromSeString.cs @@ -0,0 +1,35 @@ +using Dalamud.Interface.ImGuiSeStringRenderer; +using Dalamud.Interface.ImGuiSeStringRenderer.Internal; +using Dalamud.Interface.Textures.TextureWraps; +using Dalamud.Utility; + +namespace Dalamud.Interface.Textures.Internal; + +/// Service responsible for loading and disposing ImGui texture wraps. +internal sealed partial class TextureManager +{ + [ServiceManager.ServiceDependency] + private readonly SeStringRenderer seStringRenderer = Service.Get(); + + /// + public IDalamudTextureWrap CreateTextureFromSeString( + ReadOnlySpan text, + scoped in SeStringDrawParams drawParams = default, + string? debugName = null) + { + ThreadSafety.AssertMainThread(); + using var dd = this.seStringRenderer.CreateDrawData(text, drawParams); + var texture = this.CreateDrawListTexture(debugName ?? nameof(this.CreateTextureFromSeString)); + try + { + texture.Size = dd.Data.DisplaySize; + texture.Draw(dd.DataPtr); + return texture; + } + catch + { + texture.Dispose(); + throw; + } + } +} diff --git a/Dalamud/Interface/Textures/Internal/TextureManager.cs b/Dalamud/Interface/Textures/Internal/TextureManager.cs index 059c716ce..d0f0d8c07 100644 --- a/Dalamud/Interface/Textures/Internal/TextureManager.cs +++ b/Dalamud/Interface/Textures/Internal/TextureManager.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Dalamud.Configuration.Internal; using Dalamud.Data; using Dalamud.Game; +using Dalamud.Interface.ImGuiSeStringRenderer.Internal; using Dalamud.Interface.Internal; using Dalamud.Interface.Textures.Internal.SharedImmediateTextures; using Dalamud.Interface.Textures.TextureWraps; @@ -248,7 +249,7 @@ internal sealed partial class TextureManager usage = D3D11_USAGE.D3D11_USAGE_DYNAMIC; else usage = D3D11_USAGE.D3D11_USAGE_DEFAULT; - + using var texture = this.device.CreateTexture2D( new() { diff --git a/Dalamud/Interface/Textures/Internal/TextureManagerPluginScoped.cs b/Dalamud/Interface/Textures/Internal/TextureManagerPluginScoped.cs index 9b0fa0943..ac6de7dd7 100644 --- a/Dalamud/Interface/Textures/Internal/TextureManagerPluginScoped.cs +++ b/Dalamud/Interface/Textures/Internal/TextureManagerPluginScoped.cs @@ -6,6 +6,7 @@ using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; +using Dalamud.Interface.ImGuiSeStringRenderer; using Dalamud.Interface.Internal; using Dalamud.Interface.Textures.TextureWraps; using Dalamud.IoC; @@ -283,6 +284,18 @@ internal sealed class TextureManagerPluginScoped return textureWrap; } + /// + public IDalamudTextureWrap CreateTextureFromSeString( + ReadOnlySpan text, + scoped in SeStringDrawParams drawParams = default, + string? debugName = null) + { + var manager = this.ManagerOrThrow; + var textureWrap = manager.CreateTextureFromSeString(text, drawParams, debugName); + manager.Blame(textureWrap, this.plugin); + return textureWrap; + } + /// public IEnumerable GetSupportedImageDecoderInfos() => this.ManagerOrThrow.Wic.GetSupportedDecoderInfos(); diff --git a/Dalamud/Interface/UiBuilder.cs b/Dalamud/Interface/UiBuilder.cs index e38537018..ea0e21e97 100644 --- a/Dalamud/Interface/UiBuilder.cs +++ b/Dalamud/Interface/UiBuilder.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Threading; using System.Threading.Tasks; using Dalamud.Bindings.ImGui; @@ -12,7 +13,6 @@ using Dalamud.Interface.FontIdentifier; using Dalamud.Interface.Internal; using Dalamud.Interface.ManagedFontAtlas; using Dalamud.Interface.ManagedFontAtlas.Internals; -using Dalamud.Plugin; using Dalamud.Plugin.Internal.Types; using Dalamud.Utility; using Serilog; @@ -150,13 +150,6 @@ public interface IUiBuilder ///
public ImFontPtr FontMono { get; } - /// - /// Gets the game's active Direct3D device. - /// - // TODO: Remove it on API11/APIXI, and remove SharpDX/PInvoke/etc. dependency from Dalamud. - [Obsolete($"Use {nameof(DeviceHandle)} and wrap it using DirectX wrapper library of your choice.")] - SharpDX.Direct3D11.Device Device { get; } - /// Gets the game's active Direct3D device. /// Pointer to the instance of IUnknown that the game is using and should be containing an ID3D11Device, /// or 0 if it is not available yet. @@ -226,6 +219,12 @@ public interface IUiBuilder /// bool ShouldUseReducedMotion { get; } + /// + /// Gets a value indicating whether the user has enabled the "Enable sound effects for plugin windows" setting.
+ /// This setting is effected by the in-game "System Sounds" option and volume. + ///
+ bool PluginUISoundEffectsEnabled { get; } + /// /// Loads an ULD file that can load textures containing multiple icons in a single texture. /// @@ -302,8 +301,6 @@ public sealed class UiBuilder : IDisposable, IUiBuilder private IFontHandle? monoFontHandle; private IFontHandle? iconFontFixedWidthHandle; - private SharpDX.Direct3D11.Device? sdxDevice; - /// /// Initializes a new instance of the class and registers it. /// You do not have to call this manually. @@ -493,12 +490,6 @@ public sealed class UiBuilder : IDisposable, IUiBuilder this.InterfaceManagerWithScene?.MonoFontHandle ?? throw new InvalidOperationException("Scene is not yet ready."))); - /// - // TODO: Remove it on API11/APIXI, and remove SharpDX/PInvoke/etc. dependency from Dalamud. - [Obsolete($"Use {nameof(DeviceHandle)} and wrap it using DirectX wrapper library of your choice.")] - public SharpDX.Direct3D11.Device Device => - this.sdxDevice ??= new(this.InterfaceManagerWithScene!.Backend!.DeviceHandle); - /// public nint DeviceHandle => this.InterfaceManagerWithScene?.Backend?.DeviceHandle ?? 0; @@ -575,6 +566,9 @@ public sealed class UiBuilder : IDisposable, IUiBuilder /// public bool ShouldUseReducedMotion => Service.Get().ReduceMotions ?? false; + /// + public bool PluginUISoundEffectsEnabled => Service.Get().EnablePluginUISoundEffects; + /// /// Gets or sets a value indicating whether statistics about UI draw time should be collected. /// @@ -691,13 +685,14 @@ public sealed class UiBuilder : IDisposable, IUiBuilder FontAtlasAutoRebuildMode autoRebuildMode, bool isGlobalScaled = true, string? debugName = null) => - this.scopedFinalizer.Add(Service - .Get() - .CreateFontAtlas( - this.namespaceName + ":" + (debugName ?? "custom"), - autoRebuildMode, - isGlobalScaled, - this.plugin)); + this.scopedFinalizer.Add( + Service + .Get() + .CreateFontAtlas( + this.namespaceName + ":" + (debugName ?? "custom"), + autoRebuildMode, + isGlobalScaled, + this.plugin)); /// /// Unregister the UiBuilder. Do not call this in plugin code. @@ -868,6 +863,15 @@ public sealed class UiBuilder : IDisposable, IUiBuilder // Note: do not dispose w; we do not own it } + public ILockedImFont? TryLock(out string? errorMessage) + { + if (this.wrapped is { } w) + return w.TryLock(out errorMessage); + + errorMessage = nameof(ObjectDisposedException); + return null; + } + public ILockedImFont Lock() => this.wrapped?.Lock() ?? throw new ObjectDisposedException(nameof(FontHandleWrapper)); @@ -876,7 +880,13 @@ public sealed class UiBuilder : IDisposable, IUiBuilder public void Pop() => this.WrappedNotDisposed.Pop(); public Task WaitAsync() => - this.WrappedNotDisposed.WaitAsync().ContinueWith(_ => (IFontHandle)this); + this.wrapped?.WaitAsync().ContinueWith(_ => (IFontHandle)this) + ?? Task.FromException(new ObjectDisposedException(nameof(FontHandleWrapper))); + + public Task WaitAsync(CancellationToken cancellationToken) => + this.wrapped?.WaitAsync(cancellationToken) + .ContinueWith(_ => (IFontHandle)this, cancellationToken) + ?? Task.FromException(new ObjectDisposedException(nameof(FontHandleWrapper))); public override string ToString() => $"{nameof(FontHandleWrapper)}({this.wrapped?.ToString() ?? "disposed"})"; diff --git a/Dalamud/Interface/Utility/BufferBackedImDrawData.cs b/Dalamud/Interface/Utility/BufferBackedImDrawData.cs new file mode 100644 index 000000000..e6128992a --- /dev/null +++ b/Dalamud/Interface/Utility/BufferBackedImDrawData.cs @@ -0,0 +1,92 @@ +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +using Dalamud.Bindings.ImGui; + +namespace Dalamud.Interface.Utility; + +/// Wrapper aroundx containing one . +public unsafe struct BufferBackedImDrawData : IDisposable +{ + private nint buffer; + + /// Initializes a new instance of the struct. + /// Address of buffer to use. + private BufferBackedImDrawData(nint buffer) => this.buffer = buffer; + + /// Gets the stored in this buffer. + public readonly ref ImDrawData Data => ref ((DataStruct*)this.buffer)->Data; + + /// Gets the stored in this buffer. + public readonly ImDrawDataPtr DataPtr => new((ImDrawData*)Unsafe.AsPointer(ref this.Data)); + + /// Gets the stored in this buffer. + public readonly ref ImDrawList List => ref ((DataStruct*)this.buffer)->List; + + /// Gets the stored in this buffer. + public readonly ImDrawListPtr ListPtr => new((ImDrawList*)Unsafe.AsPointer(ref this.List)); + + /// Creates a new instance of . + /// A new instance of . + public static BufferBackedImDrawData Create() + { + if (ImGui.GetCurrentContext().IsNull || ImGui.GetIO().FontDefault.Handle is null) + throw new("ImGui is not ready"); + + var res = new BufferBackedImDrawData(Marshal.AllocHGlobal(sizeof(DataStruct))); + var ds = (DataStruct*)res.buffer; + *ds = default; + + var atlas = ImGui.GetIO().Fonts; + ds->SharedData = *ImGui.GetDrawListSharedData().Handle; + ds->SharedData.TexIdCommon = atlas.Textures[atlas.TextureIndexCommon].TexID; + ds->SharedData.TexUvWhitePixel = atlas.TexUvWhitePixel; + ds->SharedData.TexUvLines = (Vector4*)Unsafe.AsPointer(ref atlas.TexUvLines[0]); + ds->SharedData.Font = ImGui.GetIO().FontDefault; + ds->SharedData.FontSize = ds->SharedData.Font->FontSize; + ds->SharedData.ClipRectFullscreen = new( + float.NegativeInfinity, + float.NegativeInfinity, + float.PositiveInfinity, + float.PositiveInfinity); + + ds->List.Data = &ds->SharedData; + ds->ListPtr = &ds->List; + ds->Data.CmdLists = &ds->ListPtr; + ds->Data.CmdListsCount = 1; + ds->Data.FramebufferScale = Vector2.One; + + res.ListPtr._ResetForNewFrame(); + res.ListPtr.PushClipRectFullScreen(); + res.ListPtr.PushTextureID(new(atlas.TextureIndexCommon)); + return res; + } + + /// Updates the statistics information stored in from . + public readonly void UpdateDrawDataStatistics() + { + this.Data.TotalIdxCount = this.List.IdxBuffer.Size; + this.Data.TotalVtxCount = this.List.VtxBuffer.Size; + } + + /// + public void Dispose() + { + if (this.buffer != 0) + { + this.ListPtr._ClearFreeMemory(); + Marshal.FreeHGlobal(this.buffer); + this.buffer = 0; + } + } + + [StructLayout(LayoutKind.Sequential)] + private struct DataStruct + { + public ImDrawData Data; + public ImDrawList* ListPtr; + public ImDrawList List; + public ImDrawListSharedData SharedData; + } +} diff --git a/Dalamud/Interface/Utility/ImGuiHelpers.cs b/Dalamud/Interface/Utility/ImGuiHelpers.cs index 87f258250..ee2840d3d 100644 --- a/Dalamud/Interface/Utility/ImGuiHelpers.cs +++ b/Dalamud/Interface/Utility/ImGuiHelpers.cs @@ -575,6 +575,15 @@ public static partial class ImGuiHelpers public static unsafe ImFontPtr OrElse(this ImFontPtr self, ImFontPtr other) => self.IsNull ? other : self; + /// Creates a draw data that will draw the given SeString onto it. + /// SeString to render. + /// Initial rendering style. + /// A new self-contained draw data. + internal static BufferBackedImDrawData CreateDrawData( + ReadOnlySpan sss, + scoped in SeStringDrawParams style = default) => + Service.Get().CreateDrawData(sss, style); + /// /// Mark 4K page as used, after adding a codepoint to a font. /// diff --git a/Dalamud/Interface/Utility/Internal/DevTextureSaveMenu.cs b/Dalamud/Interface/Utility/Internal/DevTextureSaveMenu.cs index 86435e8c1..4a0137c88 100644 --- a/Dalamud/Interface/Utility/Internal/DevTextureSaveMenu.cs +++ b/Dalamud/Interface/Utility/Internal/DevTextureSaveMenu.cs @@ -6,10 +6,12 @@ using System.Text; using System.Threading.Tasks; using Dalamud.Bindings.ImGui; +using Dalamud.Game; using Dalamud.Interface.ImGuiFileDialog; using Dalamud.Interface.ImGuiNotification; using Dalamud.Interface.ImGuiNotification.Internal; using Dalamud.Interface.Internal; +using Dalamud.Interface.Internal.Windows.Data.Widgets; using Dalamud.Interface.Textures.Internal; using Dalamud.Interface.Textures.TextureWraps; using Serilog; @@ -33,6 +35,14 @@ internal sealed class DevTextureSaveMenu : IInternalDisposableService this.interfaceManager.Draw += this.InterfaceManagerOnDraw; } + private enum ContextMenuActionType + { + None, + SaveAsFile, + CopyToClipboard, + SendToTexWidget, + } + /// void IInternalDisposableService.DisposeService() => this.interfaceManager.Draw -= this.InterfaceManagerOnDraw; @@ -66,15 +76,16 @@ internal sealed class DevTextureSaveMenu : IInternalDisposableService var textureManager = await Service.GetAsync(); var popupName = $"{nameof(this.ShowTextureSaveMenuAsync)}_{textureWrap.Handle.Handle:X}"; + ContextMenuActionType action; BitmapCodecInfo? encoder; { var first = true; var encoders = textureManager.Wic.GetSupportedEncoderInfos().ToList(); - var tcs = new TaskCompletionSource( + var tcs = new TaskCompletionSource<(ContextMenuActionType Action, BitmapCodecInfo? Codec)>( TaskCreationOptions.RunContinuationsAsynchronously); Service.Get().Draw += DrawChoices; - encoder = await tcs.Task; + (action, encoder) = await tcs.Task; [SuppressMessage("ReSharper", "AccessToDisposedClosure", Justification = "This shall not escape")] void DrawChoices() @@ -98,13 +109,20 @@ internal sealed class DevTextureSaveMenu : IInternalDisposableService } if (ImGui.Selectable("Copy"u8)) - tcs.TrySetResult(null); + tcs.TrySetResult((ContextMenuActionType.CopyToClipboard, null)); + if (ImGui.Selectable("Send to TexWidget"u8)) + tcs.TrySetResult((ContextMenuActionType.SendToTexWidget, null)); + + ImGui.Separator(); + foreach (var encoder2 in encoders) { if (ImGui.Selectable(encoder2.Name)) - tcs.TrySetResult(encoder2); + tcs.TrySetResult((ContextMenuActionType.SaveAsFile, encoder2)); } + ImGui.Separator(); + const float previewImageWidth = 320; var size = textureWrap.Size; if (size.X > previewImageWidth) @@ -120,50 +138,68 @@ internal sealed class DevTextureSaveMenu : IInternalDisposableService } } - if (encoder is null) + switch (action) { - isCopy = true; - await textureManager.CopyToClipboardAsync(textureWrap, name, true); - } - else - { - var props = new Dictionary(); - if (encoder.ContainerGuid == GUID.GUID_ContainerFormatTiff) - props["CompressionQuality"] = 1.0f; - else if (encoder.ContainerGuid == GUID.GUID_ContainerFormatJpeg || - encoder.ContainerGuid == GUID.GUID_ContainerFormatHeif || - encoder.ContainerGuid == GUID.GUID_ContainerFormatWmp) - props["ImageQuality"] = 1.0f; + case ContextMenuActionType.CopyToClipboard: + isCopy = true; + await textureManager.CopyToClipboardAsync(textureWrap, name, true); + break; - var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - this.fileDialogManager.SaveFileDialog( - "Save texture...", - $"{encoder.Name.Replace(',', '.')}{{{string.Join(',', encoder.Extensions)}}}", - name + encoder.Extensions.First(), - encoder.Extensions.First(), - (ok, path2) => - { - if (!ok) - tcs.SetCanceled(); - else - tcs.SetResult(path2); - }); - var path = await tcs.Task.ConfigureAwait(false); - - await textureManager.SaveToFileAsync(textureWrap, encoder.ContainerGuid, path, props: props); - - var notif = Service.Get().AddNotification( - new() - { - Content = $"File saved to: {path}", - Title = initiatorName, - Type = NotificationType.Success, - }); - notif.Click += n => + case ContextMenuActionType.SendToTexWidget: { - Process.Start(new ProcessStartInfo(path) { UseShellExecute = true }); - n.Notification.DismissNow(); - }; + var framework = await Service.GetAsync(); + var dalamudInterface = await Service.GetAsync(); + await framework.RunOnFrameworkThread( + () => + { + var texWidget = dalamudInterface.GetDataWindowWidget(); + dalamudInterface.SetDataWindowWidget(texWidget); + texWidget.AddTexture(Task.FromResult(textureWrap.CreateWrapSharingLowLevelResource())); + }); + break; + } + + case ContextMenuActionType.SaveAsFile when encoder is not null: + { + var props = new Dictionary(); + if (encoder.ContainerGuid == GUID.GUID_ContainerFormatTiff) + props["CompressionQuality"] = 1.0f; + else if (encoder.ContainerGuid == GUID.GUID_ContainerFormatJpeg || + encoder.ContainerGuid == GUID.GUID_ContainerFormatHeif || + encoder.ContainerGuid == GUID.GUID_ContainerFormatWmp) + props["ImageQuality"] = 1.0f; + + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + this.fileDialogManager.SaveFileDialog( + "Save texture...", + $"{encoder.Name.Replace(',', '.')}{{{string.Join(',', encoder.Extensions)}}}", + name + encoder.Extensions.First(), + encoder.Extensions.First(), + (ok, path2) => + { + if (!ok) + tcs.SetCanceled(); + else + tcs.SetResult(path2); + }); + var path = await tcs.Task.ConfigureAwait(false); + + await textureManager.SaveToFileAsync(textureWrap, encoder.ContainerGuid, path, props: props); + + var notif = Service.Get().AddNotification( + new() + { + Content = $"File saved to: {path}", + Title = initiatorName, + Type = NotificationType.Success, + }); + notif.Click += n => + { + Process.Start(new ProcessStartInfo(path) { UseShellExecute = true }); + n.Notification.DismissNow(); + }; + break; + } } } catch (Exception e) diff --git a/Dalamud/Interface/Windowing/Window.cs b/Dalamud/Interface/Windowing/Window.cs index f12e87099..48352daa2 100644 --- a/Dalamud/Interface/Windowing/Window.cs +++ b/Dalamud/Interface/Windowing/Window.cs @@ -1,9 +1,6 @@ using System.Collections.Generic; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Linq; using System.Numerics; -using System.Runtime.InteropServices; using System.Threading.Tasks; using CheapLoc; @@ -19,10 +16,13 @@ using Dalamud.Interface.Utility.Internal; using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Windowing.Persistence; using Dalamud.Logging.Internal; -using Dalamud.Utility; using FFXIVClientStructs.FFXIV.Client.UI; +using TerraFX.Interop.Windows; + +using static TerraFX.Interop.Windows.Windows; + namespace Dalamud.Interface.Windowing; /// @@ -31,11 +31,15 @@ namespace Dalamud.Interface.Windowing; public abstract class Window { private const float FadeInOutTime = 0.072f; + private const string AdditionsPopupName = "WindowSystemContextActions"; private static readonly ModuleLog Log = new("WindowSystem"); private static bool wasEscPressedLastFrame = false; + private readonly TitleBarButton additionsButton; + private readonly List allButtons = []; + private bool internalLastIsOpen = false; private bool internalIsOpen = false; private bool internalIsPinned = false; @@ -72,6 +76,20 @@ public abstract class Window this.WindowName = name; this.Flags = flags; this.ForceMainWindow = forceMainWindow; + + this.additionsButton = new() + { + Icon = FontAwesomeIcon.Bars, + IconOffset = new Vector2(2.5f, 1), + Click = _ => + { + this.internalIsClickthrough = false; + this.presetDirty = false; + ImGui.OpenPopup(AdditionsPopupName); + }, + Priority = int.MinValue, + AvailableClickthrough = true, + }; } /// @@ -425,8 +443,17 @@ public abstract class Window UIGlobals.PlaySoundEffect(this.OnOpenSfxId); } - this.PreDraw(); - this.ApplyConditionals(); + var isErrorStylePushed = false; + if (!this.hasError) + { + this.PreDraw(); + this.ApplyConditionals(); + } + else + { + Style.StyleModelV1.DalamudStandard.Push(); + isErrorStylePushed = true; + } if (this.ForceMainWindow) ImGuiHelpers.ForceNextWindowMainViewport(); @@ -448,10 +475,22 @@ public abstract class Window var flags = this.Flags; if (this.internalIsPinned || this.internalIsClickthrough) + { flags |= ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoResize; + } if (this.internalIsClickthrough) + { flags |= ImGuiWindowFlags.NoInputs | ImGuiWindowFlags.NoNav | ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoScrollWithMouse | ImGuiWindowFlags.NoMouseInputs; + } + + // If we have an error, reset all flags to default, and unlock window size. + if (this.hasError) + { + flags = ImGuiWindowFlags.None; + ImGui.SetNextWindowCollapsed(false, ImGuiCond.Once); + ImGui.SetNextWindowSizeConstraints(Vector2.Zero, Vector2.PositiveInfinity); + } if (this.CanShowCloseButton ? ImGui.Begin(this.WindowName, ref this.internalIsOpen, flags) : ImGui.Begin(this.WindowName, flags)) { @@ -461,14 +500,12 @@ public abstract class Window ImGuiP.GetCurrentWindow().InheritNoInputs = this.internalIsClickthrough; } - // Not supported yet on non-main viewports - if ((this.internalIsPinned || this.internalIsClickthrough || this.internalAlpha.HasValue) && - ImGui.GetWindowViewport().ID != ImGui.GetMainViewport().ID) + if (ImGui.GetWindowViewport().ID != ImGui.GetMainViewport().ID) { - this.internalAlpha = null; - this.internalIsPinned = false; - this.internalIsClickthrough = false; - this.presetDirty = true; + if ((flags & ImGuiWindowFlags.NoInputs) == ImGuiWindowFlags.NoInputs) + ImGui.GetWindowViewport().Flags |= ImGuiViewportFlags.NoInputs; + else + ImGui.GetWindowViewport().Flags &= ~ImGuiViewportFlags.NoInputs; } if (this.hasError) @@ -492,7 +529,6 @@ public abstract class Window } } - const string additionsPopupName = "WindowSystemContextActions"; var flagsApplicableForTitleBarIcons = !flags.HasFlag(ImGuiWindowFlags.NoDecoration) && !flags.HasFlag(ImGuiWindowFlags.NoTitleBar); var showAdditions = (this.AllowPinning || this.AllowClickthrough) && @@ -503,13 +539,8 @@ public abstract class Window { ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 1f); - if (ImGui.BeginPopup(additionsPopupName, ImGuiWindowFlags.NoMove)) + if (ImGui.BeginPopup(AdditionsPopupName, ImGuiWindowFlags.NoMove)) { - var isAvailable = ImGuiHelpers.CheckIsWindowOnMainViewport(); - - if (!isAvailable) - ImGui.BeginDisabled(); - if (this.internalIsClickthrough) ImGui.BeginDisabled(); @@ -557,21 +588,11 @@ public abstract class Window this.presetDirty = true; } - if (isAvailable) - { - ImGui.TextColored(ImGuiColors.DalamudGrey, - Loc.Localize("WindowSystemContextActionClickthroughDisclaimer", - "Open this menu again by clicking the three dashes to disable clickthrough.")); - } - else - { - ImGui.TextColored(ImGuiColors.DalamudGrey, - Loc.Localize("WindowSystemContextActionViewportDisclaimer", - "These features are only available if this window is inside the game window.")); - } - - if (!isAvailable) - ImGui.EndDisabled(); + ImGui.TextColored( + ImGuiColors.DalamudGrey, + Loc.Localize( + "WindowSystemContextActionClickthroughDisclaimer", + "Open this menu again by clicking the three dashes to disable clickthrough.")); if (ImGui.Button(Loc.Localize("WindowSystemContextActionPrintWindow", "Print window"))) printWindow = true; @@ -582,34 +603,15 @@ public abstract class Window ImGui.PopStyleVar(); } - unsafe + if (flagsApplicableForTitleBarIcons) { - var window = ImGuiP.GetCurrentWindow(); - - ImRect outRect; - ImGuiP.TitleBarRect(&outRect, window); - - var additionsButton = new TitleBarButton - { - Icon = FontAwesomeIcon.Bars, - IconOffset = new Vector2(2.5f, 1), - Click = _ => - { - this.internalIsClickthrough = false; - this.presetDirty = false; - ImGui.OpenPopup(additionsPopupName); - }, - Priority = int.MinValue, - AvailableClickthrough = true, - }; - - if (flagsApplicableForTitleBarIcons) - { - this.DrawTitleBarButtons(window, flags, outRect, - showAdditions - ? this.TitleBarButtons.Append(additionsButton) - : this.TitleBarButtons); - } + this.allButtons.Clear(); + this.allButtons.EnsureCapacity(this.TitleBarButtons.Count + 1); + this.allButtons.AddRange(this.TitleBarButtons); + if (showAdditions) + this.allButtons.Add(this.additionsButton); + this.allButtons.Sort(static (a, b) => b.Priority - a.Priority); + this.DrawTitleBarButtons(); } if (wasFocused) @@ -670,7 +672,17 @@ public abstract class Window Task.FromResult(tex)); } - this.PostDraw(); + if (!this.hasError) + { + this.PostDraw(); + } + else + { + if (isErrorStylePushed) + { + Style.StyleModelV1.DalamudStandard.Pop(); + } + } this.PostHandlePreset(persistence); @@ -766,8 +778,11 @@ public abstract class Window } } - private unsafe void DrawTitleBarButtons(ImGuiWindowPtr window, ImGuiWindowFlags flags, ImRect titleBarRect, IEnumerable buttons) + private unsafe void DrawTitleBarButtons() { + var window = ImGuiP.GetCurrentWindow(); + var flags = window.Flags; + var titleBarRect = window.TitleBarRect(); ImGui.PushClipRect(ImGui.GetWindowPos(), ImGui.GetWindowPos() + ImGui.GetWindowSize(), false); var style = ImGui.GetStyle(); @@ -802,26 +817,22 @@ public abstract class Window var max = pos + new Vector2(fontSize, fontSize); ImRect bb = new(pos, max); var isClipped = !ImGuiP.ItemAdd(bb, id, null, 0); - bool hovered, held; - var pressed = false; + bool hovered, held, pressed; if (this.internalIsClickthrough) { - hovered = false; - held = false; - // ButtonBehavior does not function if the window is clickthrough, so we have to do it ourselves - if (ImGui.IsMouseHoveringRect(pos, max)) - { - hovered = true; + var pad = ImGui.GetStyle().TouchExtraPadding; + var rect = new ImRect(pos - pad, max + pad); + hovered = rect.Contains(ImGui.GetMousePos()); - // We can't use ImGui native functions here, because they don't work with clickthrough - if ((Windows.Win32.PInvoke.GetKeyState((int)VirtualKey.LBUTTON) & 0x8000) != 0) - { - held = true; - pressed = true; - } - } + // Temporarily enable inputs + // This will be reset on next frame, and then enabled again if it is still being hovered + if (hovered && ImGui.GetWindowViewport().ID != ImGui.GetMainViewport().ID) + ImGui.GetWindowViewport().Flags &= ~ImGuiViewportFlags.NoInputs; + + // We can't use ImGui native functions here, because they don't work with clickthrough + pressed = held = hovered && (GetKeyState(VK.VK_LBUTTON) & 0x8000) != 0; } else { @@ -850,7 +861,7 @@ public abstract class Window return pressed; } - foreach (var button in buttons.OrderBy(x => x.Priority)) + foreach (var button in this.allButtons) { if (this.internalIsClickthrough && !button.AvailableClickthrough) return; @@ -897,7 +908,7 @@ public abstract class Window private void DrawErrorMessage() { // TODO: Once window systems are services, offer to reload the plugin - ImGui.TextColoredWrapped(ImGuiColors.DalamudRed,Loc.Localize("WindowSystemErrorOccurred", "An error occurred while rendering this window. Please contact the developer for details.")); + ImGui.TextColoredWrapped(ImGuiColors.DalamudRed, Loc.Localize("WindowSystemErrorOccurred", "An error occurred while rendering this window. Please contact the developer for details.")); ImGuiHelpers.ScaledDummy(5); @@ -1004,7 +1015,7 @@ public abstract class Window /// /// Gets or sets an action that is called when the button is clicked. /// - public Action Click { get; set; } + public Action? Click { get; set; } /// /// Gets or sets the priority the button shall be shown in. diff --git a/Dalamud/NativeMethods.json b/Dalamud/NativeMethods.json index ffb313dfc..46fd3504f 100644 --- a/Dalamud/NativeMethods.json +++ b/Dalamud/NativeMethods.json @@ -1,4 +1,5 @@ { "$schema": "https://aka.ms/CsWin32.schema.json", + "useSafeHandles": false, "allowMarshaling": false } diff --git a/Dalamud/Plugin/Services/IPlayerState.cs b/Dalamud/Plugin/Services/IPlayerState.cs index 1416dfb77..21d88010b 100644 --- a/Dalamud/Plugin/Services/IPlayerState.cs +++ b/Dalamud/Plugin/Services/IPlayerState.cs @@ -79,7 +79,7 @@ public interface IPlayerState : IDalamudService bool IsLevelSynced { get; } /// - /// Gets the effective level of the local character. + /// Gets the effective level of the local character, taking level sync into account. /// short EffectiveLevel { get; } diff --git a/Dalamud/Plugin/Services/ITextureProvider.cs b/Dalamud/Plugin/Services/ITextureProvider.cs index 7cd1b7c86..dc0522aa8 100644 --- a/Dalamud/Plugin/Services/ITextureProvider.cs +++ b/Dalamud/Plugin/Services/ITextureProvider.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Reflection; @@ -6,6 +6,7 @@ using System.Threading; using System.Threading.Tasks; using Dalamud.Bindings.ImGui; +using Dalamud.Interface.ImGuiSeStringRenderer; using Dalamud.Interface.Internal.Windows.Data.Widgets; using Dalamud.Interface.Textures; using Dalamud.Interface.Textures.TextureWraps; @@ -186,6 +187,17 @@ public interface ITextureProvider : IDalamudService string? debugName = null, CancellationToken cancellationToken = default); + /// Creates a texture by drawing a SeString onto it. + /// SeString to render. + /// Parameters for drawing. + /// Name for debug display purposes. + /// The new texture. + /// Can be only be used from the main thread. + public IDalamudTextureWrap CreateTextureFromSeString( + ReadOnlySpan text, + scoped in SeStringDrawParams drawParams = default, + string? debugName = null); + /// Gets the supported bitmap decoders. /// The supported bitmap decoders. /// diff --git a/Dalamud/SafeMemory.cs b/Dalamud/SafeMemory.cs index a8ac40a5d..ca0c8ff92 100644 --- a/Dalamud/SafeMemory.cs +++ b/Dalamud/SafeMemory.cs @@ -1,6 +1,8 @@ using System.Runtime.InteropServices; using System.Text; +using Windows.Win32.Foundation; + namespace Dalamud; /// @@ -12,11 +14,11 @@ namespace Dalamud; /// public static class SafeMemory { - private static readonly SafeHandle Handle; + private static readonly HANDLE Handle; static SafeMemory() { - Handle = Windows.Win32.PInvoke.GetCurrentProcess_SafeHandle(); + Handle = Windows.Win32.PInvoke.GetCurrentProcess(); } /// @@ -28,6 +30,12 @@ public static class SafeMemory /// Whether the read succeeded. public static unsafe bool ReadBytes(IntPtr address, int count, out byte[] buffer) { + if (Handle.IsNull) + { + buffer = []; + return false; + } + buffer = new byte[count <= 0 ? 0 : count]; fixed (byte* p = buffer) { @@ -54,6 +62,9 @@ public static class SafeMemory /// Whether the write succeeded. public static unsafe bool WriteBytes(IntPtr address, byte[] buffer) { + if (Handle.IsNull) + return false; + if (buffer.Length == 0) return true; diff --git a/Dalamud/Service/LoadingDialog.cs b/Dalamud/Service/LoadingDialog.cs index 424087743..ea45d3bb2 100644 --- a/Dalamud/Service/LoadingDialog.cs +++ b/Dalamud/Service/LoadingDialog.cs @@ -1,4 +1,4 @@ -using System.Collections.Concurrent; +using System.Collections.Concurrent; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Drawing; @@ -294,18 +294,18 @@ internal sealed class LoadingDialog ? null : Icon.ExtractAssociatedIcon(Path.Combine(workingDirectory, "Dalamud.Injector.exe")); - fixed (void* pszEmpty = "-") - fixed (void* pszWindowTitle = "Dalamud") - fixed (void* pszDalamudBoot = "Dalamud.Boot.dll") - fixed (void* pszThemesManifestResourceName = "RT_MANIFEST_THEMES") - fixed (void* pszHide = Loc.Localize("LoadingDialogHide", "Hide")) - fixed (void* pszShowLatestLogs = Loc.Localize("LoadingDialogShowLatestLogs", "Show Latest Logs")) - fixed (void* pszHideLatestLogs = Loc.Localize("LoadingDialogHideLatestLogs", "Hide Latest Logs")) + fixed (char* pszEmpty = "-") + fixed (char* pszWindowTitle = "Dalamud") + fixed (char* pszDalamudBoot = "Dalamud.Boot.dll") + fixed (char* pszThemesManifestResourceName = "RT_MANIFEST_THEMES") + fixed (char* pszHide = Loc.Localize("LoadingDialogHide", "Hide")) + fixed (char* pszShowLatestLogs = Loc.Localize("LoadingDialogShowLatestLogs", "Show Latest Logs")) + fixed (char* pszHideLatestLogs = Loc.Localize("LoadingDialogHideLatestLogs", "Hide Latest Logs")) { var taskDialogButton = new TASKDIALOG_BUTTON { nButtonID = IDOK, - pszButtonText = (ushort*)pszHide, + pszButtonText = pszHide, }; var taskDialogConfig = new TASKDIALOGCONFIG { @@ -318,8 +318,8 @@ internal sealed class LoadingDialog (int)TDF_CALLBACK_TIMER | (extractedIcon is null ? 0 : (int)TDF_USE_HICON_MAIN), dwCommonButtons = 0, - pszWindowTitle = (ushort*)pszWindowTitle, - pszMainIcon = extractedIcon is null ? TD.TD_INFORMATION_ICON : (ushort*)extractedIcon.Handle, + pszWindowTitle = pszWindowTitle, + pszMainIcon = extractedIcon is null ? TD.TD_INFORMATION_ICON : (char*)extractedIcon.Handle, pszMainInstruction = null, pszContent = null, cButtons = 1, @@ -329,9 +329,9 @@ internal sealed class LoadingDialog pRadioButtons = null, nDefaultRadioButton = 0, pszVerificationText = null, - pszExpandedInformation = (ushort*)pszEmpty, - pszExpandedControlText = (ushort*)pszShowLatestLogs, - pszCollapsedControlText = (ushort*)pszHideLatestLogs, + pszExpandedInformation = pszEmpty, + pszExpandedControlText = pszShowLatestLogs, + pszCollapsedControlText = pszHideLatestLogs, pszFooterIcon = null, pszFooter = null, pfCallback = &HResultFuncBinder, @@ -348,8 +348,8 @@ internal sealed class LoadingDialog { cbSize = (uint)sizeof(ACTCTXW), dwFlags = ACTCTX_FLAG_HMODULE_VALID | ACTCTX_FLAG_RESOURCE_NAME_VALID, - lpResourceName = (ushort*)pszThemesManifestResourceName, - hModule = GetModuleHandleW((ushort*)pszDalamudBoot), + lpResourceName = pszThemesManifestResourceName, + hModule = GetModuleHandleW(pszDalamudBoot), }; hActCtx = CreateActCtxW(&actctx); if (hActCtx == default) diff --git a/Dalamud/Storage/Assets/DalamudAssetPurpose.cs b/Dalamud/Storage/Assets/DalamudAssetPurpose.cs index e6c7bd920..69de1f871 100644 --- a/Dalamud/Storage/Assets/DalamudAssetPurpose.cs +++ b/Dalamud/Storage/Assets/DalamudAssetPurpose.cs @@ -11,12 +11,12 @@ public enum DalamudAssetPurpose Empty = 0, /// - /// The asset is a .png file, and can be purposed as a . + /// The asset is a .png file, and can be purposed as a . /// TextureFromPng = 10, - + /// - /// The asset is a raw texture, and can be purposed as a . + /// The asset is a raw texture, and can be purposed as a . /// TextureFromRaw = 1001, diff --git a/Dalamud/Utility/ClipboardFormats.cs b/Dalamud/Utility/ClipboardFormats.cs index 07b6c00d6..b80e05dd3 100644 --- a/Dalamud/Utility/ClipboardFormats.cs +++ b/Dalamud/Utility/ClipboardFormats.cs @@ -30,8 +30,8 @@ internal static class ClipboardFormats private static unsafe uint ClipboardFormatFromName(ReadOnlySpan name) { uint cf; - fixed (void* p = name) - cf = RegisterClipboardFormatW((ushort*)p); + fixed (char* p = name) + cf = RegisterClipboardFormatW(p); if (cf != 0) return cf; throw Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()) ?? diff --git a/Dalamud/Utility/ErrorHandling.cs b/Dalamud/Utility/ErrorHandling.cs new file mode 100644 index 000000000..3c025a12e --- /dev/null +++ b/Dalamud/Utility/ErrorHandling.cs @@ -0,0 +1,21 @@ +using System.Runtime.InteropServices; + +namespace Dalamud.Utility; + +/// +/// Utilities for handling errors inside Dalamud. +/// +internal static partial class ErrorHandling +{ + /// + /// Crash the game at this point, and show the crash handler with the supplied context. + /// + /// The context to show in the crash handler. + public static void CrashWithContext(string context) + { + BootVehRaiseExternalEvent(context); + } + + [LibraryImport("Dalamud.Boot.dll", EntryPoint = "BootVehRaiseExternalEventW", StringMarshalling = StringMarshalling.Utf16)] + private static partial void BootVehRaiseExternalEvent(string info); +} diff --git a/Dalamud/Utility/FilesystemUtil.cs b/Dalamud/Utility/FilesystemUtil.cs index 3b4298b37..f1b62ee21 100644 --- a/Dalamud/Utility/FilesystemUtil.cs +++ b/Dalamud/Utility/FilesystemUtil.cs @@ -1,7 +1,8 @@ -using System.ComponentModel; +using System.ComponentModel; using System.IO; using System.Text; +using Windows.Win32.Foundation; using Windows.Win32.Storage.FileSystem; namespace Dalamud.Utility; @@ -47,30 +48,39 @@ public static class FilesystemUtil // Open the temp file var tempPath = path + ".tmp"; - using var tempFile = Windows.Win32.PInvoke.CreateFile( + var tempFile = Windows.Win32.PInvoke.CreateFile( tempPath, (uint)(FILE_ACCESS_RIGHTS.FILE_GENERIC_READ | FILE_ACCESS_RIGHTS.FILE_GENERIC_WRITE), FILE_SHARE_MODE.FILE_SHARE_NONE, null, FILE_CREATION_DISPOSITION.CREATE_ALWAYS, FILE_FLAGS_AND_ATTRIBUTES.FILE_ATTRIBUTE_NORMAL, - null); + HANDLE.Null); - if (tempFile.IsInvalid) + if (tempFile.IsNull) throw new Win32Exception(); // Write the data uint bytesWritten = 0; - if (!Windows.Win32.PInvoke.WriteFile(tempFile, new ReadOnlySpan(bytes), &bytesWritten, null)) - throw new Win32Exception(); + fixed (byte* ptr = bytes) + { + if (!Windows.Win32.PInvoke.WriteFile(tempFile, ptr, (uint)bytes.Length, &bytesWritten, null)) + throw new Win32Exception(); + } if (bytesWritten != bytes.Length) + { + Windows.Win32.PInvoke.CloseHandle(tempFile); throw new Exception($"Could not write all bytes to temp file ({bytesWritten} of {bytes.Length})"); + } if (!Windows.Win32.PInvoke.FlushFileBuffers(tempFile)) + { + Windows.Win32.PInvoke.CloseHandle(tempFile); throw new Win32Exception(); + } - tempFile.Close(); + Windows.Win32.PInvoke.CloseHandle(tempFile); if (!Windows.Win32.PInvoke.MoveFileEx(tempPath, path, MOVE_FILE_FLAGS.MOVEFILE_REPLACE_EXISTING | MOVE_FILE_FLAGS.MOVEFILE_WRITE_THROUGH)) throw new Win32Exception(); diff --git a/Dalamud/Utility/TerraFxCom/ManagedIStream.cs b/Dalamud/Utility/TerraFxCom/ManagedIStream.cs index caec65da2..eb1997daf 100644 --- a/Dalamud/Utility/TerraFxCom/ManagedIStream.cs +++ b/Dalamud/Utility/TerraFxCom/ManagedIStream.cs @@ -57,60 +57,60 @@ internal sealed unsafe class ManagedIStream : IStream.Interface, IRefCountable static ManagedIStream? ToManagedObject(void* pThis) => GCHandle.FromIntPtr(((nint*)pThis)[1]).Target as ManagedIStream; - [UnmanagedCallersOnly] + [UnmanagedCallersOnly(CallConvs = [typeof(CallConvMemberFunction)])] static int QueryInterfaceStatic(IStream* pThis, Guid* riid, void** ppvObject) => ToManagedObject(pThis)?.QueryInterface(riid, ppvObject) ?? E.E_UNEXPECTED; - [UnmanagedCallersOnly] + [UnmanagedCallersOnly(CallConvs = [typeof(CallConvMemberFunction)])] static uint AddRefStatic(IStream* pThis) => (uint)(ToManagedObject(pThis)?.AddRef() ?? 0); - [UnmanagedCallersOnly] + [UnmanagedCallersOnly(CallConvs = [typeof(CallConvMemberFunction)])] static uint ReleaseStatic(IStream* pThis) => (uint)(ToManagedObject(pThis)?.Release() ?? 0); - [UnmanagedCallersOnly] + [UnmanagedCallersOnly(CallConvs = [typeof(CallConvMemberFunction)])] static int ReadStatic(IStream* pThis, void* pv, uint cb, uint* pcbRead) => ToManagedObject(pThis)?.Read(pv, cb, pcbRead) ?? E.E_UNEXPECTED; - [UnmanagedCallersOnly] + [UnmanagedCallersOnly(CallConvs = [typeof(CallConvMemberFunction)])] static int WriteStatic(IStream* pThis, void* pv, uint cb, uint* pcbWritten) => ToManagedObject(pThis)?.Write(pv, cb, pcbWritten) ?? E.E_UNEXPECTED; - [UnmanagedCallersOnly] + [UnmanagedCallersOnly(CallConvs = [typeof(CallConvMemberFunction)])] static int SeekStatic( IStream* pThis, LARGE_INTEGER dlibMove, uint dwOrigin, ULARGE_INTEGER* plibNewPosition) => ToManagedObject(pThis)?.Seek(dlibMove, dwOrigin, plibNewPosition) ?? E.E_UNEXPECTED; - [UnmanagedCallersOnly] + [UnmanagedCallersOnly(CallConvs = [typeof(CallConvMemberFunction)])] static int SetSizeStatic(IStream* pThis, ULARGE_INTEGER libNewSize) => ToManagedObject(pThis)?.SetSize(libNewSize) ?? E.E_UNEXPECTED; - [UnmanagedCallersOnly] + [UnmanagedCallersOnly(CallConvs = [typeof(CallConvMemberFunction)])] static int CopyToStatic( IStream* pThis, IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten) => ToManagedObject(pThis)?.CopyTo(pstm, cb, pcbRead, pcbWritten) ?? E.E_UNEXPECTED; - [UnmanagedCallersOnly] + [UnmanagedCallersOnly(CallConvs = [typeof(CallConvMemberFunction)])] static int CommitStatic(IStream* pThis, uint grfCommitFlags) => ToManagedObject(pThis)?.Commit(grfCommitFlags) ?? E.E_UNEXPECTED; - [UnmanagedCallersOnly] + [UnmanagedCallersOnly(CallConvs = [typeof(CallConvMemberFunction)])] static int RevertStatic(IStream* pThis) => ToManagedObject(pThis)?.Revert() ?? E.E_UNEXPECTED; - [UnmanagedCallersOnly] + [UnmanagedCallersOnly(CallConvs = [typeof(CallConvMemberFunction)])] static int LockRegionStatic(IStream* pThis, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, uint dwLockType) => ToManagedObject(pThis)?.LockRegion(libOffset, cb, dwLockType) ?? E.E_UNEXPECTED; - [UnmanagedCallersOnly] + [UnmanagedCallersOnly(CallConvs = [typeof(CallConvMemberFunction)])] static int UnlockRegionStatic( IStream* pThis, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, uint dwLockType) => ToManagedObject(pThis)?.UnlockRegion(libOffset, cb, dwLockType) ?? E.E_UNEXPECTED; - [UnmanagedCallersOnly] + [UnmanagedCallersOnly(CallConvs = [typeof(CallConvMemberFunction)])] static int StatStatic(IStream* pThis, STATSTG* pstatstg, uint grfStatFlag) => ToManagedObject(pThis)?.Stat(pstatstg, grfStatFlag) ?? E.E_UNEXPECTED; - [UnmanagedCallersOnly] + [UnmanagedCallersOnly(CallConvs = [typeof(CallConvMemberFunction)])] static int CloneStatic(IStream* pThis, IStream** ppstm) => ToManagedObject(pThis)?.Clone(ppstm) ?? E.E_UNEXPECTED; } diff --git a/Dalamud/Utility/TerraFxCom/TerraFxComInterfaceExtensions.cs b/Dalamud/Utility/TerraFxCom/TerraFxComInterfaceExtensions.cs index f9252839f..ec108403e 100644 --- a/Dalamud/Utility/TerraFxCom/TerraFxComInterfaceExtensions.cs +++ b/Dalamud/Utility/TerraFxCom/TerraFxComInterfaceExtensions.cs @@ -88,7 +88,7 @@ internal static unsafe partial class TerraFxComInterfaceExtensions fixed (char* pPath = path) { SHCreateStreamOnFileEx( - (ushort*)pPath, + pPath, grfMode, (uint)attributes, fCreate, @@ -115,7 +115,7 @@ internal static unsafe partial class TerraFxComInterfaceExtensions { fixed (char* pName = name) { - var option = new PROPBAG2 { pstrName = (ushort*)pName }; + var option = new PROPBAG2 { pstrName = pName }; return obj.Write(1, &option, &varValue); } } @@ -145,7 +145,7 @@ internal static unsafe partial class TerraFxComInterfaceExtensions try { fixed (char* pName = name) - return obj.SetMetadataByName((ushort*)pName, &propVarValue); + return obj.SetMetadataByName(pName, &propVarValue); } finally { @@ -165,7 +165,7 @@ internal static unsafe partial class TerraFxComInterfaceExtensions public static HRESULT RemoveMetadataByName(ref this IWICMetadataQueryWriter obj, string name) { fixed (char* pName = name) - return obj.RemoveMetadataByName((ushort*)pName); + return obj.RemoveMetadataByName(pName); } [LibraryImport("propsys.dll")] diff --git a/Dalamud/Utility/Util.cs b/Dalamud/Utility/Util.cs index f6abc336c..e273decac 100644 --- a/Dalamud/Utility/Util.cs +++ b/Dalamud/Utility/Util.cs @@ -158,16 +158,6 @@ public static partial class Util return branchInternal = gitBranch; } - /// - /// Gets the active Dalamud track, if this instance was launched through XIVLauncher and used a version - /// downloaded from webservices. - /// - /// The name of the track, or null. - internal static string? GetActiveTrack() - { - return Environment.GetEnvironmentVariable("DALAMUD_BRANCH"); - } - /// public static unsafe string DescribeAddress(void* p) => DescribeAddress((nint)p); @@ -703,6 +693,16 @@ public static partial class Util } } + /// + /// Gets the active Dalamud track, if this instance was launched through XIVLauncher and used a version + /// downloaded from webservices. + /// + /// The name of the track, or null. + internal static string? GetActiveTrack() + { + return Environment.GetEnvironmentVariable("DALAMUD_BRANCH"); + } + /// /// Gets a random, inoffensive, human-friendly string. /// @@ -858,7 +858,7 @@ public static partial class Util var sizeWithTerminators = pathBytesSize + (pathBytes.Length * 2); var dropFilesSize = sizeof(DROPFILES); - var hGlobal = Win32_PInvoke.GlobalAlloc_SafeHandle( + var hGlobal = Win32_PInvoke.GlobalAlloc( GLOBAL_ALLOC_FLAGS.GHND, // struct size + size of encoded strings + null terminator for each // string + two null terminators for end of list @@ -896,12 +896,11 @@ public static partial class Util { Win32_PInvoke.SetClipboardData( (uint)CLIPBOARD_FORMAT.CF_HDROP, - hGlobal); + (Windows.Win32.Foundation.HANDLE)hGlobal.Value); Win32_PInvoke.CloseClipboard(); return true; } - hGlobal.Dispose(); return false; } diff --git a/Dalamud/Utility/VectorExtensions.cs b/Dalamud/Utility/VectorExtensions.cs deleted file mode 100644 index f617c8420..000000000 --- a/Dalamud/Utility/VectorExtensions.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System.Numerics; - -namespace Dalamud.Utility; - -/// -/// Extension methods for System.Numerics.VectorN and SharpDX.VectorN. -/// -public static class VectorExtensions -{ - /// - /// Converts a SharpDX vector to System.Numerics. - /// - /// Vector to convert. - /// A converted vector. - public static Vector2 ToSystem(this SharpDX.Vector2 vec) => new(x: vec.X, y: vec.Y); - - /// - /// Converts a SharpDX vector to System.Numerics. - /// - /// Vector to convert. - /// A converted vector. - public static Vector3 ToSystem(this SharpDX.Vector3 vec) => new(x: vec.X, y: vec.Y, z: vec.Z); - - /// - /// Converts a SharpDX vector to System.Numerics. - /// - /// Vector to convert. - /// A converted vector. - public static Vector4 ToSystem(this SharpDX.Vector4 vec) => new(x: vec.X, y: vec.Y, z: vec.Z, w: vec.W); - - /// - /// Converts a System.Numerics vector to SharpDX. - /// - /// Vector to convert. - /// A converted vector. - public static SharpDX.Vector2 ToSharpDX(this Vector2 vec) => new(x: vec.X, y: vec.Y); - - /// - /// Converts a System.Numerics vector to SharpDX. - /// - /// Vector to convert. - /// A converted vector. - public static SharpDX.Vector3 ToSharpDX(this Vector3 vec) => new(x: vec.X, y: vec.Y, z: vec.Z); - - /// - /// Converts a System.Numerics vector to SharpDX. - /// - /// Vector to convert. - /// A converted vector. - public static SharpDX.Vector4 ToSharpDX(this Vector4 vec) => new(x: vec.X, y: vec.Y, z: vec.Z, w: vec.W); -} diff --git a/DalamudCrashHandler/DalamudCrashHandler.cpp b/DalamudCrashHandler/DalamudCrashHandler.cpp index ec7115ffd..3955bd983 100644 --- a/DalamudCrashHandler/DalamudCrashHandler.cpp +++ b/DalamudCrashHandler/DalamudCrashHandler.cpp @@ -119,7 +119,7 @@ std::wstring describe_module(const std::filesystem::path& path) { return std::format(L"", GetLastError()); UINT size = 0; - + std::wstring version = L"v?.?.?.?"; if (LPVOID lpBuffer; VerQueryValueW(block.data(), L"\\", &lpBuffer, &size)) { const auto& v = *static_cast(lpBuffer); @@ -176,7 +176,7 @@ const std::map& get_remote_modules() { std::vector buf(8192); for (size_t i = 0; i < 64; i++) { if (DWORD needed; !EnumProcessModules(g_hProcess, &buf[0], static_cast(std::span(buf).size_bytes()), &needed)) { - std::cerr << std::format("EnumProcessModules error: 0x{:x}", GetLastError()) << std::endl; + std::cerr << std::format("EnumProcessModules error: 0x{:x}", GetLastError()) << std::endl; break; } else if (needed > std::span(buf).size_bytes()) { buf.resize(needed / sizeof(HMODULE) + 16); @@ -201,7 +201,7 @@ const std::map& get_remote_modules() { data[hModule] = nth64.OptionalHeader.SizeOfImage; } - + return data; }(); @@ -292,35 +292,43 @@ std::wstring to_address_string(const DWORD64 address, const bool try_ptrderef = void print_exception_info(HANDLE hThread, const EXCEPTION_POINTERS& ex, const CONTEXT& ctx, std::wostringstream& log) { std::vector exRecs; - if (ex.ExceptionRecord) { + if (ex.ExceptionRecord) + { size_t rec_index = 0; size_t read; - exRecs.emplace_back(); + for (auto pRemoteExRec = ex.ExceptionRecord; - pRemoteExRec - && rec_index < 64 - && ReadProcessMemory(g_hProcess, pRemoteExRec, &exRecs.back(), sizeof exRecs.back(), &read) - && read >= offsetof(EXCEPTION_RECORD, ExceptionInformation) - && read >= static_cast(reinterpret_cast(&exRecs.back().ExceptionInformation[exRecs.back().NumberParameters]) - reinterpret_cast(&exRecs.back())); - rec_index++) { + pRemoteExRec && rec_index < 64; + rec_index++) + { + exRecs.emplace_back(); + + if (!ReadProcessMemory(g_hProcess, pRemoteExRec, &exRecs.back(), sizeof exRecs.back(), &read) + || read < offsetof(EXCEPTION_RECORD, ExceptionInformation) + || read < static_cast(reinterpret_cast(&exRecs.back().ExceptionInformation[exRecs. + back().NumberParameters]) - reinterpret_cast(&exRecs.back()))) + { + exRecs.pop_back(); + break; + } log << std::format(L"\nException Info #{}\n", rec_index); log << std::format(L"Address: {:X}\n", exRecs.back().ExceptionCode); log << std::format(L"Flags: {:X}\n", exRecs.back().ExceptionFlags); log << std::format(L"Address: {:X}\n", reinterpret_cast(exRecs.back().ExceptionAddress)); - if (!exRecs.back().NumberParameters) - continue; - log << L"Parameters: "; - for (DWORD i = 0; i < exRecs.back().NumberParameters; ++i) { - if (i != 0) - log << L", "; - log << std::format(L"{:X}", exRecs.back().ExceptionInformation[i]); + if (exRecs.back().NumberParameters) + { + log << L"Parameters: "; + for (DWORD i = 0; i < exRecs.back().NumberParameters; ++i) + { + if (i != 0) + log << L", "; + log << std::format(L"{:X}", exRecs.back().ExceptionInformation[i]); + } } pRemoteExRec = exRecs.back().ExceptionRecord; - exRecs.emplace_back(); } - exRecs.pop_back(); } log << L"\nCall Stack\n{"; @@ -410,7 +418,7 @@ void print_exception_info_extended(const EXCEPTION_POINTERS& ex, const CONTEXT& std::wstring escape_shell_arg(const std::wstring& arg) { // https://docs.microsoft.com/en-us/archive/blogs/twistylittlepassagesallalike/everyone-quotes-command-line-arguments-the-wrong-way - + std::wstring res; if (!arg.empty() && arg.find_first_of(L" \t\n\v\"") == std::wstring::npos) { res.append(arg); @@ -504,7 +512,7 @@ void export_tspack(HWND hWndParent, const std::filesystem::path& logDir, const s filePath.emplace(pFilePath); std::fstream fileStream(*filePath, std::ios::binary | std::ios::in | std::ios::out | std::ios::trunc); - + mz_zip_archive zipa{}; zipa.m_pIO_opaque = &fileStream; zipa.m_pRead = [](void* pOpaque, mz_uint64 file_ofs, void* pBuf, size_t n) -> size_t { @@ -566,7 +574,7 @@ void export_tspack(HWND hWndParent, const std::filesystem::path& logDir, const s const auto hLogFile = CreateFileW(logFilePath.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, nullptr); if (hLogFile == INVALID_HANDLE_VALUE) throw_last_error(std::format("indiv. log file: CreateFileW({})", ws_to_u8(logFilePath.wstring()))); - + std::unique_ptr hLogFileClose(hLogFile, &CloseHandle); LARGE_INTEGER size, baseOffset{}; @@ -695,7 +703,7 @@ int main() { // IFileSaveDialog only works on STA CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); - + std::vector args; if (int argc = 0; const auto argv = CommandLineToArgvW(GetCommandLineW(), &argc)) { for (auto i = 0; i < argc; i++) @@ -823,14 +831,14 @@ int main() { hr = pOleWindow->GetWindow(&hwndProgressDialog); if (SUCCEEDED(hr)) { - SetWindowPos(hwndProgressDialog, HWND_TOPMOST, 0, 0, 0, 0, + SetWindowPos(hwndProgressDialog, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); SetForegroundWindow(hwndProgressDialog); } - + pOleWindow->Release(); } - + } else { std::cerr << "Failed to create progress window" << std::endl; @@ -852,14 +860,14 @@ int main() { https://github.com/sumatrapdfreader/sumatrapdf/blob/master/src/utils/DbgHelpDyn.cpp */ - + if (g_bSymbolsAvailable) { SymRefreshModuleList(g_hProcess); } else if(!assetDir.empty()) { auto symbol_search_path = std::format(L".;{}", (assetDir / "UIRes" / "pdb").wstring()); - + g_bSymbolsAvailable = SymInitializeW(g_hProcess, symbol_search_path.c_str(), true); std::wcout << std::format(L"Init symbols with PDB at {}", symbol_search_path) << std::endl; @@ -870,12 +878,12 @@ int main() { g_bSymbolsAvailable = SymInitializeW(g_hProcess, nullptr, true); std::cout << "Init symbols without PDB" << std::endl; } - + if (!g_bSymbolsAvailable) { std::wcerr << std::format(L"SymInitialize error: 0x{:x}", GetLastError()) << std::endl; } - if (pProgressDialog) + if (pProgressDialog) pProgressDialog->SetLine(3, L"Reading troubleshooting data", FALSE, NULL); std::wstring stackTrace(exinfo.dwStackTraceLength, L'\0'); @@ -930,13 +938,23 @@ int main() { } while (false); } + const bool is_external_event = exinfo.ExceptionRecord.ExceptionCode == CUSTOM_EXCEPTION_EXTERNAL_EVENT; + std::wostringstream log; - log << std::format(L"Unhandled native exception occurred at {}", to_address_string(exinfo.ContextRecord.Rip, false)) << std::endl; - log << std::format(L"Code: {:X}", exinfo.ExceptionRecord.ExceptionCode) << std::endl; + + if (!is_external_event) + { + log << std::format(L"Unhandled native exception occurred at {}", to_address_string(exinfo.ContextRecord.Rip, false)) << std::endl; + log << std::format(L"Code: {:X}", exinfo.ExceptionRecord.ExceptionCode) << std::endl; + } + else + { + log << L"CLR error occurred" << std::endl; + } if (shutup) log << L"======= Crash handler was globally muted(shutdown?) =======" << std::endl; - + if (dumpPath.empty()) log << L"Dump skipped" << std::endl; else if (dumpError.empty()) @@ -949,9 +967,19 @@ int main() { if (pProgressDialog) pProgressDialog->SetLine(3, L"Refreshing Module List", FALSE, NULL); + std::wstring window_log_str; + + // Cut the log here for external events, the rest is unreadable and doesn't matter since we can't get + // symbols for mixed-mode stacks yet. + if (is_external_event) + window_log_str = log.str(); + SymRefreshModuleList(GetCurrentProcess()); print_exception_info(exinfo.hThreadHandle, exinfo.ExceptionPointers, exinfo.ContextRecord, log); - const auto window_log_str = log.str(); + + if (!is_external_event) + window_log_str = log.str(); + print_exception_info_extended(exinfo.ExceptionPointers, exinfo.ContextRecord, log); std::wofstream(logPath) << log.str(); @@ -986,8 +1014,8 @@ int main() { config.pButtons = buttons; config.cButtons = ARRAYSIZE(buttons); config.nDefaultButton = IdButtonRestart; - config.pszExpandedControlText = L"Hide stack trace"; - config.pszCollapsedControlText = L"Stack trace for plugin developers"; + config.pszExpandedControlText = L"Hide further information"; + config.pszCollapsedControlText = L"Further information for developers"; config.pszExpandedInformation = window_log_str.c_str(); config.pszWindowTitle = L"Dalamud Crash Handler"; config.pRadioButtons = radios; @@ -1003,7 +1031,7 @@ int main() { R"aa(Help | Open log directory | Open log file)aa" ); #endif - + // Can't do this, xiv stops pumping messages here //config.hwndParent = FindWindowA("FFXIVGAME", NULL); @@ -1056,13 +1084,13 @@ int main() { return (*reinterpret_cast(dwRefData))(hwnd, uNotification, wParam, lParam); }; config.lpCallbackData = reinterpret_cast(&callback); - + if (pProgressDialog) { pProgressDialog->StopProgressDialog(); pProgressDialog->Release(); pProgressDialog = NULL; } - + const auto kill_game = [&] { TerminateProcess(g_hProcess, exinfo.ExceptionRecord.ExceptionCode); }; if (shutup) { diff --git a/Directory.Packages.props b/Directory.Packages.props index 903a8ee88..58e355400 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -26,10 +26,8 @@ - - - - + + diff --git a/build/DalamudBuild.cs b/build/DalamudBuild.cs index ba2b09a4d..1a189f2c7 100644 --- a/build/DalamudBuild.cs +++ b/build/DalamudBuild.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.IO; using Nuke.Common; using Nuke.Common.Execution; using Nuke.Common.Git; @@ -128,7 +127,7 @@ public class DalamudBuild : NukeBuild if (IsCIBuild) { s = s - .SetProcessArgumentConfigurator(a => a.Add("/clp:NoSummary")); // Disable MSBuild summary on CI builds + .SetProcessAdditionalArguments("/clp:NoSummary"); // Disable MSBuild summary on CI builds } // We need to emit compiler generated files for the docs build, since docfx can't run generators directly // TODO: This fails every build after this because of redefinitions... @@ -238,7 +237,6 @@ public class DalamudBuild : NukeBuild .SetProject(InjectorProjectFile) .SetConfiguration(Configuration)); - FileSystemTasks.DeleteDirectory(ArtifactsDirectory); - Directory.CreateDirectory(ArtifactsDirectory); + ArtifactsDirectory.CreateOrCleanDirectory(); }); } diff --git a/build/build.csproj b/build/build.csproj index 1e1416d92..7096c7f8a 100644 --- a/build/build.csproj +++ b/build/build.csproj @@ -11,7 +11,7 @@ false - + diff --git a/imgui/Dalamud.Bindings.ImGui/ImVector.cs b/imgui/Dalamud.Bindings.ImGui/ImVector.cs index 9a10c1d6b..67e450193 100644 --- a/imgui/Dalamud.Bindings.ImGui/ImVector.cs +++ b/imgui/Dalamud.Bindings.ImGui/ImVector.cs @@ -1,7 +1,12 @@ -using System.Runtime.CompilerServices; +using System.Collections; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace Dalamud.Bindings.ImGui; +/// +/// A structure representing a dynamic array for unmanaged types. +/// public unsafe struct ImVector { public readonly int Size; @@ -15,23 +20,23 @@ public unsafe struct ImVector Data = data; } - public ref T Ref(int index) - { - return ref Unsafe.AsRef((byte*)Data + index * Unsafe.SizeOf()); - } + public readonly ref T Ref(int index) => ref Unsafe.AsRef((byte*)this.Data + (index * Unsafe.SizeOf())); - public IntPtr Address(int index) - { - return (IntPtr)((byte*)Data + index * Unsafe.SizeOf()); - } + public readonly nint Address(int index) => (nint)((byte*)this.Data + (index * Unsafe.SizeOf())); } /// /// A structure representing a dynamic array for unmanaged types. /// /// The type of elements in the vector, must be unmanaged. -public unsafe struct ImVector where T : unmanaged +[StructLayout(LayoutKind.Sequential)] +public unsafe struct ImVector : IEnumerable + where T : unmanaged { + private int size; + private int capacity; + private T* data; + /// /// Initializes a new instance of the struct with the specified size, capacity, and data pointer. /// @@ -45,11 +50,6 @@ public unsafe struct ImVector where T : unmanaged this.data = data; } - private int size; - private int capacity; - private unsafe T* data; - - /// /// Gets or sets the element at the specified index. /// @@ -58,80 +58,72 @@ public unsafe struct ImVector where T : unmanaged /// Thrown when the index is out of range. public T this[int index] { - get + readonly get { - if (index < 0 || index >= size) - { + if (index < 0 || index >= this.size) throw new IndexOutOfRangeException(); - } - return data[index]; + return this.data[index]; } set { - if (index < 0 || index >= size) - { + if (index < 0 || index >= this.size) throw new IndexOutOfRangeException(); - } - data[index] = value; + this.data[index] = value; } } /// /// Gets a pointer to the first element of the vector. /// - public readonly T* Data => data; + public readonly T* Data => this.data; /// /// Gets a pointer to the first element of the vector. /// - public readonly T* Front => data; + public readonly T* Front => this.data; /// /// Gets a pointer to the last element of the vector. /// - public readonly T* Back => size > 0 ? data + size - 1 : null; + public readonly T* Back => this.size > 0 ? this.data + this.size - 1 : null; /// /// Gets or sets the capacity of the vector. /// public int Capacity { - readonly get => capacity; + readonly get => this.capacity; set { - if (capacity == value) - { + ArgumentOutOfRangeException.ThrowIfLessThan(value, this.size, nameof(Capacity)); + if (this.capacity == value) return; - } - if (data == null) + if (this.data == null) { - data = (T*)ImGui.MemAlloc((nuint)(value * sizeof(T))); + this.data = (T*)ImGui.MemAlloc((nuint)(value * sizeof(T))); } else { - int newSize = Math.Min(size, value); - T* newData = (T*)ImGui.MemAlloc((nuint)(value * sizeof(T))); - Buffer.MemoryCopy(data, newData, (nuint)(value * sizeof(T)), (nuint)(newSize * sizeof(T))); - ImGui.MemFree(data); - data = newData; - size = newSize; + var newSize = Math.Min(this.size, value); + var newData = (T*)ImGui.MemAlloc((nuint)(value * sizeof(T))); + Buffer.MemoryCopy(this.data, newData, (nuint)(value * sizeof(T)), (nuint)(newSize * sizeof(T))); + ImGui.MemFree(this.data); + this.data = newData; + this.size = newSize; } - capacity = value; + this.capacity = value; // Clear the rest of the data - for (int i = size; i < capacity; i++) - { - data[i] = default; - } + new Span(this.data + this.size, this.capacity - this.size).Clear(); } } /// /// Gets the number of elements in the vector. /// - public readonly int Size => size; + public readonly int Size => this.size; /// /// Grows the capacity of the vector to at least the specified value. @@ -139,10 +131,8 @@ public unsafe struct ImVector where T : unmanaged /// The new capacity. public void Grow(int newCapacity) { - if (newCapacity > capacity) - { - Capacity = newCapacity * 2; - } + var newCapacity2 = this.capacity > 0 ? this.capacity + (this.capacity / 2) : 8; + this.Capacity = newCapacity2 > newCapacity ? newCapacity2 : newCapacity; } /// @@ -151,10 +141,8 @@ public unsafe struct ImVector where T : unmanaged /// The minimum capacity required. public void EnsureCapacity(int size) { - if (size > capacity) - { + if (size > this.capacity) Grow(size); - } } /// @@ -164,25 +152,46 @@ public unsafe struct ImVector where T : unmanaged public void Resize(int newSize) { EnsureCapacity(newSize); - size = newSize; + this.size = newSize; } /// /// Clears all elements from the vector. /// - public void Clear() + public void Clear() => this.size = 0; + + /// + /// Adds an element to the end of the vector. + /// + /// The value to add. + [OverloadResolutionPriority(1)] + public void PushBack(T value) { - size = 0; + this.EnsureCapacity(this.size + 1); + this.data[this.size++] = value; } /// /// Adds an element to the end of the vector. /// /// The value to add. - public void PushBack(T value) + [OverloadResolutionPriority(2)] + public void PushBack(in T value) { - EnsureCapacity(size + 1); - data[size++] = value; + EnsureCapacity(this.size + 1); + this.data[this.size++] = value; + } + + /// + /// Adds an element to the front of the vector. + /// + /// The value to add. + public void PushFront(in T value) + { + if (this.size == 0) + this.PushBack(value); + else + this.Insert(0, value); } /// @@ -190,48 +199,126 @@ public unsafe struct ImVector where T : unmanaged /// public void PopBack() { - if (size > 0) + if (this.size > 0) { - size--; + this.size--; } } + public ref T Insert(int index, in T v) { + ArgumentOutOfRangeException.ThrowIfNegative(index, nameof(index)); + ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(index, this.size, nameof(index)); + this.EnsureCapacity(this.size + 1); + if (index < this.size) + { + Buffer.MemoryCopy( + this.data + index, + this.data + index + 1, + (this.size - index) * sizeof(T), + (this.size - index) * sizeof(T)); + } + + this.data[index] = v; + this.size++; + return ref this.data[index]; + } + + public Span InsertRange(int index, ReadOnlySpan v) + { + ArgumentOutOfRangeException.ThrowIfNegative(index, nameof(index)); + ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(index, this.size, nameof(index)); + this.EnsureCapacity(this.size + v.Length); + if (index < this.size) + { + Buffer.MemoryCopy( + this.data + index, + this.data + index + v.Length, + (this.size - index) * sizeof(T), + (this.size - index) * sizeof(T)); + } + + var dstSpan = new Span(this.data + index, v.Length); + v.CopyTo(new(this.data + index, v.Length)); + this.size += v.Length; + return dstSpan; + } + /// /// Frees the memory allocated for the vector. /// public void Free() { - if (data != null) + if (this.data != null) { - ImGui.MemFree(data); - data = null; - size = 0; - capacity = 0; + ImGui.MemFree(this.data); + this.data = null; + this.size = 0; + this.capacity = 0; } } - public ref T Ref(int index) + public readonly ref T Ref(int index) { - return ref Unsafe.AsRef((byte*)Data + index * Unsafe.SizeOf()); + return ref Unsafe.AsRef((byte*)Data + (index * Unsafe.SizeOf())); } - public ref TCast Ref(int index) + public readonly ref TCast Ref(int index) { - return ref Unsafe.AsRef((byte*)Data + index * Unsafe.SizeOf()); + return ref Unsafe.AsRef((byte*)Data + (index * Unsafe.SizeOf())); } - public void* Address(int index) + public readonly void* Address(int index) { - return (byte*)Data + index * Unsafe.SizeOf(); + return (byte*)Data + (index * Unsafe.SizeOf()); } - public void* Address(int index) + public readonly void* Address(int index) { - return (byte*)Data + index * Unsafe.SizeOf(); + return (byte*)Data + (index * Unsafe.SizeOf()); } - public ImVector* ToUntyped() + public readonly ImVector* ToUntyped() { - return (ImVector*)Unsafe.AsPointer(ref this); + return (ImVector*)Unsafe.AsPointer(ref Unsafe.AsRef(in this)); + } + + public readonly Span AsSpan() => new(this.data, this.size); + + public readonly Enumerator GetEnumerator() => new(this.data, this.data + this.size); + + readonly IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); + + readonly IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); + + public struct Enumerator(T* begin, T* end) : IEnumerator, IEnumerable + { + private T* current = null; + + public readonly ref T Current => ref *this.current; + + readonly T IEnumerator.Current => this.Current; + + readonly object IEnumerator.Current => this.Current; + + public bool MoveNext() + { + var next = this.current == null ? begin : this.current + 1; + if (next == end) + return false; + this.current = next; + return true; + } + + public void Reset() => this.current = null; + + public readonly Enumerator GetEnumerator() => new(begin, end); + + readonly void IDisposable.Dispose() + { + } + + readonly IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); + + readonly IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); } } diff --git a/lib/FFXIVClientStructs b/lib/FFXIVClientStructs index e5f586630..e5dedba42 160000 --- a/lib/FFXIVClientStructs +++ b/lib/FFXIVClientStructs @@ -1 +1 @@ -Subproject commit e5f586630ef06fa48d5dc0d8c0fa679323093c77 +Subproject commit e5dedba42a3fea8f050ea54ac583a5874bf51c6f diff --git a/lib/cimgui b/lib/cimgui index 27c8565f6..bc3272967 160000 --- a/lib/cimgui +++ b/lib/cimgui @@ -1 +1 @@ -Subproject commit 27c8565f631b004c3266373890e41ecc627f775b +Subproject commit bc327296758d57d3bdc963cb6ce71dd5b0c7e54c diff --git a/targets/Dalamud.Plugin.Bootstrap.targets b/targets/Dalamud.Plugin.Bootstrap.targets deleted file mode 100644 index db4bf6cd7..000000000 --- a/targets/Dalamud.Plugin.Bootstrap.targets +++ /dev/null @@ -1,11 +0,0 @@ - - - - $(appdata)\XIVLauncher\addon\Hooks\dev\ - $(HOME)/.xlcore/dalamud/Hooks/dev/ - $(HOME)/Library/Application Support/XIV on Mac/dalamud/Hooks/dev/ - $(DALAMUD_HOME)/ - - - - diff --git a/targets/Dalamud.Plugin.targets b/targets/Dalamud.Plugin.targets deleted file mode 100644 index 08d19735e..000000000 --- a/targets/Dalamud.Plugin.targets +++ /dev/null @@ -1,35 +0,0 @@ - - - - net8.0-windows - x64 - enable - latest - true - false - false - true - true - $(AssemblySearchPaths);$(DalamudLibPath) - - - - - - - - - - - - - - - - - - - - - -